From 698410ab6fd480c4ea08a7adfb4694404ef9ba15 Mon Sep 17 00:00:00 2001
From: Karen Tracey <kmtracey@gmail.com>
Date: Mon, 1 Mar 2010 23:05:35 +0000
Subject: [PATCH] Fixed #12992: Adjusted the new template loader code so that
 the template file name is correctly reported on the debug page when a
 template syntax error is raised.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12643 bcc190cf-cafb-0310-a4f2-bffc1f526a37
---
 django/template/__init__.py              |  2 +-
 django/template/loader.py                | 14 ++++++---
 django/template/loaders/cached.py        |  4 +--
 tests/regressiontests/templates/tests.py | 37 ++++++++++++++++++++++++
 4 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/django/template/__init__.py b/django/template/__init__.py
index a07cb7310e..7fb01f05b6 100644
--- a/django/template/__init__.py
+++ b/django/template/__init__.py
@@ -87,7 +87,7 @@ ALLOWED_VARIABLE_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01
 
 # what to report as the origin for templates that come from non-loader sources
 # (e.g. strings)
-UNKNOWN_SOURCE="&lt;unknown source&gt;"
+UNKNOWN_SOURCE = '<unknown source>'
 
 # match a variable or block tag and capture the entire tag, including start/end delimiters
 tag_re = re.compile('(%s.*?%s|%s.*?%s|%s.*?%s)' % (re.escape(BLOCK_TAG_START), re.escape(BLOCK_TAG_END),
diff --git a/django/template/loader.py b/django/template/loader.py
index 031df6c0e1..d81c896ad4 100644
--- a/django/template/loader.py
+++ b/django/template/loader.py
@@ -12,6 +12,11 @@
 # might be shown to the user for debugging purposes, so it should identify where
 # the template was loaded from.
 #
+# A loader may return an already-compiled template instead of the actual
+# template source. In that case the path returned should be None, since the
+# path information is associated with the template during the compilation,
+# which has already been done.
+#
 # Each loader should have an "is_usable" attribute set. This is a boolean that
 # specifies whether the loader can be used in this Python installation. Each
 # loader is responsible for setting this when it's initialized.
@@ -37,9 +42,10 @@ class BaseLoader(object):
         return self.load_template(template_name, template_dirs)
 
     def load_template(self, template_name, template_dirs=None):
-        source, origin = self.load_template_source(template_name, template_dirs)
-        template = get_template_from_string(source, name=template_name)
-        return template, origin
+        source, display_name = self.load_template_source(template_name, template_dirs)
+        origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
+        template = get_template_from_string(source, origin, template_name)
+        return template, None
 
     def load_template_source(self, template_name, template_dirs=None):
         """
@@ -66,7 +72,7 @@ class LoaderOrigin(Origin):
         return self.loader(self.loadname, self.dirs)[0]
 
 def make_origin(display_name, loader, name, dirs):
-    if settings.TEMPLATE_DEBUG:
+    if settings.TEMPLATE_DEBUG and display_name:
         return LoaderOrigin(display_name, loader, name, dirs)
     else:
         return None
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index 796d45ad2b..6209d766c0 100644
--- a/django/template/loaders/cached.py
+++ b/django/template/loaders/cached.py
@@ -38,8 +38,8 @@ class Loader(BaseLoader):
             template, origin = self.find_template(template_name, template_dirs)
             if not hasattr(template, 'render'):
                 template = get_template_from_string(template, origin, template_name)
-            self.template_cache[template_name] = (template, origin)
-        return self.template_cache[template_name]
+            self.template_cache[template_name] = template
+        return self.template_cache[template_name], None
 
     def reset(self):
         "Empty the template cache."
diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py
index 307feccac0..31c9e249a9 100644
--- a/tests/regressiontests/templates/tests.py
+++ b/tests/regressiontests/templates/tests.py
@@ -155,6 +155,43 @@ class Templates(unittest.TestCase):
             test_template_sources('/DIR1/index.HTML', template_dirs,
                                   ['/dir1/index.html'])
 
+    def test_loader_debug_origin(self):
+        # Turn TEMPLATE_DEBUG on, so that the origin file name will be kept with
+        # the compiled templates.
+        old_td, settings.TEMPLATE_DEBUG = settings.TEMPLATE_DEBUG, True
+
+        old_loaders = loader.template_source_loaders
+        loader.template_source_loaders = (filesystem.Loader(),)
+
+        # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
+        # point to a directory containing a 404.html file. Also that
+        # the file system and app directories loaders both inherit the
+        # load_template method from the BaseLoader class, so we only need
+        # to test one of them.
+        load_name = '404.html'
+        template = loader.get_template(load_name)
+        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)
+
+        # Aso test the cached loader, since it overrides load_template
+        cache_loader = cached.Loader(('',))
+        cache_loader._cached_loaders = loader.template_source_loaders
+        loader.template_source_loaders = (cache_loader,)
+
+        template = loader.get_template(load_name)
+        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_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)
+
+        loader.template_source_loaders = old_loaders
+        settings.TEMPLATE_DEBUG = old_td
+
     def test_token_smart_split(self):
         # Regression test for #7027
         token = template.Token(template.TOKEN_BLOCK, 'sometag _("Page not found") value|yesno:_("yes,no")')