From bf9ba45f6b5da97154f317ba0b8349b2822a00ba Mon Sep 17 00:00:00 2001 From: Julien Phalip Date: Thu, 25 Aug 2011 23:02:15 +0000 Subject: [PATCH] Fixed #16677 -- Fixed the future version of the ssi template tag to work with template file names that contain spaces. Note that this fix cannot be applied to the currently deprecated version of the ssi tag since it requires an unquoted literal as parameter. Many thanks to Aymeric Augustin for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@16687 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/templatetags/future.py | 2 +- .../templates/ssi include with spaces.html | 1 + tests/regressiontests/templates/tests.py | 40 ++++++++++++++----- 3 files changed, 31 insertions(+), 12 deletions(-) create mode 100644 tests/regressiontests/templates/templates/ssi include with spaces.html diff --git a/django/templatetags/future.py b/django/templatetags/future.py index 14c1ad31ad..9fb2d1138f 100644 --- a/django/templatetags/future.py +++ b/django/templatetags/future.py @@ -19,7 +19,7 @@ def ssi(parser, token): {% ssi "/home/html/ljworld.com/includes/right_generic.html" parsed %} """ - bits = token.contents.split() + bits = token.split_contents() parsed = False if len(bits) not in (2, 3): raise TemplateSyntaxError("'ssi' tag takes one argument: the path to" diff --git a/tests/regressiontests/templates/templates/ssi include with spaces.html b/tests/regressiontests/templates/templates/ssi include with spaces.html new file mode 100644 index 0000000000..1c85648861 --- /dev/null +++ b/tests/regressiontests/templates/templates/ssi include with spaces.html @@ -0,0 +1 @@ +This is for testing an ssi include with spaces in its name. {{ test }} diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 1d1efe52c7..8c722b8bae 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -508,7 +508,8 @@ class Templates(unittest.TestCase): def get_template_tests(self): # SYNTAX -- # 'template_name': ('template contents', 'context dict', 'expected string output' or Exception class) - return { + basedir = os.path.dirname(os.path.abspath(__file__)) + tests = { ### BASIC SYNTAX ################################################ # Plain text should go through the template parser untouched @@ -1350,27 +1351,34 @@ class Templates(unittest.TestCase): ### SSI TAG ######################################################## # Test normal behavior - 'old-ssi01': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), - 'old-ssi02': ('{%% ssi %s %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), + 'old-ssi01': ('{%% ssi %s %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), + 'old-ssi02': ('{%% ssi %s %%}' % os.path.join(basedir, 'not_here'), {}, ''), # Test parsed output - 'old-ssi06': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), - 'old-ssi07': ('{%% ssi %s parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''), + 'old-ssi06': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), + 'old-ssi07': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'not_here'), {'test': 'Look ma! It parsed!'}, ''), + + # Test space in file name + 'old-ssi08': ('{%% ssi %s %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {}, template.TemplateSyntaxError), + 'old-ssi09': ('{%% ssi %s parsed %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {'test': 'Look ma! It parsed!'}, template.TemplateSyntaxError), # Future compatibility # Test normal behavior - 'ssi01': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), - 'ssi02': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), - 'ssi03': ("{%% load ssi from future %%}{%% ssi '%s' %%}" % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {}, ''), + 'ssi01': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {}, 'This is for testing an ssi include. {{ test }}\n'), + 'ssi02': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'not_here'), {}, ''), + 'ssi03': ("{%% load ssi from future %%}{%% ssi '%s' %%}" % os.path.join(basedir, 'not_here'), {}, ''), # Test passing as a variable - 'ssi04': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'), + 'ssi04': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': os.path.join(basedir, 'templates', 'ssi_include.html')}, 'This is for testing an ssi include. {{ test }}\n'), 'ssi05': ('{% load ssi from future %}{% ssi ssi_file %}', {'ssi_file': 'no_file'}, ''), # Test parsed output - 'ssi06': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), - 'ssi07': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(os.path.dirname(os.path.abspath(__file__)), 'not_here'), {'test': 'Look ma! It parsed!'}, ''), + 'ssi06': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi_include.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include. Look ma! It parsed!\n'), + 'ssi07': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'not_here'), {'test': 'Look ma! It parsed!'}, ''), + # Test space in file name + 'ssi08': ('{%% load ssi from future %%}{%% ssi "%s" %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {}, 'This is for testing an ssi include with spaces in its name. {{ test }}\n'), + 'ssi09': ('{%% load ssi from future %%}{%% ssi "%s" parsed %%}' % os.path.join(basedir, 'templates', 'ssi include with spaces.html'), {'test': 'Look ma! It parsed!'}, 'This is for testing an ssi include with spaces in its name. Look ma! It parsed!\n'), ### TEMPLATETAG TAG ####################################################### 'templatetag01': ('{% templatetag openblock %}', {}, '{%'), @@ -1612,6 +1620,16 @@ class Templates(unittest.TestCase): 'static-statictag01': ('{% load static %}{% static "admin/base.css" %}', {}, urljoin(settings.STATIC_URL, 'admin/base.css')), 'static-statictag02': ('{% load static %}{% static base_css %}', {'base_css': 'admin/base.css'}, urljoin(settings.STATIC_URL, 'admin/base.css')), } + # Until Django 1.5, the ssi tag takes an unquoted constant in argument, + # and there's no way to escape spaces. As a consequence it's impossible + # to include a file if its absolute path contains a space, as + # demonstrated by tests old-ssi08 and old-ssi09. + # If the patch to the Django chekout contains a space, the following + # tests will raise an exception too. + if ' ' in basedir: + for test_name in 'old-ssi01', 'old-ssi02', 'old-ssi06', 'old-ssi07': + tests[test_name] = tests[test_name][:-1] + (template.TemplateSyntaxError,) + return tests class TemplateTagLoading(unittest.TestCase):