utils.py 4.3 KB

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