# HG changeset patch # User cmlenz # Date 1155679147 0 # Node ID 7306bf730ff36bb535b3bbdf2becc956a23b8feb # Parent a0a52cf4e4deb0d97653a1860a26fbea4c43479a `Template.generate()` now accepts the context data as keyword arguments, so that you don't have to import the `Context` class every time you want to pass data into a template. diff --git a/COPYING b/COPYING --- a/COPYING +++ b/COPYING @@ -1,4 +1,4 @@ -Copyright (C) 2006 Christopher Lenz +Copyright (C) 2006 Edgewall Software All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/examples/basic/run.py b/examples/basic/run.py --- a/examples/basic/run.py +++ b/examples/basic/run.py @@ -5,7 +5,7 @@ import sys import time -from markup.template import Context, TemplateLoader +from markup.template import TemplateLoader def test(): base_path = os.path.dirname(os.path.abspath(__file__)) @@ -19,12 +19,12 @@ items=['Number %d' % num for num in range(1, 15)], prefix='#') - print tmpl.generate(Context(**data)).render(method='html') + print tmpl.generate(**data).render(method='html') times = [] for i in range(1000): start = time.clock() - list(tmpl.generate(Context(**data))) + list(tmpl.generate(**data)) times.append(time.clock() - start) sys.stdout.write('.') sys.stdout.flush() diff --git a/examples/bench/basic.py b/examples/bench/basic.py --- a/examples/bench/basic.py +++ b/examples/bench/basic.py @@ -7,13 +7,13 @@ __all__ = ['clearsilver', 'django', 'kid', 'markup', 'simpletal'] def markup(dirname, verbose=False): - from markup.template import Context, TemplateLoader + from markup.template import TemplateLoader loader = TemplateLoader([dirname], auto_reload=False) template = loader.load('template.html') def render(): - ctxt = Context(title='Just a test', user='joe', - items=['Number %d' % num for num in range(1, 15)]) - return template.generate(ctxt).render('xhtml') + data = dict(title='Just a test', user='joe', + items=['Number %d' % num for num in range(1, 15)]) + return template.generate(**data).render('xhtml') if verbose: print render() diff --git a/examples/bench/bigtable.py b/examples/bench/bigtable.py --- a/examples/bench/bigtable.py +++ b/examples/bench/bigtable.py @@ -12,7 +12,7 @@ import cElementTree as cet from elementtree import ElementTree as et from markup.builder import tag -from markup.template import Context, Template +from markup.template import Template import neo_cgi import neo_cs import neo_util @@ -66,8 +66,7 @@ def test_markup(): """Markup template""" - ctxt = Context(table=table) - stream = markup_tmpl.generate(ctxt) + stream = markup_tmpl.generate(table=table) stream.render('html', strip_whitespace=False) def test_markup_builder(): @@ -76,8 +75,7 @@ tag.tr([tag.td(c) for c in row.values()]) for row in table ]).generate() - ctxt = Context(table=stream) - stream = markup_tmpl2.generate(ctxt) + stream = markup_tmpl2.generate(table=stream) stream.render('html', strip_whitespace=False) def test_builder(): diff --git a/markup/plugin.py b/markup/plugin.py --- a/markup/plugin.py +++ b/markup/plugin.py @@ -75,5 +75,4 @@ data.update(self.get_extra_vars()) data.update(info) - ctxt = Context(**data) - return template.generate(ctxt) + return template.generate(**data) diff --git a/markup/template.py b/markup/template.py --- a/markup/template.py +++ b/markup/template.py @@ -31,8 +31,7 @@ from markup.input import XMLParser from markup.path import Path -__all__ = ['Context', 'BadDirectiveError', 'TemplateError', - 'TemplateSyntaxError', 'TemplateNotFound', 'Template', +__all__ = ['TemplateSyntaxError', 'TemplateNotFound', 'Template', 'TemplateLoader'] @@ -178,11 +177,10 @@ The value of the `py:attrs` attribute should be a dictionary. The keys and values of that dictionary will be added as attributes to the element: - >>> ctxt = Context(foo={'class': 'collapse'}) >>> tmpl = Template('''''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(foo={'class': 'collapse'}) @@ -190,8 +188,7 @@ If the value evaluates to `None` (or any other non-truth value), no attributes are added: - >>> ctxt = Context(foo=None) - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(foo=None) @@ -229,11 +226,10 @@ This directive replaces the content of the element with the result of evaluating the value of the `py:content` attribute: - >>> ctxt = Context(bar='Bye') >>> tmpl = Template('''''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(bar='Bye') @@ -266,14 +262,13 @@ A named template function can be used just like a normal Python function from template expressions: - >>> ctxt = Context(bar='Bye') >>> tmpl = Template('''
...

... ${greeting}, ${name}! ...

... ${echo('Hi', name='you')} ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(bar='Bye')

Hi, you! @@ -283,14 +278,13 @@ If a function does not require parameters, the parenthesis can be omitted both when defining and when calling it: - >>> ctxt = Context(bar='Bye') >>> tmpl = Template('''

...

... Hello, world! ...

... ${helloworld} ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(bar='Bye')

Hello, world! @@ -343,11 +337,10 @@ """Implementation of the `py:for` template directive for repeating an element based on an iterable in the context data. - >>> ctxt = Context(items=[1, 2, 3]) >>> tmpl = Template('''

''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(items=[1, 2, 3]) @@ -390,11 +383,10 @@ """Implementation of the `py:if` template directive for conditionally excluding elements from being output. - >>> ctxt = Context(foo=True, bar='Hello') >>> tmpl = Template('''
... ${bar} ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(foo=True, bar='Hello')
Hello
@@ -450,11 +442,10 @@ This directive replaces the element with the result of evaluating the value of the `py:replace` attribute: - >>> ctxt = Context(bar='Bye') >>> tmpl = Template('''
... Hello ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(bar='Bye')
Bye
@@ -462,11 +453,10 @@ This directive is equivalent to `py:content` combined with `py:strip`, providing a less verbose way to achieve the same effect: - >>> ctxt = Context(bar='Bye') >>> tmpl = Template('''
... Hello ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate(bar='Bye')
Bye
@@ -538,14 +528,13 @@ If no `py:when` directive is matched then the fallback directive `py:otherwise` will be used. - >>> ctxt = Context() >>> tmpl = Template('''
... 0 ... 1 ... 2 ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate()
1
@@ -558,7 +547,7 @@ ... 1 ... 2 ...
''') - >>> print tmpl.generate(ctxt) + >>> print tmpl.generate()
2
@@ -627,7 +616,7 @@ >>> tmpl = Template('''
... $x $y $z ...
''') - >>> print tmpl.generate(Context(x=42)) + >>> print tmpl.generate(x=42)
42 7 52
@@ -839,16 +828,25 @@ return _interpolate(text, [cls._FULL_EXPR_RE, cls._SHORT_EXPR_RE]) _interpolate = classmethod(_interpolate) - def generate(self, ctxt=None): + def generate(self, *args, **kwargs): """Apply the template to the given context data. - @param ctxt: a `Context` instance containing the data for the template + Any keyword arguments are made available to the template as context + data. + + Only one positional argument is accepted: if it is provided, it must be + an instance of the `Context` class, and keyword arguments are ignored. + This calling style is used for internal processing. + @return: a markup event stream representing the result of applying the template to the context data. """ - if ctxt is None: - ctxt = Context() - if not hasattr(ctxt, '_match_templates'): + if args: + assert len(args) == 1 + ctxt = args[0] + assert isinstance(ctxt, Context) + else: + ctxt = Context(**kwargs) ctxt._match_templates = [] stream = self.stream diff --git a/markup/tests/template.py b/markup/tests/template.py --- a/markup/tests/template.py +++ b/markup/tests/template.py @@ -16,8 +16,7 @@ import sys from markup.core import Markup, Stream -from markup.template import BadDirectiveError, Context, Template, \ - TemplateSyntaxError +from markup.template import BadDirectiveError, Template, TemplateSyntaxError class AttrsDirectiveTestCase(unittest.TestCase): @@ -33,7 +32,7 @@ items = [{'id': 1, 'class': 'foo'}, {'id': 2, 'class': 'bar'}] self.assertEqual(""" - """, str(tmpl.generate(Context(items=items)))) + """, str(tmpl.generate(items=items))) def test_update_existing_attr(self): """ @@ -202,7 +201,7 @@ 3 4 5 - """, str(tmpl.generate(Context(items=range(1, 6))))) + """, str(tmpl.generate(items=range(1, 6)))) def test_as_element(self): """ @@ -219,7 +218,7 @@ 3 4 5 - """, str(tmpl.generate(Context(items=range(1, 6))))) + """, str(tmpl.generate(items=range(1, 6)))) class IfDirectiveTestCase(unittest.TestCase): @@ -235,7 +234,7 @@ """) self.assertEqual(""" Hello - """, str(tmpl.generate(Context(foo=True, bar='Hello')))) + """, str(tmpl.generate(foo=True, bar='Hello'))) def test_as_element(self): """ @@ -246,7 +245,7 @@ """) self.assertEqual(""" Hello - """, str(tmpl.generate(Context(foo=True, bar='Hello')))) + """, str(tmpl.generate(foo=True, bar='Hello'))) class MatchDirectiveTestCase(unittest.TestCase): @@ -427,7 +426,7 @@ 42 84 42 -
""", str(tmpl.generate(Context(x=42)))) + """, str(tmpl.generate(x=42))) def test_as_element(self): tmpl = Template("""
@@ -435,7 +434,7 @@
""") self.assertEqual("""
84 -
""", str(tmpl.generate(Context(x=42)))) + """, str(tmpl.generate(x=42))) class TemplateTestCase(unittest.TestCase): @@ -488,9 +487,8 @@ self.assertEqual(' baz', parts[2][1]) def test_interpolate_mixed3(self): - ctxt = Context(var=42) tmpl = Template(' ${var} $var') - self.assertEqual(' 42 42', str(tmpl.generate(ctxt))) + self.assertEqual(' 42 42', str(tmpl.generate(var=42))) def test_interpolate_non_string_attrs(self): tmpl = Template('') @@ -498,8 +496,7 @@ def test_interpolate_list_result(self): tmpl = Template('$foo') - ctxt = Context(foo=('buzz',)) - self.assertEqual('buzz', str(tmpl.generate(ctxt))) + self.assertEqual('buzz', str(tmpl.generate(foo=('buzz',)))) def test_empty_attr(self): tmpl = Template('') @@ -560,7 +557,7 @@ """) self.assertEqual("""
foo -
""", str(tmpl.generate(Context(myvar=Markup('foo'))))) + """, str(tmpl.generate(myvar=Markup('foo')))) def test_text_noescape_quotes(self): """ @@ -571,7 +568,7 @@ """) self.assertEqual("""
"foo" -
""", str(tmpl.generate(Context(myvar='"foo"')))) + """, str(tmpl.generate(myvar='"foo"'))) def test_attr_escape_quotes(self): """ @@ -582,7 +579,7 @@ """) self.assertEqual("""
-
""", str(tmpl.generate(Context(myvar='"foo"')))) + """, str(tmpl.generate(myvar='"foo"'))) def test_directive_element(self): tmpl = Template("""
@@ -590,7 +587,7 @@
""") self.assertEqual("""
bar -
""", str(tmpl.generate(Context(myvar='"foo"')))) + """, str(tmpl.generate(myvar='"foo"'))) def test_normal_comment(self): tmpl = Template("""