• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

uwefladrich / scriptengine / 7021324889

28 Nov 2023 03:55PM UTC coverage: 91.371% (-0.3%) from 91.671%
7021324889

Pull #100

github

uwefladrich
Update CHANGES
Pull Request #100: Better Jinja2 error messages

23 of 38 new or added lines in 4 files covered. (60.53%)

1 existing line in 1 file now uncovered.

1906 of 2086 relevant lines covered (91.37%)

0.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

76.09
/src/scriptengine/jinja.py
1
"""ScriptEngine helpers: Jinja2 rendering"""
1✔
2

3
import datetime
1✔
4
import os
1✔
5

6
import jinja2
1✔
7

8
from scriptengine.exceptions import ScriptEngineParseJinjaError
1✔
9

10

11
def string_to_datetime(string, format="%Y-%m-%d %H:%M:%S"):
1✔
12
    """Jinja2 filter to convert a string to datetime.datetime"""
13
    return datetime.datetime.strptime(string, format)
×
14

15

16
def string_to_date(string, format="%Y-%m-%d %H:%M:%S"):
1✔
17
    """Jinja2 filter to convert a string to datetime.date"""
18
    return datetime.datetime.strptime(string, format).date()
×
19

20

21
def basename(path):
1✔
22
    """Jinja2 filter that returns a path's base name"""
23
    return os.path.basename(path)
×
24

25

26
def dirname(path):
1✔
27
    """Jinja2 filter that returns a path's dir name"""
28
    return os.path.dirname(path)
×
29

30

31
def exists(path):
1✔
32
    """Jinja2 filter that returns whether a path exists or not"""
33
    return os.path.exists(path)
×
34

35

36
def path_join(pathlist):
1✔
37
    """Jinja2 filter that composes a path from components"""
38
    return os.path.join(*pathlist)
×
39

40

41
def filters():
1✔
42
    """Return all defined Jinja2 filters by their name and corresponding function"""
43
    return {
1✔
44
        "datetime": string_to_datetime,
45
        "date": string_to_date,
46
        "basename": basename,
47
        "dirname": dirname,
48
        "exists": exists,
49
        "path_join": path_join,
50
    }
51

52

53
# Jinja2 Environment to be used for rendering of parameters in the YAML files
54
_param_env = jinja2.Environment(loader=jinja2.BaseLoader)
1✔
55
for name, function in filters().items():
1✔
56
    _param_env.filters[name] = function
1✔
57

58

59
def _strtobool(value):
1✔
60
    if value in ("y", "yes", "t", "true", "on", "1"):
1✔
61
        return True
1✔
62
    elif value in ("n", "no", "f", "false", "off", "0"):
1✔
63
        return False
1✔
64
    raise ValueError(f"Cannot convert '{value}' to a boolean value")
×
65

66

67
def render(arg, context, recursive=True, boolean=False):
1✔
68
    """Renders a string with Jinja2.
69

70
    The argument is rendered via jinja2.Template().render() if it is a string,
71
    or returned unchanged otherwise. Rendering is done either once or
72
    recursively until no further variables can be substituted. The result is
73
    returned either as string, or converted into a bool (True/False).
74

75
    Args:
76
        arg: The string to be rendered. If it is not a string, arg is returned
77
            without changes.
78
        recursive (bool): If true (default), the string is rendered
79
            recursively, i.e. until it's value doesn't change anymore. If
80
            false, the string is rendered once.
81
        boolean (bool): If false (default) the rendered string is returned
82
            (i.e. the return value is a string). If true, the rendered
83
            string is evaluated in a boolean context in Jinja2.  The return
84
            value is true or false in this case.
85
        context (dict): A dictionary that provides the context for
86
            jinja2.Template().render()
87

88
    Returns:
89
        str: The rendered string (of boolean==False), OR
90
        bool: The rendered string, evaluated as bool (if boolean=True)
91
    """
92

93
    def render_with_context(string_arg):
1✔
94
        try:
1✔
95
            # Render string in parameter environment using context
96
            return _param_env.from_string(string_arg).render(context)
1✔
NEW
97
        except jinja2.TemplateError as e:
×
98
            raise ScriptEngineParseJinjaError(
×
99
                f"Jinja2 {type(e).__name__} while parsing '{string_arg}'"
100
                f"{' (in boolean context): ' if boolean else ': '}"
101
                f"{e}"
102
            )
103

104
    if isinstance(arg, str):
1✔
105
        rendered_string = render_with_context(arg)
1✔
106
        if recursive:
1✔
107
            next_rendered_string = render_with_context(rendered_string)
1✔
108
            while rendered_string != next_rendered_string:
1✔
109
                rendered_string = next_rendered_string
×
110
                next_rendered_string = render_with_context(rendered_string)
×
111
        if boolean:
1✔
112
            expr = f"{{% if {rendered_string} %}}1{{% else %}}0{{% endif %}}"
1✔
113
            return _strtobool(render_with_context(expr))
1✔
114
        return rendered_string
1✔
115
    else:
116
        return arg
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc