Commit 39987aaf by Chris Jerdonek

Fixed issue #68: "remove markupsafe dependency"

parent 49fdb477
......@@ -21,6 +21,7 @@ API changes:
* Template class replaced by a Renderer class. [cjerdonek]
* ``Loader.load_template()`` changed to ``Loader.get()``. [cjerdonek]
* Removed output_encoding options. [cjerdonek]
* Removed automatic use of markupsafe, if available. [cjerdonek]
Bug fixes:
......
......@@ -13,13 +13,6 @@ from .loader import Loader
from .renderengine import RenderEngine
markupsafe = None
try:
import markupsafe
except ImportError:
pass
class Renderer(object):
"""
......@@ -66,10 +59,10 @@ class Renderer(object):
this class will only pass it unicode strings. The constructor
assigns this function to the constructed instance's escape()
method.
The argument defaults to markupsafe.escape when markupsafe
is importable and cgi.escape otherwise. To disable escaping
entirely, one can pass `lambda u: u` as the escape function,
for example.
The argument defaults to `cgi.escape(s, quote=True)`. To
disable escaping entirely, one can pass `lambda u: u` as the
escape function, for example. One may also wish to consider
using markupsafe's escape function: markupsafe.escape().
default_encoding: the name of the encoding to use when converting
to unicode any strings of type `str` encountered during the
......@@ -87,19 +80,14 @@ class Renderer(object):
default_encoding = sys.getdefaultencoding()
if escape is None:
if markupsafe:
escape = markupsafe.escape
else:
# The quote=True argument causes double quotes to be escaped,
# but not single quotes:
# http://docs.python.org/library/cgi.html#cgi.escape
escape = lambda s: cgi.escape(s, quote=True)
# The quote=True argument causes double quotes to be escaped,
# 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:
loader = Loader(encoding=default_encoding, decode_errors=decode_errors)
self._literal = markupsafe.Markup if markupsafe else unicode
self.decode_errors = decode_errors
self.default_encoding = default_encoding
self.escape = escape
......@@ -194,8 +182,7 @@ class Renderer(object):
"""
Render the given template using the given context.
The return value is markupsafe.Markup if markup was importable
and unicode otherwise.
Returns a unicode string.
Arguments:
......@@ -218,6 +205,5 @@ class Renderer(object):
template = self._to_unicode_hard(template)
rendered = engine.render(template, context)
rendered = self._literal(rendered)
return rendered
return unicode(rendered)
......@@ -5,15 +5,7 @@ import pystache
from pystache import renderer
class PystacheTests(object):
"""
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.
"""
class PystacheTests(unittest.TestCase):
def _assert_rendered(self, expected, template, context):
actual = pystache.render(template, context)
......@@ -122,30 +114,3 @@ class PystacheTests(object):
template = """{{#s1}}foo{{/s1}} {{#s2}}<{{/s2}}"""
context = {'s1': True, 's2': [True]}
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
class RendererInitTestCase(unittest.TestCase):
"""A class to test the Renderer.__init__() method."""
"""
Tests the Renderer.__init__() method.
"""
def test_loader(self):
"""Test that the loader attribute is set correctly."""
"""
Test that the loader attribute is set correctly.
"""
loader = {'foo': 'bar'}
r = Renderer(loader=loader)
self.assertEquals(r.loader, {'foo': 'bar'})
def test_loader__default(self):
"""Test that the default loader is constructed correctly."""
"""
Test that the default loader is constructed correctly.
"""
r = Renderer()
actual = r.loader
......@@ -35,7 +44,10 @@ class RendererInitTestCase(unittest.TestCase):
self.assertEquals(actual.__dict__, expected.__dict__)
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')
actual = r.loader
......@@ -45,7 +57,10 @@ class RendererInitTestCase(unittest.TestCase):
self.assertEquals(actual.__dict__, expected.__dict__)
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')
actual = r.loader
......@@ -54,49 +69,7 @@ class RendererInitTestCase(unittest.TestCase):
# Check all attributes for good measure.
self.assertEquals(actual.__dict__, expected.__dict__)
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):
def test_escape__default(self):
escape = Renderer().escape
self.assertEquals(escape(">"), "&gt;")
......@@ -104,21 +77,12 @@ class RendererTestCase(unittest.TestCase):
# Single quotes are not escaped.
self.assertEquals(escape("'"), "'")
def test_init__escape__default_with_markupsafe(self):
if not self._was_markupsafe_imported():
# 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
def test_escape(self):
escape = lambda s: "**" + s
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.
......@@ -126,7 +90,7 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer()
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.
......@@ -134,7 +98,7 @@ class RendererTestCase(unittest.TestCase):
renderer = 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.
......@@ -142,7 +106,7 @@ class RendererTestCase(unittest.TestCase):
renderer = Renderer()
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.
......@@ -150,6 +114,14 @@ class RendererTestCase(unittest.TestCase):
renderer = 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().
def test_unicode__default_encoding(self):
......@@ -182,22 +154,30 @@ class RendererTestCase(unittest.TestCase):
# U+FFFD is the official Unicode replacement character.
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):
renderer = Renderer()
actual = renderer.render(u'foo')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, u'foo')
def test_render__str(self):
renderer = Renderer()
actual = renderer.render('foo')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, 'foo')
def test_render__non_ascii_character(self):
renderer = Renderer()
actual = renderer.render(u'Poincaré')
self.assertTrue(isinstance(actual, unicode))
self.assertEquals(actual, u'Poincaré')
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