From c1e3040890aceff048d50110935e00e5ac4f79f6 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sun, 18 Mar 2007 22:41:09 +0100 Subject: [PATCH] [svn] fixed jinja inheritance bug and improved unittests --HG-- branch : trunk --- jinja/datastructure.py | 3 +- jinja/translators/python.py | 2 +- tests/conftest.py | 37 +++++++++++-------- tests/runtime/templates/c.html | 1 - tests/test_filters.py | 12 +++++++ tests/test_inheritance.py | 66 ++++++++++++++++++++++++++++++++++ tests/test_macros.py | 54 ++++++++++++++++++++++++++++ tests/test_tests.py | 1 - 8 files changed, 157 insertions(+), 19 deletions(-) create mode 100644 tests/test_inheritance.py create mode 100644 tests/test_macros.py diff --git a/jinja/datastructure.py b/jinja/datastructure.py index 2b53a58..f409eb5 100644 --- a/jinja/datastructure.py +++ b/jinja/datastructure.py @@ -56,7 +56,8 @@ class UndefinedType(object): return self def __iter__(self): - return iter(int, 0) + if False: + yield None def __getattr__(self, arg): return self diff --git a/jinja/translators/python.py b/jinja/translators/python.py index 6d5b924..0a53a62 100644 --- a/jinja/translators/python.py +++ b/jinja/translators/python.py @@ -257,6 +257,7 @@ class PythonTranslator(Translator): # root template. requirements_todo = [] parent = None + overwrites = {} while node.extends is not None: # handle all requirements but not those from the @@ -269,7 +270,6 @@ class PythonTranslator(Translator): parent = self.environment.loader.parse(node.extends.template, node.filename) # look up all block nodes and let them override each other - overwrites = {} for n in get_nodes(nodes.Block, node): overwrites[n.name] = n for n in get_nodes(nodes.Block, parent): diff --git a/tests/conftest.py b/tests/conftest.py index 8ec3737..aa060fa 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -14,11 +14,29 @@ import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) import py -from inspect import isclass from jinja import Environment +from jinja.parser import Parser -simple_env = Environment(trim_blocks=True) +class GlobalLoader(object): + + def __init__(self, scope): + self.scope = scope + + def get_source(self, environment, name, parent, scope=None): + return self.scope[name.upper() + 'TEMPLATE'] + + def parse(self, environment, name, parent, scope=None): + return Parser(environment, self.get_source(environment, name, + parent, scope), name).parse() + + def load(self, environment, name, translator, scope=None): + return translator.process(environment, self.parse(environment, + name, None, scope)) + + +loader = GlobalLoader(globals()) +simple_env = Environment(trim_blocks=True, loader=loader) class Module(py.test.collect.Module): @@ -29,27 +47,16 @@ class Module(py.test.collect.Module): def join(self, name): obj = getattr(self.obj, name) - if isclass(obj): - return JinjaClassCollector(name, parent=self) - elif hasattr(obj, 'func_code'): + if hasattr(obj, 'func_code'): return JinjaTestFunction(name, parent=self) class JinjaTestFunction(py.test.collect.Function): def execute(self, target, *args): + loader.scope = target.func_globals co = target.func_code if 'env' in co.co_varnames[:co.co_argcount]: target(self.parent.env, *args) else: target(*args) - - -class JinjaClassCollector(py.test.collect.Class): - - Function = JinjaTestFunction - - def setup(self): - cls = self.obj - cls.env = self.parent.env - super(JinjaClassCollector, self).setup() diff --git a/tests/runtime/templates/c.html b/tests/runtime/templates/c.html index 61e5a48..1cc4f71 100644 --- a/tests/runtime/templates/c.html +++ b/tests/runtime/templates/c.html @@ -3,5 +3,4 @@ {% block block3 %}from template c.html{% endblock %} {% block block7 %} nested block from b.html, overridden in c.html - {{ 1 / 0 }} {% endblock %} diff --git a/tests/test_filters.py b/tests/test_filters.py index 2d728b0..eab73d5 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -47,6 +47,8 @@ UPPER = '''{{ "foo"|upper }}''' URLENCODE = '''{{ "f#b"|urlencode }}''' URLIZE = '''{{ "foo http://www.example.com/ bar"|urlize }}''' WORDCOUNT = '''{{ "foo bar baz"|wordcount }}''' +BLOCK = '''{% filter lower|escape %}{% endfilter %}''' +CHAINING = '''{{ ['', '']|first|upper|escape }}''' def test_capitalize(env): @@ -189,3 +191,13 @@ def test_urlize(env): def test_wordcount(env): tmpl = env.from_string(WORDCOUNT) assert tmpl.render() == '3' + + +def test_block(env): + tmpl = env.from_string(BLOCK) + assert tmpl.render() == '<hehe>' + + +def test_chaining(env): + tmpl = env.from_string(CHAINING) + assert tmpl.render() == '<FOO>' diff --git a/tests/test_inheritance.py b/tests/test_inheritance.py new file mode 100644 index 0000000..96a1065 --- /dev/null +++ b/tests/test_inheritance.py @@ -0,0 +1,66 @@ +# -*- coding: utf-8 -*- +""" + unit test for the inheritance + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: 2007 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + + +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 %} +''' + + +def test_layout(env): + tmpl = env.get_template('layout') + assert tmpl.render() == ('|block 1 from layout|block 2 from ' + 'layout|nested block 4 from layout|') + + +def test_level1(env): + tmpl = env.get_template('level1') + assert tmpl.render() == ('|block 1 from level1|block 2 from ' + 'layout|nested block 4 from layout|') + + +def test_level2(env): + 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(env): + tmpl = env.get_template('level3') + assert tmpl.render() == ('|block 1 from level1|block 5 from level3|' + 'block 4 from level3|') + + +def test_level4(env): + tmpl = env.get_template('level4') + assert tmpl.render() == ('|block 1 from level1|block 5 from ' + 'level3|block 3 from level4|') diff --git a/tests/test_macros.py b/tests/test_macros.py new file mode 100644 index 0000000..c28499b --- /dev/null +++ b/tests/test_macros.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +""" + unit test for the macros + ~~~~~~~~~~~~~~~~~~~~~~~~ + + :copyright: 2007 by Armin Ronacher. + :license: BSD, see LICENSE for more details. +""" + +SIMPLE = '''\ +{% macro say_hello name %}Hello {{ name }}!{% endmacro %} +{{ say_hello('Peter') }}\ +''' + +KWARGSFAILURE = '''\ +{% macro foo bar %}...{% endmacro %} +{{ foo(bar='blub') }}\ +''' + +SCOPING = '''\ +{% macro level1 data1 %} +{% macro level2 data2 %}{{ data1 }}|{{ data2 }}{% endmacro %} +{{ level2('bar') }}{% endmacro %} +{{ level1('foo') }}|{{ level2('bar') }}\ +''' + +ARGUMENTS = '''\ +{% macro m a, b, c='c', d='d' %}{{ a }}|{{ b }}|{{ c }}|{{ d }}{% endmacro %} +{{ m() }}|{{ m('a') }}|{{ m('a', 'b') }}|{{ m(1, 2, 3) }}\ +''' + +def test_simple(env): + tmpl = env.from_string(SIMPLE) + assert tmpl.render() == 'Hello Peter!' + + +def test_kwargs_failure(env): + tmpl = env.from_string(KWARGSFAILURE) + try: + tmpl.render() + except TypeError, e: + pass + else: + raise AssertionError('kwargs failure test failed') + + +def test_scoping(env): + tmpl = env.from_string(SCOPING) + assert tmpl.render() == 'foo|bar|' + + +def test_arguments(env): + tmpl = env.from_string(ARGUMENTS) + assert tmpl.render() == '||c|d|a||c|d|a|b|c|d|1|2|3|d' diff --git a/tests/test_tests.py b/tests/test_tests.py index 22bdec4..387f3fb 100644 --- a/tests/test_tests.py +++ b/tests/test_tests.py @@ -59,4 +59,3 @@ def test_sequence(env): def test_upper(env): tmpl = env.from_string(UPPER) assert tmpl.render() == 'True|False' - -- 2.26.2