mirror of
				https://github.com/django/django.git
				synced 2025-10-30 09:06:13 +00:00 
			
		
		
		
	[1.8.x] Cleaned up template loader tests.
Backport of 1827aa9024 from master
			
			
This commit is contained in:
		
							
								
								
									
										1
									
								
								tests/template_tests/templates/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								tests/template_tests/templates/index.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | |||||||
|  | index | ||||||
							
								
								
									
										125
									
								
								tests/template_tests/test_engine.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								tests/template_tests/test_engine.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | |||||||
|  | import os | ||||||
|  |  | ||||||
|  | from django.template import Context | ||||||
|  | from django.template.engine import Engine | ||||||
|  | from django.test import SimpleTestCase, ignore_warnings | ||||||
|  | from django.utils.deprecation import RemovedInDjango20Warning | ||||||
|  |  | ||||||
|  | from .utils import ROOT, TEMPLATE_DIR | ||||||
|  |  | ||||||
|  | OTHER_DIR = os.path.join(ROOT, 'other_templates') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ignore_warnings(category=RemovedInDjango20Warning) | ||||||
|  | class DeprecatedRenderToStringTest(SimpleTestCase): | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         self.engine = Engine(dirs=[TEMPLATE_DIR]) | ||||||
|  |  | ||||||
|  |     def test_basic_context(self): | ||||||
|  |         self.assertEqual( | ||||||
|  |             self.engine.render_to_string('test_context.html', {'obj': 'test'}), | ||||||
|  |             'obj:test\n', | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def test_existing_context_kept_clean(self): | ||||||
|  |         context = Context({'obj': 'before'}) | ||||||
|  |         output = self.engine.render_to_string( | ||||||
|  |             'test_context.html', {'obj': 'after'}, context_instance=context, | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(output, 'obj:after\n') | ||||||
|  |         self.assertEqual(context['obj'], 'before') | ||||||
|  |  | ||||||
|  |     def test_no_empty_dict_pushed_to_stack(self): | ||||||
|  |         """ | ||||||
|  |         #21741 -- An empty dict should not be pushed to the context stack when | ||||||
|  |         render_to_string is called without a context argument. | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         # The stack should have a length of 1, corresponding to the builtins | ||||||
|  |         self.assertEqual( | ||||||
|  |             '1', | ||||||
|  |             self.engine.render_to_string('test_context_stack.html').strip(), | ||||||
|  |         ) | ||||||
|  |         self.assertEqual( | ||||||
|  |             '1', | ||||||
|  |             self.engine.render_to_string( | ||||||
|  |                 'test_context_stack.html', | ||||||
|  |                 context_instance=Context() | ||||||
|  |             ).strip(), | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class LoaderTests(SimpleTestCase): | ||||||
|  |  | ||||||
|  |     def test_debug_nodelist_name(self): | ||||||
|  |         engine = Engine(dirs=[TEMPLATE_DIR], debug=True) | ||||||
|  |         template_name = 'index.html' | ||||||
|  |         template = engine.get_template(template_name) | ||||||
|  |         name = template.nodelist[0].source[0].name | ||||||
|  |         self.assertTrue(name.endswith(template_name)) | ||||||
|  |  | ||||||
|  |     def test_origin(self): | ||||||
|  |         engine = Engine(dirs=[TEMPLATE_DIR], debug=True) | ||||||
|  |         template = engine.get_template('index.html') | ||||||
|  |         self.assertEqual(template.origin.loadname, 'index.html') | ||||||
|  |  | ||||||
|  |     def test_origin_debug_false(self): | ||||||
|  |         engine = Engine(dirs=[TEMPLATE_DIR], debug=False) | ||||||
|  |         template = engine.get_template('index.html') | ||||||
|  |         self.assertEqual(template.origin, None) | ||||||
|  |  | ||||||
|  |     def test_loader_priority(self): | ||||||
|  |         """ | ||||||
|  |         #21460 -- Check that the order of template loader works. | ||||||
|  |         """ | ||||||
|  |         loaders = [ | ||||||
|  |             'django.template.loaders.filesystem.Loader', | ||||||
|  |             'django.template.loaders.app_directories.Loader', | ||||||
|  |         ] | ||||||
|  |         engine = Engine(dirs=[OTHER_DIR, TEMPLATE_DIR], loaders=loaders) | ||||||
|  |         template = engine.get_template('priority/foo.html') | ||||||
|  |         self.assertEqual(template.render(Context()), 'priority\n') | ||||||
|  |  | ||||||
|  |     def test_cached_loader_priority(self): | ||||||
|  |         """ | ||||||
|  |         Check that the order of template loader works. Refs #21460. | ||||||
|  |         """ | ||||||
|  |         loaders = [ | ||||||
|  |             ('django.template.loaders.cached.Loader', [ | ||||||
|  |                 'django.template.loaders.filesystem.Loader', | ||||||
|  |                 'django.template.loaders.app_directories.Loader', | ||||||
|  |             ]), | ||||||
|  |         ] | ||||||
|  |         engine = Engine(dirs=[OTHER_DIR, TEMPLATE_DIR], loaders=loaders) | ||||||
|  |  | ||||||
|  |         template = engine.get_template('priority/foo.html') | ||||||
|  |         self.assertEqual(template.render(Context()), 'priority\n') | ||||||
|  |  | ||||||
|  |         template = engine.get_template('priority/foo.html') | ||||||
|  |         self.assertEqual(template.render(Context()), 'priority\n') | ||||||
|  |  | ||||||
|  |  | ||||||
|  | @ignore_warnings(category=RemovedInDjango20Warning) | ||||||
|  | class TemplateDirsOverrideTests(SimpleTestCase): | ||||||
|  |     DIRS = ((OTHER_DIR, ), [OTHER_DIR]) | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         self.engine = Engine() | ||||||
|  |  | ||||||
|  |     def test_render_to_string(self): | ||||||
|  |         for dirs in self.DIRS: | ||||||
|  |             self.assertEqual( | ||||||
|  |                 self.engine.render_to_string('test_dirs.html', dirs=dirs), | ||||||
|  |                 'spam eggs\n', | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |     def test_get_template(self): | ||||||
|  |         for dirs in self.DIRS: | ||||||
|  |             template = self.engine.get_template('test_dirs.html', dirs=dirs) | ||||||
|  |             self.assertEqual(template.render(Context()), 'spam eggs\n') | ||||||
|  |  | ||||||
|  |     def test_select_template(self): | ||||||
|  |         for dirs in self.DIRS: | ||||||
|  |             template = self.engine.select_template(['test_dirs.html'], dirs=dirs) | ||||||
|  |             self.assertEqual(template.render(Context()), 'spam eggs\n') | ||||||
| @@ -1,22 +1,18 @@ | |||||||
| """ | # -*- coding: utf-8 -*- | ||||||
| Test cases for the template loaders | from __future__ import unicode_literals | ||||||
|  |  | ||||||
| Note: This test requires setuptools! |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| import os.path | import os.path | ||||||
| import sys | import sys | ||||||
| import types | import types | ||||||
| import unittest | import unittest | ||||||
|  | from contextlib import contextmanager | ||||||
|  |  | ||||||
| from django.template import Context, TemplateDoesNotExist, loader | from django.template import Context, TemplateDoesNotExist | ||||||
| from django.template.engine import Engine | from django.template.engine import Engine | ||||||
| from django.template.loaders import cached, eggs | from django.test import SimpleTestCase, override_settings | ||||||
| from django.test import SimpleTestCase, ignore_warnings, override_settings |  | ||||||
| from django.utils import six | from django.utils import six | ||||||
| from django.utils._os import upath |  | ||||||
| from django.utils.deprecation import RemovedInDjango20Warning | from .utils import TEMPLATE_DIR | ||||||
| from django.utils.six import StringIO |  | ||||||
|  |  | ||||||
| try: | try: | ||||||
|     import pkg_resources |     import pkg_resources | ||||||
| @@ -24,38 +20,86 @@ except ImportError: | |||||||
|     pkg_resources = None |     pkg_resources = None | ||||||
|  |  | ||||||
|  |  | ||||||
| TEMPLATES_DIR = os.path.join(os.path.dirname(upath(__file__)), 'templates') | class CachedLoaderTests(SimpleTestCase): | ||||||
|  |  | ||||||
| GLOBAL_TEMPLATES_DIR = os.path.join(os.path.dirname(os.path.dirname(upath(__file__))), 'templates') |     def create_engine(self, **kwargs): | ||||||
|  |         return Engine( | ||||||
|  |             loaders=[ | ||||||
|  |                 ('django.template.loaders.cached.Loader', [ | ||||||
|  |                     'django.template.loaders.filesystem.Loader', | ||||||
|  |                 ]), | ||||||
|  |             ], | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def test_templatedir_caching(self): | ||||||
|  |         """ | ||||||
|  |         #13573 -- Template directories should be part of the cache key. | ||||||
|  |         """ | ||||||
|  |         engine = self.create_engine() | ||||||
|  |  | ||||||
| # Mock classes and objects for pkg_resources functions. |         # Retrieve a template specifying a template directory to check | ||||||
| class MockLoader(object): |         t1, name = engine.find_template('test.html', (os.path.join(TEMPLATE_DIR, 'first'),)) | ||||||
|     pass |         # Now retrieve the same template name, but from a different directory | ||||||
|  |         t2, name = 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 create_egg(name, resources): |     def test_missing_template_is_cached(self): | ||||||
|     """ |         """ | ||||||
|     Creates a mock egg with a list of resources. |         #19949 -- TemplateDoesNotExist exceptions should be cached. | ||||||
|  |         """ | ||||||
|  |         engine = self.create_engine() | ||||||
|  |         loader = engine.template_loaders[0] | ||||||
|  |  | ||||||
|     name: The name of the module. |         self.assertFalse('missing.html' in loader.template_cache) | ||||||
|     resources: A dictionary of resources. Keys are the names and values the data. |  | ||||||
|     """ |         with self.assertRaises(TemplateDoesNotExist): | ||||||
|     egg = types.ModuleType(name) |             loader.load_template("missing.html") | ||||||
|     egg.__loader__ = MockLoader() |  | ||||||
|     egg.__path__ = ['/some/bogus/path/'] |         self.assertEqual( | ||||||
|     egg.__file__ = '/some/bogus/path/__init__.pyc' |             loader.template_cache["missing.html"], | ||||||
|     egg._resources = resources |             TemplateDoesNotExist, | ||||||
|     sys.modules[name] = egg |             "Cached loader failed to cache the TemplateDoesNotExist exception", | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def test_debug_nodelist_name(self): | ||||||
|  |         template_name = 'index.html' | ||||||
|  |         engine = Engine(dirs=[TEMPLATE_DIR], debug=True) | ||||||
|  |  | ||||||
|  |         template = engine.get_template(template_name) | ||||||
|  |         name = template.nodelist[0].source[0].name | ||||||
|  |         self.assertTrue( | ||||||
|  |             name.endswith(template_name), | ||||||
|  |             'Template loaded through cached loader has incorrect name for debug page: %s' % template_name, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         template = engine.get_template(template_name) | ||||||
|  |         name = template.nodelist[0].source[0].name | ||||||
|  |         self.assertTrue( | ||||||
|  |             name.endswith(template_name), | ||||||
|  |             'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
| @unittest.skipUnless(pkg_resources, 'setuptools is not installed') | @unittest.skipUnless(pkg_resources, 'setuptools is not installed') | ||||||
| class EggLoaderTest(SimpleTestCase): | class EggLoaderTests(SimpleTestCase): | ||||||
|  |  | ||||||
|     def setUp(self): |     @contextmanager | ||||||
|         self.loader = eggs.Loader(Engine.get_default()) |     def create_egg(self, name, resources): | ||||||
|  |         """ | ||||||
|  |         Creates a mock egg with a list of resources. | ||||||
|  |  | ||||||
|  |         name: The name of the module. | ||||||
|  |         resources: A dictionary of template names mapped to file-like objects. | ||||||
|  |         """ | ||||||
|  |  | ||||||
|  |         if six.PY2: | ||||||
|  |             name = name.encode('utf-8') | ||||||
|  |  | ||||||
|  |         class MockLoader(object): | ||||||
|  |             pass | ||||||
|  |  | ||||||
|         # Defined here b/c at module scope we may not have pkg_resources |  | ||||||
|         class MockProvider(pkg_resources.NullProvider): |         class MockProvider(pkg_resources.NullProvider): | ||||||
|             def __init__(self, module): |             def __init__(self, module): | ||||||
|                 pkg_resources.NullProvider.__init__(self, module) |                 pkg_resources.NullProvider.__init__(self, module) | ||||||
| @@ -76,181 +120,123 @@ class EggLoaderTest(SimpleTestCase): | |||||||
|             def _fn(self, base, resource_name): |             def _fn(self, base, resource_name): | ||||||
|                 return os.path.normcase(resource_name) |                 return os.path.normcase(resource_name) | ||||||
|  |  | ||||||
|  |         egg = types.ModuleType(name) | ||||||
|  |         egg.__loader__ = MockLoader() | ||||||
|  |         egg.__path__ = ['/some/bogus/path/'] | ||||||
|  |         egg.__file__ = '/some/bogus/path/__init__.pyc' | ||||||
|  |         egg._resources = resources | ||||||
|  |         sys.modules[name] = egg | ||||||
|         pkg_resources._provider_factories[MockLoader] = MockProvider |         pkg_resources._provider_factories[MockLoader] = MockProvider | ||||||
|  |  | ||||||
|         self.empty_egg = create_egg("egg_empty", {}) |         try: | ||||||
|         self.egg_1 = create_egg("egg_1", { |             yield | ||||||
|             os.path.normcase('templates/y.html'): StringIO("y"), |         finally: | ||||||
|             os.path.normcase('templates/x.txt'): StringIO("x"), |             del sys.modules[name] | ||||||
|         }) |             del pkg_resources._provider_factories[MockLoader] | ||||||
|  |  | ||||||
|     @override_settings(INSTALLED_APPS=['egg_empty']) |  | ||||||
|     def test_empty(self): |  | ||||||
|         "Loading any template on an empty egg should fail" |  | ||||||
|         with self.assertRaises(TemplateDoesNotExist): |  | ||||||
|             self.loader.load_template_source("not-existing.html") |  | ||||||
|  |  | ||||||
|     @override_settings(INSTALLED_APPS=['egg_1']) |  | ||||||
|     def test_non_existing(self): |  | ||||||
|         "Template loading fails if the template is not in the egg" |  | ||||||
|         with self.assertRaises(TemplateDoesNotExist): |  | ||||||
|             self.loader.load_template_source("not-existing.html") |  | ||||||
|  |  | ||||||
|     @override_settings(INSTALLED_APPS=['egg_1']) |  | ||||||
|     def test_existing(self): |  | ||||||
|         "A template can be loaded from an egg" |  | ||||||
|         contents, template_name = self.loader.load_template_source("y.html") |  | ||||||
|         self.assertEqual(contents, "y") |  | ||||||
|         self.assertEqual(template_name, "egg:egg_1:templates/y.html") |  | ||||||
|  |  | ||||||
|     def test_not_installed(self): |  | ||||||
|         "Loading an existent template from an egg not included in any app should fail" |  | ||||||
|         with self.assertRaises(TemplateDoesNotExist): |  | ||||||
|             self.loader.load_template_source("y.html") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class CachedLoader(SimpleTestCase): |  | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|         self.loader = cached.Loader(Engine.get_default(), [ |         engine = Engine(loaders=[ | ||||||
|             'django.template.loaders.filesystem.Loader', |             'django.template.loaders.eggs.Loader', | ||||||
|         ]) |         ]) | ||||||
|  |         self.loader = engine.template_loaders[0] | ||||||
|  |  | ||||||
|     def test_templatedir_caching(self): |     def test_existing(self): | ||||||
|         "Check that the template directories form part of the template cache key. Refs #13573" |         templates = { | ||||||
|         # Retrieve a template specifying a template directory to check |             os.path.normcase('templates/y.html'): six.StringIO("y"), | ||||||
|         t1, name = self.loader.find_template('test.html', (os.path.join(TEMPLATES_DIR, 'first'),)) |         } | ||||||
|         # Now retrieve the same template name, but from a different directory |  | ||||||
|         t2, name = self.loader.find_template('test.html', (os.path.join(TEMPLATES_DIR, 'second'),)) |  | ||||||
|  |  | ||||||
|         # The two templates should not have the same content |         with self.create_egg('egg', templates): | ||||||
|         self.assertNotEqual(t1.render(Context({})), t2.render(Context({}))) |             with override_settings(INSTALLED_APPS=['egg']): | ||||||
|  |                 contents, template_name = self.loader.load_template_source("y.html") | ||||||
|  |                 self.assertEqual(contents, "y") | ||||||
|  |                 self.assertEqual(template_name, "egg:egg:templates/y.html") | ||||||
|  |  | ||||||
|     def test_missing_template_is_cached(self): |     def test_non_existing(self): | ||||||
|         "#19949 -- Check that the missing template is cached." |  | ||||||
|         # Check that 'missing.html' isn't already in cache before 'missing.html' is loaded |  | ||||||
|         with self.assertRaises(KeyError): |  | ||||||
|             self.loader.template_cache["missing.html"] |  | ||||||
|         # Try to load it, it should fail |  | ||||||
|         with self.assertRaises(TemplateDoesNotExist): |  | ||||||
|             self.loader.load_template("missing.html") |  | ||||||
|         # Verify that the fact that the missing template, which hasn't been found, has actually |  | ||||||
|         # been cached: |  | ||||||
|         cached_miss = self.loader.template_cache["missing.html"] |  | ||||||
|         self.assertEqual(cached_miss, TemplateDoesNotExist, |  | ||||||
|                          "Cached template loader doesn't cache file lookup misses. It should.") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @override_settings(TEMPLATES=[{ |  | ||||||
|     'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|     'DIRS': [TEMPLATES_DIR], |  | ||||||
| }]) |  | ||||||
| class RenderToStringTest(SimpleTestCase): |  | ||||||
|     def test_basic(self): |  | ||||||
|         self.assertEqual(loader.render_to_string('test_context.html'), 'obj:\n') |  | ||||||
|  |  | ||||||
|     def test_basic_context(self): |  | ||||||
|         self.assertEqual(loader.render_to_string('test_context.html', |  | ||||||
|                                                  {'obj': 'test'}), 'obj:test\n') |  | ||||||
|  |  | ||||||
|     def test_empty_list(self): |  | ||||||
|         six.assertRaisesRegex(self, TemplateDoesNotExist, |  | ||||||
|             'No template names provided$', |  | ||||||
|             loader.render_to_string, []) |  | ||||||
|  |  | ||||||
|     def test_select_templates_from_empty_list(self): |  | ||||||
|         six.assertRaisesRegex(self, TemplateDoesNotExist, |  | ||||||
|             'No template names provided$', |  | ||||||
|             loader.select_template, []) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @ignore_warnings(category=RemovedInDjango20Warning) |  | ||||||
| @override_settings(TEMPLATES=[{ |  | ||||||
|     'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|     'DIRS': [TEMPLATES_DIR], |  | ||||||
| }]) |  | ||||||
| class DeprecatedRenderToStringTest(SimpleTestCase): |  | ||||||
|  |  | ||||||
|     def test_existing_context_kept_clean(self): |  | ||||||
|         context = Context({'obj': 'before'}) |  | ||||||
|         output = loader.render_to_string('test_context.html', {'obj': 'after'}, |  | ||||||
|                                          context_instance=context) |  | ||||||
|         self.assertEqual(output, 'obj:after\n') |  | ||||||
|         self.assertEqual(context['obj'], 'before') |  | ||||||
|  |  | ||||||
|     def test_no_empty_dict_pushed_to_stack(self): |  | ||||||
|         """ |         """ | ||||||
|         No empty dict should be pushed to the context stack when render_to_string |         Template loading fails if the template is not in the egg. | ||||||
|         is called without any argument (#21741). |  | ||||||
|         """ |         """ | ||||||
|  |         with self.create_egg('egg', {}): | ||||||
|  |             with override_settings(INSTALLED_APPS=['egg']): | ||||||
|  |                 with self.assertRaises(TemplateDoesNotExist): | ||||||
|  |                     self.loader.load_template_source("not-existing.html") | ||||||
|  |  | ||||||
|         # The stack should have a length of 1, corresponding to the builtins |     def test_not_installed(self): | ||||||
|         self.assertEqual('1', |  | ||||||
|             loader.render_to_string('test_context_stack.html').strip()) |  | ||||||
|         self.assertEqual('1', |  | ||||||
|             loader.render_to_string('test_context_stack.html', context_instance=Context()).strip()) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @ignore_warnings(category=RemovedInDjango20Warning) |  | ||||||
| @override_settings(TEMPLATES=[{ |  | ||||||
|     'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
| }]) |  | ||||||
| class TemplateDirsOverrideTest(SimpleTestCase): |  | ||||||
|  |  | ||||||
|     dirs_tuple = (os.path.join(os.path.dirname(upath(__file__)), 'other_templates'),) |  | ||||||
|     dirs_list = list(dirs_tuple) |  | ||||||
|     dirs_iter = (dirs_tuple, dirs_list) |  | ||||||
|  |  | ||||||
|     def test_render_to_string(self): |  | ||||||
|         for dirs in self.dirs_iter: |  | ||||||
|             self.assertEqual(loader.render_to_string('test_dirs.html', dirs=dirs), 'spam eggs\n') |  | ||||||
|  |  | ||||||
|     def test_get_template(self): |  | ||||||
|         for dirs in self.dirs_iter: |  | ||||||
|             template = loader.get_template('test_dirs.html', dirs=dirs) |  | ||||||
|             self.assertEqual(template.render(), 'spam eggs\n') |  | ||||||
|  |  | ||||||
|     def test_select_template(self): |  | ||||||
|         for dirs in self.dirs_iter: |  | ||||||
|             template = loader.select_template(['test_dirs.html'], dirs=dirs) |  | ||||||
|             self.assertEqual(template.render(), 'spam eggs\n') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @override_settings(TEMPLATES=[{ |  | ||||||
|     'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|     'DIRS': [GLOBAL_TEMPLATES_DIR], |  | ||||||
|     'OPTIONS': { |  | ||||||
|         'loaders': [ |  | ||||||
|             ('django.template.loaders.cached.Loader', [ |  | ||||||
|                 'django.template.loaders.filesystem.Loader', |  | ||||||
|                 'django.template.loaders.app_directories.Loader', |  | ||||||
|             ]), |  | ||||||
|         ], |  | ||||||
|     }, |  | ||||||
| }]) |  | ||||||
| class PriorityCacheLoader(SimpleTestCase): |  | ||||||
|     def test_basic(self): |  | ||||||
|         """ |         """ | ||||||
|         Check that the order of template loader works. Refs #21460. |         Template loading fails if the egg is not in INSTALLED_APPS. | ||||||
|         """ |         """ | ||||||
|         t1 = loader.get_template('priority/foo.html') |         templates = { | ||||||
|         self.assertEqual(t1.render(), 'priority\n') |             os.path.normcase('templates/y.html'): six.StringIO("y"), | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         with self.create_egg('egg', templates): | ||||||
|  |             with self.assertRaises(TemplateDoesNotExist): | ||||||
|  |                 self.loader.load_template_source("y.html") | ||||||
|  |  | ||||||
|  |  | ||||||
| @override_settings(TEMPLATES=[{ | class FileSystemLoaderTests(SimpleTestCase): | ||||||
|     'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|     'DIRS': [GLOBAL_TEMPLATES_DIR], |     def setUp(self): | ||||||
|     'OPTIONS': { |         self.engine = Engine() | ||||||
|         'loaders': [ |  | ||||||
|             'django.template.loaders.filesystem.Loader', |     @contextmanager | ||||||
|             'django.template.loaders.app_directories.Loader', |     def source_checker(self, dirs): | ||||||
|         ], |         loader = self.engine.template_loaders[0] | ||||||
|     }, |  | ||||||
| }]) |         def check_sources(path, expected_sources): | ||||||
| class PriorityLoader(SimpleTestCase): |             expected_sources = [os.path.abspath(s) for s in expected_sources] | ||||||
|     def test_basic(self): |             self.assertEqual( | ||||||
|  |                 list(loader.get_template_sources(path, dirs)), | ||||||
|  |                 expected_sources, | ||||||
|  |             ) | ||||||
|  |  | ||||||
|  |         yield check_sources | ||||||
|  |  | ||||||
|  |     def test_directory_security(self): | ||||||
|  |         with self.source_checker(['/dir1', '/dir2']) as check_sources: | ||||||
|  |             check_sources('index.html', ['/dir1/index.html', '/dir2/index.html']) | ||||||
|  |             check_sources('/etc/passwd', []) | ||||||
|  |             check_sources('etc/passwd', ['/dir1/etc/passwd', '/dir2/etc/passwd']) | ||||||
|  |             check_sources('../etc/passwd', []) | ||||||
|  |             check_sources('../../../etc/passwd', []) | ||||||
|  |             check_sources('/dir1/index.html', ['/dir1/index.html']) | ||||||
|  |             check_sources('../dir2/index.html', ['/dir2/index.html']) | ||||||
|  |             check_sources('/dir1blah', []) | ||||||
|  |             check_sources('../dir1blah', []) | ||||||
|  |  | ||||||
|  |     def test_unicode_template_name(self): | ||||||
|  |         with self.source_checker(['/dir1', '/dir2']) as check_sources: | ||||||
|  |             # UTF-8 bytestrings are permitted. | ||||||
|  |             check_sources(b'\xc3\x85ngstr\xc3\xb6m', ['/dir1/Ångström', '/dir2/Ångström']) | ||||||
|  |             # Unicode strings are permitted. | ||||||
|  |             check_sources('Ångström', ['/dir1/Ångström', '/dir2/Ångström']) | ||||||
|  |  | ||||||
|  |     def test_utf8_bytestring(self): | ||||||
|         """ |         """ | ||||||
|         Check that the order of template loader works. Refs #21460. |         Invalid UTF-8 encoding in bytestrings should raise a useful error | ||||||
|         """ |         """ | ||||||
|         t1 = loader.get_template('priority/foo.html') |         engine = Engine() | ||||||
|         self.assertEqual(t1.render(), 'priority\n') |         loader = engine.template_loaders[0] | ||||||
|  |         with self.assertRaises(UnicodeDecodeError): | ||||||
|  |             list(loader.get_template_sources(b'\xc3\xc3', ['/dir1'])) | ||||||
|  |  | ||||||
|  |     def test_unicode_dir_name(self): | ||||||
|  |         with self.source_checker([b'/Stra\xc3\x9fe']) as check_sources: | ||||||
|  |             check_sources('Ångström', ['/Straße/Ångström']) | ||||||
|  |             check_sources(b'\xc3\x85ngstr\xc3\xb6m', ['/Straße/Ångström']) | ||||||
|  |  | ||||||
|  |     @unittest.skipUnless( | ||||||
|  |         os.path.normcase('/TEST') == os.path.normpath('/test'), | ||||||
|  |         "This test only runs on case-sensitive file systems.", | ||||||
|  |     ) | ||||||
|  |     def test_case_sensitivity(self): | ||||||
|  |         with self.source_checker(['/dir1', '/DIR2']) as check_sources: | ||||||
|  |             check_sources('index.html', ['/dir1/index.html', '/DIR2/index.html']) | ||||||
|  |             check_sources('/DIR1/index.HTML', ['/DIR1/index.HTML']) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AppDirectoriesLoaderTest(FileSystemLoaderTests): | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         self.engine = Engine( | ||||||
|  |             loaders=['django.template.loaders.app_directories.Loader'], | ||||||
|  |         ) | ||||||
|   | |||||||
| @@ -13,7 +13,6 @@ from django.template import ( | |||||||
|     base as template_base, engines, loader, |     base as template_base, engines, loader, | ||||||
| ) | ) | ||||||
| from django.template.engine import Engine | from django.template.engine import Engine | ||||||
| from django.template.loaders import app_directories, filesystem |  | ||||||
| from django.test import RequestFactory, SimpleTestCase | from django.test import RequestFactory, SimpleTestCase | ||||||
| from django.test.utils import ( | from django.test.utils import ( | ||||||
|     extend_sys_path, ignore_warnings, override_settings, |     extend_sys_path, ignore_warnings, override_settings, | ||||||
| @@ -21,126 +20,18 @@ from django.test.utils import ( | |||||||
| from django.utils._os import upath | from django.utils._os import upath | ||||||
| from django.utils.deprecation import RemovedInDjango20Warning | from django.utils.deprecation import RemovedInDjango20Warning | ||||||
|  |  | ||||||
| TESTS_DIR = os.path.dirname(os.path.dirname(os.path.abspath(upath(__file__)))) | TEMPLATES_DIR = os.path.join(os.path.dirname(upath(__file__)), 'templates') | ||||||
|  |  | ||||||
| TEMPLATES_DIR = os.path.join(TESTS_DIR, 'templates') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TemplateLoaderTests(SimpleTestCase): | class TemplateTests(SimpleTestCase): | ||||||
|  |  | ||||||
|     def test_loaders_security(self): |  | ||||||
|         ad_loader = app_directories.Loader(Engine.get_default()) |  | ||||||
|         fs_loader = filesystem.Loader(Engine.get_default()) |  | ||||||
|  |  | ||||||
|         def test_template_sources(path, template_dirs, expected_sources): |  | ||||||
|             if isinstance(expected_sources, list): |  | ||||||
|                 # Fix expected sources so they are abspathed |  | ||||||
|                 expected_sources = [os.path.abspath(s) for s in expected_sources] |  | ||||||
|             # Test the two loaders (app_directores and filesystem). |  | ||||||
|             func1 = lambda p, t: list(ad_loader.get_template_sources(p, t)) |  | ||||||
|             func2 = lambda p, t: list(fs_loader.get_template_sources(p, t)) |  | ||||||
|             for func in (func1, func2): |  | ||||||
|                 if isinstance(expected_sources, list): |  | ||||||
|                     self.assertEqual(func(path, template_dirs), expected_sources) |  | ||||||
|                 else: |  | ||||||
|                     self.assertRaises(expected_sources, func, path, template_dirs) |  | ||||||
|  |  | ||||||
|         template_dirs = ['/dir1', '/dir2'] |  | ||||||
|         test_template_sources('index.html', template_dirs, |  | ||||||
|                               ['/dir1/index.html', '/dir2/index.html']) |  | ||||||
|         test_template_sources('/etc/passwd', template_dirs, []) |  | ||||||
|         test_template_sources('etc/passwd', template_dirs, |  | ||||||
|                               ['/dir1/etc/passwd', '/dir2/etc/passwd']) |  | ||||||
|         test_template_sources('../etc/passwd', template_dirs, []) |  | ||||||
|         test_template_sources('../../../etc/passwd', template_dirs, []) |  | ||||||
|         test_template_sources('/dir1/index.html', template_dirs, |  | ||||||
|                               ['/dir1/index.html']) |  | ||||||
|         test_template_sources('../dir2/index.html', template_dirs, |  | ||||||
|                               ['/dir2/index.html']) |  | ||||||
|         test_template_sources('/dir1blah', template_dirs, []) |  | ||||||
|         test_template_sources('../dir1blah', template_dirs, []) |  | ||||||
|  |  | ||||||
|         # UTF-8 bytestrings are permitted. |  | ||||||
|         test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', template_dirs, |  | ||||||
|                               ['/dir1/Ångström', '/dir2/Ångström']) |  | ||||||
|         # Unicode strings are permitted. |  | ||||||
|         test_template_sources('Ångström', template_dirs, |  | ||||||
|                               ['/dir1/Ångström', '/dir2/Ångström']) |  | ||||||
|         test_template_sources('Ångström', [b'/Stra\xc3\x9fe'], ['/Straße/Ångström']) |  | ||||||
|         test_template_sources(b'\xc3\x85ngstr\xc3\xb6m', [b'/Stra\xc3\x9fe'], |  | ||||||
|                               ['/Straße/Ångström']) |  | ||||||
|         # Invalid UTF-8 encoding in bytestrings is not. Should raise a |  | ||||||
|         # semi-useful error message. |  | ||||||
|         test_template_sources(b'\xc3\xc3', template_dirs, UnicodeDecodeError) |  | ||||||
|  |  | ||||||
|         # Case insensitive tests (for win32). Not run unless we're on |  | ||||||
|         # a case insensitive operating system. |  | ||||||
|         if os.path.normcase('/TEST') == os.path.normpath('/test'): |  | ||||||
|             template_dirs = ['/dir1', '/DIR2'] |  | ||||||
|             test_template_sources('index.html', template_dirs, |  | ||||||
|                                   ['/dir1/index.html', '/DIR2/index.html']) |  | ||||||
|             test_template_sources('/DIR1/index.HTML', template_dirs, |  | ||||||
|                                   ['/DIR1/index.HTML']) |  | ||||||
|  |  | ||||||
|     @override_settings(TEMPLATES=[{ |  | ||||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|         'DIRS': [TEMPLATES_DIR], |  | ||||||
|         'OPTIONS': { |  | ||||||
|             # Turn DEBUG on, so that the origin file name will be kept with |  | ||||||
|             # the compiled templates. |  | ||||||
|             'debug': True, |  | ||||||
|         } |  | ||||||
|     }]) |  | ||||||
|     def test_loader_debug_origin(self): |  | ||||||
|         load_name = 'login.html' |  | ||||||
|  |  | ||||||
|         # We rely on the fact the file system and app directories loaders both |  | ||||||
|         # inherit the load_template method from the base Loader class, so we |  | ||||||
|         # only need to test one of them. |  | ||||||
|         template = loader.get_template(load_name).template |  | ||||||
|         template_name = template.nodelist[0].source[0].name |  | ||||||
|         self.assertTrue(template_name.endswith(load_name), |  | ||||||
|             'Template loaded by filesystem loader has incorrect name for debug page: %s' % template_name) |  | ||||||
|  |  | ||||||
|     @override_settings(TEMPLATES=[{ |  | ||||||
|         'BACKEND': 'django.template.backends.django.DjangoTemplates', |  | ||||||
|         'DIRS': [TEMPLATES_DIR], |  | ||||||
|         'OPTIONS': { |  | ||||||
|             'debug': True, |  | ||||||
|             'loaders': [ |  | ||||||
|                 ('django.template.loaders.cached.Loader', [ |  | ||||||
|                     'django.template.loaders.filesystem.Loader', |  | ||||||
|                 ]), |  | ||||||
|             ], |  | ||||||
|         }, |  | ||||||
|     }]) |  | ||||||
|     def test_cached_loader_debug_origin(self): |  | ||||||
|         load_name = 'login.html' |  | ||||||
|  |  | ||||||
|         # Test the cached loader separately since it overrides load_template. |  | ||||||
|         template = loader.get_template(load_name).template |  | ||||||
|         template_name = template.nodelist[0].source[0].name |  | ||||||
|         self.assertTrue(template_name.endswith(load_name), |  | ||||||
|             'Template loaded through cached loader has incorrect name for debug page: %s' % template_name) |  | ||||||
|  |  | ||||||
|         template = loader.get_template(load_name).template |  | ||||||
|         template_name = template.nodelist[0].source[0].name |  | ||||||
|         self.assertTrue(template_name.endswith(load_name), |  | ||||||
|             'Cached template loaded through cached loader has incorrect name for debug page: %s' % template_name) |  | ||||||
|  |  | ||||||
|     @override_settings(DEBUG=True) |  | ||||||
|     def test_loader_origin(self): |  | ||||||
|         template = loader.get_template('login.html') |  | ||||||
|         self.assertEqual(template.origin.loadname, 'login.html') |  | ||||||
|  |  | ||||||
|     @override_settings(DEBUG=True) |     @override_settings(DEBUG=True) | ||||||
|     def test_string_origin(self): |     def test_string_origin(self): | ||||||
|         template = Template('string template') |         template = Template('string template') | ||||||
|         self.assertEqual(template.origin.source, 'string template') |         self.assertEqual(template.origin.source, 'string template') | ||||||
|  |  | ||||||
|     def test_debug_false_origin(self): |  | ||||||
|         template = loader.get_template('login.html') | class IncludeTests(SimpleTestCase): | ||||||
|         self.assertEqual(template.origin, None) |  | ||||||
|  |  | ||||||
|     # Test the base loader class via the app loader. load_template |     # Test the base loader class via the app loader. load_template | ||||||
|     # from base is used by all shipped loaders excepting cached, |     # from base is used by all shipped loaders excepting cached, | ||||||
|   | |||||||
| @@ -15,6 +15,7 @@ from django.utils.encoding import python_2_unicode_compatible | |||||||
| from django.utils.safestring import mark_safe | from django.utils.safestring import mark_safe | ||||||
|  |  | ||||||
| ROOT = os.path.dirname(os.path.abspath(upath(__file__))) | ROOT = os.path.dirname(os.path.abspath(upath(__file__))) | ||||||
|  | TEMPLATE_DIR = os.path.join(ROOT, 'templates') | ||||||
|  |  | ||||||
|  |  | ||||||
| def setup(templates, *args, **kwargs): | def setup(templates, *args, **kwargs): | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user