Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/websdk/jinja2/testsuite
diff options
context:
space:
mode:
Diffstat (limited to 'websdk/jinja2/testsuite')
-rw-r--r--websdk/jinja2/testsuite/__init__.py95
-rw-r--r--websdk/jinja2/testsuite/api.py245
-rw-r--r--websdk/jinja2/testsuite/core_tags.py285
-rw-r--r--websdk/jinja2/testsuite/debug.py60
-rw-r--r--websdk/jinja2/testsuite/doctests.py29
-rw-r--r--websdk/jinja2/testsuite/ext.py455
-rw-r--r--websdk/jinja2/testsuite/filters.py356
-rw-r--r--websdk/jinja2/testsuite/imports.py141
-rw-r--r--websdk/jinja2/testsuite/inheritance.py227
-rw-r--r--websdk/jinja2/testsuite/lexnparse.py387
-rw-r--r--websdk/jinja2/testsuite/loader.py218
-rw-r--r--websdk/jinja2/testsuite/regression.py255
-rw-r--r--websdk/jinja2/testsuite/res/__init__.py0
-rw-r--r--websdk/jinja2/testsuite/res/templates/broken.html3
-rw-r--r--websdk/jinja2/testsuite/res/templates/foo/test.html1
-rw-r--r--websdk/jinja2/testsuite/res/templates/syntaxerror.html4
-rw-r--r--websdk/jinja2/testsuite/res/templates/test.html1
-rw-r--r--websdk/jinja2/testsuite/security.py165
-rw-r--r--websdk/jinja2/testsuite/tests.py93
-rw-r--r--websdk/jinja2/testsuite/utils.py82
20 files changed, 3102 insertions, 0 deletions
diff --git a/websdk/jinja2/testsuite/__init__.py b/websdk/jinja2/testsuite/__init__.py
new file mode 100644
index 0000000..1f10ef6
--- /dev/null
+++ b/websdk/jinja2/testsuite/__init__.py
@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite
+ ~~~~~~~~~~~~~~~~
+
+ All the unittests of Jinja2. These tests can be executed by
+ either running run-tests.py using multiple Python versions at
+ the same time.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import re
+import sys
+import unittest
+from traceback import format_exception
+from jinja2 import loaders
+
+
+here = os.path.dirname(os.path.abspath(__file__))
+
+dict_loader = loaders.DictLoader({
+ 'justdict.html': 'FOO'
+})
+package_loader = loaders.PackageLoader('jinja2.testsuite.res', 'templates')
+filesystem_loader = loaders.FileSystemLoader(here + '/res/templates')
+function_loader = loaders.FunctionLoader({'justfunction.html': 'FOO'}.get)
+choice_loader = loaders.ChoiceLoader([dict_loader, package_loader])
+prefix_loader = loaders.PrefixLoader({
+ 'a': filesystem_loader,
+ 'b': dict_loader
+})
+
+
+class JinjaTestCase(unittest.TestCase):
+
+ ### use only these methods for testing. If you need standard
+ ### unittest method, wrap them!
+
+ def setup(self):
+ pass
+
+ def teardown(self):
+ pass
+
+ def setUp(self):
+ self.setup()
+
+ def tearDown(self):
+ self.teardown()
+
+ def assert_equal(self, a, b):
+ return self.assertEqual(a, b)
+
+ def assert_raises(self, *args, **kwargs):
+ return self.assertRaises(*args, **kwargs)
+
+ def assert_traceback_matches(self, callback, expected_tb):
+ try:
+ callback()
+ except Exception, e:
+ tb = format_exception(*sys.exc_info())
+ if re.search(expected_tb.strip(), ''.join(tb)) is None:
+ raise self.fail('Traceback did not match:\n\n%s\nexpected:\n%s'
+ % (''.join(tb), expected_tb))
+ else:
+ self.fail('Expected exception')
+
+
+def suite():
+ from jinja2.testsuite import ext, filters, tests, core_tags, \
+ loader, inheritance, imports, lexnparse, security, api, \
+ regression, debug, utils, doctests
+ suite = unittest.TestSuite()
+ suite.addTest(ext.suite())
+ suite.addTest(filters.suite())
+ suite.addTest(tests.suite())
+ suite.addTest(core_tags.suite())
+ suite.addTest(loader.suite())
+ suite.addTest(inheritance.suite())
+ suite.addTest(imports.suite())
+ suite.addTest(lexnparse.suite())
+ suite.addTest(security.suite())
+ suite.addTest(api.suite())
+ suite.addTest(regression.suite())
+ suite.addTest(debug.suite())
+ suite.addTest(utils.suite())
+
+ # doctests will not run on python 3 currently. Too many issues
+ # with that, do not test that on that platform.
+ if sys.version_info < (3, 0):
+ suite.addTest(doctests.suite())
+
+ return suite
diff --git a/websdk/jinja2/testsuite/api.py b/websdk/jinja2/testsuite/api.py
new file mode 100644
index 0000000..c8f9634
--- /dev/null
+++ b/websdk/jinja2/testsuite/api.py
@@ -0,0 +1,245 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.api
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Tests the public API and related stuff.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, Undefined, DebugUndefined, \
+ StrictUndefined, UndefinedError, meta, \
+ is_undefined, Template, DictLoader
+from jinja2.utils import Cycler
+
+env = Environment()
+
+
+class ExtendedAPITestCase(JinjaTestCase):
+
+ def test_item_and_attribute(self):
+ from jinja2.sandbox import SandboxedEnvironment
+
+ for env in Environment(), SandboxedEnvironment():
+ # the |list is necessary for python3
+ tmpl = env.from_string('{{ foo.items()|list }}')
+ assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+ tmpl = env.from_string('{{ foo|attr("items")()|list }}')
+ assert tmpl.render(foo={'items': 42}) == "[('items', 42)]"
+ tmpl = env.from_string('{{ foo["items"] }}')
+ assert tmpl.render(foo={'items': 42}) == '42'
+
+ def test_finalizer(self):
+ def finalize_none_empty(value):
+ if value is None:
+ value = u''
+ return value
+ env = Environment(finalize=finalize_none_empty)
+ tmpl = env.from_string('{% for item in seq %}|{{ item }}{% endfor %}')
+ assert tmpl.render(seq=(None, 1, "foo")) == '||1|foo'
+ tmpl = env.from_string('<{{ none }}>')
+ assert tmpl.render() == '<>'
+
+ def test_cycler(self):
+ items = 1, 2, 3
+ c = Cycler(*items)
+ for item in items + items:
+ assert c.current == item
+ assert c.next() == item
+ c.next()
+ assert c.current == 2
+ c.reset()
+ assert c.current == 1
+
+ def test_expressions(self):
+ expr = env.compile_expression("foo")
+ assert expr() is None
+ assert expr(foo=42) == 42
+ expr2 = env.compile_expression("foo", undefined_to_none=False)
+ assert is_undefined(expr2())
+
+ expr = env.compile_expression("42 + foo")
+ assert expr(foo=42) == 84
+
+ def test_template_passthrough(self):
+ t = Template('Content')
+ assert env.get_template(t) is t
+ assert env.select_template([t]) is t
+ assert env.get_or_select_template([t]) is t
+ assert env.get_or_select_template(t) is t
+
+ def test_autoescape_autoselect(self):
+ def select_autoescape(name):
+ if name is None or '.' not in name:
+ return False
+ return name.endswith('.html')
+ env = Environment(autoescape=select_autoescape,
+ loader=DictLoader({
+ 'test.txt': '{{ foo }}',
+ 'test.html': '{{ foo }}'
+ }))
+ t = env.get_template('test.txt')
+ assert t.render(foo='<foo>') == '<foo>'
+ t = env.get_template('test.html')
+ assert t.render(foo='<foo>') == '&lt;foo&gt;'
+ t = env.from_string('{{ foo }}')
+ assert t.render(foo='<foo>') == '<foo>'
+
+
+class MetaTestCase(JinjaTestCase):
+
+ def test_find_undeclared_variables(self):
+ ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
+ x = meta.find_undeclared_variables(ast)
+ assert x == set(['bar'])
+
+ ast = env.parse('{% set foo = 42 %}{{ bar + foo }}'
+ '{% macro meh(x) %}{{ x }}{% endmacro %}'
+ '{% for item in seq %}{{ muh(item) + meh(seq) }}{% endfor %}')
+ x = meta.find_undeclared_variables(ast)
+ assert x == set(['bar', 'seq', 'muh'])
+
+ def test_find_refererenced_templates(self):
+ ast = env.parse('{% extends "layout.html" %}{% include helper %}')
+ i = meta.find_referenced_templates(ast)
+ assert i.next() == 'layout.html'
+ assert i.next() is None
+ assert list(i) == []
+
+ ast = env.parse('{% extends "layout.html" %}'
+ '{% from "test.html" import a, b as c %}'
+ '{% import "meh.html" as meh %}'
+ '{% include "muh.html" %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['layout.html', 'test.html', 'meh.html', 'muh.html']
+
+ def test_find_included_templates(self):
+ ast = env.parse('{% include ["foo.html", "bar.html"] %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html']
+
+ ast = env.parse('{% include ("foo.html", "bar.html") %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html']
+
+ ast = env.parse('{% include ["foo.html", "bar.html", foo] %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html', None]
+
+ ast = env.parse('{% include ("foo.html", "bar.html", foo) %}')
+ i = meta.find_referenced_templates(ast)
+ assert list(i) == ['foo.html', 'bar.html', None]
+
+
+class StreamingTestCase(JinjaTestCase):
+
+ def test_basic_streaming(self):
+ tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+ "}} - {{ item }}</li>{%- endfor %}</ul>")
+ stream = tmpl.stream(seq=range(4))
+ self.assert_equal(stream.next(), '<ul>')
+ self.assert_equal(stream.next(), '<li>1 - 0</li>')
+ self.assert_equal(stream.next(), '<li>2 - 1</li>')
+ self.assert_equal(stream.next(), '<li>3 - 2</li>')
+ self.assert_equal(stream.next(), '<li>4 - 3</li>')
+ self.assert_equal(stream.next(), '</ul>')
+
+ def test_buffered_streaming(self):
+ tmpl = env.from_string("<ul>{% for item in seq %}<li>{{ loop.index "
+ "}} - {{ item }}</li>{%- endfor %}</ul>")
+ stream = tmpl.stream(seq=range(4))
+ stream.enable_buffering(size=3)
+ self.assert_equal(stream.next(), u'<ul><li>1 - 0</li><li>2 - 1</li>')
+ self.assert_equal(stream.next(), u'<li>3 - 2</li><li>4 - 3</li></ul>')
+
+ def test_streaming_behavior(self):
+ tmpl = env.from_string("")
+ stream = tmpl.stream()
+ assert not stream.buffered
+ stream.enable_buffering(20)
+ assert stream.buffered
+ stream.disable_buffering()
+ assert not stream.buffered
+
+
+class UndefinedTestCase(JinjaTestCase):
+
+ def test_stopiteration_is_undefined(self):
+ def test():
+ raise StopIteration()
+ t = Template('A{{ test() }}B')
+ assert t.render(test=test) == 'AB'
+ t = Template('A{{ test().missingattribute }}B')
+ self.assert_raises(UndefinedError, t.render, test=test)
+
+ def test_undefined_and_special_attributes(self):
+ try:
+ Undefined('Foo').__dict__
+ except AttributeError:
+ pass
+ else:
+ assert False, "Expected actual attribute error"
+
+ def test_default_undefined(self):
+ env = Environment(undefined=Undefined)
+ self.assert_equal(env.from_string('{{ missing }}').render(), u'')
+ self.assert_raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+ self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+ self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42), '')
+ self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+ def test_debug_undefined(self):
+ env = Environment(undefined=DebugUndefined)
+ self.assert_equal(env.from_string('{{ missing }}').render(), '{{ missing }}')
+ self.assert_raises(UndefinedError,
+ env.from_string('{{ missing.attribute }}').render)
+ self.assert_equal(env.from_string('{{ missing|list }}').render(), '[]')
+ self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+ self.assert_equal(env.from_string('{{ foo.missing }}').render(foo=42),
+ u"{{ no such element: int object['missing'] }}")
+ self.assert_equal(env.from_string('{{ not missing }}').render(), 'True')
+
+ def test_strict_undefined(self):
+ env = Environment(undefined=StrictUndefined)
+ self.assert_raises(UndefinedError, env.from_string('{{ missing }}').render)
+ self.assert_raises(UndefinedError, env.from_string('{{ missing.attribute }}').render)
+ self.assert_raises(UndefinedError, env.from_string('{{ missing|list }}').render)
+ self.assert_equal(env.from_string('{{ missing is not defined }}').render(), 'True')
+ self.assert_raises(UndefinedError, env.from_string('{{ foo.missing }}').render, foo=42)
+ self.assert_raises(UndefinedError, env.from_string('{{ not missing }}').render)
+
+ def test_indexing_gives_undefined(self):
+ t = Template("{{ var[42].foo }}")
+ self.assert_raises(UndefinedError, t.render, var=0)
+
+ def test_none_gives_proper_error(self):
+ try:
+ Environment().getattr(None, 'split')()
+ except UndefinedError, e:
+ assert e.message == "'None' has no attribute 'split'"
+ else:
+ assert False, 'expected exception'
+
+ def test_object_repr(self):
+ try:
+ Undefined(obj=42, name='upper')()
+ except UndefinedError, e:
+ assert e.message == "'int object' has no attribute 'upper'"
+ else:
+ assert False, 'expected exception'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ExtendedAPITestCase))
+ suite.addTest(unittest.makeSuite(MetaTestCase))
+ suite.addTest(unittest.makeSuite(StreamingTestCase))
+ suite.addTest(unittest.makeSuite(UndefinedTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/core_tags.py b/websdk/jinja2/testsuite/core_tags.py
new file mode 100644
index 0000000..2b5f580
--- /dev/null
+++ b/websdk/jinja2/testsuite/core_tags.py
@@ -0,0 +1,285 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.core_tags
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the core tags like for and if.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, TemplateSyntaxError, UndefinedError, \
+ DictLoader
+
+env = Environment()
+
+
+class ForLoopTestCase(JinjaTestCase):
+
+ def test_simple(self):
+ tmpl = env.from_string('{% for item in seq %}{{ item }}{% endfor %}')
+ assert tmpl.render(seq=range(10)) == '0123456789'
+
+ def test_else(self):
+ tmpl = env.from_string('{% for item in seq %}XXX{% else %}...{% endfor %}')
+ assert tmpl.render() == '...'
+
+ def test_empty_blocks(self):
+ tmpl = env.from_string('<{% for item in seq %}{% else %}{% endfor %}>')
+ assert tmpl.render() == '<>'
+
+ def test_context_vars(self):
+ tmpl = env.from_string('''{% for item in seq -%}
+ {{ loop.index }}|{{ loop.index0 }}|{{ loop.revindex }}|{{
+ loop.revindex0 }}|{{ loop.first }}|{{ loop.last }}|{{
+ loop.length }}###{% endfor %}''')
+ one, two, _ = tmpl.render(seq=[0, 1]).split('###')
+ (one_index, one_index0, one_revindex, one_revindex0, one_first,
+ one_last, one_length) = one.split('|')
+ (two_index, two_index0, two_revindex, two_revindex0, two_first,
+ two_last, two_length) = two.split('|')
+
+ assert int(one_index) == 1 and int(two_index) == 2
+ assert int(one_index0) == 0 and int(two_index0) == 1
+ assert int(one_revindex) == 2 and int(two_revindex) == 1
+ assert int(one_revindex0) == 1 and int(two_revindex0) == 0
+ assert one_first == 'True' and two_first == 'False'
+ assert one_last == 'False' and two_last == 'True'
+ assert one_length == two_length == '2'
+
+ def test_cycling(self):
+ tmpl = env.from_string('''{% for item in seq %}{{
+ loop.cycle('<1>', '<2>') }}{% endfor %}{%
+ for item in seq %}{{ loop.cycle(*through) }}{% endfor %}''')
+ output = tmpl.render(seq=range(4), through=('<1>', '<2>'))
+ assert output == '<1><2>' * 4
+
+ def test_scope(self):
+ tmpl = env.from_string('{% for item in seq %}{% endfor %}{{ item }}')
+ output = tmpl.render(seq=range(10))
+ assert not output
+
+ def test_varlen(self):
+ def inner():
+ for item in range(5):
+ yield item
+ tmpl = env.from_string('{% for item in iter %}{{ item }}{% endfor %}')
+ output = tmpl.render(iter=inner())
+ assert output == '01234'
+
+ def test_noniter(self):
+ tmpl = env.from_string('{% for item in none %}...{% endfor %}')
+ self.assert_raises(TypeError, tmpl.render)
+
+ def test_recursive(self):
+ tmpl = env.from_string('''{% for item in seq recursive -%}
+ [{{ item.a }}{% if item.b %}<{{ loop(item.b) }}>{% endif %}]
+ {%- endfor %}''')
+ assert tmpl.render(seq=[
+ dict(a=1, b=[dict(a=1), dict(a=2)]),
+ dict(a=2, b=[dict(a=1), dict(a=2)]),
+ dict(a=3, b=[dict(a='a')])
+ ]) == '[1<[1][2]>][2<[1][2]>][3<[a]>]'
+
+ def test_looploop(self):
+ tmpl = env.from_string('''{% for row in table %}
+ {%- set rowloop = loop -%}
+ {% for cell in row -%}
+ [{{ rowloop.index }}|{{ loop.index }}]
+ {%- endfor %}
+ {%- endfor %}''')
+ assert tmpl.render(table=['ab', 'cd']) == '[1|1][1|2][2|1][2|2]'
+
+ def test_reversed_bug(self):
+ tmpl = env.from_string('{% for i in items %}{{ i }}'
+ '{% if not loop.last %}'
+ ',{% endif %}{% endfor %}')
+ assert tmpl.render(items=reversed([3, 2, 1])) == '1,2,3'
+
+ def test_loop_errors(self):
+ tmpl = env.from_string('''{% for item in [1] if loop.index
+ == 0 %}...{% endfor %}''')
+ self.assert_raises(UndefinedError, tmpl.render)
+ tmpl = env.from_string('''{% for item in [] %}...{% else
+ %}{{ loop }}{% endfor %}''')
+ assert tmpl.render() == ''
+
+ def test_loop_filter(self):
+ tmpl = env.from_string('{% for item in range(10) if item '
+ 'is even %}[{{ item }}]{% endfor %}')
+ assert tmpl.render() == '[0][2][4][6][8]'
+ tmpl = env.from_string('''
+ {%- for item in range(10) if item is even %}[{{
+ loop.index }}:{{ item }}]{% endfor %}''')
+ assert tmpl.render() == '[1:0][2:2][3:4][4:6][5:8]'
+
+ def test_loop_unassignable(self):
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ '{% for loop in seq %}...{% endfor %}')
+
+ def test_scoped_special_var(self):
+ t = env.from_string('{% for s in seq %}[{{ loop.first }}{% for c in s %}'
+ '|{{ loop.first }}{% endfor %}]{% endfor %}')
+ assert t.render(seq=('ab', 'cd')) == '[True|True|False][False|True|False]'
+
+ def test_scoped_loop_var(self):
+ t = env.from_string('{% for x in seq %}{{ loop.first }}'
+ '{% for y in seq %}{% endfor %}{% endfor %}')
+ assert t.render(seq='ab') == 'TrueFalse'
+ t = env.from_string('{% for x in seq %}{% for y in seq %}'
+ '{{ loop.first }}{% endfor %}{% endfor %}')
+ assert t.render(seq='ab') == 'TrueFalseTrueFalse'
+
+ def test_recursive_empty_loop_iter(self):
+ t = env.from_string('''
+ {%- for item in foo recursive -%}{%- endfor -%}
+ ''')
+ assert t.render(dict(foo=[])) == ''
+
+ def test_call_in_loop(self):
+ t = env.from_string('''
+ {%- macro do_something() -%}
+ [{{ caller() }}]
+ {%- endmacro %}
+
+ {%- for i in [1, 2, 3] %}
+ {%- call do_something() -%}
+ {{ i }}
+ {%- endcall %}
+ {%- endfor -%}
+ ''')
+ assert t.render() == '[1][2][3]'
+
+ def test_scoping_bug(self):
+ t = env.from_string('''
+ {%- for item in foo %}...{{ item }}...{% endfor %}
+ {%- macro item(a) %}...{{ a }}...{% endmacro %}
+ {{- item(2) -}}
+ ''')
+ assert t.render(foo=(1,)) == '...1......2...'
+
+ def test_unpacking(self):
+ tmpl = env.from_string('{% for a, b, c in [[1, 2, 3]] %}'
+ '{{ a }}|{{ b }}|{{ c }}{% endfor %}')
+ assert tmpl.render() == '1|2|3'
+
+
+class IfConditionTestCase(JinjaTestCase):
+
+ def test_simple(self):
+ tmpl = env.from_string('''{% if true %}...{% endif %}''')
+ assert tmpl.render() == '...'
+
+ def test_elif(self):
+ tmpl = env.from_string('''{% if false %}XXX{% elif true
+ %}...{% else %}XXX{% endif %}''')
+ assert tmpl.render() == '...'
+
+ def test_else(self):
+ tmpl = env.from_string('{% if false %}XXX{% else %}...{% endif %}')
+ assert tmpl.render() == '...'
+
+ def test_empty(self):
+ tmpl = env.from_string('[{% if true %}{% else %}{% endif %}]')
+ assert tmpl.render() == '[]'
+
+ def test_complete(self):
+ tmpl = env.from_string('{% if a %}A{% elif b %}B{% elif c == d %}'
+ 'C{% else %}D{% endif %}')
+ assert tmpl.render(a=0, b=False, c=42, d=42.0) == 'C'
+
+ def test_no_scope(self):
+ tmpl = env.from_string('{% if a %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ assert tmpl.render(a=True) == '1'
+ tmpl = env.from_string('{% if true %}{% set foo = 1 %}{% endif %}{{ foo }}')
+ assert tmpl.render() == '1'
+
+
+class MacrosTestCase(JinjaTestCase):
+ env = Environment(trim_blocks=True)
+
+ def test_simple(self):
+ tmpl = self.env.from_string('''\
+{% macro say_hello(name) %}Hello {{ name }}!{% endmacro %}
+{{ say_hello('Peter') }}''')
+ assert tmpl.render() == 'Hello Peter!'
+
+ def test_scoping(self):
+ tmpl = self.env.from_string('''\
+{% macro level1(data1) %}
+{% macro level2(data2) %}{{ data1 }}|{{ data2 }}{% endmacro %}
+{{ level2('bar') }}{% endmacro %}
+{{ level1('foo') }}''')
+ assert tmpl.render() == 'foo|bar'
+
+ def test_arguments(self):
+ tmpl = self.env.from_string('''\
+{% macro m(a, b, c='c', d='d') %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %}
+{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}''')
+ assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d'
+
+ def test_varargs(self):
+ tmpl = self.env.from_string('''\
+{% macro test() %}{{ varargs|join('|') }}{% endmacro %}\
+{{ test(1, 2, 3) }}''')
+ assert tmpl.render() == '1|2|3'
+
+ def test_simple_call(self):
+ tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller() }}]]{% endmacro %}\
+{% call test() %}data{% endcall %}''')
+ assert tmpl.render() == '[[data]]'
+
+ def test_complex_call(self):
+ tmpl = self.env.from_string('''\
+{% macro test() %}[[{{ caller('data') }}]]{% endmacro %}\
+{% call(data) test() %}{{ data }}{% endcall %}''')
+ assert tmpl.render() == '[[data]]'
+
+ def test_caller_undefined(self):
+ tmpl = self.env.from_string('''\
+{% set caller = 42 %}\
+{% macro test() %}{{ caller is not defined }}{% endmacro %}\
+{{ test() }}''')
+ assert tmpl.render() == 'True'
+
+ def test_include(self):
+ self.env = Environment(loader=DictLoader({'include':
+ '{% macro test(foo) %}[{{ foo }}]{% endmacro %}'}))
+ tmpl = self.env.from_string('{% from "include" import test %}{{ test("foo") }}')
+ assert tmpl.render() == '[foo]'
+
+ def test_macro_api(self):
+ tmpl = self.env.from_string('{% macro foo(a, b) %}{% endmacro %}'
+ '{% macro bar() %}{{ varargs }}{{ kwargs }}{% endmacro %}'
+ '{% macro baz() %}{{ caller() }}{% endmacro %}')
+ assert tmpl.module.foo.arguments == ('a', 'b')
+ assert tmpl.module.foo.defaults == ()
+ assert tmpl.module.foo.name == 'foo'
+ assert not tmpl.module.foo.caller
+ assert not tmpl.module.foo.catch_kwargs
+ assert not tmpl.module.foo.catch_varargs
+ assert tmpl.module.bar.arguments == ()
+ assert tmpl.module.bar.defaults == ()
+ assert not tmpl.module.bar.caller
+ assert tmpl.module.bar.catch_kwargs
+ assert tmpl.module.bar.catch_varargs
+ assert tmpl.module.baz.caller
+
+ def test_callself(self):
+ tmpl = self.env.from_string('{% macro foo(x) %}{{ x }}{% if x > 1 %}|'
+ '{{ foo(x - 1) }}{% endif %}{% endmacro %}'
+ '{{ foo(5) }}')
+ assert tmpl.render() == '5|4|3|2|1'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ForLoopTestCase))
+ suite.addTest(unittest.makeSuite(IfConditionTestCase))
+ suite.addTest(unittest.makeSuite(MacrosTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/debug.py b/websdk/jinja2/testsuite/debug.py
new file mode 100644
index 0000000..7552dec
--- /dev/null
+++ b/websdk/jinja2/testsuite/debug.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.debug
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the debug system.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+import unittest
+
+from jinja2.testsuite import JinjaTestCase, filesystem_loader
+
+from jinja2 import Environment, TemplateSyntaxError
+
+env = Environment(loader=filesystem_loader)
+
+
+class DebugTestCase(JinjaTestCase):
+
+ if sys.version_info[:2] != (2, 4):
+ def test_runtime_error(self):
+ def test():
+ tmpl.render(fail=lambda: 1 / 0)
+ tmpl = env.get_template('broken.html')
+ self.assert_traceback_matches(test, r'''
+ File ".*?broken.html", line 2, in (top-level template code|<module>)
+ \{\{ fail\(\) \}\}
+ File ".*?debug.pyc?", line \d+, in <lambda>
+ tmpl\.render\(fail=lambda: 1 / 0\)
+ZeroDivisionError: (int(eger)? )?division (or modulo )?by zero
+''')
+
+ def test_syntax_error(self):
+ # XXX: the .*? is necessary for python3 which does not hide
+ # some of the stack frames we don't want to show. Not sure
+ # what's up with that, but that is not that critical. Should
+ # be fixed though.
+ self.assert_traceback_matches(lambda: env.get_template('syntaxerror.html'), r'''(?sm)
+ File ".*?syntaxerror.html", line 4, in (template|<module>)
+ \{% endif %\}.*?
+(jinja2\.exceptions\.)?TemplateSyntaxError: Encountered unknown tag 'endif'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.
+ ''')
+
+ def test_regular_syntax_error(self):
+ def test():
+ raise TemplateSyntaxError('wtf', 42)
+ self.assert_traceback_matches(test, r'''
+ File ".*debug.pyc?", line \d+, in test
+ raise TemplateSyntaxError\('wtf', 42\)
+(jinja2\.exceptions\.)?TemplateSyntaxError: wtf
+ line 42''')
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(DebugTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/doctests.py b/websdk/jinja2/testsuite/doctests.py
new file mode 100644
index 0000000..616d3b6
--- /dev/null
+++ b/websdk/jinja2/testsuite/doctests.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.doctests
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ The doctests. Collects all tests we want to test from
+ the Jinja modules.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+import doctest
+
+
+def suite():
+ from jinja2 import utils, sandbox, runtime, meta, loaders, \
+ ext, environment, bccache, nodes
+ suite = unittest.TestSuite()
+ suite.addTest(doctest.DocTestSuite(utils))
+ suite.addTest(doctest.DocTestSuite(sandbox))
+ suite.addTest(doctest.DocTestSuite(runtime))
+ suite.addTest(doctest.DocTestSuite(meta))
+ suite.addTest(doctest.DocTestSuite(loaders))
+ suite.addTest(doctest.DocTestSuite(ext))
+ suite.addTest(doctest.DocTestSuite(environment))
+ suite.addTest(doctest.DocTestSuite(bccache))
+ suite.addTest(doctest.DocTestSuite(nodes))
+ return suite
diff --git a/websdk/jinja2/testsuite/ext.py b/websdk/jinja2/testsuite/ext.py
new file mode 100644
index 0000000..6ca6c22
--- /dev/null
+++ b/websdk/jinja2/testsuite/ext.py
@@ -0,0 +1,455 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.ext
+ ~~~~~~~~~~~~~~~~~~~~
+
+ Tests for the extensions.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import re
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, DictLoader, contextfunction, nodes
+from jinja2.exceptions import TemplateAssertionError
+from jinja2.ext import Extension
+from jinja2.lexer import Token, count_newlines
+from jinja2.utils import next
+
+# 2.x / 3.x
+try:
+ from io import BytesIO
+except ImportError:
+ from StringIO import StringIO as BytesIO
+
+
+importable_object = 23
+
+_gettext_re = re.compile(r'_\((.*?)\)(?s)')
+
+
+i18n_templates = {
+ 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+ '{% block body %}{% endblock %}',
+ 'child.html': '{% extends "master.html" %}{% block body %}'
+ '{% trans %}watch out{% endtrans %}{% endblock %}',
+ 'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+ '{{ user_count }} users online{% endtrans %}',
+ 'stringformat.html': '{{ _("User: %(num)s")|format(num=user_count) }}'
+}
+
+newstyle_i18n_templates = {
+ 'master.html': '<title>{{ page_title|default(_("missing")) }}</title>'
+ '{% block body %}{% endblock %}',
+ 'child.html': '{% extends "master.html" %}{% block body %}'
+ '{% trans %}watch out{% endtrans %}{% endblock %}',
+ 'plural.html': '{% trans user_count %}One user online{% pluralize %}'
+ '{{ user_count }} users online{% endtrans %}',
+ 'stringformat.html': '{{ _("User: %(num)s", num=user_count) }}',
+ 'ngettext.html': '{{ ngettext("%(num)s apple", "%(num)s apples", apples) }}',
+ 'ngettext_long.html': '{% trans num=apples %}{{ num }} apple{% pluralize %}'
+ '{{ num }} apples{% endtrans %}',
+ 'transvars1.html': '{% trans %}User: {{ num }}{% endtrans %}',
+ 'transvars2.html': '{% trans num=count %}User: {{ num }}{% endtrans %}',
+ 'transvars3.html': '{% trans count=num %}User: {{ count }}{% endtrans %}',
+ 'novars.html': '{% trans %}%(hello)s{% endtrans %}',
+ 'vars.html': '{% trans %}{{ foo }}%(foo)s{% endtrans %}',
+ 'explicitvars.html': '{% trans foo="42" %}%(foo)s{% endtrans %}'
+}
+
+
+languages = {
+ 'de': {
+ 'missing': u'fehlend',
+ 'watch out': u'pass auf',
+ 'One user online': u'Ein Benutzer online',
+ '%(user_count)s users online': u'%(user_count)s Benutzer online',
+ 'User: %(num)s': u'Benutzer: %(num)s',
+ 'User: %(count)s': u'Benutzer: %(count)s',
+ '%(num)s apple': u'%(num)s Apfel',
+ '%(num)s apples': u'%(num)s Äpfel'
+ }
+}
+
+
+@contextfunction
+def gettext(context, string):
+ language = context.get('LANGUAGE', 'en')
+ return languages.get(language, {}).get(string, string)
+
+
+@contextfunction
+def ngettext(context, s, p, n):
+ language = context.get('LANGUAGE', 'en')
+ if n != 1:
+ return languages.get(language, {}).get(p, p)
+ return languages.get(language, {}).get(s, s)
+
+
+i18n_env = Environment(
+ loader=DictLoader(i18n_templates),
+ extensions=['jinja2.ext.i18n']
+)
+i18n_env.globals.update({
+ '_': gettext,
+ 'gettext': gettext,
+ 'ngettext': ngettext
+})
+
+newstyle_i18n_env = Environment(
+ loader=DictLoader(newstyle_i18n_templates),
+ extensions=['jinja2.ext.i18n']
+)
+newstyle_i18n_env.install_gettext_callables(gettext, ngettext, newstyle=True)
+
+class TestExtension(Extension):
+ tags = set(['test'])
+ ext_attr = 42
+
+ def parse(self, parser):
+ return nodes.Output([self.call_method('_dump', [
+ nodes.EnvironmentAttribute('sandboxed'),
+ self.attr('ext_attr'),
+ nodes.ImportedName(__name__ + '.importable_object'),
+ nodes.ContextReference()
+ ])]).set_lineno(next(parser.stream).lineno)
+
+ def _dump(self, sandboxed, ext_attr, imported_object, context):
+ return '%s|%s|%s|%s' % (
+ sandboxed,
+ ext_attr,
+ imported_object,
+ context.blocks
+ )
+
+
+class PreprocessorExtension(Extension):
+
+ def preprocess(self, source, name, filename=None):
+ return source.replace('[[TEST]]', '({{ foo }})')
+
+
+class StreamFilterExtension(Extension):
+
+ def filter_stream(self, stream):
+ for token in stream:
+ if token.type == 'data':
+ for t in self.interpolate(token):
+ yield t
+ else:
+ yield token
+
+ def interpolate(self, token):
+ pos = 0
+ end = len(token.value)
+ lineno = token.lineno
+ while 1:
+ match = _gettext_re.search(token.value, pos)
+ if match is None:
+ break
+ value = token.value[pos:match.start()]
+ if value:
+ yield Token(lineno, 'data', value)
+ lineno += count_newlines(token.value)
+ yield Token(lineno, 'variable_begin', None)
+ yield Token(lineno, 'name', 'gettext')
+ yield Token(lineno, 'lparen', None)
+ yield Token(lineno, 'string', match.group(1))
+ yield Token(lineno, 'rparen', None)
+ yield Token(lineno, 'variable_end', None)
+ pos = match.end()
+ if pos < end:
+ yield Token(lineno, 'data', token.value[pos:])
+
+
+class ExtensionsTestCase(JinjaTestCase):
+
+ def test_extend_late(self):
+ env = Environment()
+ env.add_extension('jinja2.ext.autoescape')
+ t = env.from_string('{% autoescape true %}{{ "<test>" }}{% endautoescape %}')
+ assert t.render() == '&lt;test&gt;'
+
+ def test_loop_controls(self):
+ env = Environment(extensions=['jinja2.ext.loopcontrols'])
+
+ tmpl = env.from_string('''
+ {%- for item in [1, 2, 3, 4] %}
+ {%- if item % 2 == 0 %}{% continue %}{% endif -%}
+ {{ item }}
+ {%- endfor %}''')
+ assert tmpl.render() == '13'
+
+ tmpl = env.from_string('''
+ {%- for item in [1, 2, 3, 4] %}
+ {%- if item > 2 %}{% break %}{% endif -%}
+ {{ item }}
+ {%- endfor %}''')
+ assert tmpl.render() == '12'
+
+ def test_do(self):
+ env = Environment(extensions=['jinja2.ext.do'])
+ tmpl = env.from_string('''
+ {%- set items = [] %}
+ {%- for char in "foo" %}
+ {%- do items.append(loop.index0 ~ char) %}
+ {%- endfor %}{{ items|join(', ') }}''')
+ assert tmpl.render() == '0f, 1o, 2o'
+
+ def test_with(self):
+ env = Environment(extensions=['jinja2.ext.with_'])
+ tmpl = env.from_string('''\
+ {% with a=42, b=23 -%}
+ {{ a }} = {{ b }}
+ {% endwith -%}
+ {{ a }} = {{ b }}\
+ ''')
+ assert [x.strip() for x in tmpl.render(a=1, b=2).splitlines()] \
+ == ['42 = 23', '1 = 2']
+
+ def test_extension_nodes(self):
+ env = Environment(extensions=[TestExtension])
+ tmpl = env.from_string('{% test %}')
+ assert tmpl.render() == 'False|42|23|{}'
+
+ def test_identifier(self):
+ assert TestExtension.identifier == __name__ + '.TestExtension'
+
+ def test_rebinding(self):
+ original = Environment(extensions=[TestExtension])
+ overlay = original.overlay()
+ for env in original, overlay:
+ for ext in env.extensions.itervalues():
+ assert ext.environment is env
+
+ def test_preprocessor_extension(self):
+ env = Environment(extensions=[PreprocessorExtension])
+ tmpl = env.from_string('{[[TEST]]}')
+ assert tmpl.render(foo=42) == '{(42)}'
+
+ def test_streamfilter_extension(self):
+ env = Environment(extensions=[StreamFilterExtension])
+ env.globals['gettext'] = lambda x: x.upper()
+ tmpl = env.from_string('Foo _(bar) Baz')
+ out = tmpl.render()
+ assert out == 'Foo BAR Baz'
+
+ def test_extension_ordering(self):
+ class T1(Extension):
+ priority = 1
+ class T2(Extension):
+ priority = 2
+ env = Environment(extensions=[T1, T2])
+ ext = list(env.iter_extensions())
+ assert ext[0].__class__ is T1
+ assert ext[1].__class__ is T2
+
+
+class InternationalizationTestCase(JinjaTestCase):
+
+ def test_trans(self):
+ tmpl = i18n_env.get_template('child.html')
+ assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+ def test_trans_plural(self):
+ tmpl = i18n_env.get_template('plural.html')
+ assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+ def test_complex_plural(self):
+ tmpl = i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
+ assert tmpl.render() == '2 items'
+ self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+ def test_trans_stringformatting(self):
+ tmpl = i18n_env.get_template('stringformat.html')
+ assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+ def test_extract(self):
+ from jinja2.ext import babel_extract
+ source = BytesIO('''
+ {{ gettext('Hello World') }}
+ {% trans %}Hello World{% endtrans %}
+ {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+ '''.encode('ascii')) # make python 3 happy
+ assert list(babel_extract(source, ('gettext', 'ngettext', '_'), [], {})) == [
+ (2, 'gettext', u'Hello World', []),
+ (3, 'gettext', u'Hello World', []),
+ (4, 'ngettext', (u'%(users)s user', u'%(users)s users', None), [])
+ ]
+
+ def test_comment_extract(self):
+ from jinja2.ext import babel_extract
+ source = BytesIO('''
+ {# trans first #}
+ {{ gettext('Hello World') }}
+ {% trans %}Hello World{% endtrans %}{# trans second #}
+ {#: third #}
+ {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
+ '''.encode('utf-8')) # make python 3 happy
+ assert list(babel_extract(source, ('gettext', 'ngettext', '_'), ['trans', ':'], {})) == [
+ (3, 'gettext', u'Hello World', ['first']),
+ (4, 'gettext', u'Hello World', ['second']),
+ (6, 'ngettext', (u'%(users)s user', u'%(users)s users', None), ['third'])
+ ]
+
+
+class NewstyleInternationalizationTestCase(JinjaTestCase):
+
+ def test_trans(self):
+ tmpl = newstyle_i18n_env.get_template('child.html')
+ assert tmpl.render(LANGUAGE='de') == '<title>fehlend</title>pass auf'
+
+ def test_trans_plural(self):
+ tmpl = newstyle_i18n_env.get_template('plural.html')
+ assert tmpl.render(LANGUAGE='de', user_count=1) == 'Ein Benutzer online'
+ assert tmpl.render(LANGUAGE='de', user_count=2) == '2 Benutzer online'
+
+ def test_complex_plural(self):
+ tmpl = newstyle_i18n_env.from_string('{% trans foo=42, count=2 %}{{ count }} item{% '
+ 'pluralize count %}{{ count }} items{% endtrans %}')
+ assert tmpl.render() == '2 items'
+ self.assert_raises(TemplateAssertionError, i18n_env.from_string,
+ '{% trans foo %}...{% pluralize bar %}...{% endtrans %}')
+
+ def test_trans_stringformatting(self):
+ tmpl = newstyle_i18n_env.get_template('stringformat.html')
+ assert tmpl.render(LANGUAGE='de', user_count=5) == 'Benutzer: 5'
+
+ def test_newstyle_plural(self):
+ tmpl = newstyle_i18n_env.get_template('ngettext.html')
+ assert tmpl.render(LANGUAGE='de', apples=1) == '1 Apfel'
+ assert tmpl.render(LANGUAGE='de', apples=5) == u'5 Äpfel'
+
+ def test_autoescape_support(self):
+ env = Environment(extensions=['jinja2.ext.autoescape',
+ 'jinja2.ext.i18n'])
+ env.install_gettext_callables(lambda x: u'<strong>Wert: %(name)s</strong>',
+ lambda s, p, n: s, newstyle=True)
+ t = env.from_string('{% autoescape ae %}{{ gettext("foo", name='
+ '"<test>") }}{% endautoescape %}')
+ assert t.render(ae=True) == '<strong>Wert: &lt;test&gt;</strong>'
+ assert t.render(ae=False) == '<strong>Wert: <test></strong>'
+
+ def test_num_used_twice(self):
+ tmpl = newstyle_i18n_env.get_template('ngettext_long.html')
+ assert tmpl.render(apples=5, LANGUAGE='de') == u'5 Äpfel'
+
+ def test_num_called_num(self):
+ source = newstyle_i18n_env.compile('''
+ {% trans num=3 %}{{ num }} apple{% pluralize
+ %}{{ num }} apples{% endtrans %}
+ ''', raw=True)
+ # quite hacky, but the only way to properly test that. The idea is
+ # that the generated code does not pass num twice (although that
+ # would work) for better performance. This only works on the
+ # newstyle gettext of course
+ assert re.search(r"l_ngettext, u?'\%\(num\)s apple', u?'\%\(num\)s "
+ r"apples', 3", source) is not None
+
+ def test_trans_vars(self):
+ t1 = newstyle_i18n_env.get_template('transvars1.html')
+ t2 = newstyle_i18n_env.get_template('transvars2.html')
+ t3 = newstyle_i18n_env.get_template('transvars3.html')
+ assert t1.render(num=1, LANGUAGE='de') == 'Benutzer: 1'
+ assert t2.render(count=23, LANGUAGE='de') == 'Benutzer: 23'
+ assert t3.render(num=42, LANGUAGE='de') == 'Benutzer: 42'
+
+ def test_novars_vars_escaping(self):
+ t = newstyle_i18n_env.get_template('novars.html')
+ assert t.render() == '%(hello)s'
+ t = newstyle_i18n_env.get_template('vars.html')
+ assert t.render(foo='42') == '42%(foo)s'
+ t = newstyle_i18n_env.get_template('explicitvars.html')
+ assert t.render() == '%(foo)s'
+
+
+class AutoEscapeTestCase(JinjaTestCase):
+
+ def test_scoped_setting(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('''
+ {{ "<HelloWorld>" }}
+ {% autoescape false %}
+ {{ "<HelloWorld>" }}
+ {% endautoescape %}
+ {{ "<HelloWorld>" }}
+ ''')
+ assert tmpl.render().split() == \
+ [u'&lt;HelloWorld&gt;', u'<HelloWorld>', u'&lt;HelloWorld&gt;']
+
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=False)
+ tmpl = env.from_string('''
+ {{ "<HelloWorld>" }}
+ {% autoescape true %}
+ {{ "<HelloWorld>" }}
+ {% endautoescape %}
+ {{ "<HelloWorld>" }}
+ ''')
+ assert tmpl.render().split() == \
+ [u'<HelloWorld>', u'&lt;HelloWorld&gt;', u'<HelloWorld>']
+
+ def test_nonvolatile(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('{{ {"foo": "<test>"}|xmlattr|escape }}')
+ assert tmpl.render() == ' foo="&lt;test&gt;"'
+ tmpl = env.from_string('{% autoescape false %}{{ {"foo": "<test>"}'
+ '|xmlattr|escape }}{% endautoescape %}')
+ assert tmpl.render() == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+
+ def test_volatile(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ tmpl = env.from_string('{% autoescape foo %}{{ {"foo": "<test>"}'
+ '|xmlattr|escape }}{% endautoescape %}')
+ assert tmpl.render(foo=False) == ' foo=&#34;&amp;lt;test&amp;gt;&#34;'
+ assert tmpl.render(foo=True) == ' foo="&lt;test&gt;"'
+
+ def test_scoping(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ tmpl = env.from_string('{% autoescape true %}{% set x = "<x>" %}{{ x }}'
+ '{% endautoescape %}{{ x }}{{ "<y>" }}')
+ assert tmpl.render(x=1) == '&lt;x&gt;1<y>'
+
+ def test_volatile_scoping(self):
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ tmplsource = '''
+ {% autoescape val %}
+ {% macro foo(x) %}
+ [{{ x }}]
+ {% endmacro %}
+ {{ foo().__class__.__name__ }}
+ {% endautoescape %}
+ {{ '<testing>' }}
+ '''
+ tmpl = env.from_string(tmplsource)
+ assert tmpl.render(val=True).split()[0] == 'Markup'
+ assert tmpl.render(val=False).split()[0] == unicode.__name__
+
+ # looking at the source we should see <testing> there in raw
+ # (and then escaped as well)
+ env = Environment(extensions=['jinja2.ext.autoescape'])
+ pysource = env.compile(tmplsource, raw=True)
+ assert '<testing>\\n' in pysource
+
+ env = Environment(extensions=['jinja2.ext.autoescape'],
+ autoescape=True)
+ pysource = env.compile(tmplsource, raw=True)
+ assert '&lt;testing&gt;\\n' in pysource
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ExtensionsTestCase))
+ suite.addTest(unittest.makeSuite(InternationalizationTestCase))
+ suite.addTest(unittest.makeSuite(NewstyleInternationalizationTestCase))
+ suite.addTest(unittest.makeSuite(AutoEscapeTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/filters.py b/websdk/jinja2/testsuite/filters.py
new file mode 100644
index 0000000..aefe768
--- /dev/null
+++ b/websdk/jinja2/testsuite/filters.py
@@ -0,0 +1,356 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.filters
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests for the jinja filters.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class FilterTestCase(JinjaTestCase):
+
+ def test_capitalize(self):
+ tmpl = env.from_string('{{ "foo bar"|capitalize }}')
+ assert tmpl.render() == 'Foo bar'
+
+ def test_center(self):
+ tmpl = env.from_string('{{ "foo"|center(9) }}')
+ assert tmpl.render() == ' foo '
+
+ def test_default(self):
+ tmpl = env.from_string(
+ "{{ missing|default('no') }}|{{ false|default('no') }}|"
+ "{{ false|default('no', true) }}|{{ given|default('no') }}"
+ )
+ assert tmpl.render(given='yes') == 'no|False|no|yes'
+
+ def test_dictsort(self):
+ tmpl = env.from_string(
+ '{{ foo|dictsort }}|'
+ '{{ foo|dictsort(true) }}|'
+ '{{ foo|dictsort(false, "value") }}'
+ )
+ out = tmpl.render(foo={"aa": 0, "b": 1, "c": 2, "AB": 3})
+ assert out == ("[('aa', 0), ('AB', 3), ('b', 1), ('c', 2)]|"
+ "[('AB', 3), ('aa', 0), ('b', 1), ('c', 2)]|"
+ "[('aa', 0), ('b', 1), ('c', 2), ('AB', 3)]")
+
+ def test_batch(self):
+ tmpl = env.from_string("{{ foo|batch(3)|list }}|"
+ "{{ foo|batch(3, 'X')|list }}")
+ out = tmpl.render(foo=range(10))
+ assert out == ("[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9]]|"
+ "[[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 'X', 'X']]")
+
+ def test_slice(self):
+ tmpl = env.from_string('{{ foo|slice(3)|list }}|'
+ '{{ foo|slice(3, "X")|list }}')
+ out = tmpl.render(foo=range(10))
+ assert out == ("[[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]]|"
+ "[[0, 1, 2, 3], [4, 5, 6, 'X'], [7, 8, 9, 'X']]")
+
+ def test_escape(self):
+ tmpl = env.from_string('''{{ '<">&'|escape }}''')
+ out = tmpl.render()
+ assert out == '&lt;&#34;&gt;&amp;'
+
+ def test_striptags(self):
+ tmpl = env.from_string('''{{ foo|striptags }}''')
+ out = tmpl.render(foo=' <p>just a small \n <a href="#">'
+ 'example</a> link</p>\n<p>to a webpage</p> '
+ '<!-- <p>and some commented stuff</p> -->')
+ assert out == 'just a small example link to a webpage'
+
+ def test_filesizeformat(self):
+ tmpl = env.from_string(
+ '{{ 100|filesizeformat }}|'
+ '{{ 1000|filesizeformat }}|'
+ '{{ 1000000|filesizeformat }}|'
+ '{{ 1000000000|filesizeformat }}|'
+ '{{ 1000000000000|filesizeformat }}|'
+ '{{ 100|filesizeformat(true) }}|'
+ '{{ 1000|filesizeformat(true) }}|'
+ '{{ 1000000|filesizeformat(true) }}|'
+ '{{ 1000000000|filesizeformat(true) }}|'
+ '{{ 1000000000000|filesizeformat(true) }}'
+ )
+ out = tmpl.render()
+ assert out == (
+ '100 Bytes|0.0 kB|0.0 MB|0.0 GB|0.0 TB|100 Bytes|'
+ '1000 Bytes|1.0 KiB|0.9 MiB|0.9 GiB'
+ )
+
+ def test_first(self):
+ tmpl = env.from_string('{{ foo|first }}')
+ out = tmpl.render(foo=range(10))
+ assert out == '0'
+
+ def test_float(self):
+ tmpl = env.from_string('{{ "42"|float }}|'
+ '{{ "ajsghasjgd"|float }}|'
+ '{{ "32.32"|float }}')
+ out = tmpl.render()
+ assert out == '42.0|0.0|32.32'
+
+ def test_format(self):
+ tmpl = env.from_string('''{{ "%s|%s"|format("a", "b") }}''')
+ out = tmpl.render()
+ assert out == 'a|b'
+
+ def test_indent(self):
+ tmpl = env.from_string('{{ foo|indent(2) }}|{{ foo|indent(2, true) }}')
+ text = '\n'.join([' '.join(['foo', 'bar'] * 2)] * 2)
+ out = tmpl.render(foo=text)
+ assert out == ('foo bar foo bar\n foo bar foo bar| '
+ 'foo bar foo bar\n foo bar foo bar')
+
+ def test_int(self):
+ tmpl = env.from_string('{{ "42"|int }}|{{ "ajsghasjgd"|int }}|'
+ '{{ "32.32"|int }}')
+ out = tmpl.render()
+ assert out == '42|0|32'
+
+ def test_join(self):
+ tmpl = env.from_string('{{ [1, 2, 3]|join("|") }}')
+ out = tmpl.render()
+ assert out == '1|2|3'
+
+ env2 = Environment(autoescape=True)
+ tmpl = env2.from_string('{{ ["<foo>", "<span>foo</span>"|safe]|join }}')
+ assert tmpl.render() == '&lt;foo&gt;<span>foo</span>'
+
+ def test_join_attribute(self):
+ class User(object):
+ def __init__(self, username):
+ self.username = username
+ tmpl = env.from_string('''{{ users|join(', ', 'username') }}''')
+ assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar'
+
+ def test_last(self):
+ tmpl = env.from_string('''{{ foo|last }}''')
+ out = tmpl.render(foo=range(10))
+ assert out == '9'
+
+ def test_length(self):
+ tmpl = env.from_string('''{{ "hello world"|length }}''')
+ out = tmpl.render()
+ assert out == '11'
+
+ def test_lower(self):
+ tmpl = env.from_string('''{{ "FOO"|lower }}''')
+ out = tmpl.render()
+ assert out == 'foo'
+
+ def test_pprint(self):
+ from pprint import pformat
+ tmpl = env.from_string('''{{ data|pprint }}''')
+ data = range(1000)
+ assert tmpl.render(data=data) == pformat(data)
+
+ def test_random(self):
+ tmpl = env.from_string('''{{ seq|random }}''')
+ seq = range(100)
+ for _ in range(10):
+ assert int(tmpl.render(seq=seq)) in seq
+
+ def test_reverse(self):
+ tmpl = env.from_string('{{ "foobar"|reverse|join }}|'
+ '{{ [1, 2, 3]|reverse|list }}')
+ assert tmpl.render() == 'raboof|[3, 2, 1]'
+
+ def test_string(self):
+ x = [1, 2, 3, 4, 5]
+ tmpl = env.from_string('''{{ obj|string }}''')
+ assert tmpl.render(obj=x) == unicode(x)
+
+ def test_title(self):
+ tmpl = env.from_string('''{{ "foo bar"|title }}''')
+ assert tmpl.render() == "Foo Bar"
+
+ def test_truncate(self):
+ tmpl = env.from_string(
+ '{{ data|truncate(15, true, ">>>") }}|'
+ '{{ data|truncate(15, false, ">>>") }}|'
+ '{{ smalldata|truncate(15) }}'
+ )
+ out = tmpl.render(data='foobar baz bar' * 1000,
+ smalldata='foobar baz bar')
+ assert out == 'foobar baz barf>>>|foobar baz >>>|foobar baz bar'
+
+ def test_upper(self):
+ tmpl = env.from_string('{{ "foo"|upper }}')
+ assert tmpl.render() == 'FOO'
+
+ def test_urlize(self):
+ tmpl = env.from_string('{{ "foo http://www.example.com/ bar"|urlize }}')
+ assert tmpl.render() == 'foo <a href="http://www.example.com/">'\
+ 'http://www.example.com/</a> bar'
+
+ def test_wordcount(self):
+ tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
+ assert tmpl.render() == '3'
+
+ def test_block(self):
+ tmpl = env.from_string('{% filter lower|escape %}<HEHE>{% endfilter %}')
+ assert tmpl.render() == '&lt;hehe&gt;'
+
+ def test_chaining(self):
+ tmpl = env.from_string('''{{ ['<foo>', '<bar>']|first|upper|escape }}''')
+ assert tmpl.render() == '&lt;FOO&gt;'
+
+ def test_sum(self):
+ tmpl = env.from_string('''{{ [1, 2, 3, 4, 5, 6]|sum }}''')
+ assert tmpl.render() == '21'
+
+ def test_sum_attributes(self):
+ tmpl = env.from_string('''{{ values|sum('value') }}''')
+ assert tmpl.render(values=[
+ {'value': 23},
+ {'value': 1},
+ {'value': 18},
+ ]) == '42'
+
+ def test_sum_attributes_nested(self):
+ tmpl = env.from_string('''{{ values|sum('real.value') }}''')
+ assert tmpl.render(values=[
+ {'real': {'value': 23}},
+ {'real': {'value': 1}},
+ {'real': {'value': 18}},
+ ]) == '42'
+
+ def test_abs(self):
+ tmpl = env.from_string('''{{ -1|abs }}|{{ 1|abs }}''')
+ assert tmpl.render() == '1|1', tmpl.render()
+
+ def test_round_positive(self):
+ tmpl = env.from_string('{{ 2.7|round }}|{{ 2.1|round }}|'
+ "{{ 2.1234|round(3, 'floor') }}|"
+ "{{ 2.1|round(0, 'ceil') }}")
+ assert tmpl.render() == '3.0|2.0|2.123|3.0', tmpl.render()
+
+ def test_round_negative(self):
+ tmpl = env.from_string('{{ 21.3|round(-1)}}|'
+ "{{ 21.3|round(-1, 'ceil')}}|"
+ "{{ 21.3|round(-1, 'floor')}}")
+ assert tmpl.render() == '20.0|30.0|20.0',tmpl.render()
+
+ def test_xmlattr(self):
+ tmpl = env.from_string("{{ {'foo': 42, 'bar': 23, 'fish': none, "
+ "'spam': missing, 'blub:blub': '<?>'}|xmlattr }}")
+ out = tmpl.render().split()
+ assert len(out) == 3
+ assert 'foo="42"' in out
+ assert 'bar="23"' in out
+ assert 'blub:blub="&lt;?&gt;"' in out
+
+ def test_sort1(self):
+ tmpl = env.from_string('{{ [2, 3, 1]|sort }}|{{ [2, 3, 1]|sort(true) }}')
+ assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+ def test_sort2(self):
+ tmpl = env.from_string('{{ "".join(["c", "A", "b", "D"]|sort) }}')
+ assert tmpl.render() == 'AbcD'
+
+ def test_sort3(self):
+ tmpl = env.from_string('''{{ ['foo', 'Bar', 'blah']|sort }}''')
+ assert tmpl.render() == "['Bar', 'blah', 'foo']"
+
+ def test_sort4(self):
+ class Magic(object):
+ def __init__(self, value):
+ self.value = value
+ def __unicode__(self):
+ return unicode(self.value)
+ tmpl = env.from_string('''{{ items|sort(attribute='value')|join }}''')
+ assert tmpl.render(items=map(Magic, [3, 2, 4, 1])) == '1234'
+
+ def test_groupby(self):
+ tmpl = env.from_string('''
+ {%- for grouper, list in [{'foo': 1, 'bar': 2},
+ {'foo': 2, 'bar': 3},
+ {'foo': 1, 'bar': 1},
+ {'foo': 3, 'bar': 4}]|groupby('foo') -%}
+ {{ grouper }}{% for x in list %}: {{ x.foo }}, {{ x.bar }}{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render().split('|') == [
+ "1: 1, 2: 1, 1",
+ "2: 2, 3",
+ "3: 3, 4",
+ ""
+ ]
+
+ def test_groupby_tuple_index(self):
+ tmpl = env.from_string('''
+ {%- for grouper, list in [('a', 1), ('a', 2), ('b', 1)]|groupby(0) -%}
+ {{ grouper }}{% for x in list %}:{{ x.1 }}{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render() == 'a:1:2|b:1|'
+
+ def test_groupby_multidot(self):
+ class Date(object):
+ def __init__(self, day, month, year):
+ self.day = day
+ self.month = month
+ self.year = year
+ class Article(object):
+ def __init__(self, title, *date):
+ self.date = Date(*date)
+ self.title = title
+ articles = [
+ Article('aha', 1, 1, 1970),
+ Article('interesting', 2, 1, 1970),
+ Article('really?', 3, 1, 1970),
+ Article('totally not', 1, 1, 1971)
+ ]
+ tmpl = env.from_string('''
+ {%- for year, list in articles|groupby('date.year') -%}
+ {{ year }}{% for x in list %}[{{ x.title }}]{% endfor %}|
+ {%- endfor %}''')
+ assert tmpl.render(articles=articles).split('|') == [
+ '1970[aha][interesting][really?]',
+ '1971[totally not]',
+ ''
+ ]
+
+ def test_filtertag(self):
+ tmpl = env.from_string("{% filter upper|replace('FOO', 'foo') %}"
+ "foobar{% endfilter %}")
+ assert tmpl.render() == 'fooBAR'
+
+ def test_replace(self):
+ env = Environment()
+ tmpl = env.from_string('{{ string|replace("o", 42) }}')
+ assert tmpl.render(string='<foo>') == '<f4242>'
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ string|replace("o", 42) }}')
+ assert tmpl.render(string='<foo>') == '&lt;f4242&gt;'
+ tmpl = env.from_string('{{ string|replace("<", 42) }}')
+ assert tmpl.render(string='<foo>') == '42foo&gt;'
+ tmpl = env.from_string('{{ string|replace("o", ">x<") }}')
+ assert tmpl.render(string=Markup('foo')) == 'f&gt;x&lt;&gt;x&lt;'
+
+ def test_forceescape(self):
+ tmpl = env.from_string('{{ x|forceescape }}')
+ assert tmpl.render(x=Markup('<div />')) == u'&lt;div /&gt;'
+
+ def test_safe(self):
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ "<div>foo</div>"|safe }}')
+ assert tmpl.render() == '<div>foo</div>'
+ tmpl = env.from_string('{{ "<div>foo</div>" }}')
+ assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(FilterTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/imports.py b/websdk/jinja2/testsuite/imports.py
new file mode 100644
index 0000000..1cb12cb
--- /dev/null
+++ b/websdk/jinja2/testsuite/imports.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.imports
+ ~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the import features (with includes).
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, DictLoader
+from jinja2.exceptions import TemplateNotFound, TemplatesNotFound
+
+
+test_env = Environment(loader=DictLoader(dict(
+ module='{% macro test() %}[{{ foo }}|{{ bar }}]{% endmacro %}',
+ header='[{{ foo }}|{{ 23 }}]',
+ o_printer='({{ o }})'
+)))
+test_env.globals['bar'] = 23
+
+
+class ImportsTestCase(JinjaTestCase):
+
+ def test_context_imports(self):
+ t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string('{% import "module" as m without context %}{{ m.test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string('{% import "module" as m with context %}{{ m.test() }}')
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% from "module" import test %}{{ test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string('{% from "module" import test without context %}{{ test() }}')
+ assert t.render(foo=42) == '[|23]'
+ t = test_env.from_string('{% from "module" import test with context %}{{ test() }}')
+ assert t.render(foo=42) == '[42|23]'
+
+ def test_trailing_comma(self):
+ test_env.from_string('{% from "foo" import bar, baz with context %}')
+ test_env.from_string('{% from "foo" import bar, baz, with context %}')
+ test_env.from_string('{% from "foo" import bar, with context %}')
+ test_env.from_string('{% from "foo" import bar, with, context %}')
+ test_env.from_string('{% from "foo" import bar, with with context %}')
+
+ def test_exports(self):
+ m = test_env.from_string('''
+ {% macro toplevel() %}...{% endmacro %}
+ {% macro __private() %}...{% endmacro %}
+ {% set variable = 42 %}
+ {% for item in [1] %}
+ {% macro notthere() %}{% endmacro %}
+ {% endfor %}
+ ''').module
+ assert m.toplevel() == '...'
+ assert not hasattr(m, '__missing')
+ assert m.variable == 42
+ assert not hasattr(m, 'notthere')
+
+
+class IncludesTestCase(JinjaTestCase):
+
+ def test_context_include(self):
+ t = test_env.from_string('{% include "header" %}')
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% include "header" with context %}')
+ assert t.render(foo=42) == '[42|23]'
+ t = test_env.from_string('{% include "header" without context %}')
+ assert t.render(foo=42) == '[|23]'
+
+ def test_choice_includes(self):
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ assert t.render(foo=42) == '[42|23]'
+
+ t = test_env.from_string('{% include ["missing", "missing2"] ignore missing %}')
+ assert t.render(foo=42) == ''
+
+ t = test_env.from_string('{% include ["missing", "missing2"] %}')
+ self.assert_raises(TemplateNotFound, t.render)
+ try:
+ t.render()
+ except TemplatesNotFound, e:
+ assert e.templates == ['missing', 'missing2']
+ assert e.name == 'missing2'
+ else:
+ assert False, 'thou shalt raise'
+
+ def test_includes(t, **ctx):
+ ctx['foo'] = 42
+ assert t.render(ctx) == '[42|23]'
+
+ t = test_env.from_string('{% include ["missing", "header"] %}')
+ test_includes(t)
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x=['missing', 'header'])
+ t = test_env.from_string('{% include [x, "header"] %}')
+ test_includes(t, x='missing')
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x='header')
+ t = test_env.from_string('{% include x %}')
+ test_includes(t, x='header')
+ t = test_env.from_string('{% include [x] %}')
+ test_includes(t, x='header')
+
+ def test_include_ignoring_missing(self):
+ t = test_env.from_string('{% include "missing" %}')
+ self.assert_raises(TemplateNotFound, t.render)
+ for extra in '', 'with context', 'without context':
+ t = test_env.from_string('{% include "missing" ignore missing ' +
+ extra + ' %}')
+ assert t.render() == ''
+
+ def test_context_include_with_overrides(self):
+ env = Environment(loader=DictLoader(dict(
+ main="{% for item in [1, 2, 3] %}{% include 'item' %}{% endfor %}",
+ item="{{ item }}"
+ )))
+ assert env.get_template("main").render() == "123"
+
+ def test_unoptimized_scopes(self):
+ t = test_env.from_string("""
+ {% macro outer(o) %}
+ {% macro inner() %}
+ {% include "o_printer" %}
+ {% endmacro %}
+ {{ inner() }}
+ {% endmacro %}
+ {{ outer("FOO") }}
+ """)
+ assert t.render().strip() == '(FOO)'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(ImportsTestCase))
+ suite.addTest(unittest.makeSuite(IncludesTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/inheritance.py b/websdk/jinja2/testsuite/inheritance.py
new file mode 100644
index 0000000..355aa0c
--- /dev/null
+++ b/websdk/jinja2/testsuite/inheritance.py
@@ -0,0 +1,227 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.inheritance
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests the template inheritance feature.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, DictLoader
+
+
+LAYOUTTEMPLATE = '''\
+|{% block block1 %}block 1 from layout{% endblock %}
+|{% block block2 %}block 2 from layout{% endblock %}
+|{% block block3 %}
+{% block block4 %}nested block 4 from layout{% endblock %}
+{% endblock %}|'''
+
+LEVEL1TEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}block 1 from level1{% endblock %}'''
+
+LEVEL2TEMPLATE = '''\
+{% extends "level1" %}
+{% block block2 %}{% block block5 %}nested block 5 from level2{%
+endblock %}{% endblock %}'''
+
+LEVEL3TEMPLATE = '''\
+{% extends "level2" %}
+{% block block5 %}block 5 from level3{% endblock %}
+{% block block4 %}block 4 from level3{% endblock %}
+'''
+
+LEVEL4TEMPLATE = '''\
+{% extends "level3" %}
+{% block block3 %}block 3 from level4{% endblock %}
+'''
+
+WORKINGTEMPLATE = '''\
+{% extends "layout" %}
+{% block block1 %}
+ {% if false %}
+ {% block block2 %}
+ this should workd
+ {% endblock %}
+ {% endif %}
+{% endblock %}
+'''
+
+env = Environment(loader=DictLoader({
+ 'layout': LAYOUTTEMPLATE,
+ 'level1': LEVEL1TEMPLATE,
+ 'level2': LEVEL2TEMPLATE,
+ 'level3': LEVEL3TEMPLATE,
+ 'level4': LEVEL4TEMPLATE,
+ 'working': WORKINGTEMPLATE
+}), trim_blocks=True)
+
+
+class InheritanceTestCase(JinjaTestCase):
+
+ def test_layout(self):
+ tmpl = env.get_template('layout')
+ assert tmpl.render() == ('|block 1 from layout|block 2 from '
+ 'layout|nested block 4 from layout|')
+
+ def test_level1(self):
+ tmpl = env.get_template('level1')
+ assert tmpl.render() == ('|block 1 from level1|block 2 from '
+ 'layout|nested block 4 from layout|')
+
+ def test_level2(self):
+ tmpl = env.get_template('level2')
+ assert tmpl.render() == ('|block 1 from level1|nested block 5 from '
+ 'level2|nested block 4 from layout|')
+
+ def test_level3(self):
+ tmpl = env.get_template('level3')
+ assert tmpl.render() == ('|block 1 from level1|block 5 from level3|'
+ 'block 4 from level3|')
+
+ def test_level4(sel):
+ tmpl = env.get_template('level4')
+ assert tmpl.render() == ('|block 1 from level1|block 5 from '
+ 'level3|block 3 from level4|')
+
+ def test_super(self):
+ env = Environment(loader=DictLoader({
+ 'a': '{% block intro %}INTRO{% endblock %}|'
+ 'BEFORE|{% block data %}INNER{% endblock %}|AFTER',
+ 'b': '{% extends "a" %}{% block data %}({{ '
+ 'super() }}){% endblock %}',
+ 'c': '{% extends "b" %}{% block intro %}--{{ '
+ 'super() }}--{% endblock %}\n{% block data '
+ '%}[{{ super() }}]{% endblock %}'
+ }))
+ tmpl = env.get_template('c')
+ assert tmpl.render() == '--INTRO--|BEFORE|[(INNER)]|AFTER'
+
+ def test_working(self):
+ tmpl = env.get_template('working')
+
+ def test_reuse_blocks(self):
+ tmpl = env.from_string('{{ self.foo() }}|{% block foo %}42'
+ '{% endblock %}|{{ self.foo() }}')
+ assert tmpl.render() == '42|42|42'
+
+ def test_preserve_blocks(self):
+ env = Environment(loader=DictLoader({
+ 'a': '{% if false %}{% block x %}A{% endblock %}{% endif %}{{ self.x() }}',
+ 'b': '{% extends "a" %}{% block x %}B{{ super() }}{% endblock %}'
+ }))
+ tmpl = env.get_template('b')
+ assert tmpl.render() == 'BA'
+
+ def test_dynamic_inheritance(self):
+ env = Environment(loader=DictLoader({
+ 'master1': 'MASTER1{% block x %}{% endblock %}',
+ 'master2': 'MASTER2{% block x %}{% endblock %}',
+ 'child': '{% extends master %}{% block x %}CHILD{% endblock %}'
+ }))
+ tmpl = env.get_template('child')
+ for m in range(1, 3):
+ assert tmpl.render(master='master%d' % m) == 'MASTER%dCHILD' % m
+
+ def test_multi_inheritance(self):
+ env = Environment(loader=DictLoader({
+ 'master1': 'MASTER1{% block x %}{% endblock %}',
+ 'master2': 'MASTER2{% block x %}{% endblock %}',
+ 'child': '''{% if master %}{% extends master %}{% else %}{% extends
+ 'master1' %}{% endif %}{% block x %}CHILD{% endblock %}'''
+ }))
+ tmpl = env.get_template('child')
+ assert tmpl.render(master='master2') == 'MASTER2CHILD'
+ assert tmpl.render(master='master1') == 'MASTER1CHILD'
+ assert tmpl.render() == 'MASTER1CHILD'
+
+ def test_scoped_block(self):
+ env = Environment(loader=DictLoader({
+ 'master.html': '{% for item in seq %}[{% block item scoped %}'
+ '{% endblock %}]{% endfor %}'
+ }))
+ t = env.from_string('{% extends "master.html" %}{% block item %}'
+ '{{ item }}{% endblock %}')
+ assert t.render(seq=range(5)) == '[0][1][2][3][4]'
+
+ def test_super_in_scoped_block(self):
+ env = Environment(loader=DictLoader({
+ 'master.html': '{% for item in seq %}[{% block item scoped %}'
+ '{{ item }}{% endblock %}]{% endfor %}'
+ }))
+ t = env.from_string('{% extends "master.html" %}{% block item %}'
+ '{{ super() }}|{{ item * 2 }}{% endblock %}')
+ assert t.render(seq=range(5)) == '[0|0][1|2][2|4][3|6][4|8]'
+
+ def test_scoped_block_after_inheritance(self):
+ env = Environment(loader=DictLoader({
+ 'layout.html': '''
+ {% block useless %}{% endblock %}
+ ''',
+ 'index.html': '''
+ {%- extends 'layout.html' %}
+ {% from 'helpers.html' import foo with context %}
+ {% block useless %}
+ {% for x in [1, 2, 3] %}
+ {% block testing scoped %}
+ {{ foo(x) }}
+ {% endblock %}
+ {% endfor %}
+ {% endblock %}
+ ''',
+ 'helpers.html': '''
+ {% macro foo(x) %}{{ the_foo + x }}{% endmacro %}
+ '''
+ }))
+ rv = env.get_template('index.html').render(the_foo=42).split()
+ assert rv == ['43', '44', '45']
+
+
+class BugFixTestCase(JinjaTestCase):
+
+ def test_fixed_macro_scoping_bug(self):
+ assert Environment(loader=DictLoader({
+ 'test.html': '''\
+ {% extends 'details.html' %}
+
+ {% macro my_macro() %}
+ my_macro
+ {% endmacro %}
+
+ {% block inner_box %}
+ {{ my_macro() }}
+ {% endblock %}
+ ''',
+ 'details.html': '''\
+ {% extends 'standard.html' %}
+
+ {% macro my_macro() %}
+ my_macro
+ {% endmacro %}
+
+ {% block content %}
+ {% block outer_box %}
+ outer_box
+ {% block inner_box %}
+ inner_box
+ {% endblock %}
+ {% endblock %}
+ {% endblock %}
+ ''',
+ 'standard.html': '''
+ {% block content %}&nbsp;{% endblock %}
+ '''
+ })).get_template("test.html").render().split() == [u'outer_box', u'my_macro']
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(InheritanceTestCase))
+ suite.addTest(unittest.makeSuite(BugFixTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/lexnparse.py b/websdk/jinja2/testsuite/lexnparse.py
new file mode 100644
index 0000000..77b76ec
--- /dev/null
+++ b/websdk/jinja2/testsuite/lexnparse.py
@@ -0,0 +1,387 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.lexnparse
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ All the unittests regarding lexing, parsing and syntax.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import sys
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment, Template, TemplateSyntaxError, \
+ UndefinedError, nodes
+
+env = Environment()
+
+
+# how does a string look like in jinja syntax?
+if sys.version_info < (3, 0):
+ def jinja_string_repr(string):
+ return repr(string)[1:]
+else:
+ jinja_string_repr = repr
+
+
+class LexerTestCase(JinjaTestCase):
+
+ def test_raw1(self):
+ tmpl = env.from_string('{% raw %}foo{% endraw %}|'
+ '{%raw%}{{ bar }}|{% baz %}{% endraw %}')
+ assert tmpl.render() == 'foo|{{ bar }}|{% baz %}'
+
+ def test_raw2(self):
+ tmpl = env.from_string('1 {%- raw -%} 2 {%- endraw -%} 3')
+ assert tmpl.render() == '123'
+
+ def test_balancing(self):
+ env = Environment('{%', '%}', '${', '}')
+ tmpl = env.from_string('''{% for item in seq
+ %}${{'foo': item}|upper}{% endfor %}''')
+ assert tmpl.render(seq=range(3)) == "{'FOO': 0}{'FOO': 1}{'FOO': 2}"
+
+ def test_comments(self):
+ env = Environment('<!--', '-->', '{', '}')
+ tmpl = env.from_string('''\
+<ul>
+<!--- for item in seq -->
+ <li>{item}</li>
+<!--- endfor -->
+</ul>''')
+ assert tmpl.render(seq=range(3)) == ("<ul>\n <li>0</li>\n "
+ "<li>1</li>\n <li>2</li>\n</ul>")
+
+ def test_string_escapes(self):
+ for char in u'\0', u'\u2668', u'\xe4', u'\t', u'\r', u'\n':
+ tmpl = env.from_string('{{ %s }}' % jinja_string_repr(char))
+ assert tmpl.render() == char
+ assert env.from_string('{{ "\N{HOT SPRINGS}" }}').render() == u'\u2668'
+
+ def test_bytefallback(self):
+ from pprint import pformat
+ tmpl = env.from_string(u'''{{ 'foo'|pprint }}|{{ 'bär'|pprint }}''')
+ assert tmpl.render() == pformat('foo') + '|' + pformat(u'bär')
+
+ def test_operators(self):
+ from jinja2.lexer import operators
+ for test, expect in operators.iteritems():
+ if test in '([{}])':
+ continue
+ stream = env.lexer.tokenize('{{ %s }}' % test)
+ stream.next()
+ assert stream.current.type == expect
+
+ def test_normalizing(self):
+ for seq in '\r', '\r\n', '\n':
+ env = Environment(newline_sequence=seq)
+ tmpl = env.from_string('1\n2\r\n3\n4\n')
+ result = tmpl.render()
+ assert result.replace(seq, 'X') == '1X2X3X4'
+
+
+class ParserTestCase(JinjaTestCase):
+
+ def test_php_syntax(self):
+ env = Environment('<?', '?>', '<?=', '?>', '<!--', '-->')
+ tmpl = env.from_string('''\
+<!-- I'm a comment, I'm not interesting -->\
+<? for item in seq -?>
+ <?= item ?>
+<?- endfor ?>''')
+ assert tmpl.render(seq=range(5)) == '01234'
+
+ def test_erb_syntax(self):
+ env = Environment('<%', '%>', '<%=', '%>', '<%#', '%>')
+ tmpl = env.from_string('''\
+<%# I'm a comment, I'm not interesting %>\
+<% for item in seq -%>
+ <%= item %>
+<%- endfor %>''')
+ assert tmpl.render(seq=range(5)) == '01234'
+
+ def test_comment_syntax(self):
+ env = Environment('<!--', '-->', '${', '}', '<!--#', '-->')
+ tmpl = env.from_string('''\
+<!--# I'm a comment, I'm not interesting -->\
+<!-- for item in seq --->
+ ${item}
+<!--- endfor -->''')
+ assert tmpl.render(seq=range(5)) == '01234'
+
+ def test_balancing(self):
+ tmpl = env.from_string('''{{{'foo':'bar'}.foo}}''')
+ assert tmpl.render() == 'bar'
+
+ def test_start_comment(self):
+ tmpl = env.from_string('''{# foo comment
+and bar comment #}
+{% macro blub() %}foo{% endmacro %}
+{{ blub() }}''')
+ assert tmpl.render().strip() == 'foo'
+
+ def test_line_syntax(self):
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%')
+ tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+ ${item}
+% endfor''')
+ assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+ range(5)
+
+ env = Environment('<%', '%>', '${', '}', '<%#', '%>', '%', '##')
+ tmpl = env.from_string('''\
+<%# regular comment %>
+% for item in seq:
+ ${item} ## the rest of the stuff
+% endfor''')
+ assert [int(x.strip()) for x in tmpl.render(seq=range(5)).split()] == \
+ range(5)
+
+ def test_line_syntax_priority(self):
+ # XXX: why is the whitespace there in front of the newline?
+ env = Environment('{%', '%}', '${', '}', '/*', '*/', '##', '#')
+ tmpl = env.from_string('''\
+/* ignore me.
+ I'm a multiline comment */
+## for item in seq:
+* ${item} # this is just extra stuff
+## endfor''')
+ assert tmpl.render(seq=[1, 2]).strip() == '* 1\n* 2'
+ env = Environment('{%', '%}', '${', '}', '/*', '*/', '#', '##')
+ tmpl = env.from_string('''\
+/* ignore me.
+ I'm a multiline comment */
+# for item in seq:
+* ${item} ## this is just extra stuff
+ ## extra stuff i just want to ignore
+# endfor''')
+ assert tmpl.render(seq=[1, 2]).strip() == '* 1\n\n* 2'
+
+ def test_error_messages(self):
+ def assert_error(code, expected):
+ try:
+ Template(code)
+ except TemplateSyntaxError, e:
+ assert str(e) == expected, 'unexpected error message'
+ else:
+ assert False, 'that was supposed to be an error'
+
+ assert_error('{% for item in seq %}...{% endif %}',
+ "Encountered unknown tag 'endif'. Jinja was looking "
+ "for the following tags: 'endfor' or 'else'. The "
+ "innermost block that needs to be closed is 'for'.")
+ assert_error('{% if foo %}{% for item in seq %}...{% endfor %}{% endfor %}',
+ "Encountered unknown tag 'endfor'. Jinja was looking for "
+ "the following tags: 'elif' or 'else' or 'endif'. The "
+ "innermost block that needs to be closed is 'if'.")
+ assert_error('{% if foo %}',
+ "Unexpected end of template. Jinja was looking for the "
+ "following tags: 'elif' or 'else' or 'endif'. The "
+ "innermost block that needs to be closed is 'if'.")
+ assert_error('{% for item in seq %}',
+ "Unexpected end of template. Jinja was looking for the "
+ "following tags: 'endfor' or 'else'. The innermost block "
+ "that needs to be closed is 'for'.")
+ assert_error('{% block foo-bar-baz %}',
+ "Block names in Jinja have to be valid Python identifiers "
+ "and may not contain hyphens, use an underscore instead.")
+ assert_error('{% unknown_tag %}',
+ "Encountered unknown tag 'unknown_tag'.")
+
+
+class SyntaxTestCase(JinjaTestCase):
+
+ def test_call(self):
+ env = Environment()
+ env.globals['foo'] = lambda a, b, c, e, g: a + b + c + e + g
+ tmpl = env.from_string("{{ foo('a', c='d', e='f', *['b'], **{'g': 'h'}) }}")
+ assert tmpl.render() == 'abdfh'
+
+ def test_slicing(self):
+ tmpl = env.from_string('{{ [1, 2, 3][:] }}|{{ [1, 2, 3][::-1] }}')
+ assert tmpl.render() == '[1, 2, 3]|[3, 2, 1]'
+
+ def test_attr(self):
+ tmpl = env.from_string("{{ foo.bar }}|{{ foo['bar'] }}")
+ assert tmpl.render(foo={'bar': 42}) == '42|42'
+
+ def test_subscript(self):
+ tmpl = env.from_string("{{ foo[0] }}|{{ foo[-1] }}")
+ assert tmpl.render(foo=[0, 1, 2]) == '0|2'
+
+ def test_tuple(self):
+ tmpl = env.from_string('{{ () }}|{{ (1,) }}|{{ (1, 2) }}')
+ assert tmpl.render() == '()|(1,)|(1, 2)'
+
+ def test_math(self):
+ tmpl = env.from_string('{{ (1 + 1 * 2) - 3 / 2 }}|{{ 2**3 }}')
+ assert tmpl.render() == '1.5|8'
+
+ def test_div(self):
+ tmpl = env.from_string('{{ 3 // 2 }}|{{ 3 / 2 }}|{{ 3 % 2 }}')
+ assert tmpl.render() == '1|1.5|1'
+
+ def test_unary(self):
+ tmpl = env.from_string('{{ +3 }}|{{ -3 }}')
+ assert tmpl.render() == '3|-3'
+
+ def test_concat(self):
+ tmpl = env.from_string("{{ [1, 2] ~ 'foo' }}")
+ assert tmpl.render() == '[1, 2]foo'
+
+ def test_compare(self):
+ tmpl = env.from_string('{{ 1 > 0 }}|{{ 1 >= 1 }}|{{ 2 < 3 }}|'
+ '{{ 2 == 2 }}|{{ 1 <= 1 }}')
+ assert tmpl.render() == 'True|True|True|True|True'
+
+ def test_inop(self):
+ tmpl = env.from_string('{{ 1 in [1, 2, 3] }}|{{ 1 not in [1, 2, 3] }}')
+ assert tmpl.render() == 'True|False'
+
+ def test_literals(self):
+ tmpl = env.from_string('{{ [] }}|{{ {} }}|{{ () }}')
+ assert tmpl.render().lower() == '[]|{}|()'
+
+ def test_bool(self):
+ tmpl = env.from_string('{{ true and false }}|{{ false '
+ 'or true }}|{{ not false }}')
+ assert tmpl.render() == 'False|True|True'
+
+ def test_grouping(self):
+ tmpl = env.from_string('{{ (true and false) or (false and true) and not false }}')
+ assert tmpl.render() == 'False'
+
+ def test_django_attr(self):
+ tmpl = env.from_string('{{ [1, 2, 3].0 }}|{{ [[1]].0.0 }}')
+ assert tmpl.render() == '1|1'
+
+ def test_conditional_expression(self):
+ tmpl = env.from_string('''{{ 0 if true else 1 }}''')
+ assert tmpl.render() == '0'
+
+ def test_short_conditional_expression(self):
+ tmpl = env.from_string('<{{ 1 if false }}>')
+ assert tmpl.render() == '<>'
+
+ tmpl = env.from_string('<{{ (1 if false).bar }}>')
+ self.assert_raises(UndefinedError, tmpl.render)
+
+ def test_filter_priority(self):
+ tmpl = env.from_string('{{ "foo"|upper + "bar"|upper }}')
+ assert tmpl.render() == 'FOOBAR'
+
+ def test_function_calls(self):
+ tests = [
+ (True, '*foo, bar'),
+ (True, '*foo, *bar'),
+ (True, '*foo, bar=42'),
+ (True, '**foo, *bar'),
+ (True, '**foo, bar'),
+ (False, 'foo, bar'),
+ (False, 'foo, bar=42'),
+ (False, 'foo, bar=23, *args'),
+ (False, 'a, b=c, *d, **e'),
+ (False, '*foo, **bar')
+ ]
+ for should_fail, sig in tests:
+ if should_fail:
+ self.assert_raises(TemplateSyntaxError,
+ env.from_string, '{{ foo(%s) }}' % sig)
+ else:
+ env.from_string('foo(%s)' % sig)
+
+ def test_tuple_expr(self):
+ for tmpl in [
+ '{{ () }}',
+ '{{ (1, 2) }}',
+ '{{ (1, 2,) }}',
+ '{{ 1, }}',
+ '{{ 1, 2 }}',
+ '{% for foo, bar in seq %}...{% endfor %}',
+ '{% for x in foo, bar %}...{% endfor %}',
+ '{% for x in foo, %}...{% endfor %}'
+ ]:
+ assert env.from_string(tmpl)
+
+ def test_trailing_comma(self):
+ tmpl = env.from_string('{{ (1, 2,) }}|{{ [1, 2,] }}|{{ {1: 2,} }}')
+ assert tmpl.render().lower() == '(1, 2)|[1, 2]|{1: 2}'
+
+ def test_block_end_name(self):
+ env.from_string('{% block foo %}...{% endblock foo %}')
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ '{% block x %}{% endblock y %}')
+
+ def test_constant_casing(self):
+ for const in True, False, None:
+ tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
+ str(const), str(const).lower(), str(const).upper()
+ ))
+ assert tmpl.render() == '%s|%s|' % (const, const)
+
+ def test_test_chaining(self):
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ '{{ foo is string is sequence }}')
+ assert env.from_string('{{ 42 is string or 42 is number }}'
+ ).render() == 'True'
+
+ def test_string_concatenation(self):
+ tmpl = env.from_string('{{ "foo" "bar" "baz" }}')
+ assert tmpl.render() == 'foobarbaz'
+
+ def test_notin(self):
+ bar = xrange(100)
+ tmpl = env.from_string('''{{ not 42 in bar }}''')
+ assert tmpl.render(bar=bar) == unicode(not 42 in bar)
+
+ def test_implicit_subscribed_tuple(self):
+ class Foo(object):
+ def __getitem__(self, x):
+ return x
+ t = env.from_string('{{ foo[1, 2] }}')
+ assert t.render(foo=Foo()) == u'(1, 2)'
+
+ def test_raw2(self):
+ tmpl = env.from_string('{% raw %}{{ FOO }} and {% BAR %}{% endraw %}')
+ assert tmpl.render() == '{{ FOO }} and {% BAR %}'
+
+ def test_const(self):
+ tmpl = env.from_string('{{ true }}|{{ false }}|{{ none }}|'
+ '{{ none is defined }}|{{ missing is defined }}')
+ assert tmpl.render() == 'True|False|None|True|False'
+
+ def test_neg_filter_priority(self):
+ node = env.parse('{{ -1|foo }}')
+ assert isinstance(node.body[0].nodes[0], nodes.Filter)
+ assert isinstance(node.body[0].nodes[0].node, nodes.Neg)
+
+ def test_const_assign(self):
+ constass1 = '''{% set true = 42 %}'''
+ constass2 = '''{% for none in seq %}{% endfor %}'''
+ for tmpl in constass1, constass2:
+ self.assert_raises(TemplateSyntaxError, env.from_string, tmpl)
+
+ def test_localset(self):
+ tmpl = env.from_string('''{% set foo = 0 %}\
+{% for item in [1, 2] %}{% set foo = 1 %}{% endfor %}\
+{{ foo }}''')
+ assert tmpl.render() == '0'
+
+ def test_parse_unary(self):
+ tmpl = env.from_string('{{ -foo["bar"] }}')
+ assert tmpl.render(foo={'bar': 42}) == '-42'
+ tmpl = env.from_string('{{ -foo["bar"]|abs }}')
+ assert tmpl.render(foo={'bar': 42}) == '42'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(LexerTestCase))
+ suite.addTest(unittest.makeSuite(ParserTestCase))
+ suite.addTest(unittest.makeSuite(SyntaxTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/loader.py b/websdk/jinja2/testsuite/loader.py
new file mode 100644
index 0000000..f62ec92
--- /dev/null
+++ b/websdk/jinja2/testsuite/loader.py
@@ -0,0 +1,218 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.loader
+ ~~~~~~~~~~~~~~~~~~~~~~~
+
+ Test the loaders.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import os
+import sys
+import tempfile
+import shutil
+import unittest
+
+from jinja2.testsuite import JinjaTestCase, dict_loader, \
+ package_loader, filesystem_loader, function_loader, \
+ choice_loader, prefix_loader
+
+from jinja2 import Environment, loaders
+from jinja2.loaders import split_template_path
+from jinja2.exceptions import TemplateNotFound
+
+
+class LoaderTestCase(JinjaTestCase):
+
+ def test_dict_loader(self):
+ env = Environment(loader=dict_loader)
+ tmpl = env.get_template('justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_package_loader(self):
+ env = Environment(loader=package_loader)
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_filesystem_loader(self):
+ env = Environment(loader=filesystem_loader)
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ tmpl = env.get_template('foo/test.html')
+ assert tmpl.render().strip() == 'FOO'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_choice_loader(self):
+ env = Environment(loader=choice_loader)
+ tmpl = env.get_template('justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ tmpl = env.get_template('test.html')
+ assert tmpl.render().strip() == 'BAR'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_function_loader(self):
+ env = Environment(loader=function_loader)
+ tmpl = env.get_template('justfunction.html')
+ assert tmpl.render().strip() == 'FOO'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing.html')
+
+ def test_prefix_loader(self):
+ env = Environment(loader=prefix_loader)
+ tmpl = env.get_template('a/test.html')
+ assert tmpl.render().strip() == 'BAR'
+ tmpl = env.get_template('b/justdict.html')
+ assert tmpl.render().strip() == 'FOO'
+ self.assert_raises(TemplateNotFound, env.get_template, 'missing')
+
+ def test_caching(self):
+ changed = False
+ class TestLoader(loaders.BaseLoader):
+ def get_source(self, environment, template):
+ return u'foo', None, lambda: not changed
+ env = Environment(loader=TestLoader(), cache_size=-1)
+ tmpl = env.get_template('template')
+ assert tmpl is env.get_template('template')
+ changed = True
+ assert tmpl is not env.get_template('template')
+ changed = False
+
+ env = Environment(loader=TestLoader(), cache_size=0)
+ assert env.get_template('template') \
+ is not env.get_template('template')
+
+ env = Environment(loader=TestLoader(), cache_size=2)
+ t1 = env.get_template('one')
+ t2 = env.get_template('two')
+ assert t2 is env.get_template('two')
+ assert t1 is env.get_template('one')
+ t3 = env.get_template('three')
+ assert 'one' in env.cache
+ assert 'two' not in env.cache
+ assert 'three' in env.cache
+
+ def test_split_template_path(self):
+ assert split_template_path('foo/bar') == ['foo', 'bar']
+ assert split_template_path('./foo/bar') == ['foo', 'bar']
+ self.assert_raises(TemplateNotFound, split_template_path, '../foo')
+
+
+class ModuleLoaderTestCase(JinjaTestCase):
+ archive = None
+
+ def compile_down(self, zip='deflated', py_compile=False):
+ super(ModuleLoaderTestCase, self).setup()
+ log = []
+ self.reg_env = Environment(loader=prefix_loader)
+ if zip is not None:
+ self.archive = tempfile.mkstemp(suffix='.zip')[1]
+ else:
+ self.archive = tempfile.mkdtemp()
+ self.reg_env.compile_templates(self.archive, zip=zip,
+ log_function=log.append,
+ py_compile=py_compile)
+ self.mod_env = Environment(loader=loaders.ModuleLoader(self.archive))
+ return ''.join(log)
+
+ def teardown(self):
+ super(ModuleLoaderTestCase, self).teardown()
+ if hasattr(self, 'mod_env'):
+ if os.path.isfile(self.archive):
+ os.remove(self.archive)
+ else:
+ shutil.rmtree(self.archive)
+ self.archive = None
+
+ def test_log(self):
+ log = self.compile_down()
+ assert 'Compiled "a/foo/test.html" as ' \
+ 'tmpl_a790caf9d669e39ea4d280d597ec891c4ef0404a' in log
+ assert 'Finished compiling templates' in log
+ assert 'Could not compile "a/syntaxerror.html": ' \
+ 'Encountered unknown tag \'endif\'' in log
+
+ def _test_common(self):
+ tmpl1 = self.reg_env.get_template('a/test.html')
+ tmpl2 = self.mod_env.get_template('a/test.html')
+ assert tmpl1.render() == tmpl2.render()
+
+ tmpl1 = self.reg_env.get_template('b/justdict.html')
+ tmpl2 = self.mod_env.get_template('b/justdict.html')
+ assert tmpl1.render() == tmpl2.render()
+
+ def test_deflated_zip_compile(self):
+ self.compile_down(zip='deflated')
+ self._test_common()
+
+ def test_stored_zip_compile(self):
+ self.compile_down(zip='stored')
+ self._test_common()
+
+ def test_filesystem_compile(self):
+ self.compile_down(zip=None)
+ self._test_common()
+
+ def test_weak_references(self):
+ self.compile_down()
+ tmpl = self.mod_env.get_template('a/test.html')
+ key = loaders.ModuleLoader.get_template_key('a/test.html')
+ name = self.mod_env.loader.module.__name__
+
+ assert hasattr(self.mod_env.loader.module, key)
+ assert name in sys.modules
+
+ # unset all, ensure the module is gone from sys.modules
+ self.mod_env = tmpl = None
+
+ try:
+ import gc
+ gc.collect()
+ except:
+ pass
+
+ assert name not in sys.modules
+
+ def test_byte_compilation(self):
+ log = self.compile_down(py_compile=True)
+ assert 'Byte-compiled "a/test.html"' in log
+ tmpl1 = self.mod_env.get_template('a/test.html')
+ mod = self.mod_env.loader.module. \
+ tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
+ assert mod.__file__.endswith('.pyc')
+
+ def test_choice_loader(self):
+ log = self.compile_down(py_compile=True)
+ assert 'Byte-compiled "a/test.html"' in log
+
+ self.mod_env.loader = loaders.ChoiceLoader([
+ self.mod_env.loader,
+ loaders.DictLoader({'DICT_SOURCE': 'DICT_TEMPLATE'})
+ ])
+
+ tmpl1 = self.mod_env.get_template('a/test.html')
+ self.assert_equal(tmpl1.render(), 'BAR')
+ tmpl2 = self.mod_env.get_template('DICT_SOURCE')
+ self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
+
+ def test_prefix_loader(self):
+ log = self.compile_down(py_compile=True)
+ assert 'Byte-compiled "a/test.html"' in log
+
+ self.mod_env.loader = loaders.PrefixLoader({
+ 'MOD': self.mod_env.loader,
+ 'DICT': loaders.DictLoader({'test.html': 'DICT_TEMPLATE'})
+ })
+
+ tmpl1 = self.mod_env.get_template('MOD/a/test.html')
+ self.assert_equal(tmpl1.render(), 'BAR')
+ tmpl2 = self.mod_env.get_template('DICT/test.html')
+ self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(LoaderTestCase))
+ suite.addTest(unittest.makeSuite(ModuleLoaderTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/regression.py b/websdk/jinja2/testsuite/regression.py
new file mode 100644
index 0000000..4db9076
--- /dev/null
+++ b/websdk/jinja2/testsuite/regression.py
@@ -0,0 +1,255 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.regression
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests corner cases and bugs.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Template, Environment, DictLoader, TemplateSyntaxError, \
+ TemplateNotFound, PrefixLoader
+
+env = Environment()
+
+
+class CornerTestCase(JinjaTestCase):
+
+ def test_assigned_scoping(self):
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {{- item -}}
+ ''')
+ assert t.render(item=42) == '[1][2][3][4]42'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {%- set item = 42 %}
+ {{- item -}}
+ ''')
+ assert t.render() == '[1][2][3][4]42'
+
+ t = env.from_string('''
+ {%- set item = 42 %}
+ {%- for item in (1, 2, 3, 4) -%}
+ [{{ item }}]
+ {%- endfor %}
+ {{- item -}}
+ ''')
+ assert t.render() == '[1][2][3][4]42'
+
+ def test_closure_scoping(self):
+ t = env.from_string('''
+ {%- set wrapper = "<FOO>" %}
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {{- wrapper -}}
+ ''')
+ assert t.render() == '[1][2][3][4]<FOO>'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {%- set wrapper = "<FOO>" %}
+ {{- wrapper -}}
+ ''')
+ assert t.render() == '[1][2][3][4]<FOO>'
+
+ t = env.from_string('''
+ {%- for item in (1, 2, 3, 4) %}
+ {%- macro wrapper() %}[{{ item }}]{% endmacro %}
+ {{- wrapper() }}
+ {%- endfor %}
+ {{- wrapper -}}
+ ''')
+ assert t.render(wrapper=23) == '[1][2][3][4]23'
+
+
+class BugTestCase(JinjaTestCase):
+
+ def test_keyword_folding(self):
+ env = Environment()
+ env.filters['testing'] = lambda value, some: value + some
+ assert env.from_string("{{ 'test'|testing(some='stuff') }}") \
+ .render() == 'teststuff'
+
+ def test_extends_output_bugs(self):
+ env = Environment(loader=DictLoader({
+ 'parent.html': '(({% block title %}{% endblock %}))'
+ }))
+
+ t = env.from_string('{% if expr %}{% extends "parent.html" %}{% endif %}'
+ '[[{% block title %}title{% endblock %}]]'
+ '{% for item in [1, 2, 3] %}({{ item }}){% endfor %}')
+ assert t.render(expr=False) == '[[title]](1)(2)(3)'
+ assert t.render(expr=True) == '((title))'
+
+ def test_urlize_filter_escaping(self):
+ tmpl = env.from_string('{{ "http://www.example.org/<foo"|urlize }}')
+ assert tmpl.render() == '<a href="http://www.example.org/&lt;foo">http://www.example.org/&lt;foo</a>'
+
+ def test_loop_call_loop(self):
+ tmpl = env.from_string('''
+
+ {% macro test() %}
+ {{ caller() }}
+ {% endmacro %}
+
+ {% for num1 in range(5) %}
+ {% call test() %}
+ {% for num2 in range(10) %}
+ {{ loop.index }}
+ {% endfor %}
+ {% endcall %}
+ {% endfor %}
+
+ ''')
+
+ assert tmpl.render().split() == map(unicode, range(1, 11)) * 5
+
+ def test_weird_inline_comment(self):
+ env = Environment(line_statement_prefix='%')
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ '% for item in seq {# missing #}\n...% endfor')
+
+ def test_old_macro_loop_scoping_bug(self):
+ tmpl = env.from_string('{% for i in (1, 2) %}{{ i }}{% endfor %}'
+ '{% macro i() %}3{% endmacro %}{{ i() }}')
+ assert tmpl.render() == '123'
+
+ def test_partial_conditional_assignments(self):
+ tmpl = env.from_string('{% if b %}{% set a = 42 %}{% endif %}{{ a }}')
+ assert tmpl.render(a=23) == '23'
+ assert tmpl.render(b=True) == '42'
+
+ def test_stacked_locals_scoping_bug(self):
+ env = Environment(line_statement_prefix='#')
+ t = env.from_string('''\
+# for j in [1, 2]:
+# set x = 1
+# for i in [1, 2]:
+# print x
+# if i % 2 == 0:
+# set x = x + 1
+# endif
+# endfor
+# endfor
+# if a
+# print 'A'
+# elif b
+# print 'B'
+# elif c == d
+# print 'C'
+# else
+# print 'D'
+# endif
+ ''')
+ assert t.render(a=0, b=False, c=42, d=42.0) == '1111C'
+
+ def test_stacked_locals_scoping_bug_twoframe(self):
+ t = Template('''
+ {% set x = 1 %}
+ {% for item in foo %}
+ {% if item == 1 %}
+ {% set x = 2 %}
+ {% endif %}
+ {% endfor %}
+ {{ x }}
+ ''')
+ rv = t.render(foo=[1]).strip()
+ assert rv == u'1'
+
+ def test_call_with_args(self):
+ t = Template("""{% macro dump_users(users) -%}
+ <ul>
+ {%- for user in users -%}
+ <li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
+ {%- endfor -%}
+ </ul>
+ {%- endmacro -%}
+
+ {% call(user) dump_users(list_of_user) -%}
+ <dl>
+ <dl>Realname</dl>
+ <dd>{{ user.realname|e }}</dd>
+ <dl>Description</dl>
+ <dd>{{ user.description }}</dd>
+ </dl>
+ {% endcall %}""")
+
+ assert [x.strip() for x in t.render(list_of_user=[{
+ 'username':'apo',
+ 'realname':'something else',
+ 'description':'test'
+ }]).splitlines()] == [
+ u'<ul><li><p>apo</p><dl>',
+ u'<dl>Realname</dl>',
+ u'<dd>something else</dd>',
+ u'<dl>Description</dl>',
+ u'<dd>test</dd>',
+ u'</dl>',
+ u'</li></ul>'
+ ]
+
+ def test_empty_if_condition_fails(self):
+ self.assert_raises(TemplateSyntaxError, Template, '{% if %}....{% endif %}')
+ self.assert_raises(TemplateSyntaxError, Template, '{% if foo %}...{% elif %}...{% endif %}')
+ self.assert_raises(TemplateSyntaxError, Template, '{% for x in %}..{% endfor %}')
+
+ def test_recursive_loop_bug(self):
+ tpl1 = Template("""
+ {% for p in foo recursive%}
+ {{p.bar}}
+ {% for f in p.fields recursive%}
+ {{f.baz}}
+ {{p.bar}}
+ {% if f.rec %}
+ {{ loop(f.sub) }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ """)
+
+ tpl2 = Template("""
+ {% for p in foo%}
+ {{p.bar}}
+ {% for f in p.fields recursive%}
+ {{f.baz}}
+ {{p.bar}}
+ {% if f.rec %}
+ {{ loop(f.sub) }}
+ {% endif %}
+ {% endfor %}
+ {% endfor %}
+ """)
+
+ def test_correct_prefix_loader_name(self):
+ env = Environment(loader=PrefixLoader({
+ 'foo': DictLoader({})
+ }))
+ try:
+ env.get_template('foo/bar.html')
+ except TemplateNotFound, e:
+ assert e.name == 'foo/bar.html'
+ else:
+ assert False, 'expected error here'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(CornerTestCase))
+ suite.addTest(unittest.makeSuite(BugTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/res/__init__.py b/websdk/jinja2/testsuite/res/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/websdk/jinja2/testsuite/res/__init__.py
diff --git a/websdk/jinja2/testsuite/res/templates/broken.html b/websdk/jinja2/testsuite/res/templates/broken.html
new file mode 100644
index 0000000..77669fa
--- /dev/null
+++ b/websdk/jinja2/testsuite/res/templates/broken.html
@@ -0,0 +1,3 @@
+Before
+{{ fail() }}
+After
diff --git a/websdk/jinja2/testsuite/res/templates/foo/test.html b/websdk/jinja2/testsuite/res/templates/foo/test.html
new file mode 100644
index 0000000..b7d6715
--- /dev/null
+++ b/websdk/jinja2/testsuite/res/templates/foo/test.html
@@ -0,0 +1 @@
+FOO
diff --git a/websdk/jinja2/testsuite/res/templates/syntaxerror.html b/websdk/jinja2/testsuite/res/templates/syntaxerror.html
new file mode 100644
index 0000000..f21b817
--- /dev/null
+++ b/websdk/jinja2/testsuite/res/templates/syntaxerror.html
@@ -0,0 +1,4 @@
+Foo
+{% for item in broken %}
+ ...
+{% endif %}
diff --git a/websdk/jinja2/testsuite/res/templates/test.html b/websdk/jinja2/testsuite/res/templates/test.html
new file mode 100644
index 0000000..ba578e4
--- /dev/null
+++ b/websdk/jinja2/testsuite/res/templates/test.html
@@ -0,0 +1 @@
+BAR
diff --git a/websdk/jinja2/testsuite/security.py b/websdk/jinja2/testsuite/security.py
new file mode 100644
index 0000000..4518eac
--- /dev/null
+++ b/websdk/jinja2/testsuite/security.py
@@ -0,0 +1,165 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.security
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ Checks the sandbox and other security features.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Environment
+from jinja2.sandbox import SandboxedEnvironment, \
+ ImmutableSandboxedEnvironment, unsafe
+from jinja2 import Markup, escape
+from jinja2.exceptions import SecurityError, TemplateSyntaxError, \
+ TemplateRuntimeError
+
+
+class PrivateStuff(object):
+
+ def bar(self):
+ return 23
+
+ @unsafe
+ def foo(self):
+ return 42
+
+ def __repr__(self):
+ return 'PrivateStuff'
+
+
+class PublicStuff(object):
+ bar = lambda self: 23
+ _foo = lambda self: 42
+
+ def __repr__(self):
+ return 'PublicStuff'
+
+
+class SandboxTestCase(JinjaTestCase):
+
+ def test_unsafe(self):
+ env = SandboxedEnvironment()
+ self.assert_raises(SecurityError, env.from_string("{{ foo.foo() }}").render,
+ foo=PrivateStuff())
+ self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PrivateStuff()), '23')
+
+ self.assert_raises(SecurityError, env.from_string("{{ foo._foo() }}").render,
+ foo=PublicStuff())
+ self.assert_equal(env.from_string("{{ foo.bar() }}").render(foo=PublicStuff()), '23')
+ self.assert_equal(env.from_string("{{ foo.__class__ }}").render(foo=42), '')
+ self.assert_equal(env.from_string("{{ foo.func_code }}").render(foo=lambda:None), '')
+ # security error comes from __class__ already.
+ self.assert_raises(SecurityError, env.from_string(
+ "{{ foo.__class__.__subclasses__() }}").render, foo=42)
+
+ def test_immutable_environment(self):
+ env = ImmutableSandboxedEnvironment()
+ self.assert_raises(SecurityError, env.from_string(
+ '{{ [].append(23) }}').render)
+ self.assert_raises(SecurityError, env.from_string(
+ '{{ {1:2}.clear() }}').render)
+
+ def test_restricted(self):
+ env = SandboxedEnvironment()
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ "{% for item.attribute in seq %}...{% endfor %}")
+ self.assert_raises(TemplateSyntaxError, env.from_string,
+ "{% for foo, bar.baz in seq %}...{% endfor %}")
+
+ def test_markup_operations(self):
+ # adding two strings should escape the unsafe one
+ unsafe = '<script type="application/x-some-script">alert("foo");</script>'
+ safe = Markup('<em>username</em>')
+ assert unsafe + safe == unicode(escape(unsafe)) + unicode(safe)
+
+ # string interpolations are safe to use too
+ assert Markup('<em>%s</em>') % '<bad user>' == \
+ '<em>&lt;bad user&gt;</em>'
+ assert Markup('<em>%(username)s</em>') % {
+ 'username': '<bad user>'
+ } == '<em>&lt;bad user&gt;</em>'
+
+ # an escaped object is markup too
+ assert type(Markup('foo') + 'bar') is Markup
+
+ # and it implements __html__ by returning itself
+ x = Markup("foo")
+ assert x.__html__() is x
+
+ # it also knows how to treat __html__ objects
+ class Foo(object):
+ def __html__(self):
+ return '<em>awesome</em>'
+ def __unicode__(self):
+ return 'awesome'
+ assert Markup(Foo()) == '<em>awesome</em>'
+ assert Markup('<strong>%s</strong>') % Foo() == \
+ '<strong><em>awesome</em></strong>'
+
+ # escaping and unescaping
+ assert escape('"<>&\'') == '&#34;&lt;&gt;&amp;&#39;'
+ assert Markup("<em>Foo &amp; Bar</em>").striptags() == "Foo & Bar"
+ assert Markup("&lt;test&gt;").unescape() == "<test>"
+
+ def test_template_data(self):
+ env = Environment(autoescape=True)
+ t = env.from_string('{% macro say_hello(name) %}'
+ '<p>Hello {{ name }}!</p>{% endmacro %}'
+ '{{ say_hello("<blink>foo</blink>") }}')
+ escaped_out = '<p>Hello &lt;blink&gt;foo&lt;/blink&gt;!</p>'
+ assert t.render() == escaped_out
+ assert unicode(t.module) == escaped_out
+ assert escape(t.module) == escaped_out
+ assert t.module.say_hello('<blink>foo</blink>') == escaped_out
+ assert escape(t.module.say_hello('<blink>foo</blink>')) == escaped_out
+
+ def test_attr_filter(self):
+ env = SandboxedEnvironment()
+ tmpl = env.from_string('{{ cls|attr("__subclasses__")() }}')
+ self.assert_raises(SecurityError, tmpl.render, cls=int)
+
+ def test_binary_operator_intercepting(self):
+ def disable_op(left, right):
+ raise TemplateRuntimeError('that operator so does not work')
+ for expr, ctx, rv in ('1 + 2', {}, '3'), ('a + 2', {'a': 2}, '4'):
+ env = SandboxedEnvironment()
+ env.binop_table['+'] = disable_op
+ t = env.from_string('{{ %s }}' % expr)
+ assert t.render(ctx) == rv
+ env.intercepted_binops = frozenset(['+'])
+ t = env.from_string('{{ %s }}' % expr)
+ try:
+ t.render(ctx)
+ except TemplateRuntimeError, e:
+ pass
+ else:
+ self.fail('expected runtime error')
+
+ def test_unary_operator_intercepting(self):
+ def disable_op(arg):
+ raise TemplateRuntimeError('that operator so does not work')
+ for expr, ctx, rv in ('-1', {}, '-1'), ('-a', {'a': 2}, '-2'):
+ env = SandboxedEnvironment()
+ env.unop_table['-'] = disable_op
+ t = env.from_string('{{ %s }}' % expr)
+ assert t.render(ctx) == rv
+ env.intercepted_unops = frozenset(['-'])
+ t = env.from_string('{{ %s }}' % expr)
+ try:
+ t.render(ctx)
+ except TemplateRuntimeError, e:
+ pass
+ else:
+ self.fail('expected runtime error')
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(SandboxTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/tests.py b/websdk/jinja2/testsuite/tests.py
new file mode 100644
index 0000000..3ece7a8
--- /dev/null
+++ b/websdk/jinja2/testsuite/tests.py
@@ -0,0 +1,93 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.tests
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Who tests the tests?
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import unittest
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2 import Markup, Environment
+
+env = Environment()
+
+
+class TestsTestCase(JinjaTestCase):
+
+ def test_defined(self):
+ tmpl = env.from_string('{{ missing is defined }}|{{ true is defined }}')
+ assert tmpl.render() == 'False|True'
+
+ def test_even(self):
+ tmpl = env.from_string('''{{ 1 is even }}|{{ 2 is even }}''')
+ assert tmpl.render() == 'False|True'
+
+ def test_odd(self):
+ tmpl = env.from_string('''{{ 1 is odd }}|{{ 2 is odd }}''')
+ assert tmpl.render() == 'True|False'
+
+ def test_lower(self):
+ tmpl = env.from_string('''{{ "foo" is lower }}|{{ "FOO" is lower }}''')
+ assert tmpl.render() == 'True|False'
+
+ def test_typechecks(self):
+ tmpl = env.from_string('''
+ {{ 42 is undefined }}
+ {{ 42 is defined }}
+ {{ 42 is none }}
+ {{ none is none }}
+ {{ 42 is number }}
+ {{ 42 is string }}
+ {{ "foo" is string }}
+ {{ "foo" is sequence }}
+ {{ [1] is sequence }}
+ {{ range is callable }}
+ {{ 42 is callable }}
+ {{ range(5) is iterable }}
+ {{ {} is mapping }}
+ {{ mydict is mapping }}
+ {{ [] is mapping }}
+ ''')
+ class MyDict(dict):
+ pass
+ assert tmpl.render(mydict=MyDict()).split() == [
+ 'False', 'True', 'False', 'True', 'True', 'False',
+ 'True', 'True', 'True', 'True', 'False', 'True',
+ 'True', 'True', 'False'
+ ]
+
+ def test_sequence(self):
+ tmpl = env.from_string(
+ '{{ [1, 2, 3] is sequence }}|'
+ '{{ "foo" is sequence }}|'
+ '{{ 42 is sequence }}'
+ )
+ assert tmpl.render() == 'True|True|False'
+
+ def test_upper(self):
+ tmpl = env.from_string('{{ "FOO" is upper }}|{{ "foo" is upper }}')
+ assert tmpl.render() == 'True|False'
+
+ def test_sameas(self):
+ tmpl = env.from_string('{{ foo is sameas false }}|'
+ '{{ 0 is sameas false }}')
+ assert tmpl.render(foo=False) == 'True|False'
+
+ def test_no_paren_for_arg1(self):
+ tmpl = env.from_string('{{ foo is sameas none }}')
+ assert tmpl.render(foo=None) == 'True'
+
+ def test_escaped(self):
+ env = Environment(autoescape=True)
+ tmpl = env.from_string('{{ x is escaped }}|{{ y is escaped }}')
+ assert tmpl.render(x='foo', y=Markup('foo')) == 'False|True'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(TestsTestCase))
+ return suite
diff --git a/websdk/jinja2/testsuite/utils.py b/websdk/jinja2/testsuite/utils.py
new file mode 100644
index 0000000..be2e902
--- /dev/null
+++ b/websdk/jinja2/testsuite/utils.py
@@ -0,0 +1,82 @@
+# -*- coding: utf-8 -*-
+"""
+ jinja2.testsuite.utils
+ ~~~~~~~~~~~~~~~~~~~~~~
+
+ Tests utilities jinja uses.
+
+ :copyright: (c) 2010 by the Jinja Team.
+ :license: BSD, see LICENSE for more details.
+"""
+import gc
+import unittest
+
+import pickle
+
+from jinja2.testsuite import JinjaTestCase
+
+from jinja2.utils import LRUCache, escape, object_type_repr
+
+
+class LRUCacheTestCase(JinjaTestCase):
+
+ def test_simple(self):
+ d = LRUCache(3)
+ d["a"] = 1
+ d["b"] = 2
+ d["c"] = 3
+ d["a"]
+ d["d"] = 4
+ assert len(d) == 3
+ assert 'a' in d and 'c' in d and 'd' in d and 'b' not in d
+
+ def test_pickleable(self):
+ cache = LRUCache(2)
+ cache["foo"] = 42
+ cache["bar"] = 23
+ cache["foo"]
+
+ for protocol in range(3):
+ copy = pickle.loads(pickle.dumps(cache, protocol))
+ assert copy.capacity == cache.capacity
+ assert copy._mapping == cache._mapping
+ assert copy._queue == cache._queue
+
+
+class HelpersTestCase(JinjaTestCase):
+
+ def test_object_type_repr(self):
+ class X(object):
+ pass
+ self.assert_equal(object_type_repr(42), 'int object')
+ self.assert_equal(object_type_repr([]), 'list object')
+ self.assert_equal(object_type_repr(X()),
+ 'jinja2.testsuite.utils.X object')
+ self.assert_equal(object_type_repr(None), 'None')
+ self.assert_equal(object_type_repr(Ellipsis), 'Ellipsis')
+
+
+class MarkupLeakTestCase(JinjaTestCase):
+
+ def test_markup_leaks(self):
+ counts = set()
+ for count in xrange(20):
+ for item in xrange(1000):
+ escape("foo")
+ escape("<foo>")
+ escape(u"foo")
+ escape(u"<foo>")
+ counts.add(len(gc.get_objects()))
+ assert len(counts) == 1, 'ouch, c extension seems to leak objects'
+
+
+def suite():
+ suite = unittest.TestSuite()
+ suite.addTest(unittest.makeSuite(LRUCacheTestCase))
+ suite.addTest(unittest.makeSuite(HelpersTestCase))
+
+ # this test only tests the c extension
+ if not hasattr(escape, 'func_code'):
+ suite.addTest(unittest.makeSuite(MarkupLeakTestCase))
+
+ return suite