1# -*- coding: utf-8 -*-
2"""
3    jinja2.tests
4    ~~~~~~~~~~~~
5
6    Jinja test functions. Used with the "is" operator.
7
8    :copyright: (c) 2010 by the Jinja Team.
9    :license: BSD, see LICENSE for more details.
10"""
11import re
12from jinja2.runtime import Undefined
13from jinja2._compat import text_type, string_types, mapping_types
14
15
16number_re = re.compile(r'^-?\d+(\.\d+)?$')
17regex_type = type(number_re)
18
19
20test_callable = callable
21
22
23def test_odd(value):
24    """Return true if the variable is odd."""
25    return value % 2 == 1
26
27
28def test_even(value):
29    """Return true if the variable is even."""
30    return value % 2 == 0
31
32
33def test_divisibleby(value, num):
34    """Check if a variable is divisible by a number."""
35    return value % num == 0
36
37
38def test_defined(value):
39    """Return true if the variable is defined:
40
41    .. sourcecode:: jinja
42
43        {% if variable is defined %}
44            value of variable: {{ variable }}
45        {% else %}
46            variable is not defined
47        {% endif %}
48
49    See the :func:`default` filter for a simple way to set undefined
50    variables.
51    """
52    return not isinstance(value, Undefined)
53
54
55def test_undefined(value):
56    """Like :func:`defined` but the other way round."""
57    return isinstance(value, Undefined)
58
59
60def test_none(value):
61    """Return true if the variable is none."""
62    return value is None
63
64
65def test_lower(value):
66    """Return true if the variable is lowercased."""
67    return text_type(value).islower()
68
69
70def test_upper(value):
71    """Return true if the variable is uppercased."""
72    return text_type(value).isupper()
73
74
75def test_string(value):
76    """Return true if the object is a string."""
77    return isinstance(value, string_types)
78
79
80def test_mapping(value):
81    """Return true if the object is a mapping (dict etc.).
82
83    .. versionadded:: 2.6
84    """
85    return isinstance(value, mapping_types)
86
87
88def test_number(value):
89    """Return true if the variable is a number."""
90    return isinstance(value, (int, float, complex))
91
92
93def test_sequence(value):
94    """Return true if the variable is a sequence. Sequences are variables
95    that are iterable.
96    """
97    try:
98        len(value)
99        value.__getitem__
100    except:
101        return False
102    return True
103
104
105def test_sameas(value, other):
106    """Check if an object points to the same memory address than another
107    object:
108
109    .. sourcecode:: jinja
110
111        {% if foo.attribute is sameas false %}
112            the foo attribute really is the `False` singleton
113        {% endif %}
114    """
115    return value is other
116
117
118def test_iterable(value):
119    """Check if it's possible to iterate over an object."""
120    try:
121        iter(value)
122    except TypeError:
123        return False
124    return True
125
126
127def test_escaped(value):
128    """Check if the value is escaped."""
129    return hasattr(value, '__html__')
130
131
132TESTS = {
133    'odd':              test_odd,
134    'even':             test_even,
135    'divisibleby':      test_divisibleby,
136    'defined':          test_defined,
137    'undefined':        test_undefined,
138    'none':             test_none,
139    'lower':            test_lower,
140    'upper':            test_upper,
141    'string':           test_string,
142    'mapping':          test_mapping,
143    'number':           test_number,
144    'sequence':         test_sequence,
145    'iterable':         test_iterable,
146    'callable':         test_callable,
147    'sameas':           test_sameas,
148    'escaped':          test_escaped
149}
150