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