Ticket #6262: cache_templates.4.diff
File cache_templates.4.diff, 32.4 KB (added by , 15 years ago) |
---|
-
django/test/utils.py
54 54 - Diverting the email sending functions to a test buffer 55 55 - Setting the active locale to match the LANGUAGE_CODE setting. 56 56 """ 57 Template.original_render = Template. render58 Template. render = instrumented_test_render57 Template.original_render = Template._render 58 Template._render = instrumented_test_render 59 59 60 60 mail.original_SMTPConnection = mail.SMTPConnection 61 61 mail.SMTPConnection = TestSMTPConnection … … 71 71 - Restoring the email sending functions 72 72 73 73 """ 74 Template. render = Template.original_render74 Template._render = Template.original_render 75 75 del Template.original_render 76 76 77 77 mail.SMTPConnection = mail.original_SMTPConnection -
django/template/__init__.py
173 173 for subnode in node: 174 174 yield subnode 175 175 176 def render(self, context): 177 "Display stage -- can be called many times" 176 def _render(self, context): 178 177 return self.nodelist.render(context) 179 178 179 def render(self, context, push_parser_context=True): 180 "Display stage -- can be called many times" 181 context.parser_context.push() 182 try: 183 return self._render(context) 184 finally: 185 context.parser_context.pop() 186 180 187 def compile_string(template_string, origin): 181 188 "Compiles template_string into NodeList ready for rendering" 182 189 if settings.TEMPLATE_DEBUG: -
django/template/loaders/app_directories.py
9 9 from django.conf import settings 10 10 from django.core.exceptions import ImproperlyConfigured 11 11 from django.template import TemplateDoesNotExist 12 from django.template.loader import BaseLoader 12 13 from django.utils._os import safe_join 13 14 from django.utils.importlib import import_module 14 15 … … 27 28 # It won't change, so convert it to a tuple to save memory. 28 29 app_template_dirs = tuple(app_template_dirs) 29 30 30 def get_template_sources(template_name, template_dirs=None): 31 """ 32 Returns the absolute paths to "template_name", when appended to each 33 directory in "template_dirs". Any paths that don't lie inside one of the 34 template dirs are excluded from the result set, for security reasons. 35 """ 36 if not template_dirs: 37 template_dirs = app_template_dirs 38 for template_dir in template_dirs: 39 try: 40 yield safe_join(template_dir, template_name) 41 except UnicodeDecodeError: 42 # The template dir name was a bytestring that wasn't valid UTF-8. 43 raise 44 except ValueError: 45 # The joined path was located outside of template_dir. 46 pass 31 class Loader(BaseLoader): 32 is_usable = True 47 33 34 def get_template_sources(self, template_name, template_dirs=None): 35 """ 36 Returns the absolute paths to "template_name", when appended to each 37 directory in "template_dirs". Any paths that don't lie inside one of the 38 template dirs are excluded from the result set, for security reasons. 39 """ 40 if not template_dirs: 41 template_dirs = app_template_dirs 42 for template_dir in template_dirs: 43 try: 44 yield safe_join(template_dir, template_name) 45 except UnicodeDecodeError: 46 # The template dir name was a bytestring that wasn't valid UTF-8. 47 raise 48 except ValueError: 49 # The joined path was located outside of template_dir. 50 pass 51 52 def load_template_source(self, template_name, template_dirs=None): 53 for filepath in self.get_template_sources(template_name, template_dirs): 54 try: 55 return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) 56 except IOError: 57 pass 58 raise TemplateDoesNotExist, template_name 59 60 loader = Loader() 61 48 62 def load_template_source(template_name, template_dirs=None): 49 for filepath in get_template_sources(template_name, template_dirs): 50 try: 51 return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) 52 except IOError: 53 pass 54 raise TemplateDoesNotExist, template_name 63 # For backwards compatibility 64 return loader.load_template_source(template_name, template_dirs) 55 65 load_template_source.is_usable = True -
django/template/loaders/filesystem.py
4 4 5 5 from django.conf import settings 6 6 from django.template import TemplateDoesNotExist 7 from django.template.loader import BaseLoader 7 8 from django.utils._os import safe_join 8 9 9 def get_template_sources(template_name, template_dirs=None): 10 """ 11 Returns the absolute paths to "template_name", when appended to each 12 directory in "template_dirs". Any paths that don't lie inside one of the 13 template dirs are excluded from the result set, for security reasons. 14 """ 15 if not template_dirs: 16 template_dirs = settings.TEMPLATE_DIRS 17 for template_dir in template_dirs: 18 try: 19 yield safe_join(template_dir, template_name) 20 except UnicodeDecodeError: 21 # The template dir name was a bytestring that wasn't valid UTF-8. 22 raise 23 except ValueError: 24 # The joined path was located outside of this particular 25 # template_dir (it might be inside another one, so this isn't 26 # fatal). 27 pass 10 class Loader(BaseLoader): 11 is_usable = True 28 12 13 def get_template_sources(self, template_name, template_dirs=None): 14 """ 15 Returns the absolute paths to "template_name", when appended to each 16 directory in "template_dirs". Any paths that don't lie inside one of the 17 template dirs are excluded from the result set, for security reasons. 18 """ 19 if not template_dirs: 20 template_dirs = settings.TEMPLATE_DIRS 21 for template_dir in template_dirs: 22 try: 23 yield safe_join(template_dir, template_name) 24 except UnicodeDecodeError: 25 # The template dir name was a bytestring that wasn't valid UTF-8. 26 raise 27 except ValueError: 28 # The joined path was located outside of this particular 29 # template_dir (it might be inside another one, so this isn't 30 # fatal). 31 pass 32 33 def load_template_source(self, template_name, template_dirs=None): 34 tried = [] 35 for filepath in self.get_template_sources(template_name, template_dirs): 36 try: 37 return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) 38 except IOError: 39 tried.append(filepath) 40 if tried: 41 error_msg = "Tried %s" % tried 42 else: 43 error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory." 44 raise TemplateDoesNotExist, error_msg 45 load_template_source.is_usable = True 46 47 loader = Loader() 48 29 49 def load_template_source(template_name, template_dirs=None): 30 tried = [] 31 for filepath in get_template_sources(template_name, template_dirs): 32 try: 33 return (open(filepath).read().decode(settings.FILE_CHARSET), filepath) 34 except IOError: 35 tried.append(filepath) 36 if tried: 37 error_msg = "Tried %s" % tried 38 else: 39 error_msg = "Your TEMPLATE_DIRS setting is empty. Change it to point to at least one template directory." 40 raise TemplateDoesNotExist, error_msg 50 # For backwards compatibility 51 return loader.load_template_source(template_name, template_dirs) 41 52 load_template_source.is_usable = True -
django/template/loaders/eggs.py
6 6 resource_string = None 7 7 8 8 from django.template import TemplateDoesNotExist 9 from django.template.loader import BaseLoader 9 10 from django.conf import settings 10 11 12 class Loader(BaseLoader): 13 is_usable = resource_string is not None 14 15 def load_template_source(self, template_name, template_dirs=None): 16 """ 17 Loads templates from Python eggs via pkg_resource.resource_string. 18 19 For every installed app, it tries to get the resource (app, template_name). 20 """ 21 if resource_string is not None: 22 pkg_name = 'templates/' + template_name 23 for app in settings.INSTALLED_APPS: 24 try: 25 return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name)) 26 except: 27 pass 28 raise TemplateDoesNotExist, template_name 29 30 loader = Loader() 31 11 32 def load_template_source(template_name, template_dirs=None): 12 """ 13 Loads templates from Python eggs via pkg_resource.resource_string. 14 15 For every installed app, it tries to get the resource (app, template_name). 16 """ 17 if resource_string is not None: 18 pkg_name = 'templates/' + template_name 19 for app in settings.INSTALLED_APPS: 20 try: 21 return (resource_string(app, pkg_name).decode(settings.FILE_CHARSET), 'egg:%s:%s' % (app, pkg_name)) 22 except: 23 pass 24 raise TemplateDoesNotExist, template_name 33 return loader.load_template_source(template_name, template_dirs) 25 34 load_template_source.is_usable = resource_string is not None -
django/template/loaders/cached.py
1 """ 2 Wrapper class that takes a list of template loaders as an argument and attempts 3 to load templates from them in order, caching the result. 4 """ 5 6 from django.template import TemplateDoesNotExist 7 from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin 8 from django.utils.importlib import import_module 9 from django.core.exceptions import ImproperlyConfigured 10 11 class Loader(BaseLoader): 12 is_usable = True 13 template_cache = {} 14 15 def __init__(self, loaders): 16 self._loaders = loaders 17 self._cached_loaders = [] 18 19 @property 20 def loaders(self): 21 # Resolve loaders on demand to avoid circular imports 22 if not self._cached_loaders: 23 for loader in self._loaders: 24 self._cached_loaders.append(find_template_loader(loader)) 25 return self._cached_loaders 26 27 def find_template(self, name, dirs=None): 28 for loader in self.loaders: 29 try: 30 template, display_name = loader(name, dirs) 31 return (template, make_origin(display_name, loader, name, dirs)) 32 except TemplateDoesNotExist: 33 pass 34 raise TemplateDoesNotExist, name 35 36 def load_template(self, template_name, template_dirs=None): 37 if template_name not in self.template_cache: 38 template, origin = self.find_template(template_name, template_dirs) 39 if not hasattr(template, 'render'): 40 template = get_template_from_string(template, origin, template_name) 41 self.template_cache[template_name] = (template, origin) 42 return self.template_cache[template_name] 43 44 def reset(self): 45 "Empty the template cache." 46 self.template_cache = {} -
django/template/defaulttags.py
39 39 40 40 class CycleNode(Node): 41 41 def __init__(self, cyclevars, variable_name=None): 42 self.cycle _iter = itertools_cycle(cyclevars)42 self.cyclevars = cyclevars 43 43 self.variable_name = variable_name 44 44 45 45 def render(self, context): 46 value = self.cycle_iter.next().resolve(context) 46 if self not in context.parser_context: 47 context.parser_context[self] = {'cycle_iter': itertools_cycle(self.cyclevars)} 48 cycle_iter = context.parser_context[self]['cycle_iter'] 49 value = cycle_iter.next().resolve(context) 47 50 if self.variable_name: 48 51 context[self.variable_name] = value 49 52 return value -
django/template/context.py
7 7 "pop() has been called more times than push()" 8 8 pass 9 9 10 class Context(object): 11 "A stack container for variable context" 12 def __init__(self, dict_=None, autoescape=True, current_app=None): 10 class BaseContext(object): 11 def __init__(self, dict_=None): 13 12 dict_ = dict_ or {} 14 13 self.dicts = [dict_] 15 self.autoescape = autoescape16 self.current_app = current_app17 14 18 15 def __repr__(self): 19 16 return repr(self.dicts) 20 17 21 18 def __iter__(self): 22 for d in self.dicts:19 for d in reversed(self.dicts): 23 20 yield d 24 21 25 22 def push(self): 26 23 d = {} 27 self.dicts = [d] + self.dicts24 self.dicts.append(d) 28 25 return d 29 26 30 27 def pop(self): 31 28 if len(self.dicts) == 1: 32 29 raise ContextPopException 33 return self.dicts.pop( 0)30 return self.dicts.pop() 34 31 35 32 def __setitem__(self, key, value): 36 33 "Set a variable in the current context" 37 self.dicts[ 0][key] = value34 self.dicts[-1][key] = value 38 35 39 36 def __getitem__(self, key): 40 37 "Get a variable's value, starting at the current context and going upward" 41 for d in self.dicts:38 for d in reversed(self.dicts): 42 39 if key in d: 43 40 return d[key] 44 41 raise KeyError(key) 45 42 46 43 def __delitem__(self, key): 47 44 "Delete a variable from the current context" 48 del self.dicts[ 0][key]45 del self.dicts[-1][key] 49 46 50 47 def has_key(self, key): 51 48 for d in self.dicts: … … 53 50 return True 54 51 return False 55 52 56 __contains__ = has_key 53 def __contains__(self, key): 54 return self.has_key(key) 57 55 58 56 def get(self, key, otherwise=None): 59 57 for d in self.dicts: … … 61 59 return d[key] 62 60 return otherwise 63 61 62 63 class Context(BaseContext): 64 "A stack container for variable context" 65 def __init__(self, dict_=None, autoescape=True, current_app=None): 66 self.autoescape = autoescape 67 self.current_app = current_app 68 self.parser_context = ParserContext() 69 super(Context, self).__init__(dict_) 70 64 71 def update(self, other_dict): 65 72 "Like dict.update(). Pushes an entire dictionary's keys and values onto the context." 66 73 if not hasattr(other_dict, '__getitem__'): 67 74 raise TypeError('other_dict must be a mapping (dictionary-like) object.') 68 self.dicts = [other_dict] + self.dicts75 self.dicts.append(other_dict) 69 76 return other_dict 70 77 78 class ParserContext(BaseContext): 79 """A stack container for storing Template state.""" 80 def __iter__(self): 81 for d in self.dicts[-1]: 82 yield d 83 84 def has_key(self, key): 85 return key in self.dicts[-1] 86 87 def get(self, key, otherwise=None): 88 d = self.dicts[-1] 89 if key in d: 90 return d[key] 91 return otherwise 92 71 93 # This is a function rather than module-level procedural code because we only 72 94 # want it to execute if somebody uses RequestContext. 73 95 def get_standard_processors(): -
django/template/loader_tags.py
1 1 from django.template import TemplateSyntaxError, TemplateDoesNotExist, Variable 2 2 from django.template import Library, Node, TextNode 3 from django.template.loader import get_template , get_template_from_string, find_template_source3 from django.template.loader import get_template 4 4 from django.conf import settings 5 5 from django.utils.safestring import mark_safe 6 6 7 7 register = Library() 8 8 9 BLOCK_CONTEXT_KEY = 'block_context' 10 9 11 class ExtendsError(Exception): 10 12 pass 11 13 14 class BlockContext(object): 15 def __init__(self): 16 # Dictionary of FIFO queues. 17 self.blocks = {} 18 19 def add_blocks(self, blocks): 20 for name, block in blocks.iteritems(): 21 if name in self.blocks: 22 self.blocks[name].insert(0, block) 23 else: 24 self.blocks[name] = [block] 25 26 def pop(self, name): 27 try: 28 return self.blocks[name].pop() 29 except (IndexError, KeyError): 30 return None 31 32 def push(self, name, block): 33 self.blocks[name].append(block) 34 35 def get_block(self, name): 36 try: 37 return self.blocks[name][-1] 38 except (IndexError, KeyError): 39 return None 40 12 41 class BlockNode(Node): 13 42 def __init__(self, name, nodelist, parent=None): 14 43 self.name, self.nodelist, self.parent = name, nodelist, parent … … 17 46 return "<Block Node: %s. Contents: %r>" % (self.name, self.nodelist) 18 47 19 48 def render(self, context): 49 block_context = context.parser_context.get(BLOCK_CONTEXT_KEY, None) 20 50 context.push() 21 # Save context in case of block.super(). 22 self.context = context 23 context['block'] = self 24 result = self.nodelist.render(context) 51 if block_context is None: 52 context['block'] = self 53 result = self.nodelist.render(context) 54 else: 55 push = block = block_context.pop(self.name) 56 if block is None: 57 block = self 58 # Create new block so we can store context without thread-safety issues. 59 block = BlockNode(block.name, block.nodelist) 60 block.context = context 61 context['block'] = block 62 result = block.nodelist.render(context) 63 if push is not None: 64 block_context.push(self.name, push) 25 65 context.pop() 26 66 return result 27 67 28 68 def super(self): 29 if self.parent: 30 return mark_safe(self.parent.render(self.context)) 69 parser_context = self.context.parser_context 70 if (BLOCK_CONTEXT_KEY in parser_context and 71 parser_context[BLOCK_CONTEXT_KEY].get_block(self.name) is not None): 72 return mark_safe(self.render(self.context)) 31 73 return '' 32 74 33 def add_parent(self, nodelist):34 if self.parent:35 self.parent.add_parent(nodelist)36 else:37 self.parent = BlockNode(self.name, nodelist)38 39 75 class ExtendsNode(Node): 40 76 must_be_first = True 41 77 … … 43 79 self.nodelist = nodelist 44 80 self.parent_name, self.parent_name_expr = parent_name, parent_name_expr 45 81 self.template_dirs = template_dirs 46 82 self.blocks = dict([(n.name, n) for n in nodelist.get_nodes_by_type(BlockNode)]) 83 47 84 def __repr__(self): 48 85 if self.parent_name_expr: 49 86 return "<ExtendsNode: extends %s>" % self.parent_name_expr.token … … 61 98 if hasattr(parent, 'render'): 62 99 return parent # parent is a Template object 63 100 try: 64 source, origin = find_template_source(parent, self.template_dirs)101 return get_template(parent) 65 102 except TemplateDoesNotExist: 66 103 raise TemplateSyntaxError, "Template %r cannot be extended, because it doesn't exist" % parent 67 else:68 return get_template_from_string(source, origin, parent)69 104 70 105 def render(self, context): 71 106 compiled_parent = self.get_parent(context) 72 parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)])73 for block_node in self.nodelist.get_nodes_by_type(BlockNode):74 # Check for a BlockNode with this node's name, and replace it if found.75 try:76 parent_block = parent_blocks[block_node.name]77 except KeyError:78 # This BlockNode wasn't found in the parent template, but the79 # parent block might be defined in the parent's *parent*, so we80 # add this BlockNode to the parent's ExtendsNode nodelist, so81 # it'll be checked when the parent node's render() is called.82 107 83 # Find out if the parent template has a parent itself 84 for node in compiled_parent.nodelist: 85 if not isinstance(node, TextNode): 86 # If the first non-text node is an extends, handle it. 87 if isinstance(node, ExtendsNode): 88 node.nodelist.append(block_node) 89 # Extends must be the first non-text node, so once you find 90 # the first non-text node you can stop looking. 91 break 92 else: 93 # Keep any existing parents and add a new one. Used by BlockNode. 94 parent_block.parent = block_node.parent 95 parent_block.add_parent(parent_block.nodelist) 96 parent_block.nodelist = block_node.nodelist 97 return compiled_parent.render(context) 108 if BLOCK_CONTEXT_KEY not in context.parser_context: 109 context.parser_context[BLOCK_CONTEXT_KEY] = BlockContext() 110 block_context = context.parser_context[BLOCK_CONTEXT_KEY] 98 111 112 # Add the block nodes from this node to the block context 113 block_context.add_blocks(self.blocks) 114 115 # If this block's parent doesn't have an extends node it is the root, 116 # and its block nodes also need to be added to the block context. 117 for node in compiled_parent.nodelist: 118 # The ExtendsNode has to be the first non-text node. 119 if not isinstance(node, TextNode): 120 if not isinstance(node, ExtendsNode): 121 blocks = dict([(n.name, n) for n in 122 compiled_parent.nodelist.get_nodes_by_type(BlockNode)]) 123 block_context.add_blocks(blocks) 124 break 125 126 # Call Template._render explicitly so the parser context stays 127 # the same. 128 return compiled_parent._render(context) 129 99 130 class ConstantIncludeNode(Node): 100 131 def __init__(self, template_path): 101 132 try: -
django/template/loader.py
27 27 28 28 template_source_loaders = None 29 29 30 class BaseLoader(object): 31 is_usable = False 32 33 def __call__(self, template_name, template_dirs=None): 34 return self.load_template(template_name, template_dirs) 35 36 def load_template(self, template_name, template_dirs=None): 37 source, origin = self.load_template_source(template_name, template_dirs) 38 template = get_template_from_string(source, name=template_name) 39 return template, origin 40 41 def load_template_source(self, template_name, template_dirs=None): 42 """ 43 Returns a tuple containing the source and origin for the given template 44 name. 45 46 """ 47 raise NotImplementedError 48 49 def reset(self): 50 """ 51 Resets any state maintained by the loader instance (e.g., cached 52 templates or cached loader modules). 53 54 """ 55 pass 56 30 57 class LoaderOrigin(Origin): 31 58 def __init__(self, display_name, loader, name, dirs): 32 59 super(LoaderOrigin, self).__init__(display_name) … … 41 68 else: 42 69 return None 43 70 44 def find_template_source(name, dirs=None): 71 def find_template_loader(loader): 72 if callable(loader): 73 return loader 74 elif isinstance(loader, basestring): 75 i = loader.rfind('.') 76 module, attr = loader[:i], loader[i+1:] 77 try: 78 mod = import_module(module) 79 except ImportError, e: 80 raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e) 81 try: 82 func = getattr(mod, attr) 83 except AttributeError: 84 raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr) 85 if not func.is_usable: 86 import warnings 87 warnings.warn("Your TEMPLATE_LOADERS setting includes %r, but your Python installation doesn't support that type of template loading. Consider removing that line from TEMPLATE_LOADERS." % loader) 88 else: 89 return func 90 else: 91 raise ImproperlyConfigured, 'Loader does not define a "load_template" callable template source loader' 92 93 def find_template(name, dirs=None): 45 94 # Calculate template_source_loaders the first time the function is executed 46 95 # because putting this logic in the module-level namespace may cause 47 96 # circular import errors. See Django ticket #1292. 48 97 global template_source_loaders 49 98 if template_source_loaders is None: 50 99 loaders = [] 51 for path in settings.TEMPLATE_LOADERS: 52 i = path.rfind('.') 53 module, attr = path[:i], path[i+1:] 54 try: 55 mod = import_module(module) 56 except ImportError, e: 57 raise ImproperlyConfigured, 'Error importing template source loader %s: "%s"' % (module, e) 58 try: 59 func = getattr(mod, attr) 60 except AttributeError: 61 raise ImproperlyConfigured, 'Module "%s" does not define a "%s" callable template source loader' % (module, attr) 62 if not func.is_usable: 63 import warnings 64 warnings.warn("Your TEMPLATE_LOADERS setting includes %r, but your Python installation doesn't support that type of template loading. Consider removing that line from TEMPLATE_LOADERS." % path) 65 else: 66 loaders.append(func) 100 for loader in settings.TEMPLATE_LOADERS: 101 loaders.append(find_template_loader(loader)) 67 102 template_source_loaders = tuple(loaders) 68 103 for loader in template_source_loaders: 69 104 try: … … 78 113 Returns a compiled Template object for the given template name, 79 114 handling template inheritance recursively. 80 115 """ 81 source, origin = find_template_source(template_name) 82 template = get_template_from_string(source, origin, template_name) 116 template, origin = find_template(template_name) 117 if not hasattr(template, 'render'): 118 # template needs to be compiled 119 template = get_template_from_string(template, origin, template_name) 83 120 return template 84 121 85 122 def get_template_from_string(source, origin=None, name=None): -
tests/regressiontests/test_client_regress/models.py
10 10 from django.core.urlresolvers import reverse 11 11 from django.core.exceptions import SuspiciousOperation 12 12 from django.template import TemplateDoesNotExist, TemplateSyntaxError, Context 13 from django.template.loader import find_template_loader 13 14 14 15 class AssertContainsTests(TestCase): 15 16 def setUp(self): … … 436 437 437 438 class TemplateExceptionTests(TestCase): 438 439 def setUp(self): 440 # Reset the loaders so they don't try to render cached templates. 441 for loader in settings.TEMPLATE_LOADERS: 442 loader = find_template_loader(loader) 443 if hasattr(loader, 'reset'): 444 loader.reset() 439 445 self.old_templates = settings.TEMPLATE_DIRS 440 446 settings.TEMPLATE_DIRS = () 441 447 -
tests/regressiontests/templates/tests.py
105 105 # Fix expected sources so they are normcased and abspathed 106 106 expected_sources = [os.path.normcase(os.path.abspath(s)) for s in expected_sources] 107 107 # Test the two loaders (app_directores and filesystem). 108 func1 = lambda p, t: list(app_directories. get_template_sources(p, t))109 func2 = lambda p, t: list(filesystem. get_template_sources(p, t))108 func1 = lambda p, t: list(app_directories.loader.get_template_sources(p, t)) 109 func2 = lambda p, t: list(filesystem.loader.get_template_sources(p, t)) 110 110 for func in (func1, func2): 111 111 if isinstance(expected_sources, list): 112 112 self.assertEqual(func(path, template_dirs), expected_sources) … … 197 197 except KeyError: 198 198 raise template.TemplateDoesNotExist, template_name 199 199 200 from django.template.loaders.cached import Loader 201 cache_loader = Loader((test_template_loader,)) 202 200 203 old_template_loaders = loader.template_source_loaders 201 loader.template_source_loaders = [ test_template_loader]204 loader.template_source_loaders = [cache_loader] 202 205 203 206 failures = [] 204 207 tests = template_tests.items() … … 231 234 for invalid_str, result in [('', normal_string_result), 232 235 (expected_invalid_str, invalid_string_result)]: 233 236 settings.TEMPLATE_STRING_IF_INVALID = invalid_str 234 try: 235 test_template = loader.get_template(name) 236 output = self.render(test_template, vals) 237 except ContextStackException: 238 failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (invalid_str, name)) 239 continue 240 except Exception: 241 exc_type, exc_value, exc_tb = sys.exc_info() 242 if exc_type != result: 243 tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb)) 244 failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (invalid_str, name, exc_type, exc_value, tb)) 245 continue 246 if output != result: 247 failures.append("Template test (TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (invalid_str, name, result, output)) 237 for cached in (False, True): 238 try: 239 test_template = loader.get_template(name) 240 output = self.render(test_template, vals) 241 except ContextStackException: 242 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Context stack was left imbalanced" % (cached, invalid_str, name)) 243 continue 244 except Exception: 245 exc_type, exc_value, exc_tb = sys.exc_info() 246 if exc_type != result: 247 tb = '\n'.join(traceback.format_exception(exc_type, exc_value, exc_tb)) 248 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Got %s, exception: %s\n%s" % (cached, invalid_str, name, exc_type, exc_value, tb)) 249 continue 250 if output != result: 251 failures.append("Template test (Cached='%s', TEMPLATE_STRING_IF_INVALID='%s'): %s -- FAILED. Expected %r, got %r" % (cached, invalid_str, name, result, output)) 252 cache_loader.reset() 248 253 249 254 if 'LANGUAGE_CODE' in vals[1]: 250 255 deactivate()