jinja2.tests

Built-in template tests used with the is operator.

  1"""Built-in template tests used with the ``is`` operator."""
  2
  3import operator
  4import typing as t
  5from collections import abc
  6from numbers import Number
  7
  8from .runtime import Undefined
  9from .utils import pass_environment
 10
 11if t.TYPE_CHECKING:
 12    from .environment import Environment
 13
 14
 15def test_odd(value: int) -> bool:
 16    """Return true if the variable is odd."""
 17    return value % 2 == 1
 18
 19
 20def test_even(value: int) -> bool:
 21    """Return true if the variable is even."""
 22    return value % 2 == 0
 23
 24
 25def test_divisibleby(value: int, num: int) -> bool:
 26    """Check if a variable is divisible by a number."""
 27    return value % num == 0
 28
 29
 30def test_defined(value: t.Any) -> bool:
 31    """Return true if the variable is defined:
 32
 33    .. sourcecode:: jinja
 34
 35        {% if variable is defined %}
 36            value of variable: {{ variable }}
 37        {% else %}
 38            variable is not defined
 39        {% endif %}
 40
 41    See the :func:`default` filter for a simple way to set undefined
 42    variables.
 43    """
 44    return not isinstance(value, Undefined)
 45
 46
 47def test_undefined(value: t.Any) -> bool:
 48    """Like :func:`defined` but the other way round."""
 49    return isinstance(value, Undefined)
 50
 51
 52@pass_environment
 53def test_filter(env: "Environment", value: str) -> bool:
 54    """Check if a filter exists by name. Useful if a filter may be
 55    optionally available.
 56
 57    .. code-block:: jinja
 58
 59        {% if 'markdown' is filter %}
 60            {{ value | markdown }}
 61        {% else %}
 62            {{ value }}
 63        {% endif %}
 64
 65    .. versionadded:: 3.0
 66    """
 67    return value in env.filters
 68
 69
 70@pass_environment
 71def test_test(env: "Environment", value: str) -> bool:
 72    """Check if a test exists by name. Useful if a test may be
 73    optionally available.
 74
 75    .. code-block:: jinja
 76
 77        {% if 'loud' is test %}
 78            {% if value is loud %}
 79                {{ value|upper }}
 80            {% else %}
 81                {{ value|lower }}
 82            {% endif %}
 83        {% else %}
 84            {{ value }}
 85        {% endif %}
 86
 87    .. versionadded:: 3.0
 88    """
 89    return value in env.tests
 90
 91
 92def test_none(value: t.Any) -> bool:
 93    """Return true if the variable is none."""
 94    return value is None
 95
 96
 97def test_boolean(value: t.Any) -> bool:
 98    """Return true if the object is a boolean value.
 99
100    .. versionadded:: 2.11
101    """
102    return value is True or value is False
103
104
105def test_false(value: t.Any) -> bool:
106    """Return true if the object is False.
107
108    .. versionadded:: 2.11
109    """
110    return value is False
111
112
113def test_true(value: t.Any) -> bool:
114    """Return true if the object is True.
115
116    .. versionadded:: 2.11
117    """
118    return value is True
119
120
121# NOTE: The existing 'number' test matches booleans and floats
122def test_integer(value: t.Any) -> bool:
123    """Return true if the object is an integer.
124
125    .. versionadded:: 2.11
126    """
127    return isinstance(value, int) and value is not True and value is not False
128
129
130# NOTE: The existing 'number' test matches booleans and integers
131def test_float(value: t.Any) -> bool:
132    """Return true if the object is a float.
133
134    .. versionadded:: 2.11
135    """
136    return isinstance(value, float)
137
138
139def test_lower(value: str) -> bool:
140    """Return true if the variable is lowercased."""
141    return str(value).islower()
142
143
144def test_upper(value: str) -> bool:
145    """Return true if the variable is uppercased."""
146    return str(value).isupper()
147
148
149def test_string(value: t.Any) -> bool:
150    """Return true if the object is a string."""
151    return isinstance(value, str)
152
153
154def test_mapping(value: t.Any) -> bool:
155    """Return true if the object is a mapping (dict etc.).
156
157    .. versionadded:: 2.6
158    """
159    return isinstance(value, abc.Mapping)
160
161
162def test_number(value: t.Any) -> bool:
163    """Return true if the variable is a number."""
164    return isinstance(value, Number)
165
166
167def test_sequence(value: t.Any) -> bool:
168    """Return true if the variable is a sequence. Sequences are variables
169    that are iterable.
170    """
171    try:
172        len(value)
173        value.__getitem__  # noqa B018
174    except Exception:
175        return False
176
177    return True
178
179
180def test_sameas(value: t.Any, other: t.Any) -> bool:
181    """Check if an object points to the same memory address than another
182    object:
183
184    .. sourcecode:: jinja
185
186        {% if foo.attribute is sameas false %}
187            the foo attribute really is the `False` singleton
188        {% endif %}
189    """
190    return value is other
191
192
193def test_iterable(value: t.Any) -> bool:
194    """Check if it's possible to iterate over an object."""
195    try:
196        iter(value)
197    except TypeError:
198        return False
199
200    return True
201
202
203def test_escaped(value: t.Any) -> bool:
204    """Check if the value is escaped."""
205    return hasattr(value, "__html__")
206
207
208def test_in(value: t.Any, seq: t.Container[t.Any]) -> bool:
209    """Check if value is in seq.
210
211    .. versionadded:: 2.10
212    """
213    return value in seq
214
215
216TESTS = {
217    "odd": test_odd,
218    "even": test_even,
219    "divisibleby": test_divisibleby,
220    "defined": test_defined,
221    "undefined": test_undefined,
222    "filter": test_filter,
223    "test": test_test,
224    "none": test_none,
225    "boolean": test_boolean,
226    "false": test_false,
227    "true": test_true,
228    "integer": test_integer,
229    "float": test_float,
230    "lower": test_lower,
231    "upper": test_upper,
232    "string": test_string,
233    "mapping": test_mapping,
234    "number": test_number,
235    "sequence": test_sequence,
236    "iterable": test_iterable,
237    "callable": callable,
238    "sameas": test_sameas,
239    "escaped": test_escaped,
240    "in": test_in,
241    "==": operator.eq,
242    "eq": operator.eq,
243    "equalto": operator.eq,
244    "!=": operator.ne,
245    "ne": operator.ne,
246    ">": operator.gt,
247    "gt": operator.gt,
248    "greaterthan": operator.gt,
249    "ge": operator.ge,
250    ">=": operator.ge,
251    "<": operator.lt,
252    "lt": operator.lt,
253    "lessthan": operator.lt,
254    "<=": operator.le,
255    "le": operator.le,
256}
def test_odd(value: int) -> bool:
16def test_odd(value: int) -> bool:
17    """Return true if the variable is odd."""
18    return value % 2 == 1

Return true if the variable is odd.

def test_even(value: int) -> bool:
21def test_even(value: int) -> bool:
22    """Return true if the variable is even."""
23    return value % 2 == 0

Return true if the variable is even.

def test_divisibleby(value: int, num: int) -> bool:
26def test_divisibleby(value: int, num: int) -> bool:
27    """Check if a variable is divisible by a number."""
28    return value % num == 0

Check if a variable is divisible by a number.

def test_defined(value: Any) -> bool:
31def test_defined(value: t.Any) -> bool:
32    """Return true if the variable is defined:
33
34    .. sourcecode:: jinja
35
36        {% if variable is defined %}
37            value of variable: {{ variable }}
38        {% else %}
39            variable is not defined
40        {% endif %}
41
42    See the :func:`default` filter for a simple way to set undefined
43    variables.
44    """
45    return not isinstance(value, Undefined)

Return true if the variable is defined:

.. sourcecode:: jinja

{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

See the default() filter for a simple way to set undefined variables.

def test_undefined(value: Any) -> bool:
48def test_undefined(value: t.Any) -> bool:
49    """Like :func:`defined` but the other way round."""
50    return isinstance(value, Undefined)

Like defined() but the other way round.

@pass_environment
def test_filter(env: jinja2.environment.Environment, value: str) -> bool:
53@pass_environment
54def test_filter(env: "Environment", value: str) -> bool:
55    """Check if a filter exists by name. Useful if a filter may be
56    optionally available.
57
58    .. code-block:: jinja
59
60        {% if 'markdown' is filter %}
61            {{ value | markdown }}
62        {% else %}
63            {{ value }}
64        {% endif %}
65
66    .. versionadded:: 3.0
67    """
68    return value in env.filters

Check if a filter exists by name. Useful if a filter may be optionally available.

{% if 'markdown' is filter %}
    {{ value | markdown }}
{% else %}
    {{ value }}
{% endif %}

New in version 3.0.

@pass_environment
def test_test(env: jinja2.environment.Environment, value: str) -> bool:
71@pass_environment
72def test_test(env: "Environment", value: str) -> bool:
73    """Check if a test exists by name. Useful if a test may be
74    optionally available.
75
76    .. code-block:: jinja
77
78        {% if 'loud' is test %}
79            {% if value is loud %}
80                {{ value|upper }}
81            {% else %}
82                {{ value|lower }}
83            {% endif %}
84        {% else %}
85            {{ value }}
86        {% endif %}
87
88    .. versionadded:: 3.0
89    """
90    return value in env.tests

Check if a test exists by name. Useful if a test may be optionally available.

{% if 'loud' is test %}
    {% if value is loud %}
        {{ value|upper }}
    {% else %}
        {{ value|lower }}
    {% endif %}
{% else %}
    {{ value }}
{% endif %}

New in version 3.0.

def test_none(value: Any) -> bool:
93def test_none(value: t.Any) -> bool:
94    """Return true if the variable is none."""
95    return value is None

Return true if the variable is none.

def test_boolean(value: Any) -> bool:
 98def test_boolean(value: t.Any) -> bool:
 99    """Return true if the object is a boolean value.
100
101    .. versionadded:: 2.11
102    """
103    return value is True or value is False

Return true if the object is a boolean value.

New in version 2.11.

def test_false(value: Any) -> bool:
106def test_false(value: t.Any) -> bool:
107    """Return true if the object is False.
108
109    .. versionadded:: 2.11
110    """
111    return value is False

Return true if the object is False.

New in version 2.11.

def test_true(value: Any) -> bool:
114def test_true(value: t.Any) -> bool:
115    """Return true if the object is True.
116
117    .. versionadded:: 2.11
118    """
119    return value is True

Return true if the object is True.

New in version 2.11.

def test_integer(value: Any) -> bool:
123def test_integer(value: t.Any) -> bool:
124    """Return true if the object is an integer.
125
126    .. versionadded:: 2.11
127    """
128    return isinstance(value, int) and value is not True and value is not False

Return true if the object is an integer.

New in version 2.11.

def test_float(value: Any) -> bool:
132def test_float(value: t.Any) -> bool:
133    """Return true if the object is a float.
134
135    .. versionadded:: 2.11
136    """
137    return isinstance(value, float)

Return true if the object is a float.

New in version 2.11.

def test_lower(value: str) -> bool:
140def test_lower(value: str) -> bool:
141    """Return true if the variable is lowercased."""
142    return str(value).islower()

Return true if the variable is lowercased.

def test_upper(value: str) -> bool:
145def test_upper(value: str) -> bool:
146    """Return true if the variable is uppercased."""
147    return str(value).isupper()

Return true if the variable is uppercased.

def test_string(value: Any) -> bool:
150def test_string(value: t.Any) -> bool:
151    """Return true if the object is a string."""
152    return isinstance(value, str)

Return true if the object is a string.

def test_mapping(value: Any) -> bool:
155def test_mapping(value: t.Any) -> bool:
156    """Return true if the object is a mapping (dict etc.).
157
158    .. versionadded:: 2.6
159    """
160    return isinstance(value, abc.Mapping)

Return true if the object is a mapping (dict etc.).

New in version 2.6.

def test_number(value: Any) -> bool:
163def test_number(value: t.Any) -> bool:
164    """Return true if the variable is a number."""
165    return isinstance(value, Number)

Return true if the variable is a number.

def test_sequence(value: Any) -> bool:
168def test_sequence(value: t.Any) -> bool:
169    """Return true if the variable is a sequence. Sequences are variables
170    that are iterable.
171    """
172    try:
173        len(value)
174        value.__getitem__  # noqa B018
175    except Exception:
176        return False
177
178    return True

Return true if the variable is a sequence. Sequences are variables that are iterable.

def test_sameas(value: Any, other: Any) -> bool:
181def test_sameas(value: t.Any, other: t.Any) -> bool:
182    """Check if an object points to the same memory address than another
183    object:
184
185    .. sourcecode:: jinja
186
187        {% if foo.attribute is sameas false %}
188            the foo attribute really is the `False` singleton
189        {% endif %}
190    """
191    return value is other

Check if an object points to the same memory address than another object:

.. sourcecode:: jinja

{% if foo.attribute is sameas false %}
    the foo attribute really is the `False` singleton
{% endif %}
def test_iterable(value: Any) -> bool:
194def test_iterable(value: t.Any) -> bool:
195    """Check if it's possible to iterate over an object."""
196    try:
197        iter(value)
198    except TypeError:
199        return False
200
201    return True

Check if it's possible to iterate over an object.

def test_escaped(value: Any) -> bool:
204def test_escaped(value: t.Any) -> bool:
205    """Check if the value is escaped."""
206    return hasattr(value, "__html__")

Check if the value is escaped.

def test_in(value: Any, seq: Container[Any]) -> bool:
209def test_in(value: t.Any, seq: t.Container[t.Any]) -> bool:
210    """Check if value is in seq.
211
212    .. versionadded:: 2.10
213    """
214    return value in seq

Check if value is in seq.

New in version 2.10.

TESTS = {'odd': <function test_odd>, 'even': <function test_even>, 'divisibleby': <function test_divisibleby>, 'defined': <function test_defined>, 'undefined': <function test_undefined>, 'filter': <function test_filter>, 'test': <function test_test>, 'none': <function test_none>, 'boolean': <function test_boolean>, 'false': <function test_false>, 'true': <function test_true>, 'integer': <function test_integer>, 'float': <function test_float>, 'lower': <function test_lower>, 'upper': <function test_upper>, 'string': <function test_string>, 'mapping': <function test_mapping>, 'number': <function test_number>, 'sequence': <function test_sequence>, 'iterable': <function test_iterable>, 'callable': <built-in function callable>, 'sameas': <function test_sameas>, 'escaped': <function test_escaped>, 'in': <function test_in>, '==': <built-in function eq>, 'eq': <built-in function eq>, 'equalto': <built-in function eq>, '!=': <built-in function ne>, 'ne': <built-in function ne>, '>': <built-in function gt>, 'gt': <built-in function gt>, 'greaterthan': <built-in function gt>, 'ge': <built-in function ge>, '>=': <built-in function ge>, '<': <built-in function lt>, 'lt': <built-in function lt>, 'lessthan': <built-in function lt>, '<=': <built-in function le>, 'le': <built-in function le>}