Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/jinja2/tests.py: 70%
66 statements
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:15 +0000
« prev ^ index » next coverage.py v7.3.1, created at 2023-09-25 06:15 +0000
1"""Built-in template tests used with the ``is`` operator."""
2import operator
3import typing as t
4from collections import abc
5from numbers import Number
7from .runtime import Undefined
8from .utils import pass_environment
10if t.TYPE_CHECKING:
11 from .environment import Environment
14def test_odd(value: int) -> bool:
15 """Return true if the variable is odd."""
16 return value % 2 == 1
19def test_even(value: int) -> bool:
20 """Return true if the variable is even."""
21 return value % 2 == 0
24def test_divisibleby(value: int, num: int) -> bool:
25 """Check if a variable is divisible by a number."""
26 return value % num == 0
29def test_defined(value: t.Any) -> bool:
30 """Return true if the variable is defined:
32 .. sourcecode:: jinja
34 {% if variable is defined %}
35 value of variable: {{ variable }}
36 {% else %}
37 variable is not defined
38 {% endif %}
40 See the :func:`default` filter for a simple way to set undefined
41 variables.
42 """
43 return not isinstance(value, Undefined)
46def test_undefined(value: t.Any) -> bool:
47 """Like :func:`defined` but the other way round."""
48 return isinstance(value, Undefined)
51@pass_environment
52def test_filter(env: "Environment", value: str) -> bool:
53 """Check if a filter exists by name. Useful if a filter may be
54 optionally available.
56 .. code-block:: jinja
58 {% if 'markdown' is filter %}
59 {{ value | markdown }}
60 {% else %}
61 {{ value }}
62 {% endif %}
64 .. versionadded:: 3.0
65 """
66 return value in env.filters
69@pass_environment
70def test_test(env: "Environment", value: str) -> bool:
71 """Check if a test exists by name. Useful if a test may be
72 optionally available.
74 .. code-block:: jinja
76 {% if 'loud' is test %}
77 {% if value is loud %}
78 {{ value|upper }}
79 {% else %}
80 {{ value|lower }}
81 {% endif %}
82 {% else %}
83 {{ value }}
84 {% endif %}
86 .. versionadded:: 3.0
87 """
88 return value in env.tests
91def test_none(value: t.Any) -> bool:
92 """Return true if the variable is none."""
93 return value is None
96def test_boolean(value: t.Any) -> bool:
97 """Return true if the object is a boolean value.
99 .. versionadded:: 2.11
100 """
101 return value is True or value is False
104def test_false(value: t.Any) -> bool:
105 """Return true if the object is False.
107 .. versionadded:: 2.11
108 """
109 return value is False
112def test_true(value: t.Any) -> bool:
113 """Return true if the object is True.
115 .. versionadded:: 2.11
116 """
117 return value is True
120# NOTE: The existing 'number' test matches booleans and floats
121def test_integer(value: t.Any) -> bool:
122 """Return true if the object is an integer.
124 .. versionadded:: 2.11
125 """
126 return isinstance(value, int) and value is not True and value is not False
129# NOTE: The existing 'number' test matches booleans and integers
130def test_float(value: t.Any) -> bool:
131 """Return true if the object is a float.
133 .. versionadded:: 2.11
134 """
135 return isinstance(value, float)
138def test_lower(value: str) -> bool:
139 """Return true if the variable is lowercased."""
140 return str(value).islower()
143def test_upper(value: str) -> bool:
144 """Return true if the variable is uppercased."""
145 return str(value).isupper()
148def test_string(value: t.Any) -> bool:
149 """Return true if the object is a string."""
150 return isinstance(value, str)
153def test_mapping(value: t.Any) -> bool:
154 """Return true if the object is a mapping (dict etc.).
156 .. versionadded:: 2.6
157 """
158 return isinstance(value, abc.Mapping)
161def test_number(value: t.Any) -> bool:
162 """Return true if the variable is a number."""
163 return isinstance(value, Number)
166def test_sequence(value: t.Any) -> bool:
167 """Return true if the variable is a sequence. Sequences are variables
168 that are iterable.
169 """
170 try:
171 len(value)
172 value.__getitem__
173 except Exception:
174 return False
176 return True
179def test_sameas(value: t.Any, other: t.Any) -> bool:
180 """Check if an object points to the same memory address than another
181 object:
183 .. sourcecode:: jinja
185 {% if foo.attribute is sameas false %}
186 the foo attribute really is the `False` singleton
187 {% endif %}
188 """
189 return value is other
192def test_iterable(value: t.Any) -> bool:
193 """Check if it's possible to iterate over an object."""
194 try:
195 iter(value)
196 except TypeError:
197 return False
199 return True
202def test_escaped(value: t.Any) -> bool:
203 """Check if the value is escaped."""
204 return hasattr(value, "__html__")
207def test_in(value: t.Any, seq: t.Container[t.Any]) -> bool:
208 """Check if value is in seq.
210 .. versionadded:: 2.10
211 """
212 return value in seq
215TESTS = {
216 "odd": test_odd,
217 "even": test_even,
218 "divisibleby": test_divisibleby,
219 "defined": test_defined,
220 "undefined": test_undefined,
221 "filter": test_filter,
222 "test": test_test,
223 "none": test_none,
224 "boolean": test_boolean,
225 "false": test_false,
226 "true": test_true,
227 "integer": test_integer,
228 "float": test_float,
229 "lower": test_lower,
230 "upper": test_upper,
231 "string": test_string,
232 "mapping": test_mapping,
233 "number": test_number,
234 "sequence": test_sequence,
235 "iterable": test_iterable,
236 "callable": callable,
237 "sameas": test_sameas,
238 "escaped": test_escaped,
239 "in": test_in,
240 "==": operator.eq,
241 "eq": operator.eq,
242 "equalto": operator.eq,
243 "!=": operator.ne,
244 "ne": operator.ne,
245 ">": operator.gt,
246 "gt": operator.gt,
247 "greaterthan": operator.gt,
248 "ge": operator.ge,
249 ">=": operator.ge,
250 "<": operator.lt,
251 "lt": operator.lt,
252 "lessthan": operator.lt,
253 "<=": operator.le,
254 "le": operator.le,
255}