Commit a2be08fd by Chris Jerdonek

Merge branch 'issue_69' into development: closing issue #69

parents 49fdb477 39987aaf
...@@ -21,6 +21,7 @@ API changes: ...@@ -21,6 +21,7 @@ API changes:
* Template class replaced by a Renderer class. [cjerdonek] * Template class replaced by a Renderer class. [cjerdonek]
* ``Loader.load_template()`` changed to ``Loader.get()``. [cjerdonek] * ``Loader.load_template()`` changed to ``Loader.get()``. [cjerdonek]
* Removed output_encoding options. [cjerdonek] * Removed output_encoding options. [cjerdonek]
* Removed automatic use of markupsafe, if available. [cjerdonek]
Bug fixes: Bug fixes:
......
...@@ -13,13 +13,6 @@ from .loader import Loader ...@@ -13,13 +13,6 @@ from .loader import Loader
from .renderengine import RenderEngine from .renderengine import RenderEngine
markupsafe = None
try:
import markupsafe
except ImportError:
pass
class Renderer(object): class Renderer(object):
""" """
...@@ -66,10 +59,10 @@ class Renderer(object): ...@@ -66,10 +59,10 @@ class Renderer(object):
this class will only pass it unicode strings. The constructor this class will only pass it unicode strings. The constructor
assigns this function to the constructed instance's escape() assigns this function to the constructed instance's escape()
method. method.
The argument defaults to markupsafe.escape when markupsafe The argument defaults to `cgi.escape(s, quote=True)`. To
is importable and cgi.escape otherwise. To disable escaping disable escaping entirely, one can pass `lambda u: u` as the
entirely, one can pass `lambda u: u` as the escape function, escape function, for example. One may also wish to consider
for example. using markupsafe's escape function: markupsafe.escape().
default_encoding: the name of the encoding to use when converting default_encoding: the name of the encoding to use when converting
to unicode any strings of type `str` encountered during the to unicode any strings of type `str` encountered during the
...@@ -87,19 +80,14 @@ class Renderer(object): ...@@ -87,19 +80,14 @@ class Renderer(object):
default_encoding = sys.getdefaultencoding() default_encoding = sys.getdefaultencoding()
if escape is None: if escape is None:
if markupsafe: # The quote=True argument causes double quotes to be escaped,
escape = markupsafe.escape # but not single quotes:
else: # http://docs.python.org/library/cgi.html#cgi.escape
# The quote=True argument causes double quotes to be escaped, escape = lambda s: cgi.escape(s, quote=True)
# but not single quotes:
# http://docs.python.org/library/cgi.html#cgi.escape
escape = lambda s: cgi.escape(s, quote=True)
if loader is None: if loader is None:
loader = Loader(encoding=default_encoding, decode_errors=decode_errors) loader = Loader(encoding=default_encoding, decode_errors=decode_errors)
self._literal = markupsafe.Markup if markupsafe else unicode
self.decode_errors = decode_errors self.decode_errors = decode_errors
self.default_encoding = default_encoding self.default_encoding = default_encoding
self.escape = escape self.escape = escape
...@@ -194,8 +182,7 @@ class Renderer(object): ...@@ -194,8 +182,7 @@ class Renderer(object):
""" """
Render the given template using the given context. Render the given template using the given context.
The return value is markupsafe.Markup if markup was importable Returns a unicode string.
and unicode otherwise.
Arguments: Arguments:
...@@ -218,6 +205,5 @@ class Renderer(object): ...@@ -218,6 +205,5 @@ class Renderer(object):
template = self._to_unicode_hard(template) template = self._to_unicode_hard(template)
rendered = engine.render(template, context) rendered = engine.render(template, context)
rendered = self._literal(rendered)
return rendered return unicode(rendered)
...@@ -5,15 +5,7 @@ import pystache ...@@ -5,15 +5,7 @@ import pystache
from pystache import renderer from pystache import renderer
class PystacheTests(object): class PystacheTests(unittest.TestCase):
"""
Contains tests to run with markupsafe both enabled and disabled.
To run the tests in this class, this class should be subclassed by
a class that implements unittest.TestCase.
"""
def _assert_rendered(self, expected, template, context): def _assert_rendered(self, expected, template, context):
actual = pystache.render(template, context) actual = pystache.render(template, context)
...@@ -122,30 +114,3 @@ class PystacheTests(object): ...@@ -122,30 +114,3 @@ class PystacheTests(object):
template = """{{#s1}}foo{{/s1}} {{#s2}}<{{/s2}}""" template = """{{#s1}}foo{{/s1}} {{#s2}}<{{/s2}}"""
context = {'s1': True, 's2': [True]} context = {'s1': True, 's2': [True]}
self._assert_rendered("foo <", template, context) self._assert_rendered("foo <", template, context)
class PystacheWithoutMarkupsafeTests(PystacheTests, unittest.TestCase):
"""Test pystache without markupsafe enabled."""
def setUp(self):
self.original_markupsafe = renderer.markupsafe
renderer.markupsafe = None
def tearDown(self):
renderer.markupsafe = self.original_markupsafe
# If markupsafe is available, then run the same tests again but without
# disabling markupsafe.
_BaseClass = unittest.TestCase if renderer.markupsafe else object
class PystacheWithMarkupsafeTests(PystacheTests, _BaseClass):
"""Test pystache with markupsafe enabled."""
# markupsafe.escape() escapes single quotes: "'" becomes "&#39;".
non_strings_expected = """(123 & [&#39;something&#39;])(chris & 0.9)"""
def test_markupsafe_available(self):
self.assertTrue(renderer.markupsafe, "markupsafe isn't available. "
"The with-markupsafe tests shouldn't be running.")
...@@ -16,16 +16,25 @@ from pystache.loader import Loader ...@@ -16,16 +16,25 @@ from pystache.loader import Loader
class RendererInitTestCase(unittest.TestCase): class RendererInitTestCase(unittest.TestCase):
"""A class to test the Renderer.__init__() method.""" """
Tests the Renderer.__init__() method.
"""
def test_loader(self): def test_loader(self):
"""Test that the loader attribute is set correctly.""" """
Test that the loader attribute is set correctly.
"""
loader = {'foo': 'bar'} loader = {'foo': 'bar'}
r = Renderer(loader=loader) r = Renderer(loader=loader)
self.assertEquals(r.loader, {'foo': 'bar'}) self.assertEquals(r.loader, {'foo': 'bar'})
def test_loader__default(self): def test_loader__default(self):
"""Test that the default loader is constructed correctly.""" """
Test that the default loader is constructed correctly.
"""
r = Renderer() r = Renderer()
actual = r.loader actual = r.loader
...@@ -35,7 +44,10 @@ class RendererInitTestCase(unittest.TestCase): ...@@ -35,7 +44,10 @@ class RendererInitTestCase(unittest.TestCase):
self.assertEquals(actual.__dict__, expected.__dict__) self.assertEquals(actual.__dict__, expected.__dict__)
def test_loader__default__default_encoding(self): def test_loader__default__default_encoding(self):
"""Test that the default loader inherits the default_encoding.""" """
Test that the default loader inherits the default_encoding.
"""
r = Renderer(default_encoding='foo') r = Renderer(default_encoding='foo')
actual = r.loader actual = r.loader
...@@ -45,7 +57,10 @@ class RendererInitTestCase(unittest.TestCase): ...@@ -45,7 +57,10 @@ class RendererInitTestCase(unittest.TestCase):
self.assertEquals(actual.__dict__, expected.__dict__) self.assertEquals(actual.__dict__, expected.__dict__)
def test_loader__default__decode_errors(self): def test_loader__default__decode_errors(self):
"""Test that the default loader inherits the decode_errors.""" """
Test that the default loader inherits the decode_errors.
"""
r = Renderer(decode_errors='foo') r = Renderer(decode_errors='foo')
actual = r.loader actual = r.loader
...@@ -54,49 +69,7 @@ class RendererInitTestCase(unittest.TestCase): ...@@ -54,49 +69,7 @@ class RendererInitTestCase(unittest.TestCase):
# Check all attributes for good measure. # Check all attributes for good measure.
self.assertEquals(actual.__dict__, expected.__dict__) self.assertEquals(actual.__dict__, expected.__dict__)
def test_escape__default(self):
class RendererTestCase(unittest.TestCase):
"""Test the Renderer class."""
def setUp(self):
"""
Disable markupsafe.
"""
self.original_markupsafe = renderer.markupsafe
renderer.markupsafe = None
def tearDown(self):
self._restore_markupsafe()
def _renderer(self):
return Renderer()
def _was_markupsafe_imported(self):
return bool(self.original_markupsafe)
def _restore_markupsafe(self):
"""
Restore markupsafe to its original state.
"""
renderer.markupsafe = self.original_markupsafe
def test__was_markupsafe_imported(self):
"""
Test that our helper function works.
"""
markupsafe = None
try:
import markupsafe
except:
pass
self.assertEquals(bool(markupsafe), self._was_markupsafe_imported())
def test_init__escape__default_without_markupsafe(self):
escape = Renderer().escape escape = Renderer().escape
self.assertEquals(escape(">"), "&gt;") self.assertEquals(escape(">"), "&gt;")
...@@ -104,21 +77,12 @@ class RendererTestCase(unittest.TestCase): ...@@ -104,21 +77,12 @@ class RendererTestCase(unittest.TestCase):
# Single quotes are not escaped. # Single quotes are not escaped.
self.assertEquals(escape("'"), "'") self.assertEquals(escape("'"), "'")
def test_init__escape__default_with_markupsafe(self): def test_escape(self):
if not self._was_markupsafe_imported(): escape = lambda s: "**" + s
# Then we cannot test this case.
return
self._restore_markupsafe()
renderer = Renderer()
self.assertEquals(renderer.escape(">'"), "&gt;&#39;")
def test_init__escape(self):
escape = lambda s: "foo" + s
renderer = Renderer(escape=escape) renderer = Renderer(escape=escape)
self.assertEquals(renderer.escape("bar"), "foobar") self.assertEquals(renderer.escape("bar"), "**bar")
def test_init__default_encoding__default(self): def test_default_encoding__default(self):
""" """
Check the default value. Check the default value.
...@@ -126,7 +90,7 @@ class RendererTestCase(unittest.TestCase): ...@@ -126,7 +90,7 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer() renderer = Renderer()
self.assertEquals(renderer.default_encoding, sys.getdefaultencoding()) self.assertEquals(renderer.default_encoding, sys.getdefaultencoding())
def test_init__default_encoding(self): def test_default_encoding(self):
""" """
Check that the constructor sets the attribute correctly. Check that the constructor sets the attribute correctly.
...@@ -134,7 +98,7 @@ class RendererTestCase(unittest.TestCase): ...@@ -134,7 +98,7 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer(default_encoding="foo") renderer = Renderer(default_encoding="foo")
self.assertEquals(renderer.default_encoding, "foo") self.assertEquals(renderer.default_encoding, "foo")
def test_init__decode_errors__default(self): def test_decode_errors__default(self):
""" """
Check the default value. Check the default value.
...@@ -142,7 +106,7 @@ class RendererTestCase(unittest.TestCase): ...@@ -142,7 +106,7 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer() renderer = Renderer()
self.assertEquals(renderer.decode_errors, 'strict') self.assertEquals(renderer.decode_errors, 'strict')
def test_init__decode_errors(self): def test_decode_errors(self):
""" """
Check that the constructor sets the attribute correctly. Check that the constructor sets the attribute correctly.
...@@ -150,6 +114,14 @@ class RendererTestCase(unittest.TestCase): ...@@ -150,6 +114,14 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer(decode_errors="foo") renderer = Renderer(decode_errors="foo")
self.assertEquals(renderer.decode_errors, "foo") self.assertEquals(renderer.decode_errors, "foo")
class RendererTestCase(unittest.TestCase):
"""Test the Renderer class."""
def _renderer(self):
return Renderer()
## Test Renderer.unicode(). ## Test Renderer.unicode().
def test_unicode__default_encoding(self): def test_unicode__default_encoding(self):
...@@ -182,22 +154,30 @@ class RendererTestCase(unittest.TestCase): ...@@ -182,22 +154,30 @@ class RendererTestCase(unittest.TestCase):
# U+FFFD is the official Unicode replacement character. # U+FFFD is the official Unicode replacement character.
self.assertEquals(renderer.unicode(s), u'd\ufffd\ufffdf') self.assertEquals(renderer.unicode(s), u'd\ufffd\ufffdf')
## Test the render() method.
def test_render__return_type(self):
"""
Check that render() returns a string of type unicode.
"""
renderer = Renderer()
rendered = renderer.render('foo')
self.assertEquals(type(rendered), unicode)
def test_render__unicode(self): def test_render__unicode(self):
renderer = Renderer() renderer = Renderer()
actual = renderer.render(u'foo') actual = renderer.render(u'foo')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, u'foo') self.assertEquals(actual, u'foo')
def test_render__str(self): def test_render__str(self):
renderer = Renderer() renderer = Renderer()
actual = renderer.render('foo') actual = renderer.render('foo')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, 'foo') self.assertEquals(actual, 'foo')
def test_render__non_ascii_character(self): def test_render__non_ascii_character(self):
renderer = Renderer() renderer = Renderer()
actual = renderer.render(u'Poincaré') actual = renderer.render(u'Poincaré')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, u'Poincaré') self.assertEquals(actual, u'Poincaré')
def test_render__context(self): def test_render__context(self):
......
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