| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 | """Built-in template tests used with the ``is`` operator."""import operatorimport typing as tfrom collections import abcfrom numbers import Numberfrom .runtime import Undefinedfrom .utils import pass_environmentif t.TYPE_CHECKING:    from .environment import Environmentdef test_odd(value: int) -> bool:    """Return true if the variable is odd."""    return value % 2 == 1def test_even(value: int) -> bool:    """Return true if the variable is even."""    return value % 2 == 0def test_divisibleby(value: int, num: int) -> bool:    """Check if a variable is divisible by a number."""    return value % num == 0def test_defined(value: t.Any) -> bool:    """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 :func:`default` filter for a simple way to set undefined    variables.    """    return not isinstance(value, Undefined)def test_undefined(value: t.Any) -> bool:    """Like :func:`defined` but the other way round."""    return isinstance(value, Undefined)@pass_environmentdef test_filter(env: "Environment", value: str) -> bool:    """Check if a filter exists by name. Useful if a filter may be    optionally available.    .. code-block:: jinja        {% if 'markdown' is filter %}            {{ value | markdown }}        {% else %}            {{ value }}        {% endif %}    .. versionadded:: 3.0    """    return value in env.filters@pass_environmentdef test_test(env: "Environment", value: str) -> bool:    """Check if a test exists by name. Useful if a test may be    optionally available.    .. code-block:: jinja        {% if 'loud' is test %}            {% if value is loud %}                {{ value|upper }}            {% else %}                {{ value|lower }}            {% endif %}        {% else %}            {{ value }}        {% endif %}    .. versionadded:: 3.0    """    return value in env.testsdef test_none(value: t.Any) -> bool:    """Return true if the variable is none."""    return value is Nonedef test_boolean(value: t.Any) -> bool:    """Return true if the object is a boolean value.    .. versionadded:: 2.11    """    return value is True or value is Falsedef test_false(value: t.Any) -> bool:    """Return true if the object is False.    .. versionadded:: 2.11    """    return value is Falsedef test_true(value: t.Any) -> bool:    """Return true if the object is True.    .. versionadded:: 2.11    """    return value is True# NOTE: The existing 'number' test matches booleans and floatsdef test_integer(value: t.Any) -> bool:    """Return true if the object is an integer.    .. versionadded:: 2.11    """    return isinstance(value, int) and value is not True and value is not False# NOTE: The existing 'number' test matches booleans and integersdef test_float(value: t.Any) -> bool:    """Return true if the object is a float.    .. versionadded:: 2.11    """    return isinstance(value, float)def test_lower(value: str) -> bool:    """Return true if the variable is lowercased."""    return str(value).islower()def test_upper(value: str) -> bool:    """Return true if the variable is uppercased."""    return str(value).isupper()def test_string(value: t.Any) -> bool:    """Return true if the object is a string."""    return isinstance(value, str)def test_mapping(value: t.Any) -> bool:    """Return true if the object is a mapping (dict etc.).    .. versionadded:: 2.6    """    return isinstance(value, abc.Mapping)def test_number(value: t.Any) -> bool:    """Return true if the variable is a number."""    return isinstance(value, Number)def test_sequence(value: t.Any) -> bool:    """Return true if the variable is a sequence. Sequences are variables    that are iterable.    """    try:        len(value)        value.__getitem__    except Exception:        return False    return Truedef test_sameas(value: t.Any, other: t.Any) -> bool:    """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 %}    """    return value is otherdef test_iterable(value: t.Any) -> bool:    """Check if it's possible to iterate over an object."""    try:        iter(value)    except TypeError:        return False    return Truedef test_escaped(value: t.Any) -> bool:    """Check if the value is escaped."""    return hasattr(value, "__html__")def test_in(value: t.Any, seq: t.Container) -> bool:    """Check if value is in seq.    .. versionadded:: 2.10    """    return value in seqTESTS = {    "odd": test_odd,    "even": test_even,    "divisibleby": test_divisibleby,    "defined": test_defined,    "undefined": test_undefined,    "filter": test_filter,    "test": test_test,    "none": test_none,    "boolean": test_boolean,    "false": test_false,    "true": test_true,    "integer": test_integer,    "float": test_float,    "lower": test_lower,    "upper": test_upper,    "string": test_string,    "mapping": test_mapping,    "number": test_number,    "sequence": test_sequence,    "iterable": test_iterable,    "callable": callable,    "sameas": test_sameas,    "escaped": test_escaped,    "in": test_in,    "==": operator.eq,    "eq": operator.eq,    "equalto": operator.eq,    "!=": operator.ne,    "ne": operator.ne,    ">": operator.gt,    "gt": operator.gt,    "greaterthan": operator.gt,    "ge": operator.ge,    ">=": operator.ge,    "<": operator.lt,    "lt": operator.lt,    "lessthan": operator.lt,    "<=": operator.le,    "le": operator.le,}
 |