mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	Refs #15053 -- Removed support for non-recursive template loading.
Per deprecation timeline.
This commit is contained in:
		| @@ -130,21 +130,11 @@ class Engine(object): | ||||
|     def find_template(self, name, dirs=None, skip=None): | ||||
|         tried = [] | ||||
|         for loader in self.template_loaders: | ||||
|             if loader.supports_recursion: | ||||
|                 try: | ||||
|                     template = loader.get_template( | ||||
|                         name, template_dirs=dirs, skip=skip, | ||||
|                     ) | ||||
|                     return template, template.origin | ||||
|                 except TemplateDoesNotExist as e: | ||||
|                     tried.extend(e.tried) | ||||
|             else: | ||||
|                 # RemovedInDjango20Warning: Use old api for non-recursive | ||||
|                 # loaders. | ||||
|                 try: | ||||
|                     return loader(name, dirs) | ||||
|                 except TemplateDoesNotExist: | ||||
|                     pass | ||||
|             try: | ||||
|                 template = loader.get_template(name, skip=skip) | ||||
|                 return template, template.origin | ||||
|             except TemplateDoesNotExist as e: | ||||
|                 tried.extend(e.tried) | ||||
|         raise TemplateDoesNotExist(name, tried=tried) | ||||
|  | ||||
|     def from_string(self, template_code): | ||||
|   | ||||
| @@ -19,10 +19,6 @@ BLOCK_CONTEXT_KEY = 'block_context' | ||||
| logger = logging.getLogger('django.template') | ||||
|  | ||||
|  | ||||
| class ExtendsError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class BlockContext(object): | ||||
|     def __init__(self): | ||||
|         # Dictionary of FIFO queues. | ||||
| @@ -107,23 +103,6 @@ class ExtendsNode(Node): | ||||
|         passed as the skip argument. This enables extends to work recursively | ||||
|         without extending the same template twice. | ||||
|         """ | ||||
|         # RemovedInDjango20Warning: If any non-recursive loaders are installed | ||||
|         # do a direct template lookup. If the same template name appears twice, | ||||
|         # raise an exception to avoid system recursion. | ||||
|         for loader in context.template.engine.template_loaders: | ||||
|             if not loader.supports_recursion: | ||||
|                 history = context.render_context.setdefault( | ||||
|                     self.context_key, [context.template.origin.template_name], | ||||
|                 ) | ||||
|                 if template_name in history: | ||||
|                     raise ExtendsError( | ||||
|                         "Cannot extend templates recursively when using " | ||||
|                         "non-recursive template loaders", | ||||
|                     ) | ||||
|                 template = context.template.engine.get_template(template_name) | ||||
|                 history.append(template_name) | ||||
|                 return template | ||||
|  | ||||
|         history = context.render_context.setdefault( | ||||
|             self.context_key, [context.template.origin], | ||||
|         ) | ||||
|   | ||||
| @@ -1,8 +1,4 @@ | ||||
| import warnings | ||||
|  | ||||
| from django.template import Origin, Template, TemplateDoesNotExist | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
| from django.utils.inspect import func_supports_parameter | ||||
| from django.template import Template, TemplateDoesNotExist | ||||
|  | ||||
|  | ||||
| class Loader(object): | ||||
| @@ -10,11 +6,7 @@ class Loader(object): | ||||
|     def __init__(self, engine): | ||||
|         self.engine = engine | ||||
|  | ||||
|     def __call__(self, template_name, template_dirs=None): | ||||
|         # RemovedInDjango20Warning: Allow loaders to be called like functions. | ||||
|         return self.load_template(template_name, template_dirs) | ||||
|  | ||||
|     def get_template(self, template_name, template_dirs=None, skip=None): | ||||
|     def get_template(self, template_name, skip=None): | ||||
|         """ | ||||
|         Calls self.get_template_sources() and returns a Template object for | ||||
|         the first template matching template_name. If skip is provided, | ||||
| @@ -23,13 +15,7 @@ class Loader(object): | ||||
|         """ | ||||
|         tried = [] | ||||
|  | ||||
|         args = [template_name] | ||||
|         # RemovedInDjango20Warning: Add template_dirs for compatibility with | ||||
|         # old loaders | ||||
|         if func_supports_parameter(self.get_template_sources, 'template_dirs'): | ||||
|             args.append(template_dirs) | ||||
|  | ||||
|         for origin in self.get_template_sources(*args): | ||||
|         for origin in self.get_template_sources(template_name): | ||||
|             if skip is not None and origin in skip: | ||||
|                 tried.append((origin, 'Skipped')) | ||||
|                 continue | ||||
| @@ -46,30 +32,6 @@ class Loader(object): | ||||
|  | ||||
|         raise TemplateDoesNotExist(template_name, tried=tried) | ||||
|  | ||||
|     def load_template(self, template_name, template_dirs=None): | ||||
|         warnings.warn( | ||||
|             'The load_template() method is deprecated. Use get_template() ' | ||||
|             'instead.', RemovedInDjango20Warning, | ||||
|         ) | ||||
|         source, display_name = self.load_template_source( | ||||
|             template_name, template_dirs, | ||||
|         ) | ||||
|         origin = Origin( | ||||
|             name=display_name, | ||||
|             template_name=template_name, | ||||
|             loader=self, | ||||
|         ) | ||||
|         try: | ||||
|             template = Template(source, origin, template_name, self.engine) | ||||
|         except TemplateDoesNotExist: | ||||
|             # If compiling the template we found raises TemplateDoesNotExist, | ||||
|             # back off to returning the source and display name for the | ||||
|             # template we were asked to load. This allows for correct | ||||
|             # identification of the actual template that does not exist. | ||||
|             return source, display_name | ||||
|         else: | ||||
|             return template, None | ||||
|  | ||||
|     def get_template_sources(self, template_name): | ||||
|         """ | ||||
|         An iterator that yields possible matching template paths for a | ||||
| @@ -79,26 +41,9 @@ class Loader(object): | ||||
|             'subclasses of Loader must provide a get_template_sources() method' | ||||
|         ) | ||||
|  | ||||
|     def load_template_source(self, template_name, template_dirs=None): | ||||
|         """ | ||||
|         RemovedInDjango20Warning: Returns a tuple containing the source and | ||||
|         origin for the given template name. | ||||
|         """ | ||||
|         raise NotImplementedError( | ||||
|             'subclasses of Loader must provide a load_template_source() method' | ||||
|         ) | ||||
|  | ||||
|     def reset(self): | ||||
|         """ | ||||
|         Resets any state maintained by the loader instance (e.g. cached | ||||
|         templates or cached loader modules). | ||||
|         """ | ||||
|         pass | ||||
|  | ||||
|     @property | ||||
|     def supports_recursion(self): | ||||
|         """ | ||||
|         RemovedInDjango20Warning: This is an internal property used by the | ||||
|         ExtendsNode during the deprecation of non-recursive loaders. | ||||
|         """ | ||||
|         return hasattr(self, 'get_contents') | ||||
|   | ||||
| @@ -4,13 +4,10 @@ to load templates from them in order, caching the result. | ||||
| """ | ||||
|  | ||||
| import hashlib | ||||
| import warnings | ||||
|  | ||||
| from django.template import Origin, Template, TemplateDoesNotExist | ||||
| from django.template import TemplateDoesNotExist | ||||
| from django.template.backends.django import copy_exception | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
| from django.utils.encoding import force_bytes, force_text | ||||
| from django.utils.inspect import func_supports_parameter | ||||
|  | ||||
| from .base import Loader as BaseLoader | ||||
|  | ||||
| @@ -19,7 +16,6 @@ class Loader(BaseLoader): | ||||
|  | ||||
|     def __init__(self, engine, loaders): | ||||
|         self.template_cache = {} | ||||
|         self.find_template_cache = {}  # RemovedInDjango20Warning | ||||
|         self.get_template_cache = {} | ||||
|         self.loaders = engine.get_template_loaders(loaders) | ||||
|         super(Loader, self).__init__(engine) | ||||
| @@ -27,7 +23,7 @@ class Loader(BaseLoader): | ||||
|     def get_contents(self, origin): | ||||
|         return origin.loader.get_contents(origin) | ||||
|  | ||||
|     def get_template(self, template_name, template_dirs=None, skip=None): | ||||
|     def get_template(self, template_name, skip=None): | ||||
|         """ | ||||
|         Perform the caching that gives this loader its name. Often many of the | ||||
|         templates attempted will be missing, so memory use is of concern here. | ||||
| @@ -46,7 +42,7 @@ class Loader(BaseLoader): | ||||
|         memory leak. Thus, unraised copies of the exceptions are cached and | ||||
|         copies of those copies are raised after they're fetched from the cache. | ||||
|         """ | ||||
|         key = self.cache_key(template_name, template_dirs, skip) | ||||
|         key = self.cache_key(template_name, skip) | ||||
|         cached = self.get_template_cache.get(key) | ||||
|         if cached: | ||||
|             if isinstance(cached, type) and issubclass(cached, TemplateDoesNotExist): | ||||
| @@ -56,9 +52,7 @@ class Loader(BaseLoader): | ||||
|             return cached | ||||
|  | ||||
|         try: | ||||
|             template = super(Loader, self).get_template( | ||||
|                 template_name, template_dirs, skip, | ||||
|             ) | ||||
|             template = super(Loader, self).get_template(template_name, skip) | ||||
|         except TemplateDoesNotExist as e: | ||||
|             self.get_template_cache[key] = copy_exception(e) if self.engine.debug else TemplateDoesNotExist | ||||
|             raise | ||||
| @@ -67,17 +61,12 @@ class Loader(BaseLoader): | ||||
|  | ||||
|         return template | ||||
|  | ||||
|     def get_template_sources(self, template_name, template_dirs=None): | ||||
|     def get_template_sources(self, template_name): | ||||
|         for loader in self.loaders: | ||||
|             args = [template_name] | ||||
|             # RemovedInDjango20Warning: Add template_dirs for compatibility | ||||
|             # with old loaders | ||||
|             if func_supports_parameter(loader.get_template_sources, 'template_dirs'): | ||||
|                 args.append(template_dirs) | ||||
|             for origin in loader.get_template_sources(*args): | ||||
|             for origin in loader.get_template_sources(template_name): | ||||
|                 yield origin | ||||
|  | ||||
|     def cache_key(self, template_name, template_dirs, skip=None): | ||||
|     def cache_key(self, template_name, skip=None): | ||||
|         """ | ||||
|         Generate a cache key for the template name, dirs, and skip. | ||||
|  | ||||
| @@ -97,78 +86,12 @@ class Loader(BaseLoader): | ||||
|             if matching: | ||||
|                 skip_prefix = self.generate_hash(matching) | ||||
|  | ||||
|         if template_dirs: | ||||
|             dirs_prefix = self.generate_hash(template_dirs) | ||||
|  | ||||
|         return '-'.join(filter(bool, [force_text(template_name), skip_prefix, dirs_prefix])) | ||||
|  | ||||
|     def generate_hash(self, values): | ||||
|         return hashlib.sha1(force_bytes('|'.join(values))).hexdigest() | ||||
|  | ||||
|     @property | ||||
|     def supports_recursion(self): | ||||
|         """ | ||||
|         RemovedInDjango20Warning: This is an internal property used by the | ||||
|         ExtendsNode during the deprecation of non-recursive loaders. | ||||
|         """ | ||||
|         return all(hasattr(loader, 'get_contents') for loader in self.loaders) | ||||
|  | ||||
|     def find_template(self, name, dirs=None): | ||||
|         """ | ||||
|         RemovedInDjango20Warning: An internal method to lookup the template | ||||
|         name in all the configured loaders. | ||||
|         """ | ||||
|         key = self.cache_key(name, dirs) | ||||
|         try: | ||||
|             result = self.find_template_cache[key] | ||||
|         except KeyError: | ||||
|             result = None | ||||
|             for loader in self.loaders: | ||||
|                 try: | ||||
|                     template, display_name = loader(name, dirs) | ||||
|                 except TemplateDoesNotExist: | ||||
|                     pass | ||||
|                 else: | ||||
|                     origin = Origin( | ||||
|                         name=display_name, | ||||
|                         template_name=name, | ||||
|                         loader=loader, | ||||
|                     ) | ||||
|                     result = template, origin | ||||
|                     break | ||||
|         self.find_template_cache[key] = result | ||||
|         if result: | ||||
|             return result | ||||
|         else: | ||||
|             self.template_cache[key] = TemplateDoesNotExist | ||||
|             raise TemplateDoesNotExist(name) | ||||
|  | ||||
|     def load_template(self, template_name, template_dirs=None): | ||||
|         warnings.warn( | ||||
|             'The load_template() method is deprecated. Use get_template() ' | ||||
|             'instead.', RemovedInDjango20Warning, | ||||
|         ) | ||||
|         key = self.cache_key(template_name, template_dirs) | ||||
|         template_tuple = self.template_cache.get(key) | ||||
|         # A cached previous failure: | ||||
|         if template_tuple is TemplateDoesNotExist: | ||||
|             raise TemplateDoesNotExist(template_name) | ||||
|         elif template_tuple is None: | ||||
|             template, origin = self.find_template(template_name, template_dirs) | ||||
|             if not hasattr(template, 'render'): | ||||
|                 try: | ||||
|                     template = Template(template, origin, template_name, self.engine) | ||||
|                 except TemplateDoesNotExist: | ||||
|                     # If compiling the template we found raises TemplateDoesNotExist, | ||||
|                     # back off to returning the source and display name for the template | ||||
|                     # we were asked to load. This allows for correct identification (later) | ||||
|                     # of the actual template that does not exist. | ||||
|                     self.template_cache[key] = (template, origin) | ||||
|             self.template_cache[key] = (template, None) | ||||
|         return self.template_cache[key] | ||||
|  | ||||
|     def reset(self): | ||||
|         "Empty the template cache." | ||||
|         self.template_cache.clear() | ||||
|         self.find_template_cache.clear()  # RemovedInDjango20Warning | ||||
|         self.get_template_cache.clear() | ||||
|   | ||||
| @@ -54,21 +54,3 @@ class Loader(BaseLoader): | ||||
|                 template_name=template_name, | ||||
|                 loader=self, | ||||
|             ) | ||||
|  | ||||
|     def load_template_source(self, template_name, template_dirs=None): | ||||
|         """ | ||||
|         Loads templates from Python eggs via pkg_resource.resource_string. | ||||
|  | ||||
|         For every installed app, it tries to get the resource (app, template_name). | ||||
|         """ | ||||
|         warnings.warn( | ||||
|             'The load_template_sources() method is deprecated. Use ' | ||||
|             'get_template() or get_contents() instead.', | ||||
|             RemovedInDjango20Warning, | ||||
|         ) | ||||
|         for origin in self.get_template_sources(template_name): | ||||
|             try: | ||||
|                 return self.get_contents(origin), origin.name | ||||
|             except TemplateDoesNotExist: | ||||
|                 pass | ||||
|         raise TemplateDoesNotExist(template_name) | ||||
|   | ||||
| @@ -4,12 +4,10 @@ Wrapper for loading templates from the filesystem. | ||||
|  | ||||
| import errno | ||||
| import io | ||||
| import warnings | ||||
|  | ||||
| from django.core.exceptions import SuspiciousFileOperation | ||||
| from django.template import Origin, TemplateDoesNotExist | ||||
| from django.utils._os import safe_join | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
|  | ||||
| from .base import Loader as BaseLoader | ||||
|  | ||||
| @@ -32,15 +30,13 @@ class Loader(BaseLoader): | ||||
|                 raise TemplateDoesNotExist(origin) | ||||
|             raise | ||||
|  | ||||
|     def get_template_sources(self, template_name, template_dirs=None): | ||||
|     def get_template_sources(self, template_name): | ||||
|         """ | ||||
|         Return an Origin object pointing to an absolute path in each directory | ||||
|         in template_dirs. For security reasons, if a path doesn't lie inside | ||||
|         one of the template_dirs it is excluded from the result set. | ||||
|         """ | ||||
|         if not template_dirs: | ||||
|             template_dirs = self.get_dirs() | ||||
|         for template_dir in template_dirs: | ||||
|         for template_dir in self.get_dirs(): | ||||
|             try: | ||||
|                 name = safe_join(template_dir, template_name) | ||||
|             except SuspiciousFileOperation: | ||||
| @@ -53,16 +49,3 @@ class Loader(BaseLoader): | ||||
|                 template_name=template_name, | ||||
|                 loader=self, | ||||
|             ) | ||||
|  | ||||
|     def load_template_source(self, template_name, template_dirs=None): | ||||
|         warnings.warn( | ||||
|             'The load_template_sources() method is deprecated. Use ' | ||||
|             'get_template() or get_contents() instead.', | ||||
|             RemovedInDjango20Warning, | ||||
|         ) | ||||
|         for origin in self.get_template_sources(template_name, template_dirs): | ||||
|             try: | ||||
|                 return self.get_contents(origin), origin.name | ||||
|             except TemplateDoesNotExist: | ||||
|                 pass | ||||
|         raise TemplateDoesNotExist(template_name) | ||||
|   | ||||
| @@ -2,10 +2,7 @@ | ||||
| Wrapper for loading templates from a plain Python dict. | ||||
| """ | ||||
|  | ||||
| import warnings | ||||
|  | ||||
| from django.template import Origin, TemplateDoesNotExist | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
|  | ||||
| from .base import Loader as BaseLoader | ||||
|  | ||||
| @@ -28,14 +25,3 @@ class Loader(BaseLoader): | ||||
|             template_name=template_name, | ||||
|             loader=self, | ||||
|         ) | ||||
|  | ||||
|     def load_template_source(self, template_name, template_dirs=None): | ||||
|         warnings.warn( | ||||
|             'The load_template_sources() method is deprecated. Use ' | ||||
|             'get_template() or get_contents() instead.', | ||||
|             RemovedInDjango20Warning, | ||||
|         ) | ||||
|         try: | ||||
|             return self.templates_dict[template_name], template_name | ||||
|         except KeyError: | ||||
|             raise TemplateDoesNotExist(template_name) | ||||
|   | ||||
| @@ -1057,37 +1057,6 @@ Loader methods | ||||
|         :meth:`get_contents` for custom template loaders. ``get_template()`` | ||||
|         will usually not need to be overridden. | ||||
|  | ||||
|     .. method:: load_template_source(template_name, template_dirs=None) | ||||
|  | ||||
|         Returns a tuple of (``template_string``, ``template_origin``), where | ||||
|         ``template_string`` is a string containing the template contents, | ||||
|         and ``template_origin`` is a string identifying the template source. | ||||
|         A filesystem-based loader may return the full path to the file as the | ||||
|         ``template_origin``, for example. | ||||
|  | ||||
|         ``template_dirs`` is an optional argument used to control which | ||||
|         directories the loader will search. | ||||
|  | ||||
|         This method is called automatically by :meth:`load_template` and should | ||||
|         be overridden when writing custom template loaders. | ||||
|  | ||||
|         .. deprecated:: 1.9 | ||||
|  | ||||
|              Custom loaders should use :meth:`get_template` and | ||||
|              :meth:`get_contents` instead. | ||||
|  | ||||
|     .. method:: load_template(template_name, template_dirs=None) | ||||
|  | ||||
|         Returns a tuple of (``template``, ``template_origin``), where ``template`` | ||||
|         is a ``Template`` object and ``template_origin`` is a string identifying | ||||
|         the template source. A filesystem-based loader may return the full | ||||
|         path to the file as the ``template_origin``, for example. | ||||
|  | ||||
|         .. deprecated:: 1.9 | ||||
|  | ||||
|              Custom loaders should use :meth:`get_template` and | ||||
|              :meth:`get_contents` instead. | ||||
|  | ||||
| .. admonition:: Building your own | ||||
|  | ||||
|     For examples, `read the source code for Django's built-in loaders`_. | ||||
|   | ||||
| @@ -265,3 +265,23 @@ these features. | ||||
| * The ``GeoManager`` and ``GeoQuerySet`` classes are removed. | ||||
|  | ||||
| * The ``django.contrib.gis.geoip`` module is removed. | ||||
|  | ||||
| * The ``supports_recursion`` check for template loaders is removed from: | ||||
|  | ||||
|   * ``django.template.engine.Engine.find_template()`` | ||||
|   * ``django.template.loader_tags.ExtendsNode.find_template()`` | ||||
|   * ``django.template.loaders.base.Loader.supports_recursion()`` | ||||
|   * ``django.template.loaders.cached.Loader.supports_recursion()`` | ||||
|  | ||||
| * The ``load_template`` and ``load_template_sources`` template loader methods | ||||
|   are removed. | ||||
|  | ||||
| * The ``template_dirs`` argument for template loaders is removed: | ||||
|  | ||||
|   * ``django.template.loaders.base.Loader.get_template()`` | ||||
|   * ``django.template.loaders.cached.Loader.cache_key()`` | ||||
|   * ``django.template.loaders.cached.Loader.get_template()`` | ||||
|   * ``django.template.loaders.cached.Loader.get_template_sources()`` | ||||
|   * ``django.template.loaders.filesystem.Loader.get_template_sources()`` | ||||
|  | ||||
| * ``django.template.loaders.base.Loader.__call__()`` is removed. | ||||
|   | ||||
| @@ -248,9 +248,6 @@ class IncludeTests(SimpleTestCase): | ||||
|         self.assertEqual(e.exception.args[0], 'missing.html') | ||||
|  | ||||
|     def test_extends_include_missing_cachedloader(self): | ||||
|         """ | ||||
|         Test the cache loader separately since it overrides load_template. | ||||
|         """ | ||||
|         engine = Engine(debug=True, loaders=[ | ||||
|             ('django.template.loaders.cached.Loader', [ | ||||
|                 'django.template.loaders.app_directories.Loader', | ||||
|   | ||||
| @@ -1,10 +1,7 @@ | ||||
| import os | ||||
|  | ||||
| from django.template import Context, Engine, TemplateDoesNotExist | ||||
| from django.template.loader_tags import ExtendsError | ||||
| from django.template.loaders.base import Loader | ||||
| from django.test import SimpleTestCase, ignore_warnings | ||||
| from django.utils.deprecation import RemovedInDjango20Warning | ||||
| from django.test import SimpleTestCase | ||||
|  | ||||
| from .utils import ROOT | ||||
|  | ||||
| @@ -120,64 +117,3 @@ class ExtendsBehaviorTests(SimpleTestCase): | ||||
|         template = engine.get_template('base.html') | ||||
|         output = template.render(Context({})) | ||||
|         self.assertEqual(output.strip(), 'loader2 loader1') | ||||
|  | ||||
|  | ||||
| class NonRecursiveLoader(Loader): | ||||
|  | ||||
|     def __init__(self, engine, templates_dict): | ||||
|         self.templates_dict = templates_dict | ||||
|         super(NonRecursiveLoader, self).__init__(engine) | ||||
|  | ||||
|     def load_template_source(self, template_name, template_dirs=None): | ||||
|         try: | ||||
|             return self.templates_dict[template_name], template_name | ||||
|         except KeyError: | ||||
|             raise TemplateDoesNotExist(template_name) | ||||
|  | ||||
|  | ||||
| @ignore_warnings(category=RemovedInDjango20Warning) | ||||
| class NonRecursiveLoaderExtendsTests(SimpleTestCase): | ||||
|  | ||||
|     loaders = [ | ||||
|         ('template_tests.test_extends.NonRecursiveLoader', { | ||||
|             'base.html': 'base', | ||||
|             'index.html': '{% extends "base.html" %}', | ||||
|             'recursive.html': '{% extends "recursive.html" %}', | ||||
|             'other-recursive.html': '{% extends "recursive.html" %}', | ||||
|             'a.html': '{% extends "b.html" %}', | ||||
|             'b.html': '{% extends "a.html" %}', | ||||
|         }), | ||||
|     ] | ||||
|  | ||||
|     def test_extend(self): | ||||
|         engine = Engine(loaders=self.loaders) | ||||
|         output = engine.render_to_string('index.html') | ||||
|         self.assertEqual(output, 'base') | ||||
|  | ||||
|     def test_extend_cached(self): | ||||
|         engine = Engine(loaders=[ | ||||
|             ('django.template.loaders.cached.Loader', self.loaders), | ||||
|         ]) | ||||
|         output = engine.render_to_string('index.html') | ||||
|         self.assertEqual(output, 'base') | ||||
|  | ||||
|         cache = engine.template_loaders[0].template_cache | ||||
|         self.assertIn('base.html', cache) | ||||
|         self.assertIn('index.html', cache) | ||||
|  | ||||
|         # Render a second time from cache | ||||
|         output = engine.render_to_string('index.html') | ||||
|         self.assertEqual(output, 'base') | ||||
|  | ||||
|     def test_extend_error(self): | ||||
|         engine = Engine(loaders=self.loaders) | ||||
|         msg = 'Cannot extend templates recursively when using non-recursive template loaders' | ||||
|  | ||||
|         with self.assertRaisesMessage(ExtendsError, msg): | ||||
|             engine.render_to_string('recursive.html') | ||||
|  | ||||
|         with self.assertRaisesMessage(ExtendsError, msg): | ||||
|             engine.render_to_string('other-recursive.html') | ||||
|  | ||||
|         with self.assertRaisesMessage(ExtendsError, msg): | ||||
|             engine.render_to_string('a.html') | ||||
|   | ||||
| @@ -91,62 +91,6 @@ class CachedLoaderTests(SimpleTestCase): | ||||
|         self.assertIsNone(e.__context__, error_msg) | ||||
|         self.assertIsNone(e.__cause__, error_msg) | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_template(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         template, origin = loader.load_template('index.html') | ||||
|         self.assertEqual(template.origin.template_name, 'index.html') | ||||
|  | ||||
|         cache = self.engine.template_loaders[0].template_cache | ||||
|         self.assertEqual(cache['index.html'][0], template) | ||||
|  | ||||
|         # Run a second time from cache | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         source, name = loader.load_template('index.html') | ||||
|         self.assertEqual(template.origin.template_name, 'index.html') | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_template_missing(self): | ||||
|         """ | ||||
|         #19949 -- TemplateDoesNotExist exceptions should be cached. | ||||
|         """ | ||||
|         loader = self.engine.template_loaders[0] | ||||
|  | ||||
|         self.assertNotIn('missing.html', loader.template_cache) | ||||
|  | ||||
|         with self.assertRaises(TemplateDoesNotExist): | ||||
|             loader.load_template("missing.html") | ||||
|  | ||||
|         self.assertEqual( | ||||
|             loader.template_cache["missing.html"], | ||||
|             TemplateDoesNotExist, | ||||
|             "Cached loader failed to cache the TemplateDoesNotExist exception", | ||||
|         ) | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_nonexistent_cached_template(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         template_name = 'nonexistent.html' | ||||
|  | ||||
|         # fill the template cache | ||||
|         with self.assertRaises(TemplateDoesNotExist): | ||||
|             loader.find_template(template_name) | ||||
|  | ||||
|         with self.assertRaisesMessage(TemplateDoesNotExist, template_name): | ||||
|             loader.get_template(template_name) | ||||
|  | ||||
|     def test_templatedir_caching(self): | ||||
|         """ | ||||
|         #13573 -- Template directories should be part of the cache key. | ||||
|         """ | ||||
|         # Retrieve a template specifying a template directory to check | ||||
|         t1, name = self.engine.find_template('test.html', (os.path.join(TEMPLATE_DIR, 'first'),)) | ||||
|         # Now retrieve the same template name, but from a different directory | ||||
|         t2, name = self.engine.find_template('test.html', (os.path.join(TEMPLATE_DIR, 'second'),)) | ||||
|  | ||||
|         # The two templates should not have the same content | ||||
|         self.assertNotEqual(t1.render(Context({})), t2.render(Context({}))) | ||||
|  | ||||
|     def test_template_name_leading_dash_caching(self): | ||||
|         """ | ||||
|         #26536 -- A leading dash in a template name shouldn't be stripped | ||||
| @@ -239,20 +183,6 @@ class EggLoaderTests(SimpleTestCase): | ||||
|         output = template.render(Context({})) | ||||
|         self.assertEqual(output, "y") | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_template_source(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         templates = { | ||||
|             os.path.normcase('templates/y.html'): six.StringIO("y"), | ||||
|         } | ||||
|  | ||||
|         with self.create_egg('egg', templates): | ||||
|             with override_settings(INSTALLED_APPS=['egg']): | ||||
|                 source, name = loader.load_template_source('y.html') | ||||
|  | ||||
|         self.assertEqual(source.strip(), 'y') | ||||
|         self.assertEqual(name, 'egg:egg:templates/y.html') | ||||
|  | ||||
|     def test_non_existing(self): | ||||
|         """ | ||||
|         Template loading fails if the template is not in the egg. | ||||
| @@ -323,13 +253,6 @@ class FileSystemLoaderTests(SimpleTestCase): | ||||
|         with self.assertRaises(TemplateDoesNotExist): | ||||
|             engine.get_template('index.html') | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_template_source(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         source, name = loader.load_template_source('index.html') | ||||
|         self.assertEqual(source.strip(), 'index') | ||||
|         self.assertEqual(name, os.path.join(TEMPLATE_DIR, 'index.html')) | ||||
|  | ||||
|     def test_directory_security(self): | ||||
|         with self.source_checker(['/dir1', '/dir2']) as check_sources: | ||||
|             check_sources('index.html', ['/dir1/index.html', '/dir2/index.html']) | ||||
| @@ -353,10 +276,10 @@ class FileSystemLoaderTests(SimpleTestCase): | ||||
|         """ | ||||
|         Invalid UTF-8 encoding in bytestrings should raise a useful error | ||||
|         """ | ||||
|         engine = Engine() | ||||
|         engine = self.engine | ||||
|         loader = engine.template_loaders[0] | ||||
|         with self.assertRaises(UnicodeDecodeError): | ||||
|             list(loader.get_template_sources(b'\xc3\xc3', ['/dir1'])) | ||||
|             list(loader.get_template_sources(b'\xc3\xc3')) | ||||
|  | ||||
|     def test_unicode_dir_name(self): | ||||
|         with self.source_checker([b'/Stra\xc3\x9fe']) as check_sources: | ||||
| @@ -410,14 +333,6 @@ class AppDirectoriesLoaderTests(SimpleTestCase): | ||||
|         self.assertEqual(template.origin.template_name, 'index.html') | ||||
|         self.assertEqual(template.origin.loader, self.engine.template_loaders[0]) | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     @override_settings(INSTALLED_APPS=['template_tests']) | ||||
|     def test_load_template_source(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         source, name = loader.load_template_source('index.html') | ||||
|         self.assertEqual(source.strip(), 'index') | ||||
|         self.assertEqual(name, os.path.join(TEMPLATE_DIR, 'index.html')) | ||||
|  | ||||
|     @override_settings(INSTALLED_APPS=[]) | ||||
|     def test_not_installed(self): | ||||
|         with self.assertRaises(TemplateDoesNotExist): | ||||
| @@ -440,10 +355,3 @@ class LocmemLoaderTests(SimpleTestCase): | ||||
|         self.assertEqual(template.origin.name, 'index.html') | ||||
|         self.assertEqual(template.origin.template_name, 'index.html') | ||||
|         self.assertEqual(template.origin.loader, self.engine.template_loaders[0]) | ||||
|  | ||||
|     @ignore_warnings(category=RemovedInDjango20Warning) | ||||
|     def test_load_template_source(self): | ||||
|         loader = self.engine.template_loaders[0] | ||||
|         source, name = loader.load_template_source('index.html') | ||||
|         self.assertEqual(source.strip(), 'index') | ||||
|         self.assertEqual(name, 'index.html') | ||||
|   | ||||
		Reference in New Issue
	
	Block a user