Permalink
Browse files

Fixed #6587 -- Removed nasty __path__ hacking in templatetag loading.…

… Thanks to Øyvind Satvik and Andrew Badr for their work on this patch.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12295 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 9cd1d6e commit 12d3799dd2248a3c6e61191355ed5ac43869c691 @freakboy3742 freakboy3742 committed Jan 26, 2010
@@ -309,12 +309,17 @@ def missing_docutils_page(request):
def load_all_installed_template_libraries():
# Load/register all template tag libraries from installed apps.
- for e in templatetags.__path__:
- libraries = [os.path.splitext(p)[0] for p in os.listdir(e) if p.endswith('.py') and p[0].isalpha()]
+ for module_name in template.get_templatetags_modules():
+ mod = import_module(module_name)
+ libraries = [
+ os.path.splitext(p)[0]
+ for p in os.listdir(os.path.dirname(mod.__file__))
+ if p.endswith('.py') and p[0].isalpha()
+ ]
for library_name in libraries:
try:
- lib = template.get_library("django.templatetags.%s" % library_name.split('.')[-1])
- except template.InvalidTemplateLibrary:
+ lib = template.get_library(library_name)
+ except template.InvalidTemplateLibrary, e:
pass
def get_return_data_type(func_name):
@@ -809,7 +809,7 @@ def __repr__(self):
def render(self, context):
return self.s
-
+
def _render_value_in_context(value, context):
"""
Converts any value to a string to become part of a rendered template. This
@@ -966,22 +966,70 @@ def render(self, context):
return func
return dec
-def get_library(module_name):
- lib = libraries.get(module_name, None)
+def import_library(taglib_module):
+ """Load a template tag library module.
+
+ Verifies that the library contains a 'register' attribute, and
+ returns that attribute as the representation of the library
+ """
+ try:
+ mod = import_module(taglib_module)
+ except ImportError:
+ return None
+ try:
+ return mod.register
+ except AttributeError:
+ raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % taglib_module)
+
+templatetags_modules = []
+
+def get_templatetags_modules():
+ """Return the list of all available template tag modules.
+
+ Caches the result for faster access.
+ """
+ global templatetags_modules
+ if not templatetags_modules:
+ _templatetags_modules = []
+ # Populate list once per thread.
+ for app_module in ['django'] + list(settings.INSTALLED_APPS):
+ try:
+ templatetag_module = '%s.templatetags' % app_module
+ import_module(templatetag_module)
+ _templatetags_modules.append(templatetag_module)
+ except ImportError:
+ continue
+ templatetags_modules = _templatetags_modules
+ return templatetags_modules
+
+def get_library(library_name):
+ """
+ Load the template library module with the given name.
+
+ If library is not already loaded loop over all templatetags modules to locate it.
+
+ {% load somelib %} and {% load someotherlib %} loops twice.
+
+ Subsequent loads eg. {% load somelib %} in the same process will grab the cached
+ module from libraries.
+ """
+ lib = libraries.get(library_name, None)
if not lib:
- try:
- mod = import_module(module_name)
- except ImportError, e:
- raise InvalidTemplateLibrary("Could not load template library from %s, %s" % (module_name, e))
- try:
- lib = mod.register
- libraries[module_name] = lib
- except AttributeError:
- raise InvalidTemplateLibrary("Template library %s does not have a variable named 'register'" % module_name)
+ templatetags_modules = get_templatetags_modules()
+ tried_modules = []
+ for module in templatetags_modules:
+ taglib_module = '%s.%s' % (module, library_name)
+ tried_modules.append(taglib_module)
+ lib = import_library(taglib_module)
+ if lib:
+ libraries[library_name] = lib
+ break
+ if not lib:
+ raise InvalidTemplateLibrary("Template library %s not found, tried %s" % (library_name, ','.join(tried_modules)))
return lib
-def add_to_builtins(module_name):
- builtins.append(get_library(module_name))
+def add_to_builtins(module):
+ builtins.append(import_library(module))
add_to_builtins('django.template.defaulttags')
add_to_builtins('django.template.defaultfilters')
@@ -920,7 +920,7 @@ def load(parser, token):
for taglib in bits[1:]:
# add the library to the parser
try:
- lib = get_library("django.templatetags.%s" % taglib)
+ lib = get_library(taglib)
parser.add_library(lib)
except InvalidTemplateLibrary, e:
raise TemplateSyntaxError("'%s' is not a valid tag library: %s" %
@@ -1,8 +0,0 @@
-from django.conf import settings
-from django.utils import importlib
-
-for a in settings.INSTALLED_APPS:
- try:
- __path__.extend(importlib.import_module('.templatetags', a).__path__)
- except ImportError:
- pass
@@ -59,7 +59,7 @@ def do_echo(parser, token):
register.tag("echo", do_echo)
-template.libraries['django.templatetags.testtags'] = register
+template.libraries['testtags'] = register
#####################################
# Helper objects for template tests #

0 comments on commit 12d3799

Please sign in to comment.