diff --git a/django/template/__init__.py b/django/template/__init__.py index 00949d6e59..c3167861fd 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -63,6 +63,7 @@ from django.utils.translation import ugettext as _ from django.utils.safestring import SafeData, EscapeData, mark_safe, mark_for_escaping from django.utils.formats import localize from django.utils.html import escape +from django.utils.module_loading import module_has_submodule __all__ = ('Template', 'Context', 'RequestContext', 'compile_string') @@ -980,19 +981,18 @@ def import_library(taglib_module): Verifies that the library contains a 'register' attribute, and returns that attribute as the representation of the library """ - # We need to be able to tell the difference between a tag library that - # doesn't exist, and a tag library with errors in it. - # find_module() finds, but doesn't actually load the module requested. - # If it raises ImportError, it means the module doesn't exist. - # If you then use load_module(), any ImportError is guaranteed to be - # an actual import problem with the module. app_path, taglib = taglib_module.rsplit('.',1) app_module = import_module(app_path) try: - imp.find_module(taglib, app_module.__path__) - except ImportError,e: - return None - mod = import_module(taglib_module) + mod = import_module(taglib_module) + except ImportError, e: + # If the ImportError is because the taglib submodule does not exist, that's not + # an error that should be raised. If the submodule exists and raised an ImportError + # on the attempt to load it, that we want to raise. + if not module_has_submodule(app_module, taglib): + return None + else: + raise InvalidTemplateLibrary("ImportError raised loading %s: %s" % (taglib_module, e)) try: return mod.register except AttributeError: diff --git a/tests/regressiontests/templates/eggs/tagsegg.egg b/tests/regressiontests/templates/eggs/tagsegg.egg new file mode 100755 index 0000000000..3941914b81 Binary files /dev/null and b/tests/regressiontests/templates/eggs/tagsegg.egg differ diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 372d2ab1c2..33d0650c7c 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -1287,5 +1287,48 @@ class Templates(unittest.TestCase): 'autoescape-filtertag01': ("{{ first }}{% filter safe %}{{ first }} x"}, template.TemplateSyntaxError), } + +class TemplateTagLoading(unittest.TestCase): + + def setUp(self): + self.old_path = sys.path + self.old_apps = settings.INSTALLED_APPS + self.egg_dir = '%s/eggs' % os.path.dirname(__file__) + self.old_tag_modules = template.templatetags_modules + template.templatetags_modules = [] + + def tearDown(self): + settings.INSTALLED_APPS = self.old_apps + sys.path = self.old_path + template.templatetags_modules = self.old_tag_modules + + def test_load_error(self): + ttext = "{% load broken_tag %}" + self.assertRaises(template.TemplateSyntaxError, template.Template, ttext) + try: + template.Template(ttext) + except template.TemplateSyntaxError, e: + self.assertTrue('ImportError' in e.args[0]) + self.assertTrue('Xtemplate' in e.args[0]) + + def test_load_error_egg(self): + ttext = "{% load broken_egg %}" + egg_name = '%s/tagsegg.egg' % self.egg_dir + sys.path.append(egg_name) + settings.INSTALLED_APPS = ('tagsegg',) + self.assertRaises(template.TemplateSyntaxError, template.Template, ttext) + try: + template.Template(ttext) + except template.TemplateSyntaxError, e: + self.assertTrue('ImportError' in e.args[0]) + self.assertTrue('Xtemplate' in e.args[0]) + + def test_load_working_egg(self): + ttext = "{% load working_egg %}" + egg_name = '%s/tagsegg.egg' % self.egg_dir + sys.path.append(egg_name) + settings.INSTALLED_APPS = ('tagsegg',) + t = template.Template(ttext) + if __name__ == "__main__": unittest.main()