diff --git a/examples/lambdas.py b/examples/lambdas.py index 653531dc..3fcaf9e7 100644 --- a/examples/lambdas.py +++ b/examples/lambdas.py @@ -1,3 +1,4 @@ +from pystache.compat import * from pystache import TemplateSpec def rot(s, n=13): diff --git a/pystache/compat.py b/pystache/compat.py new file mode 100644 index 00000000..47a4adac --- /dev/null +++ b/pystache/compat.py @@ -0,0 +1,52 @@ +# -*- coding: us-ascii -*- +# vim:ts=4:sw=4:softtabstop=4:smarttab:expandtab +# +# pythonbackports - support newer code on older Python implementations +# Copyright (C) 2011-2012 Chris Clark +"""New stuff is simply exposed in this module (does not mess with builtins) + +So for now simply issue: + + from pystache.compat import * +""" + + +try: + basestring +except NameError: + # probably Python 2.2 or earlier + basestring = (str, unicode) + +try: + reversed +except NameError: + # reversed was added in Python 2.4 + # NOTE this is not an iterator/generator... + def reversed(in_list): + out_list = [] + for i in range(1, len(in_list) + 1): + out_list.append(in_list[-1]) + return out_list + +try: + UnicodeDecodeError + UnicodeEncodeError +except NameError: + # probably Python 2.2 or earlier + UnicodeDecodeError = UnicodeError + UnicodeEncodeError = UnicodeError + +try: + sorted +except NameError: + # sorted was added in Python 2.4 + def sorted(iterable, cmp=None, key=None, reverse=None): + if cmp: + raise NotImplementedError('cmp not yet implemented') + if key: + raise NotImplementedError('key not yet implemented') + if reverse: + raise NotImplementedError('reverse not yet implemented') + out_list = list(iterable)[:] + out_list.sort() + return out_list diff --git a/pystache/context.py b/pystache/context.py index 1621d617..302f0770 100644 --- a/pystache/context.py +++ b/pystache/context.py @@ -5,6 +5,9 @@ """ +from pystache.compat import * + + class NotFound(object): pass # We use this private global variable as a return value to represent a key # not being found on lookup. This lets us distinguish between the case @@ -102,7 +105,6 @@ def __repr__(self): """ return "%s%s" % (self.__class__.__name__, tuple(self._stack)) - @staticmethod def create(*context, **kwargs): """ Build a Context instance from a sequence of context-like items. @@ -157,6 +159,7 @@ def create(*context, **kwargs): context.push(kwargs) return context + create = staticmethod(create) def get(self, key, default=None): """ diff --git a/pystache/locator.py b/pystache/locator.py index a1f06dbb..cd461687 100644 --- a/pystache/locator.py +++ b/pystache/locator.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * import os import re import sys @@ -12,6 +13,12 @@ from pystache import defaults +try: + os.path.extsep +except AttributeError: + # monkey patch and guess, probably Python 2.2 + os.path.extsep = '.' + class Locator(object): def __init__(self, extension=None): diff --git a/pystache/parser.py b/pystache/parser.py index d07ebf64..141ffeff 100644 --- a/pystache/parser.py +++ b/pystache/parser.py @@ -105,9 +105,9 @@ def parse(self, template, index=0, section_key=None): # Normalize the matches dictionary. if matches['change'] is not None: - matches.update(tag='=', tag_key=matches['delims']) + matches.update({'tag': '=', 'tag_key': matches['delims']}) elif matches['raw'] is not None: - matches.update(tag='&', tag_key=matches['raw_name']) + matches.update({'tag': '&', 'tag_key': matches['raw_name']}) tag_type = matches['tag'] tag_key = matches['tag_key'] diff --git a/pystache/renderengine.py b/pystache/renderengine.py index 4361dcaa..843d20b8 100644 --- a/pystache/renderengine.py +++ b/pystache/renderengine.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * import re from parser import Parser diff --git a/pystache/renderer.py b/pystache/renderer.py index 5bd2a3f7..56217bab 100644 --- a/pystache/renderer.py +++ b/pystache/renderer.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * from pystache import defaults from pystache.context import Context from pystache.loader import Loader @@ -125,13 +126,13 @@ def __init__(self, file_encoding=None, string_encoding=None, # but instead letting the caller pass the initial context to the # main render() method by reference. This approach would probably # be less likely to be misused. - @property def context(self): """ Return the current rendering context [experimental]. """ return self._context + context = property(context) def _to_unicode_soft(self, s): """ diff --git a/tests/common.py b/tests/common.py index adc3ec23..c2e1b10c 100644 --- a/tests/common.py +++ b/tests/common.py @@ -49,5 +49,6 @@ class AssertIsMixin: # unittest.assertIs() is not available until Python 2.7: # http://docs.python.org/library/unittest.html#unittest.TestCase.assertIsNone + # assertTrue not available until 2.4? def assertIs(self, first, second): - self.assertTrue(first is second, msg="%s is not %s" % (repr(first), repr(second))) + self.assert_(first is second, msg="%s is not %s" % (repr(first), repr(second))) diff --git a/tests/test_commands.py b/tests/test_commands.py index f1817e70..663fe4b2 100644 --- a/tests/test_commands.py +++ b/tests/test_commands.py @@ -43,3 +43,6 @@ def testMainSimple(self): def tearDown(self): sys.stdout = ORIGINAL_STDOUT + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_context.py b/tests/test_context.py index decf4fb1..972231ed 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -70,7 +70,7 @@ def foo_callable(self): item = {"foo": foo_callable} self.assertNotEquals(_get_value(item, "foo"), "bar") - self.assertTrue(_get_value(item, "foo") is foo_callable) + self.assert_(_get_value(item, "foo") is foo_callable) def test_dictionary__key_missing(self): """ @@ -323,7 +323,7 @@ def test_get__key_missing(self): """ context = Context() - self.assertTrue(context.get("foo") is None) + self.assert_(context.get("foo") is None) def test_get__default(self): """ @@ -398,3 +398,6 @@ def test_copy(self): # Confirm the original is unchanged. self.assertEquals(original.get(key), "buzz") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_loader.py b/tests/test_loader.py index 119ebefc..bd47c757 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * import os import sys import unittest @@ -196,3 +197,6 @@ def test_reader__to_unicode__attribute(self): #actual = reader.read(path) #self.assertString(actual, u'non-ascii: ') + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_locator.py b/tests/test_locator.py index 94a55ad5..e8a2ec25 100644 --- a/tests/test_locator.py +++ b/tests/test_locator.py @@ -32,7 +32,7 @@ def test_init__extension(self): self.assertEquals(locator.template_extension, 'txt') locator = Locator(extension=False) - self.assertTrue(locator.template_extension is False) + self.assert_(locator.template_extension is False) def test_get_object_directory(self): locator = Locator() @@ -79,7 +79,7 @@ def test_find_name__using_list_of_paths(self): locator = Locator() path = locator.find_name(search_dirs=['doesnt_exist', 'examples'], template_name='simple') - self.assertTrue(path) + self.assert_(path) def test_find_name__precedence(self): """ @@ -91,8 +91,8 @@ def test_find_name__precedence(self): dir1 = DATA_DIR dir2 = os.path.join(DATA_DIR, 'locator') - self.assertTrue(locator.find_name(search_dirs=[dir1], template_name='duplicate')) - self.assertTrue(locator.find_name(search_dirs=[dir2], template_name='duplicate')) + self.assert_(locator.find_name(search_dirs=[dir1], template_name='duplicate')) + self.assert_(locator.find_name(search_dirs=[dir2], template_name='duplicate')) path = locator.find_name(search_dirs=[dir2, dir1], template_name='duplicate') dirpath = os.path.dirname(path) @@ -148,3 +148,6 @@ class FooBar(object): foo = FooBar() self.assertEquals(locator.make_template_name(foo), 'foo_bar') + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_pystache.py b/tests/test_pystache.py index f9857cd2..c5a2bebc 100644 --- a/tests/test_pystache.py +++ b/tests/test_pystache.py @@ -114,3 +114,6 @@ def test_later_list_section_with_escapable_character(self): template = """{{#s1}}foo{{/s1}} {{#s2}}<{{/s2}}""" context = {'s1': True, 's2': [True]} self._assert_rendered("foo <", template, context) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_renderengine.py b/tests/test_renderengine.py index 6c2831a1..e534121a 100644 --- a/tests/test_renderengine.py +++ b/tests/test_renderengine.py @@ -387,11 +387,11 @@ def test_section__lambda(self): def test_section__iterable(self): """ Check that objects supporting iteration (aside from dicts) behave like lists. - """ + template = '{{#iterable}}{{.}}{{/iterable}}' - context = {'iterable': (i for i in range(3))} # type 'generator' + context = {'iterable': xrange(3)} # type 'generator' self._assert_render(u'012', template, context) context = {'iterable': xrange(4)} # type 'xrange' @@ -453,3 +453,6 @@ def test_custom_delimiters__not_retroactive(self): expected = u' {{foo}} ' self._assert_render(expected, '{{=$ $=}} {{foo}} ') self._assert_render(expected, '{{=$ $=}} {{foo}} $={{ }}=$') # was yielding u' '. + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_renderer.py b/tests/test_renderer.py index a69d11a6..1eac6278 100644 --- a/tests/test_renderer.py +++ b/tests/test_renderer.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * import codecs import os import sys @@ -33,7 +34,7 @@ def test_partials__default(self): """ renderer = Renderer() - self.assertTrue(renderer.partials is None) + self.assert_(renderer.partials is None) def test_partials(self): """ @@ -482,7 +483,7 @@ class MyUnicode(unicode): s = MyUnicode("abc") self.assertEquals(type(s), MyUnicode) - self.assertTrue(isinstance(s, unicode)) + self.assert_(isinstance(s, unicode)) self.assertEquals(type(literal(s)), unicode) ## Test the engine's escape attribute. @@ -551,6 +552,9 @@ class MyUnicode(unicode): s = MyUnicode("abc") self.assertEquals(type(s), MyUnicode) - self.assertTrue(isinstance(s, unicode)) + self.assert_(isinstance(s, unicode)) self.assertEquals(type(escape(s)), unicode) + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_simple.py b/tests/test_simple.py index e19187f2..8da45b3b 100644 --- a/tests/test_simple.py +++ b/tests/test_simple.py @@ -81,3 +81,6 @@ def test_template_partial_extension(self): ------- ## Again, Welcome! ##""") + +if __name__ == '__main__': + unittest.main() diff --git a/tests/test_template_spec.py b/tests/test_template_spec.py index 9599c37c..73e28d7a 100644 --- a/tests/test_template_spec.py +++ b/tests/test_template_spec.py @@ -5,6 +5,7 @@ """ +from pystache.compat import * import os.path import sys import unittest @@ -337,7 +338,7 @@ def test_find__with_directory(self): view = SampleView() view.template_rel_path = 'foo/bar.txt' - self.assertTrue(locator._find_relative(view)[0] is not None) + self.assert_(locator._find_relative(view)[0] is not None) actual = locator._find(view) expected = os.path.abspath(os.path.join(DATA_DIR, 'foo/bar.txt')) @@ -352,7 +353,7 @@ def test_find__without_directory(self): locator = self._make_locator() view = SampleView() - self.assertTrue(locator._find_relative(view)[0] is None) + self.assert_(locator._find_relative(view)[0] is None) actual = locator._find(view) expected = os.path.abspath(os.path.join(DATA_DIR, 'sample_view.mustache')) @@ -386,3 +387,6 @@ def test_get_template__template_encoding(self): view.template_encoding = 'utf-8' self._assert_get_template(view, u"non-ascii: é") + +if __name__ == '__main__': + unittest.main()