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