1# -*- coding: utf-8 -*- 2"""Built-in template tests used with the ``is`` operator.""" 3import decimal 4import operator 5import re 6 7from ._compat import abc 8from ._compat import integer_types 9from ._compat import string_types 10from ._compat import text_type 11from .runtime import Undefined 12 13number_re = re.compile(r"^-?\d+(\.\d+)?$") 14regex_type = type(number_re) 15test_callable = callable 16 17 18def test_odd(value): 19 """Return true if the variable is odd.""" 20 return value % 2 == 1 21 22 23def test_even(value): 24 """Return true if the variable is even.""" 25 return value % 2 == 0 26 27 28def test_divisibleby(value, num): 29 """Check if a variable is divisible by a number.""" 30 return value % num == 0 31 32 33def test_defined(value): 34 """Return true if the variable is defined: 35 36 .. sourcecode:: jinja 37 38 {% if variable is defined %} 39 value of variable: {{ variable }} 40 {% else %} 41 variable is not defined 42 {% endif %} 43 44 See the :func:`default` filter for a simple way to set undefined 45 variables. 46 """ 47 return not isinstance(value, Undefined) 48 49 50def test_undefined(value): 51 """Like :func:`defined` but the other way round.""" 52 return isinstance(value, Undefined) 53 54 55def test_none(value): 56 """Return true if the variable is none.""" 57 return value is None 58 59 60def test_boolean(value): 61 """Return true if the object is a boolean value. 62 63 .. versionadded:: 2.11 64 """ 65 return value is True or value is False 66 67 68def test_false(value): 69 """Return true if the object is False. 70 71 .. versionadded:: 2.11 72 """ 73 return value is False 74 75 76def test_true(value): 77 """Return true if the object is True. 78 79 .. versionadded:: 2.11 80 """ 81 return value is True 82 83 84# NOTE: The existing 'number' test matches booleans and floats 85def test_integer(value): 86 """Return true if the object is an integer. 87 88 .. versionadded:: 2.11 89 """ 90 return isinstance(value, integer_types) and value is not True and value is not False 91 92 93# NOTE: The existing 'number' test matches booleans and integers 94def test_float(value): 95 """Return true if the object is a float. 96 97 .. versionadded:: 2.11 98 """ 99 return isinstance(value, float) 100 101 102def test_lower(value): 103 """Return true if the variable is lowercased.""" 104 return text_type(value).islower() 105 106 107def test_upper(value): 108 """Return true if the variable is uppercased.""" 109 return text_type(value).isupper() 110 111 112def test_string(value): 113 """Return true if the object is a string.""" 114 return isinstance(value, string_types) 115 116 117def test_mapping(value): 118 """Return true if the object is a mapping (dict etc.). 119 120 .. versionadded:: 2.6 121 """ 122 return isinstance(value, abc.Mapping) 123 124 125def test_number(value): 126 """Return true if the variable is a number.""" 127 return isinstance(value, integer_types + (float, complex, decimal.Decimal)) 128 129 130def test_sequence(value): 131 """Return true if the variable is a sequence. Sequences are variables 132 that are iterable. 133 """ 134 try: 135 len(value) 136 value.__getitem__ 137 except Exception: 138 return False 139 return True 140 141 142def test_sameas(value, other): 143 """Check if an object points to the same memory address than another 144 object: 145 146 .. sourcecode:: jinja 147 148 {% if foo.attribute is sameas false %} 149 the foo attribute really is the `False` singleton 150 {% endif %} 151 """ 152 return value is other 153 154 155def test_iterable(value): 156 """Check if it's possible to iterate over an object.""" 157 try: 158 iter(value) 159 except TypeError: 160 return False 161 return True 162 163 164def test_escaped(value): 165 """Check if the value is escaped.""" 166 return hasattr(value, "__html__") 167 168 169def test_in(value, seq): 170 """Check if value is in seq. 171 172 .. versionadded:: 2.10 173 """ 174 return value in seq 175 176 177TESTS = { 178 "odd": test_odd, 179 "even": test_even, 180 "divisibleby": test_divisibleby, 181 "defined": test_defined, 182 "undefined": test_undefined, 183 "none": test_none, 184 "boolean": test_boolean, 185 "false": test_false, 186 "true": test_true, 187 "integer": test_integer, 188 "float": test_float, 189 "lower": test_lower, 190 "upper": test_upper, 191 "string": test_string, 192 "mapping": test_mapping, 193 "number": test_number, 194 "sequence": test_sequence, 195 "iterable": test_iterable, 196 "callable": test_callable, 197 "sameas": test_sameas, 198 "escaped": test_escaped, 199 "in": test_in, 200 "==": operator.eq, 201 "eq": operator.eq, 202 "equalto": operator.eq, 203 "!=": operator.ne, 204 "ne": operator.ne, 205 ">": operator.gt, 206 "gt": operator.gt, 207 "greaterthan": operator.gt, 208 "ge": operator.ge, 209 ">=": operator.ge, 210 "<": operator.lt, 211 "lt": operator.lt, 212 "lessthan": operator.lt, 213 "<=": operator.le, 214 "le": operator.le, 215} 216