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