1. import functools
    
  2. import os
    
  3. 
    
  4. from django.template.engine import Engine
    
  5. from django.test.utils import override_settings
    
  6. from django.utils.safestring import mark_safe
    
  7. 
    
  8. ROOT = os.path.dirname(os.path.abspath(__file__))
    
  9. TEMPLATE_DIR = os.path.join(ROOT, "templates")
    
  10. 
    
  11. 
    
  12. def setup(templates, *args, test_once=False):
    
  13.     """
    
  14.     Runs test method multiple times in the following order:
    
  15. 
    
  16.     debug       cached      string_if_invalid
    
  17.     -----       ------      -----------------
    
  18.     False       False
    
  19.     False       True
    
  20.     False       False       INVALID
    
  21.     False       True        INVALID
    
  22.     True        False
    
  23.     True        True
    
  24. 
    
  25.     Use test_once=True to test deprecation warnings since the message won't be
    
  26.     displayed multiple times.
    
  27.     """
    
  28. 
    
  29.     for arg in args:
    
  30.         templates.update(arg)
    
  31. 
    
  32.     # numerous tests make use of an inclusion tag
    
  33.     # add this in here for simplicity
    
  34.     templates["inclusion.html"] = "{{ result }}"
    
  35. 
    
  36.     loaders = [
    
  37.         (
    
  38.             "django.template.loaders.cached.Loader",
    
  39.             [
    
  40.                 ("django.template.loaders.locmem.Loader", templates),
    
  41.             ],
    
  42.         ),
    
  43.     ]
    
  44. 
    
  45.     def decorator(func):
    
  46.         # Make Engine.get_default() raise an exception to ensure that tests
    
  47.         # are properly isolated from Django's global settings.
    
  48.         @override_settings(TEMPLATES=None)
    
  49.         @functools.wraps(func)
    
  50.         def inner(self):
    
  51.             # Set up custom template tag libraries if specified
    
  52.             libraries = getattr(self, "libraries", {})
    
  53. 
    
  54.             self.engine = Engine(
    
  55.                 libraries=libraries,
    
  56.                 loaders=loaders,
    
  57.             )
    
  58.             func(self)
    
  59.             if test_once:
    
  60.                 return
    
  61.             func(self)
    
  62. 
    
  63.             self.engine = Engine(
    
  64.                 libraries=libraries,
    
  65.                 loaders=loaders,
    
  66.                 string_if_invalid="INVALID",
    
  67.             )
    
  68.             func(self)
    
  69.             func(self)
    
  70. 
    
  71.             self.engine = Engine(
    
  72.                 debug=True,
    
  73.                 libraries=libraries,
    
  74.                 loaders=loaders,
    
  75.             )
    
  76.             func(self)
    
  77.             func(self)
    
  78. 
    
  79.         return inner
    
  80. 
    
  81.     return decorator
    
  82. 
    
  83. 
    
  84. # Helper objects
    
  85. 
    
  86. 
    
  87. class SomeException(Exception):
    
  88.     silent_variable_failure = True
    
  89. 
    
  90. 
    
  91. class SomeOtherException(Exception):
    
  92.     pass
    
  93. 
    
  94. 
    
  95. class ShouldNotExecuteException(Exception):
    
  96.     pass
    
  97. 
    
  98. 
    
  99. class SomeClass:
    
  100.     def __init__(self):
    
  101.         self.otherclass = OtherClass()
    
  102. 
    
  103.     def method(self):
    
  104.         return "SomeClass.method"
    
  105. 
    
  106.     def method2(self, o):
    
  107.         return o
    
  108. 
    
  109.     def method3(self):
    
  110.         raise SomeException
    
  111. 
    
  112.     def method4(self):
    
  113.         raise SomeOtherException
    
  114. 
    
  115.     def method5(self):
    
  116.         raise TypeError
    
  117. 
    
  118.     def __getitem__(self, key):
    
  119.         if key == "silent_fail_key":
    
  120.             raise SomeException
    
  121.         elif key == "noisy_fail_key":
    
  122.             raise SomeOtherException
    
  123.         raise KeyError
    
  124. 
    
  125.     @property
    
  126.     def silent_fail_attribute(self):
    
  127.         raise SomeException
    
  128. 
    
  129.     @property
    
  130.     def noisy_fail_attribute(self):
    
  131.         raise SomeOtherException
    
  132. 
    
  133.     @property
    
  134.     def attribute_error_attribute(self):
    
  135.         raise AttributeError
    
  136. 
    
  137.     @property
    
  138.     def type_error_attribute(self):
    
  139.         raise TypeError
    
  140. 
    
  141. 
    
  142. class OtherClass:
    
  143.     def method(self):
    
  144.         return "OtherClass.method"
    
  145. 
    
  146. 
    
  147. class TestObj:
    
  148.     def is_true(self):
    
  149.         return True
    
  150. 
    
  151.     def is_false(self):
    
  152.         return False
    
  153. 
    
  154.     def is_bad(self):
    
  155.         raise ShouldNotExecuteException()
    
  156. 
    
  157. 
    
  158. class SilentGetItemClass:
    
  159.     def __getitem__(self, key):
    
  160.         raise SomeException
    
  161. 
    
  162. 
    
  163. class SilentAttrClass:
    
  164.     def b(self):
    
  165.         raise SomeException
    
  166. 
    
  167.     b = property(b)
    
  168. 
    
  169. 
    
  170. class UTF8Class:
    
  171.     "Class whose __str__ returns non-ASCII data"
    
  172. 
    
  173.     def __str__(self):
    
  174.         return "ŠĐĆŽćžšđ"
    
  175. 
    
  176. 
    
  177. # These two classes are used to test auto-escaping of string output.
    
  178. class UnsafeClass:
    
  179.     def __str__(self):
    
  180.         return "you & me"
    
  181. 
    
  182. 
    
  183. class SafeClass:
    
  184.     def __str__(self):
    
  185.         return mark_safe("you > me")