Selaa lähdekoodia

Moved all template loaders under django.template.loaders.

Reformatted the code of base.Loader according to modern standards.

Turned the test template loader into a regular locmem.Loader -- but
didn't document it.

Added a normal deprecation path for BaseLoader which is a public API.

Added an accelerated deprecation path for TestTemplateLoader which is
a private API.
Aymeric Augustin 10 vuotta sitten
vanhempi
commit
2577ae6a08

+ 17 - 39
django/template/loader.py

@@ -25,54 +25,18 @@
 # Python eggs) sets is_usable to False if the "pkg_resources" module isn't
 # installed, because pkg_resources is necessary to read eggs.
 
+import warnings
+
 from django.core.exceptions import ImproperlyConfigured
 from django.template.base import Origin, Template, Context, TemplateDoesNotExist
 from django.conf import settings
+from django.utils.deprecation import RemovedInDjango20Warning
 from django.utils.module_loading import import_string
 from django.utils import six
 
 template_source_loaders = None
 
 
-class BaseLoader(object):
-    is_usable = False
-
-    def __init__(self, *args, **kwargs):
-        pass
-
-    def __call__(self, template_name, template_dirs=None):
-        return self.load_template(template_name, template_dirs)
-
-    def load_template(self, template_name, template_dirs=None):
-        source, display_name = self.load_template_source(template_name, template_dirs)
-        origin = make_origin(display_name, self.load_template_source, template_name, template_dirs)
-        try:
-            template = get_template_from_string(source, origin, template_name)
-            return template, None
-        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.
-            return source, display_name
-
-    def load_template_source(self, template_name, template_dirs=None):
-        """
-        Returns a tuple containing the source and origin for the given template
-        name.
-
-        """
-        raise NotImplementedError('subclasses of BaseLoader 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
-
-
 class LoaderOrigin(Origin):
     def __init__(self, display_name, loader, name, dirs):
         super(LoaderOrigin, self).__init__(display_name)
@@ -199,3 +163,17 @@ def select_template(template_name_list, dirs=None):
             continue
     # If we get here, none of the templates could be loaded
     raise TemplateDoesNotExist(', '.join(not_found))
+
+
+# This line must remain at the bottom to avoid import loops.
+from .loaders import base
+
+
+class BaseLoader(base.Loader):
+
+    def __init__(self, *args, **kwargs):
+        warnings.warn(
+            "django.template.loader.BaseLoader was renamed to "
+            "django.template.loaders.base.Loader.",
+            RemovedInDjango20Warning, stacklevel=2)
+        super(BaseLoader, self).__init__(*args, **kwargs)

+ 2 - 1
django/template/loaders/app_directories.py

@@ -11,10 +11,11 @@ from django.apps import apps
 from django.conf import settings
 from django.core.exceptions import SuspiciousFileOperation
 from django.template.base import TemplateDoesNotExist
-from django.template.loader import BaseLoader
 from django.utils._os import safe_join
 from django.utils import six
 
+from .base import Loader as BaseLoader
+
 
 def calculate_app_template_dirs():
     if six.PY2:

+ 47 - 0
django/template/loaders/base.py

@@ -0,0 +1,47 @@
+from django.template.base import TemplateDoesNotExist
+from django.template.loader import get_template_from_string, make_origin
+
+
+class Loader(object):
+    is_usable = False
+
+    def __init__(self, *args, **kwargs):
+        # XXX dropping arguments silently may not be the best idea.
+        pass
+
+    def __call__(self, template_name, template_dirs=None):
+        return self.load_template(template_name, template_dirs)
+
+    def load_template(self, template_name, template_dirs=None):
+        source, display_name = self.load_template_source(
+            template_name, template_dirs)
+        origin = make_origin(
+            display_name, self.load_template_source,
+            template_name, template_dirs)
+
+        try:
+            template = get_template_from_string(source, origin, template_name)
+        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 load_template_source(self, template_name, template_dirs=None):
+        """
+        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

+ 3 - 1
django/template/loaders/cached.py

@@ -5,9 +5,11 @@ to load templates from them in order, caching the result.
 
 import hashlib
 from django.template.base import TemplateDoesNotExist
-from django.template.loader import BaseLoader, get_template_from_string, find_template_loader, make_origin
+from django.template.loader import get_template_from_string, find_template_loader, make_origin
 from django.utils.encoding import force_bytes
 
+from .base import Loader as BaseLoader
+
 
 class Loader(BaseLoader):
     is_usable = True

+ 2 - 1
django/template/loaders/eggs.py

@@ -9,9 +9,10 @@ except ImportError:
 from django.apps import apps
 from django.conf import settings
 from django.template.base import TemplateDoesNotExist
-from django.template.loader import BaseLoader
 from django.utils import six
 
+from .base import Loader as BaseLoader
+
 
 class Loader(BaseLoader):
     is_usable = resource_string is not None

+ 2 - 1
django/template/loaders/filesystem.py

@@ -7,9 +7,10 @@ import io
 from django.conf import settings
 from django.core.exceptions import SuspiciousFileOperation
 from django.template.base import TemplateDoesNotExist
-from django.template.loader import BaseLoader
 from django.utils._os import safe_join
 
+from .base import Loader as BaseLoader
+
 
 class Loader(BaseLoader):
     is_usable = True

+ 22 - 0
django/template/loaders/locmem.py

@@ -0,0 +1,22 @@
+"""
+Wrapper for loading templates from a plain Python dict.
+"""
+
+from django.template.base import TemplateDoesNotExist
+
+from .base import Loader as BaseLoader
+
+
+class Loader(BaseLoader):
+    is_usable = True
+
+    def __init__(self, templates_dict):
+        self.templates_dict = templates_dict
+
+    def load_template_source(self, template_name, template_dirs=None,
+                             skip_template=None):
+        try:
+            return (self.templates_dict[template_name],
+                    "test:%s" % template_name)
+        except KeyError:
+            raise TemplateDoesNotExist(template_name)

+ 12 - 18
django/test/utils.py

@@ -14,8 +14,8 @@ from django.core import mail
 from django.core.signals import request_started
 from django.db import reset_queries
 from django.http import request
-from django.template import Template, loader, TemplateDoesNotExist
-from django.template.loaders import cached
+from django.template import Template, loader
+from django.template.loaders import cached, locmem
 from django.test.signals import template_rendered, setting_changed
 from django.utils import six
 from django.utils.decorators import ContextDecorator
@@ -189,20 +189,14 @@ class override_template_loaders(ContextDecorator):
         delattr(loader, RESTORE_LOADERS_ATTR)
 
 
-class TestTemplateLoader(loader.BaseLoader):
-    "A custom template loader that loads templates from a dictionary."
-    is_usable = True
+class TestTemplateLoader(locmem.Loader):
 
-    def __init__(self, templates_dict):
-        self.templates_dict = templates_dict
-
-    def load_template_source(self, template_name, template_dirs=None,
-                             skip_template=None):
-        try:
-            return (self.templates_dict[template_name],
-                    "test:%s" % template_name)
-        except KeyError:
-            raise TemplateDoesNotExist(template_name)
+    def __init__(self, *args, **kwargs):
+        warnings.warn(
+            "django.test.utils.TestTemplateLoader was renamed to "
+            "django.template.loaders.locmem.Loader.",
+            RemovedInDjango19Warning, stacklevel=2)
+        super(TestTemplateLoader, self).__init__(*args, **kwargs)
 
 
 class override_with_test_loader(override_template_loaders):
@@ -238,11 +232,11 @@ class override_with_test_loader(override_template_loaders):
     @classmethod
     def _get_loader(cls, templates_dict, use_cached_loader=False):
         if use_cached_loader:
-            loader = cached.Loader(['TestTemplateLoader'])
-            loader._cached_loaders = [TestTemplateLoader(templates_dict)]
+            loader = cached.Loader(['django.template.loaders.locmem.Loader'])
+            loader._cached_loaders = [locmem.Loader(templates_dict)]
             return loader
         else:
-            return TestTemplateLoader(templates_dict)
+            return locmem.Loader(templates_dict)
 
 
 class override_settings(object):

+ 3 - 0
docs/internals/deprecation.txt

@@ -82,6 +82,9 @@ details on these changes.
 * The backwards compatibility shim to allow ``FormMixin.get_form()`` to be
   defined with no default value for its ``form_class`` argument will be removed.
 
+* The backwards compatibility alias ``django.template.loader.BaseLoader`` will
+  be removed.
+
 .. _deprecation-removed-in-1.9:
 
 1.9

+ 6 - 1
docs/ref/templates/api.txt

@@ -967,11 +967,16 @@ with the Django loading and rendering system!
 
 The next step is to write a ``Loader`` class that returns instances of our custom
 template class instead of the default :class:`~django.template.Template`. Custom ``Loader``
-classes should inherit from ``django.template.loader.BaseLoader`` and override
+classes should inherit from ``django.template.loaders.base.Loader`` and override
 the ``load_template_source()`` method, which takes a ``template_name`` argument,
 loads the template from disk (or elsewhere), and returns a tuple:
 ``(template_string, template_origin)``.
 
+.. versionchanged:: 1.8
+
+    ``django.template.loaders.base.Loader`` used to be defined at
+    ``django.template.loader.BaseLoader``.
+
 The ``load_template()`` method of the ``Loader`` class retrieves the template
 string by calling ``load_template_source()``, instantiates a ``Template`` from
 the template source, and returns a tuple: ``(template, template_origin)``. Since

+ 7 - 0
docs/releases/1.8.txt

@@ -1029,6 +1029,13 @@ The decorators :func:`~django.test.override_settings` and
 class decorators. As a consequence, when overriding ``setUpClass()`` or
 ``tearDownClass()``, the ``super`` implementation should always be called.
 
+``django.template.loader.BaseLoader``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``django.template.loader.BaseLoader`` was renamed to
+``django.template.loaders.base.Loader``. If you've written a custom template
+loader that inherits ``BaseLoader``, you must inherit ``Loader`` instead.
+
 .. removed-features-1.8:
 
 Features removed in 1.8

+ 2 - 2
tests/template_tests/tests.py

@@ -221,7 +221,7 @@ class TemplateLoaderTests(TestCase):
         # We rely on the fact that runtests.py sets up TEMPLATE_DIRS to
         # point to a directory containing a login.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
+        # load_template method from the base Loader class, so we only need
         # to test one of them.
         load_name = 'login.html'
         template = loader.get_template(load_name)
@@ -306,7 +306,7 @@ class TemplateLoaderTests(TestCase):
     def test_extends_include_missing_cachedloader(self):
         """
         Same as test_extends_include_missing_baseloader, only tests
-        behavior of the cached loader instead of BaseLoader.
+        behavior of the cached loader instead of base loader.
         """
         cache_loader = cached.Loader(('',))
         cache_loader._cached_loaders = (app_directories.Loader(),)