Commit 1ab7a4a3 by Chris Jerdonek

Merge branch 'issue_55' into development: more to finish issue #55

parents 2a8ba739 b445ee65
...@@ -128,9 +128,12 @@ class Template(object): ...@@ -128,9 +128,12 @@ class Template(object):
def _unicode_and_escape(self, s): def _unicode_and_escape(self, s):
if not isinstance(s, unicode): if not isinstance(s, unicode):
s = unicode(s) s = self.unicode(s)
return self.escape(s) return self.escape(s)
def unicode(self, s):
return unicode(s, self.default_encoding, self.decode_errors)
def escape(self, u): def escape(self, u):
""" """
Escape a unicode string, and return it. Escape a unicode string, and return it.
...@@ -142,7 +145,6 @@ class Template(object): ...@@ -142,7 +145,6 @@ class Template(object):
""" """
pass pass
def literal(self, s): def literal(self, s):
""" """
Convert the given string to a unicode string, without escaping it. Convert the given string to a unicode string, without escaping it.
...@@ -154,7 +156,7 @@ class Template(object): ...@@ -154,7 +156,7 @@ class Template(object):
markupsafe.Markup (which subclasses unicode). markupsafe.Markup (which subclasses unicode).
""" """
return self._literal(s, self.default_encoding, self.decode_errors) return self._literal(self.unicode(s))
def _initialize_context(self, context, **kwargs): def _initialize_context(self, context, **kwargs):
""" """
...@@ -174,7 +176,6 @@ class Template(object): ...@@ -174,7 +176,6 @@ class Template(object):
self.context = context self.context = context
def _compile_regexps(self): def _compile_regexps(self):
""" """
Compile and set the regular expression attributes. Compile and set the regular expression attributes.
...@@ -271,7 +272,8 @@ class Template(object): ...@@ -271,7 +272,8 @@ class Template(object):
def _render_dictionary(self, template, context): def _render_dictionary(self, template, context):
self.context.push(context) self.context.push(context)
template = Template(template, load_template=self.load_template, escape=self.escape) template = Template(template, load_template=self.load_template, escape=self.escape,
default_encoding=self.default_encoding, decode_errors=self.decode_errors)
out = template.render(self.context) out = template.render(self.context)
self.context.pop() self.context.pop()
...@@ -287,6 +289,10 @@ class Template(object): ...@@ -287,6 +289,10 @@ class Template(object):
@modifiers.set(None) @modifiers.set(None)
def _render_tag(self, tag_name): def _render_tag(self, tag_name):
"""
Return the value of a variable as an escaped unicode string.
"""
raw = self.context.get(tag_name, '') raw = self.context.get(tag_name, '')
# For methods with no return value # For methods with no return value
...@@ -301,6 +307,14 @@ class Template(object): ...@@ -301,6 +307,14 @@ class Template(object):
else: else:
return '' return ''
# If we don't first convert to a string type, the call to self._unicode_and_escape()
# will yield an error like the following:
#
# TypeError: coercing to Unicode: need string or buffer, ... found
#
if not isinstance(raw, basestring):
raw = str(raw)
return self._unicode_and_escape(raw) return self._unicode_and_escape(raw)
@modifiers.set('!') @modifiers.set('!')
...@@ -310,7 +324,8 @@ class Template(object): ...@@ -310,7 +324,8 @@ class Template(object):
@modifiers.set('>') @modifiers.set('>')
def _render_partial(self, template_name): def _render_partial(self, template_name):
markup = self.load_template(template_name) markup = self.load_template(template_name)
template = Template(markup, load_template=self.load_template, escape=self.escape) template = Template(markup, load_template=self.load_template, escape=self.escape,
default_encoding=self.default_encoding, decode_errors=self.decode_errors)
return template.render(self.context) return template.render(self.context)
@modifiers.set('=') @modifiers.set('=')
......
...@@ -88,35 +88,33 @@ class TemplateTestCase(unittest.TestCase): ...@@ -88,35 +88,33 @@ class TemplateTestCase(unittest.TestCase):
template = Template(decode_errors="foo") template = Template(decode_errors="foo")
self.assertEquals(template.decode_errors, "foo") self.assertEquals(template.decode_errors, "foo")
def test_literal(self): def test_unicode(self):
template = Template() template = Template()
actual = template.literal("abc") actual = template.literal("abc")
self.assertEquals(actual, "abc") self.assertEquals(actual, "abc")
self.assertEquals(type(actual), unicode) self.assertEquals(type(actual), unicode)
def test_literal__default_encoding(self): def test_unicode__default_encoding(self):
template = Template() template = Template()
template.default_encoding = "utf-8" s = "é"
actual = template.literal("é")
self.assertEquals(actual, u"é")
def test_literal__default_encoding__error(self):
template = Template()
template.default_encoding = "ascii" template.default_encoding = "ascii"
self.assertRaises(UnicodeDecodeError, template.literal, "é") self.assertRaises(UnicodeDecodeError, template.unicode, s)
template.default_encoding = "utf-8"
self.assertEquals(template.unicode(s), u"é")
def test_literal__decode_errors(self): def test_unicode__decode_errors(self):
template = Template() template = Template()
template.default_encoding = "ascii"
s = "é" s = "é"
template.default_encoding = "ascii"
template.decode_errors = "strict" template.decode_errors = "strict"
self.assertRaises(UnicodeDecodeError, template.literal, s) self.assertRaises(UnicodeDecodeError, template.unicode, s)
template.decode_errors = "replace" template.decode_errors = "replace"
actual = template.literal(s)
# U+FFFD is the official Unicode replacement character. # U+FFFD is the official Unicode replacement character.
self.assertEquals(actual, u'\ufffd\ufffd') self.assertEquals(template.unicode(s), u'\ufffd\ufffd')
def test_literal__with_markupsafe(self): def test_literal__with_markupsafe(self):
if not self._was_markupsafe_imported(): if not self._was_markupsafe_imported():
...@@ -295,3 +293,37 @@ class TemplateTestCase(unittest.TestCase): ...@@ -295,3 +293,37 @@ class TemplateTestCase(unittest.TestCase):
template = Template("{{#list}}{{name}}: {{greeting}}; {{/list}}") template = Template("{{#list}}{{name}}: {{greeting}}; {{/list}}")
self.assertEquals(template.render(context), "Al: Hi; Bo: Hi; ") self.assertEquals(template.render(context), "Al: Hi; Bo: Hi; ")
def test_render__encoding_in_context_value(self):
template = Template('{{test}}')
context = {'test': "déf"}
template.decode_errors = 'ignore'
template.default_encoding = 'ascii'
self.assertEquals(template.render(context), "df")
template.default_encoding = 'utf_8'
self.assertEquals(template.render(context), u"déf")
def test_render__encoding_in_section_context_value(self):
template = Template('{{#test}}{{foo}}{{/test}}')
context = {'test': {'foo': "déf"}}
template.decode_errors = 'ignore'
template.default_encoding = 'ascii'
self.assertEquals(template.render(context), "df")
template.default_encoding = 'utf_8'
self.assertEquals(template.render(context), u"déf")
def test_render__encoding_in_partial_context_value(self):
load_template = lambda x: "{{foo}}"
template = Template('{{>partial}}', load_template=load_template)
context = {'foo': "déf"}
template.decode_errors = 'ignore'
template.default_encoding = 'ascii'
self.assertEquals(template.render(context), "df")
template.default_encoding = 'utf_8'
self.assertEquals(template.render(context), u"déf")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment