summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2014-11-15 20:58:26 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2014-11-16 21:41:44 +0100
commit9eeb788cfb70d07d87b3d07434d6a149ab2d7471 (patch)
tree10045a7dde41390e86c4e9c471f6955b69a8ce09 /django
parent1851dcf377d05a5d167cf482674e4c4a4e2502a5 (diff)
Refactored getting the list of template loaders.
This provides the opportunity to move utility functions specific to the Django Template Language outside of django.template.loader.
Diffstat (limited to 'django')
-rw-r--r--django/template/loader.py60
-rw-r--r--django/template/loaders/cached.py3
-rw-r--r--django/template/loaders/utils.py57
-rw-r--r--django/test/signals.py4
-rw-r--r--django/views/debug.py14
5 files changed, 72 insertions, 66 deletions
diff --git a/django/template/loader.py b/django/template/loader.py
index c62c383322..093d7d172b 100644
--- a/django/template/loader.py
+++ b/django/template/loader.py
@@ -1,13 +1,9 @@
import warnings
-from django.core.exceptions import ImproperlyConfigured
-from django.template.base import Origin, Template, Context, TemplateDoesNotExist
from django.conf import settings
+from django.template.base import Origin, Template, Context, TemplateDoesNotExist
+from django.template.loaders.utils import get_template_loaders
from django.utils.deprecation import RemovedInDjango20Warning
-from django.utils.module_loading import import_string
-from django.utils import six
-
-template_source_loaders = None
class LoaderOrigin(Origin):
@@ -26,58 +22,8 @@ def make_origin(display_name, loader, name, dirs):
return None
-def find_template_loader(loader):
- if isinstance(loader, (tuple, list)):
- loader, args = loader[0], loader[1:]
- else:
- args = []
- if isinstance(loader, six.string_types):
- TemplateLoader = import_string(loader)
-
- if hasattr(TemplateLoader, 'load_template_source'):
- func = TemplateLoader(*args)
- else:
- warnings.warn(
- "Function-based template loaders are deprecated. Please use "
- "class-based template loaders instead. Inherit base.Loader "
- "and provide a load_template_source() method.",
- RemovedInDjango20Warning, stacklevel=2)
-
- # Try loading module the old way - string is full path to callable
- if args:
- raise ImproperlyConfigured(
- "Error importing template source loader %s - can't pass "
- "arguments to function-based loader." % loader
- )
- func = TemplateLoader
-
- if not func.is_usable:
- import warnings
- 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
- )
- return None
- else:
- return func
- else:
- raise ImproperlyConfigured('Loader does not define a "load_template" callable template source loader')
-
-
def find_template(name, dirs=None):
- # Calculate template_source_loaders the first time the function is executed
- # because putting this logic in the module-level namespace may cause
- # circular import errors. See Django ticket #1292.
- global template_source_loaders
- if template_source_loaders is None:
- loaders = []
- for loader_name in settings.TEMPLATE_LOADERS:
- loader = find_template_loader(loader_name)
- if loader is not None:
- loaders.append(loader)
- template_source_loaders = tuple(loaders)
- for loader in template_source_loaders:
+ for loader in get_template_loaders():
try:
source, display_name = loader(name, dirs)
return (source, make_origin(display_name, loader, name, dirs))
diff --git a/django/template/loaders/cached.py b/django/template/loaders/cached.py
index e217efc93f..180ed9900d 100644
--- a/django/template/loaders/cached.py
+++ b/django/template/loaders/cached.py
@@ -5,7 +5,8 @@ to load templates from them in order, caching the result.
import hashlib
from django.template.base import TemplateDoesNotExist
-from django.template.loader import get_template_from_string, find_template_loader, make_origin
+from django.template.loader import get_template_from_string, make_origin
+from django.template.loaders.utils import find_template_loader
from django.utils.encoding import force_bytes
from .base import Loader as BaseLoader
diff --git a/django/template/loaders/utils.py b/django/template/loaders/utils.py
new file mode 100644
index 0000000000..4850c9f1aa
--- /dev/null
+++ b/django/template/loaders/utils.py
@@ -0,0 +1,57 @@
+import warnings
+
+from django.conf import settings
+from django.core.exceptions import ImproperlyConfigured
+from django.utils import lru_cache
+from django.utils import six
+from django.utils.deprecation import RemovedInDjango20Warning
+from django.utils.module_loading import import_string
+
+
+@lru_cache.lru_cache()
+def get_template_loaders():
+ loaders = []
+ for loader_name in settings.TEMPLATE_LOADERS:
+ loader = find_template_loader(loader_name)
+ if loader is not None:
+ loaders.append(loader)
+ # Immutable return value because it will be cached and shared by callers.
+ return tuple(loaders)
+
+
+def find_template_loader(loader):
+ if isinstance(loader, (tuple, list)):
+ loader, args = loader[0], loader[1:]
+ else:
+ args = []
+ if isinstance(loader, six.string_types):
+ TemplateLoader = import_string(loader)
+
+ if hasattr(TemplateLoader, 'load_template_source'):
+ func = TemplateLoader(*args)
+ else:
+ warnings.warn(
+ "Function-based template loaders are deprecated. "
+ "Please use class-based template loaders instead. "
+ "Inherit django.template.loaders.base.Loader "
+ "and provide a load_template_source() method.",
+ RemovedInDjango20Warning, stacklevel=2)
+
+ # Try loading module the old way - string is full path to callable
+ if args:
+ raise ImproperlyConfigured(
+ "Error importing template source loader %s - can't pass "
+ "arguments to function-based loader." % loader)
+ func = TemplateLoader
+
+ if not func.is_usable:
+ 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)
+ return None
+ else:
+ return func
+ else:
+ raise ImproperlyConfigured(
+ "Invalid value in TEMPLATE_LOADERS: %r" % loader)
diff --git a/django/test/signals.py b/django/test/signals.py
index e080d976ee..f065e155b8 100644
--- a/django/test/signals.py
+++ b/django/test/signals.py
@@ -87,8 +87,8 @@ def clear_context_processors_cache(**kwargs):
@receiver(setting_changed)
def clear_template_loaders_cache(**kwargs):
if kwargs['setting'] == 'TEMPLATE_LOADERS':
- from django.template import loader
- loader.template_source_loaders = None
+ from django.template.loaders.utils import get_template_loaders
+ get_template_loaders.cache_clear()
@receiver(setting_changed)
diff --git a/django/views/debug.py b/django/views/debug.py
index 95264afbd5..59136ce90c 100644
--- a/django/views/debug.py
+++ b/django/views/debug.py
@@ -12,6 +12,7 @@ from django.http import (HttpResponse, HttpResponseNotFound, HttpRequest,
build_request_repr)
from django.template import Template, Context, TemplateDoesNotExist
from django.template.defaultfilters import force_escape, pprint
+from django.template.loaders.utils import get_template_loaders
from django.utils.datastructures import MultiValueDict
from django.utils.html import escape
from django.utils.encoding import force_bytes, smart_text
@@ -279,14 +280,15 @@ class ExceptionReporter(object):
"""Return a dictionary containing traceback information."""
if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
- from django.template.loader import template_source_loaders
self.template_does_not_exist = True
self.loader_debug_info = []
- # If the template_source_loaders haven't been populated yet, you need
- # to provide an empty list for this for loop to not fail.
- if template_source_loaders is None:
- template_source_loaders = []
- for loader in template_source_loaders:
+ # If Django fails in get_template_loaders, provide an empty list
+ # for the following loop to not fail.
+ try:
+ template_loaders = get_template_loaders()
+ except Exception:
+ template_loaders = []
+ for loader in template_loaders:
try:
source_list_func = loader.get_template_sources
# NOTE: This assumes exc_value is the name of the template that