1import contextlib 2import os 3import re 4import unittest 5 6from mako import compat 7from mako.cache import CacheImpl 8from mako.cache import register_plugin 9from mako.compat import py33 10from mako.compat import py3k 11from mako.template import Template 12from mako.util import update_wrapper 13 14try: 15 # unitttest has a SkipTest also but pytest doesn't 16 # honor it unless nose is imported too... 17 from nose import SkipTest 18except ImportError: 19 from _pytest.runner import Skipped as SkipTest 20 21template_base = os.path.join(os.path.dirname(__file__), "templates") 22module_base = os.path.join(template_base, "modules") 23 24 25class TemplateTest(unittest.TestCase): 26 def _file_template(self, filename, **kw): 27 filepath = self._file_path(filename) 28 return Template( 29 uri=filename, filename=filepath, module_directory=module_base, **kw 30 ) 31 32 def _file_path(self, filename): 33 name, ext = os.path.splitext(filename) 34 35 if py3k: 36 py3k_path = os.path.join(template_base, name + "_py3k" + ext) 37 if os.path.exists(py3k_path): 38 return py3k_path 39 40 return os.path.join(template_base, filename) 41 42 def _do_file_test( 43 self, 44 filename, 45 expected, 46 filters=None, 47 unicode_=True, 48 template_args=None, 49 **kw 50 ): 51 t1 = self._file_template(filename, **kw) 52 self._do_test( 53 t1, 54 expected, 55 filters=filters, 56 unicode_=unicode_, 57 template_args=template_args, 58 ) 59 60 def _do_memory_test( 61 self, 62 source, 63 expected, 64 filters=None, 65 unicode_=True, 66 template_args=None, 67 **kw 68 ): 69 t1 = Template(text=source, **kw) 70 self._do_test( 71 t1, 72 expected, 73 filters=filters, 74 unicode_=unicode_, 75 template_args=template_args, 76 ) 77 78 def _do_test( 79 self, 80 template, 81 expected, 82 filters=None, 83 template_args=None, 84 unicode_=True, 85 ): 86 if template_args is None: 87 template_args = {} 88 if unicode_: 89 output = template.render_unicode(**template_args) 90 else: 91 output = template.render(**template_args) 92 93 if filters: 94 output = filters(output) 95 eq_(output, expected) 96 97 98def eq_(a, b, msg=None): 99 """Assert a == b, with repr messaging on failure.""" 100 assert a == b, msg or "%r != %r" % (a, b) 101 102 103def teardown(): 104 import shutil 105 106 shutil.rmtree(module_base, True) 107 108 109if py33: 110 from unittest import mock # noqa 111else: 112 import mock # noqa 113 114 115@contextlib.contextmanager 116def raises(except_cls, message=None): 117 try: 118 yield 119 success = False 120 except except_cls as e: 121 if message: 122 assert re.search( 123 message, compat.text_type(e), re.UNICODE 124 ), "%r !~ %s" % (message, e) 125 print(compat.text_type(e).encode("utf-8")) 126 success = True 127 128 # assert outside the block so it works for AssertionError too ! 129 assert success, "Callable did not raise an exception" 130 131 132def assert_raises(except_cls, callable_, *args, **kw): 133 with raises(except_cls): 134 return callable_(*args, **kw) 135 136 137def assert_raises_message(except_cls, msg, callable_, *args, **kwargs): 138 with raises(except_cls, msg): 139 return callable_(*args, **kwargs) 140 141 142def skip_if(predicate, reason=None): 143 """Skip a test if predicate is true.""" 144 reason = reason or predicate.__name__ 145 146 def decorate(fn): 147 fn_name = fn.__name__ 148 149 def maybe(*args, **kw): 150 if predicate(): 151 msg = "'%s' skipped: %s" % (fn_name, reason) 152 raise SkipTest(msg) 153 else: 154 return fn(*args, **kw) 155 156 return update_wrapper(maybe, fn) 157 158 return decorate 159 160 161def requires_python_3(fn): 162 return skip_if(lambda: not py3k, "Requires Python 3.xx")(fn) 163 164 165def requires_python_2(fn): 166 return skip_if(lambda: py3k, "Requires Python 2.xx")(fn) 167 168 169def requires_pygments_14(fn): 170 try: 171 import pygments 172 173 version = pygments.__version__ 174 except: 175 version = "0" 176 return skip_if( 177 lambda: version < "1.4", "Requires pygments 1.4 or greater" 178 )(fn) 179 180 181def requires_no_pygments_exceptions(fn): 182 def go(*arg, **kw): 183 from mako import exceptions 184 185 exceptions._install_fallback() 186 try: 187 return fn(*arg, **kw) 188 finally: 189 exceptions._install_highlighting() 190 191 return update_wrapper(go, fn) 192 193 194class PlainCacheImpl(CacheImpl): 195 """Simple memory cache impl so that tests which 196 use caching can run without beaker. """ 197 198 def __init__(self, cache): 199 self.cache = cache 200 self.data = {} 201 202 def get_or_create(self, key, creation_function, **kw): 203 if key in self.data: 204 return self.data[key] 205 else: 206 self.data[key] = data = creation_function(**kw) 207 return data 208 209 def put(self, key, value, **kw): 210 self.data[key] = value 211 212 def get(self, key, **kw): 213 return self.data[key] 214 215 def invalidate(self, key, **kw): 216 del self.data[key] 217 218 219register_plugin("plain", __name__, "PlainCacheImpl") 220