From 063a9d8f6e6da72c101562d0af286b8c1b7f5eb4 Mon Sep 17 00:00:00 2001 From: Mike Bayer <mike_mp@zzzcomputing.com> Date: Sun, 26 Nov 2006 03:32:03 +0000 Subject: [PATCH] changed %component to %def --- doc/makotemplates.txt | 128 ++++++------- examples/bench/mako/template.html | 4 +- examples/bench/mako_inheritance/base.html | 4 +- lib/mako/codegen.py | 106 +++++------ lib/mako/parsetree.py | 6 +- lib/mako/runtime.py | 9 +- lib/mako/template.py | 14 +- test/alltests.py | 2 +- test/call.py | 76 ++++---- test/{component.py => def.py} | 216 +++++++++++----------- test/filters.py | 18 +- test/inheritance.py | 28 +-- test/lexer.py | 60 +++--- test/namespace.py | 36 ++-- 14 files changed, 357 insertions(+), 350 deletions(-) rename test/{component.py => def.py} (72%) diff --git a/doc/makotemplates.txt b/doc/makotemplates.txt index 3c1b019..08835d6 100644 --- a/doc/makotemplates.txt +++ b/doc/makotemplates.txt @@ -70,9 +70,9 @@ Hyperfast and Lightweight Templating for the Python Platform - callable blocks, with or without arguments, which also pull names from the enclosing scope: # define: - <%component name="foo(x, y)"> + <%def name="foo(x, y)"> hi im foo ${x} ${y} ${z} - </%component> + </%def> # then call: ${foo(4,5)} @@ -81,27 +81,27 @@ Hyperfast and Lightweight Templating for the Python Platform - "component-calls-with-content" - call any def, nesting any number locally-defined blocks of text as arguments. This is the basis for creating custom tags: # define: - <%component name="foo(x, y)"> + <%def name="foo(x, y)"> ${head()} foo ${x} {$y} ${body()} - </%component> + </%def> # then call, defining two more blocks <%call expr="foo(3, 4)"> - <%component name="head"> + <%def name="head"> the header - </%component> + </%def> main body </%call> - - filters, either the standard builtins or custom functions, applicable to any expression or `<%component>` definition: + - filters, either the standard builtins or custom functions, applicable to any expression or `<%def>` definition: ${"some text" | h} - <%component name="foo" filter="filter1, x"> + <%def name="foo" filter="filter1, x"> ... - </%component> + </%def> - custom tags can be created as templated components, or Python modules containing callables. Whole sets of custom tags can be imported into the current template's namespace using the `<%namespace>` tag. - caching built in from the ground up. any template or block of text within can be cached using memory, file, DBM or memcached backends. @@ -265,7 +265,7 @@ In fact every <%tag> can use expressions (i.e. ${}) inside of their quoted secti The include tag requires that the template being called has a `TemplateLookup` available with which to locate the included template. -Add the `import="true"` flag to the `<%include>` tag and when you include the file, all the `<%component>` and `<%namespace>` sections declared in that file (described later) are pulled into the local namespace of the template, as though they were declared locally: +Add the `import="true"` flag to the `<%include>` tag and when you include the file, all the `<%def>` and `<%namespace>` sections declared in that file (described later) are pulled into the local namespace of the template, as though they were declared locally: <%include file="somefile.html" import="true"/> @@ -273,15 +273,15 @@ Add the `import="true"` flag to the `<%include>` tag and when you include the fi The component is the single tag used to demarcate any block of text and/or code. It exists within generated Python as a callable function. - <%component name="hello"> + <%def name="hello"> hello world - </%component> + </%def> They are normally called as expressions. the component: ${hello()} -A `<%component>` can be declared anywhere inside a template, and becomes available throughout the template, including above where it was declared. The callable generated by `<%component>` gets generated outside of the enclosing template's callable. The name of the callable is then placed in the variable namespace of the parent component. +A `<%def>` can be declared anywhere inside a template, and becomes available throughout the template, including above where it was declared. The callable generated by `<%def>` gets generated outside of the enclosing template's callable. The name of the callable is then placed in the variable namespace of the parent component. Components have access to the current contextual namespace in exactly the same way their parent template does. @@ -289,33 +289,33 @@ Components have access to the current contextual namespace in exactly the same w ${account()} - <%component name="account"> + <%def name="account"> Account for ${username}:<br/> % for row in accountdata: Value: ${row}<br/> % endfor - </%component> + </%def> You can also pass arguments to a component, which show up in the component's variable namespace overriding whatever is in the enclosing namespace: ${account(name='john')} - <%component name="account"> + <%def name="account"> Hi ${name} - </%component> + </%def> If you want your component to have positional arguments, you can declare them: - <%component name="account(accountname, type)"> + <%def name="account(accountname, type)"> account name: ${accountname}, type ${type} - </%component> + </%def> As well as keyword arguments explicitly declared, using normal Python conventions: - <%component name="account(accountname, type='personal')"> + <%def name="account(accountname, type='personal')"> account name: ${accountname}, type ${type} - </%component> + </%def> When you declare explicit arguments in your component signature, they are required following normal Python conventions. This is in contrast to using variable names implicitly from the template's context, which produces `None` if the name doesn't exist. Additionally, explicitly declared arguments are handy in case you have the same names declared at the module level, and you'd like to insure that you get those arguments from the component call itself. @@ -335,15 +335,15 @@ Then, just call the components off of `mystuff`: #### Components within Components -The component model is totally recursive. Declaring `<%component>` inside another `<%component>` leads it to be local to its parent: +The component model is totally recursive. Declaring `<%def>` inside another `<%def>` leads it to be local to its parent: - <%component name="mycomponent"> - <%component name="subcomponent"> + <%def name="mycomponent"> + <%def name="subcomponent"> a sub component - </%component> + </%def> im the component, and the subcomopnent is ${subcomponent()} - </%component> + </%def> The recursive component model becomes very handy for doing layouts, including usage within inheriting templates. @@ -351,13 +351,13 @@ The recursive component model becomes very handy for doing layouts, including us A flip-side to component within component is a component call with content. This is where you call a component, and at the same time declare a block of content that can be used by the component being called. This is the basic method used to declare "custom tags". To achieve this, use the `<%call>` tag instead of the regular expression syntax. By default, the body of content is assigned to the name `body`: - <%component name="buildtable"> + <%def name="buildtable"> <table> <tr><td> ${body()} </td></tr> </table> - </%component> + </%def> <%call expr="buildtable"> I am the table body. @@ -373,11 +373,11 @@ This produces the output: The `body` name is executed each time its referenced. This means you can use component-call-with-content to build iterators, conditionals, etc: - <%component name="lister(count)"> + <%def name="lister(count)"> % for x in range(1,count): ${body()} % endfor - </%component> + </%def> <%call expr="lister(3)"> hi @@ -391,11 +391,11 @@ Produces: A custom "conditional" tag: - <%component name="conditional(expr)"> + <%def name="conditional(expr)"> % if expr: ${body()} % - </%component> + </%def> <%call expr="conditional(4==4)"> im the result @@ -407,7 +407,7 @@ Produces: Since `body` is a callable, the hosting component can pass arguments: - <%component name="layoutdata(somedata)"> + <%def name="layoutdata(somedata)"> <table> % for item in somedata: <tr> @@ -417,7 +417,7 @@ Since `body` is a callable, the hosting component can pass arguments: </tr> % endfor </table> - </%component> + </%def> <%call expr="layoutdata([[1,2,3],[4,5,6],[7,8,9]])"> Body data: ${col} @@ -435,7 +435,7 @@ Produces: If you combine nested components with the component call with content, you can build whole layouts quite easily: - <%component name="layout"> + <%def name="layout"> # a layout component <div class="mainlayout"> <div class="header"> @@ -448,19 +448,19 @@ If you combine nested components with the component call with content, you can b ${body()} </div> </div> - </%component> + </%def> # calls the layout component <%call expr="layout"> - <%component name="header"> + <%def name="header"> I am the header - </%component> - <%component name="sidebar"> + </%def> + <%def name="sidebar"> <ul> <li>sidebar 1</li> <li>sidebar 2</li> </ul> - </%component> + </%def> this is the body </%call> @@ -484,20 +484,20 @@ The above layout would produce: ### Inheritance -Inheritance allows you to specify another template file that should take control of execution, using the current template's namespace. This is provided via the <%inherit> tag. This works similarly to the component call with content example above, where `body` is the main body of the template and you can also define other `<%component>` sections: +Inheritance allows you to specify another template file that should take control of execution, using the current template's namespace. This is provided via the <%inherit> tag. This works similarly to the component call with content example above, where `body` is the main body of the template and you can also define other `<%def>` sections: # page.html: <%inherit name="base.html"/> - <%component name="header"> + <%def name="header"> this is the header - </%component> + </%def> I am the body - <%component name="footer"> + <%def name="footer"> this is the footer - </%component> + </%def> # base.html: @@ -551,10 +551,10 @@ Filters are callable functions that receive a single textual argument as a strin ${"this is some text" | html} -Or using the `filter` keyword for a `<%component>` or `<%call>` directive: +Or using the `filter` keyword for a `<%def>` or `<%call>` directive: - <%component name="mycomp" filter="html"> - </%component> + <%def name="mycomp" filter="html"> + </%def> Standard built-in filters are included: `html`, `xml`, `url`. @@ -567,11 +567,11 @@ Creating your own filters is easy. Any callable that is in the template's names ${"hiya" | myfilter} -Filters can also be defined using the `<%component>` tag. The text to be filtered is placed into the name 'text': +Filters can also be defined using the `<%def>` tag. The text to be filtered is placed into the name 'text': - <%component myfilter> + <%def myfilter> text${text}filtered - </%component> + </%def> ${"hiya" | myfilter} @@ -583,25 +583,25 @@ Filters can take arguments ! Using a python function: %> ${"hiya" | pythonfilter('hello', 'world')} -Or a `<%component>`: +Or a `<%def>`: - <%component componentfilter(arg1, arg2='foo')> + <%def componentfilter(arg1, arg2='foo')> text${text}filtered - </%component> + </%def> ${"hiya" | componentfilter('hello', 'world')} ### Caching -Any template or component can be cached using the `cache` argument to the `%page` or `%component` directives: +Any template or component can be cached using the `cache` argument to the `%page` or `%def` directives: <%page cache="true"/> template text - <%component name="mycomp" cache="true" cache_timeout="30" cache_type="memory"> + <%def name="mycomp" cache="true" cache_timeout="30" cache_type="memory"> other text - </%component> + </%def> Cache arguments: - cache="false|true" - turn caching on @@ -615,13 +615,13 @@ Namespaces are used to organize groups of components into categories, and also t If the file `components.html` defines these two components: # components.html - <%component name="comp1"> + <%def name="comp1"> this is comp1 - </%component> + </%def> - <%component name="comp2"> + <%def name="comp2"> this is comp2 - </%component> + </%def> You can make another file, for example `index.html`, that pulls those two components into a namespace called `comp`: @@ -631,13 +631,13 @@ You can make another file, for example `index.html`, that pulls those two compon Heres comp1: ${comp.comp1()} Heres comp2: ${comp.comp2()} -The `<%namespace>` tag is more powerful than that. You can also declare `<%components>` within the namespace: +The `<%namespace>` tag is more powerful than that. You can also declare `<%defs>` within the namespace: # define a namespace <%namespace name="stuff"> - <%component name="comp1"> + <%def name="comp1"> comp1 - </%component> + </%def> </%namespace> # then call it diff --git a/examples/bench/mako/template.html b/examples/bench/mako/template.html index d861d54..2bd9fce 100644 --- a/examples/bench/mako/template.html +++ b/examples/bench/mako/template.html @@ -7,9 +7,9 @@ </head> <body> -<%component name="greeting(name)"> +<%def name="greeting(name)"> <p>hello ${name}!</p> -</%component> +</%def> <%include file="header.html"/> diff --git a/examples/bench/mako_inheritance/base.html b/examples/bench/mako_inheritance/base.html index f076e78..87f0f24 100644 --- a/examples/bench/mako_inheritance/base.html +++ b/examples/bench/mako_inheritance/base.html @@ -7,9 +7,9 @@ </head> <body> -<%component name="greeting(name)"> +<%def name="greeting(name)"> <p>hello ${name}!</p> -</%component> +</%def> <div id="header"> <h1>${title}</h1> diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py index 581058a..78aa21d 100644 --- a/lib/mako/codegen.py +++ b/lib/mako/codegen.py @@ -34,7 +34,7 @@ class Compiler(object): module_identifiers = module_identifiers.branch(n) main_identifiers = module_identifiers.branch(self.node) - module_identifiers.toplevelcomponents = module_identifiers.toplevelcomponents.union(main_identifiers.toplevelcomponents) + module_identifiers.topleveldefs = module_identifiers.topleveldefs.union(main_identifiers.topleveldefs) # module-level names, python code printer.writeline("from mako import runtime") @@ -44,7 +44,7 @@ class Compiler(object): printer.writeline("UNDEFINED = runtime.UNDEFINED") printer.writeline("from mako import filters") [module_identifiers.declared.add(x) for x in ["UNDEFINED"]] - printer.writeline("_exports = %s" % repr([n.name for n in main_identifiers.toplevelcomponents])) + printer.writeline("_exports = %s" % repr([n.name for n in main_identifiers.topleveldefs])) printer.write("\n\n") @@ -55,8 +55,8 @@ class Compiler(object): # print main render() method _GenerateRenderMethod(printer, module_identifiers, self.node) - # print render() for each top-level component - for node in main_identifiers.toplevelcomponents: + # print render() for each top-level def + for node in main_identifiers.topleveldefs: _GenerateRenderMethod(printer, module_identifiers, node) return buf.getvalue() @@ -68,16 +68,16 @@ class _GenerateRenderMethod(object): self.last_source_line = -1 self.node = node - if isinstance(node, parsetree.ComponentTag): + if isinstance(node, parsetree.DefTag): name = "render_" + node.name args = node.function_decl.get_argument_expressions() - self.in_component = True + self.in_def = True filtered = len(node.filter_args.args) > 0 buffered = eval(node.attributes.get('buffered', 'False')) else: name = "render" args = None - self.in_component = False + self.in_def = False buffered = filtered = False if args is None: @@ -85,7 +85,7 @@ class _GenerateRenderMethod(object): else: args = [a for a in ['context'] + args] - if not self.in_component: + if not self.in_def: self._inherit() printer.writeline("def %s(%s):" % (name, ','.join(args))) @@ -102,7 +102,7 @@ class _GenerateRenderMethod(object): for n in node.nodes: n.accept_visitor(self) - self.write_component_finish(node, buffered, filtered) + self.write_def_finish(node, buffered, filtered) printer.write("\n\n") @@ -119,18 +119,18 @@ class _GenerateRenderMethod(object): def write_variable_declares(self, identifiers, first=None): """write variable declarations at the top of a function. - the variable declarations are in the form of callable definitions for components and/or + the variable declarations are in the form of callable definitions for defs and/or name lookup within the function's context argument. the names declared are based on the names that are referenced in the function body, which don't otherwise have any explicit assignment operation. names that are assigned within the body are assumed to be locally-scoped variables and are not separately declared. - for component callable definitions, if the component is a top-level callable then a - 'stub' callable is generated which wraps the current Context into a closure. if the component + for def callable definitions, if the def is a top-level callable then a + 'stub' callable is generated which wraps the current Context into a closure. if the def is not top-level, it is fully rendered as a local closure.""" - # collection of all components available to us in this scope - comp_idents = dict([(c.name, c) for c in identifiers.components]) + # collection of all defs available to us in this scope + comp_idents = dict([(c.name, c) for c in identifiers.defs]) to_write = util.Set() @@ -138,7 +138,7 @@ class _GenerateRenderMethod(object): to_write = to_write.union(identifiers.undeclared) # write closure functions for closures that we define right here - to_write = to_write.union(util.Set([c.name for c in identifiers.closurecomponents])) + to_write = to_write.union(util.Set([c.name for c in identifiers.closuredefs])) # remove identifiers that are declared in the argument signature of the callable to_write = to_write.difference(identifiers.argument_declared) @@ -152,9 +152,9 @@ class _GenerateRenderMethod(object): if ident in comp_idents: comp = comp_idents[ident] if comp.is_root(): - self.write_component_decl(comp, identifiers) + self.write_def_decl(comp, identifiers) else: - self.write_inline_component(comp, identifiers) + self.write_inline_def(comp, identifiers) else: if first is not None: self.printer.writeline("%s = %s.get(%s, context.get(%s, UNDEFINED))" % (ident, first, repr(ident), repr(ident))) @@ -166,8 +166,8 @@ class _GenerateRenderMethod(object): self.printer.writeline("# SOURCE LINE %d" % node.lineno, is_comment=True) self.last_source_line = node.lineno - def write_component_decl(self, node, identifiers): - """write a locally-available callable referencing a top-level component""" + def write_def_decl(self, node, identifiers): + """write a locally-available callable referencing a top-level def""" funcname = node.function_decl.funcname namedecls = node.function_decl.get_argument_expressions() nameargs = node.function_decl.get_argument_expressions(include_defaults=False) @@ -179,8 +179,8 @@ class _GenerateRenderMethod(object): self.printer.writeline("return render_%s(%s)" % (funcname, ",".join(nameargs))) self.printer.writeline(None) - def write_inline_component(self, node, identifiers): - """write a locally-available component callable inside an enclosing component.""" + def write_inline_def(self, node, identifiers): + """write a locally-available def callable inside an enclosing def.""" namedecls = node.function_decl.get_argument_expressions() self.printer.writeline("def %s(%s):" % (node.name, ",".join(namedecls))) filtered = len(node.filter_args.args) > 0 @@ -195,9 +195,9 @@ class _GenerateRenderMethod(object): for n in node.nodes: n.accept_visitor(self) - self.write_component_finish(node, buffered, filtered) + self.write_def_finish(node, buffered, filtered) - def write_component_finish(self, node, buffered, filtered): + def write_def_finish(self, node, buffered, filtered): if not buffered: self.printer.writeline("return ''") if buffered or filtered: @@ -241,9 +241,9 @@ class _GenerateRenderMethod(object): self.write_source_comment(node) self.printer.write_indented_block(node.text) - if not self.in_component: - # if we are the "template" component, fudge locally declared/modified variables into the "__locals" dictionary, - # which is used for component calls within the same template, to simulate "enclosing scope" + if not self.in_def: + # if we are the "template" def, fudge locally declared/modified variables into the "__locals" dictionary, + # which is used for def calls within the same template, to simulate "enclosing scope" self.printer.writeline('__locals.update(%s)' % (",".join(["%s=%s" % (x, x) for x in node.declared_identifiers()]))) def visitIncludeTag(self, node): @@ -255,18 +255,18 @@ class _GenerateRenderMethod(object): self.printer.writeline("def make_namespace():") export = [] identifiers = self.identifiers.branch(node) - class NSComponentVisitor(object): - def visitComponentTag(s, node): - self.write_inline_component(node, identifiers) + class NSDefVisitor(object): + def visitDefTag(s, node): + self.write_inline_def(node, identifiers) export.append(node.name) - vis = NSComponentVisitor() + vis = NSDefVisitor() for n in node.nodes: n.accept_visitor(vis) self.printer.writeline("return [%s]" % (','.join(export))) self.printer.writeline(None) self.printer.writeline("%s = runtime.Namespace(%s, context.clean_inheritance_tokens(), templateuri=%s, callables=make_namespace())" % (node.name, repr(node.name), node.parsed_attributes.get('file', 'None'))) - def visitComponentTag(self, node): + def visitDefTag(self, node): pass def visitCallTag(self, node): @@ -274,15 +274,15 @@ class _GenerateRenderMethod(object): self.printer.writeline("def ccall(context):") export = ['body'] identifiers = self.identifiers.branch(node) - class ComponentVisitor(object): - def visitComponentTag(s, node): - self.write_inline_component(node, identifiers) + class DefVisitor(object): + def visitDefTag(s, node): + self.write_inline_def(node, identifiers) export.append(node.name) - vis = ComponentVisitor() + vis = DefVisitor() for n in node.nodes: n.accept_visitor(vis) self.printer.writeline("def body(**kwargs):") - body_identifiers = identifiers.branch(node, includecomponents=False, includenode=False) + body_identifiers = identifiers.branch(node, includedefs=False, includenode=False) self.write_variable_declares(body_identifiers, first="kwargs") for n in node.nodes: n.accept_visitor(self) @@ -300,16 +300,16 @@ class _GenerateRenderMethod(object): class _Identifiers(object): """tracks the status of identifier names as template code is rendered.""" - def __init__(self, node=None, parent=None, includecomponents=True, includenode=True): + def __init__(self, node=None, parent=None, includedefs=True, includenode=True): if parent is not None: # things that have already been declared in an enclosing namespace (i.e. names we can just use) - self.declared = util.Set(parent.declared).union([c.name for c in parent.closurecomponents]).union(parent.locally_declared) + self.declared = util.Set(parent.declared).union([c.name for c in parent.closuredefs]).union(parent.locally_declared) - # top level components that are available - self.toplevelcomponents = util.Set(parent.toplevelcomponents) + # top level defs that are available + self.topleveldefs = util.Set(parent.topleveldefs) else: self.declared = util.Set() - self.toplevelcomponents = util.Set() + self.topleveldefs = util.Set() # things within this level that are referenced before they are declared (e.g. assigned to) self.undeclared = util.Set() @@ -319,17 +319,17 @@ class _Identifiers(object): self.locally_declared = util.Set() # assignments made in explicit python blocks. these will be propigated to - # the context of local component calls. + # the context of local def calls. self.locally_assigned = util.Set() - # things that are declared in the argument signature of the component callable + # things that are declared in the argument signature of the def callable self.argument_declared = util.Set() - # closure components that are defined in this level - self.closurecomponents = util.Set() + # closure defs that are defined in this level + self.closuredefs = util.Set() self.node = node - self.includecomponents = includecomponents + self.includedefs = includedefs if node is not None: if includenode: node.accept_visitor(self) @@ -341,10 +341,10 @@ class _Identifiers(object): """create a new Identifiers for a new Node, with this Identifiers as the parent.""" return _Identifiers(node, self, **kwargs) - components = property(lambda s:s.toplevelcomponents.union(s.closurecomponents)) + defs = property(lambda s:s.topleveldefs.union(s.closuredefs)) def __repr__(self): - return "Identifiers(%s, %s, %s, %s, %s)" % (repr(list(self.declared)), repr(list(self.locally_declared)), repr(list(self.undeclared)), repr([c.name for c in self.toplevelcomponents]), repr([c.name for c in self.closurecomponents])) + return "Identifiers(%s, %s, %s, %s, %s)" % (repr(list(self.declared)), repr(list(self.locally_declared)), repr(list(self.undeclared)), repr([c.name for c in self.topleveldefs]), repr([c.name for c in self.closuredefs])) def check_declared(self, node): """update the state of this Identifiers with the undeclared and declared identifiers of the given node.""" @@ -362,19 +362,19 @@ class _Identifiers(object): if not node.ismodule: self.check_declared(node) self.locally_assigned = self.locally_assigned.union(node.declared_identifiers()) - def visitComponentTag(self, node): - if not self.includecomponents: + def visitDefTag(self, node): + if not self.includedefs: return if node.is_root(): - self.toplevelcomponents.add(node) + self.topleveldefs.add(node) elif node is not self.node: - self.closurecomponents.add(node) + self.closuredefs.add(node) for ident in node.undeclared_identifiers(): if ident != 'context' and ident not in self.declared.union(self.locally_declared): self.undeclared.add(ident) for ident in node.declared_identifiers(): self.argument_declared.add(ident) - # visit components only one level deep + # visit defs only one level deep if node is self.node: for n in node.nodes: n.accept_visitor(self) diff --git a/lib/mako/parsetree.py b/lib/mako/parsetree.py index 3446942..4ee3cba 100644 --- a/lib/mako/parsetree.py +++ b/lib/mako/parsetree.py @@ -227,10 +227,10 @@ class NamespaceTag(Tag): def declared_identifiers(self): return [self.name] -class ComponentTag(Tag): - __keyword__ = 'component' +class DefTag(Tag): + __keyword__ = 'def' def __init__(self, keyword, attributes, **kwargs): - super(ComponentTag, self).__init__(keyword, attributes, ('buffered'), ('name','filter'), ('name',), **kwargs) + super(DefTag, self).__init__(keyword, attributes, ('buffered'), ('name','filter'), ('name',), **kwargs) name = attributes['name'] if re.match(r'^[\w_]+$',name): name = name + "()" diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py index ce98686..1a81c09 100644 --- a/lib/mako/runtime.py +++ b/lib/mako/runtime.py @@ -71,6 +71,12 @@ class Undefined(object): raise NameError("Undefined") UNDEFINED = Undefined() + +class _AttrGateway(object): + def __init__(self,ns): + self.ns = ns + def __getattr__(self, key): + return getattr(self.ns.template.module, key) class Namespace(object): """provides access to collections of rendering methods, which can be local, from other templates, or from imported modules""" @@ -81,6 +87,7 @@ class Namespace(object): self.template = _lookup_template(context, templateuri) else: self.template = template + self.attributes = _AttrGateway(self) self.context = context self.inherits = inherits if callables is not None: @@ -101,7 +108,7 @@ class Namespace(object): callable_ = self.template.module.render else: try: - callable_ = self.template.get_component(key).callable_ + callable_ = self.template.get_def(key).callable_ except AttributeError: callable_ = None if callable_ is not None: diff --git a/lib/mako/template.py b/lib/mako/template.py index 1aacf4e..0d6947b 100644 --- a/lib/mako/template.py +++ b/lib/mako/template.py @@ -80,17 +80,17 @@ class Template(object): the data is written to the context's buffer.""" runtime._render_context(self, self.callable_, context, *args, **kwargs) - def get_component(self, name): - """return a component of this template as an individual Template of its own.""" - return ComponentTemplate(self, getattr(self.module, "render_%s" % name)) + def get_def(self, name): + """return a def of this template as an individual Template of its own.""" + return DefTemplate(self, getattr(self.module, "render_%s" % name)) -class ComponentTemplate(Template): - """a Template which represents a callable component in a parent template.""" +class DefTemplate(Template): + """a Template which represents a callable def in a parent template.""" def __init__(self, parent, callable_): self.parent = parent self.callable_ = callable_ - def get_component(self, name): - return self.parent.get_component(name) + def get_def(self, name): + return self.parent.get_def(name) def _compile_text(text, identifier, filename): node = Lexer(text).parse() diff --git a/test/alltests.py b/test/alltests.py index b2b602f..b209e06 100644 --- a/test/alltests.py +++ b/test/alltests.py @@ -6,7 +6,7 @@ def suite(): 'pygen', 'lexer', 'template', - 'component', + 'def', 'namespace', 'inheritance', 'call' diff --git a/test/call.py b/test/call.py index 4d8d1cb..15208f7 100644 --- a/test/call.py +++ b/test/call.py @@ -5,9 +5,9 @@ from util import result_lines class CallTest(unittest.TestCase): def test_call(self): t = Template(""" - <%component name="foo"> + <%def name="foo"> hi im foo ${caller.body(y=5)} - </%component> + </%def> <%call expr="foo()"> this is the body, y is ${y} @@ -19,23 +19,23 @@ class CallTest(unittest.TestCase): def test_compound_call(self): t = Template(""" - <%component name="bar"> + <%def name="bar"> this is bar - </%component> + </%def> - <%component name="comp1"> + <%def name="comp1"> this comp1 should not be called - </%component> + </%def> - <%component name="foo"> + <%def name="foo"> foo calling comp1: ${caller.comp1(x=5)} foo calling body: ${caller.body()} - </%component> + </%def> <%call expr="foo()"> - <%component name="comp1(x)"> + <%def name="comp1(x)"> this is comp1, ${x} - </%component> + </%def> this is the body, ${comp1(6)} </%call> ${bar()} @@ -45,16 +45,16 @@ class CallTest(unittest.TestCase): def test_multi_call(self): t = Template(""" - <%component name="a"> + <%def name="a"> this is a. <%call expr="b()"> this is a's ccall. heres my body: ${caller.body()} </%call> - </%component> - <%component name="b"> + </%def> + <%def name="b"> this is b. heres my body: ${caller.body()} whats in the body's caller's body ? ${caller.context['caller'].body()} - </%component> + </%def> <%call expr="a()"> heres the main templ call @@ -72,22 +72,22 @@ class CallTest(unittest.TestCase): def test_multi_call_in_nested(self): t = Template(""" - <%component name="embedded"> - <%component name="a"> + <%def name="embedded"> + <%def name="a"> this is a. <%call expr="b()"> this is a's ccall. heres my body: ${caller.body()} </%call> - </%component> - <%component name="b"> + </%def> + <%def name="b"> this is b. heres my body: ${caller.body()} whats in the body's caller's body ? ${caller.context['caller'].body()} - </%component> + </%def> <%call expr="a()"> heres the main templ call </%call> - </%component> + </%def> ${embedded()} """) assert result_lines(t.render()) == [ @@ -101,46 +101,46 @@ class CallTest(unittest.TestCase): def test_call_in_nested(self): t = Template(""" - <%component name="a"> + <%def name="a"> this is a ${b()} - <%component name="b"> + <%def name="b"> this is b <%call expr="c()"> this is the body in b's call </%call> - </%component> - <%component name="c"> + </%def> + <%def name="c"> this is c: ${caller.body()} - </%component> - </%component> + </%def> + </%def> ${a()} """) assert result_lines(t.render()) == ['this is a', 'this is b', 'this is c:', "this is the body in b's call"] def test_call_in_nested_2(self): t = Template(""" - <%component name="a"> - <%component name="d"> + <%def name="a"> + <%def name="d"> not this d - </%component> + </%def> this is a ${b()} - <%component name="b"> - <%component name="d"> + <%def name="b"> + <%def name="d"> not this d either - </%component> + </%def> this is b <%call expr="c()"> - <%component name="d"> + <%def name="d"> this is d - </%component> + </%def> this is the body in b's call </%call> - </%component> - <%component name="c"> + </%def> + <%def name="c"> this is c: ${caller.body()} the embedded "d" is: ${caller.d()} - </%component> - </%component> + </%def> + </%def> ${a()} """) assert result_lines(t.render()) == ['this is a', 'this is b', 'this is c:', "this is the body in b's call", 'the embedded "d" is:', 'this is d'] diff --git a/test/component.py b/test/def.py similarity index 72% rename from test/component.py rename to test/def.py index 3b0593f..1513422 100644 --- a/test/component.py +++ b/test/def.py @@ -3,54 +3,54 @@ from mako import lookup import unittest from util import flatten_result -class ComponentTest(unittest.TestCase): - def test_component_noargs(self): +class DefTest(unittest.TestCase): + def test_def_noargs(self): template = Template(""" ${mycomp()} - <%component name="mycomp"> + <%def name="mycomp"> hello mycomp ${variable} - </%component> + </%def> """) assert template.render(variable='hi').strip() == """hello mycomp hi""" - def test_component_blankargs(self): + def test_def_blankargs(self): template = Template(""" - <%component name="mycomp()"> + <%def name="mycomp()"> hello mycomp ${variable} - </%component> + </%def> ${mycomp()}""") assert template.render(variable='hi').strip() == """hello mycomp hi""" - def test_component_args(self): + def test_def_args(self): template = Template(""" - <%component name="mycomp(a, b)"> + <%def name="mycomp(a, b)"> hello mycomp ${variable}, ${a}, ${b} - </%component> + </%def> ${mycomp(5, 6)}""") assert template.render(variable='hi', a=5, b=6).strip() == """hello mycomp hi, 5, 6""" - def test_inter_component(self): - """test components calling each other""" + def test_inter_def(self): + """test defs calling each other""" template = Template(""" ${b()} - <%component name="a">\ + <%def name="a">\ im a - </%component> + </%def> - <%component name="b"> + <%def name="b"> im b and heres a: ${a()} - </%component> + </%def> - <%component name="c"> + <%def name="c"> im c - </%component> + </%def> """) # check that "a" is declared in "b", but not in "c" assert "a" not in template.module.render_c.func_code.co_varnames @@ -63,9 +63,9 @@ class ScopeTest(unittest.TestCase): """test scoping rules. The key is, enclosing scope always takes precedence over contextual scope.""" def test_scope_one(self): t = Template(""" - <%component name="a"> + <%def name="a"> this is a, and y is ${y} - </%component> + </%def> ${a()} @@ -100,17 +100,17 @@ class ScopeTest(unittest.TestCase): <% x = 5 %> - <%component name="a"> + <%def name="a"> this is a. x is ${x}. - </%component> + </%def> - <%component name="b"> + <%def name="b"> <% x = 9 %> this is b. x is ${x}. calling a. ${a()} - </%component> + </%def> ${b()} """) @@ -120,86 +120,86 @@ class ScopeTest(unittest.TestCase): """test that variables are pulled from 'enclosing' scope before context.""" # same as test four, but adds a scope around it. t = Template(""" - <%component name="enclosing"> + <%def name="enclosing"> <% x = 5 %> - <%component name="a"> + <%def name="a"> this is a. x is ${x}. - </%component> + </%def> - <%component name="b"> + <%def name="b"> <% x = 9 %> this is b. x is ${x}. calling a. ${a()} - </%component> + </%def> ${b()} - </%component> + </%def> ${enclosing()} """) assert flatten_result(t.render()) == "this is b. x is 9. calling a. this is a. x is 5." def test_scope_six(self): - """test that the initial context counts as 'enclosing' scope, for plain components""" + """test that the initial context counts as 'enclosing' scope, for plain defs""" t = Template(""" - <%component name="a"> + <%def name="a"> a: x is ${x} - </%component> + </%def> - <%component name="b"> + <%def name="b"> <% x = 10 %> b. x is ${x}. ${a()} - </%component> + </%def> ${b()} """) assert flatten_result(t.render(x=5)) == "b. x is 10. a: x is 5" def test_scope_seven(self): - """test that the initial context counts as 'enclosing' scope, for nested components""" + """test that the initial context counts as 'enclosing' scope, for nested defs""" t = Template(""" - <%component name="enclosing"> - <%component name="a"> + <%def name="enclosing"> + <%def name="a"> a: x is ${x} - </%component> + </%def> - <%component name="b"> + <%def name="b"> <% x = 10 %> b. x is ${x}. ${a()} - </%component> + </%def> ${b()} - </%component> + </%def> ${enclosing()} """) assert flatten_result(t.render(x=5)) == "b. x is 10. a: x is 5" def test_scope_eight(self): - """test that the initial context counts as 'enclosing' scope, for nested components""" + """test that the initial context counts as 'enclosing' scope, for nested defs""" t = Template(""" - <%component name="enclosing"> - <%component name="a"> + <%def name="enclosing"> + <%def name="a"> a: x is ${x} - </%component> + </%def> - <%component name="b"> + <%def name="b"> <% x = 10 %> b. x is ${x}. ${a()} - </%component> + </%def> ${b()} - </%component> + </%def> ${enclosing()} """) assert flatten_result(t.render(x=5)) == "b. x is 10. a: x is 5" @@ -227,17 +227,17 @@ class ScopeTest(unittest.TestCase): def test_scope_ten(self): t = Template(""" - <%component name="a"> - <%component name="b"> + <%def name="a"> + <%def name="b"> <% y = 19 %> b/c: ${c()} b/y: ${y} - </%component> - <%component name="c"> + </%def> + <%def name="c"> c/y: ${y} - </%component> + </%def> <% # we assign to "y". but the 'enclosing scope' of "b" and "c" is from the "y" on the outside @@ -245,7 +245,7 @@ class ScopeTest(unittest.TestCase): %> a/y: ${y} a/b: ${b()} - </%component> + </%def> <% y = 7 @@ -260,14 +260,14 @@ class ScopeTest(unittest.TestCase): <% y = 10 %> - <%component name="a"> + <%def name="a"> y is: ${y} <% # should raise error ? y = 15 %> y is ${y} - </%component> + </%def> ${a()} """) try: @@ -278,20 +278,20 @@ class ScopeTest(unittest.TestCase): def test_unbound_scope_two(self): t = Template(""" - <%component name="enclosing"> + <%def name="enclosing"> <% y = 10 %> - <%component name="a"> + <%def name="a"> y is: ${y} <% # should raise error ? y = 15 %> y is ${y} - </%component> + </%def> ${a()} - </%component> + </%def> ${enclosing()} """) try: @@ -300,124 +300,124 @@ class ScopeTest(unittest.TestCase): except UnboundLocalError: assert True -class NestedComponentTest(unittest.TestCase): - def test_nested_component(self): +class NestedDefTest(unittest.TestCase): + def test_nested_def(self): t = Template(""" ${hi()} - <%component name="hi"> + <%def name="hi"> hey, im hi. and heres ${foo()}, ${bar()} - <%component name="foo"> + <%def name="foo"> this is foo - </%component> + </%def> - <%component name="bar"> + <%def name="bar"> this is bar - </%component> - </%component> + </%def> + </%def> """) assert flatten_result(t.render()) == "hey, im hi. and heres this is foo , this is bar" def test_nested_with_args(self): t = Template(""" ${a()} - <%component name="a"> - <%component name="b(x, y=2)"> + <%def name="a"> + <%def name="b(x, y=2)"> b x is ${x} y is ${y} - </%component> + </%def> a ${b(5)} - </%component> + </%def> """) assert flatten_result(t.render()) == "a b x is 5 y is 2" - def test_nested_component_2(self): + def test_nested_def_2(self): template = Template(""" ${a()} - <%component name="a"> - <%component name="b"> - <%component name="c"> + <%def name="a"> + <%def name="b"> + <%def name="c"> comp c - </%component> + </%def> ${c()} - </%component> + </%def> ${b()} - </%component> + </%def> """) assert flatten_result(template.render()) == "comp c" - def test_nested_nested_component(self): + def test_nested_nested_def(self): t = Template(""" ${a()} - <%component name="a"> + <%def name="a"> a - <%component name="b1"> + <%def name="b1"> a_b1 - </%component> - <%component name="b2"> + </%def> + <%def name="b2"> a_b2 ${c1()} - <%component name="c1"> + <%def name="c1"> a_b2_c1 - </%component> - </%component> - <%component name="b3"> + </%def> + </%def> + <%def name="b3"> a_b3 ${c1()} - <%component name="c1"> + <%def name="c1"> a_b3_c1 heres x: ${x} <% y = 7 %> y is ${y} - </%component> - <%component name="c2"> + </%def> + <%def name="c2"> a_b3_c2 y is ${y} c1 is ${c1()} - </%component> + </%def> ${c2()} - </%component> + </%def> ${b1()} ${b2()} ${b3()} - </%component> + </%def> """) assert flatten_result(t.render(x=5, y=None)) == "a a_b1 a_b2 a_b2_c1 a_b3 a_b3_c1 heres x: 5 y is 7 a_b3_c2 y is None c1 is a_b3_c1 heres x: 5 y is 7" - def test_nested_nested_component_2(self): + def test_nested_nested_def_2(self): t = Template(""" - <%component name="a"> + <%def name="a"> this is a ${b()} - <%component name="b"> + <%def name="b"> this is b ${c()} - </%component> + </%def> - <%component name="c"> + <%def name="c"> this is c - </%component> - </%component> + </%def> + </%def> ${a()} """ ) assert flatten_result(t.render()) == "this is a this is b this is c" def test_outer_scope(self): t = Template(""" - <%component name="a"> + <%def name="a"> a: x is ${x} - </%component> + </%def> - <%component name="b"> - <%component name="c"> + <%def name="b"> + <%def name="c"> <% x = 10 %> c. x is ${x}. ${a()} - </%component> + </%def> b. ${c()} - </%component> + </%def> ${b()} diff --git a/test/filters.py b/test/filters.py index 6f0bf15..43e9c58 100644 --- a/test/filters.py +++ b/test/filters.py @@ -19,11 +19,11 @@ class FilterTest(unittest.TestCase): return lambda x: "MYFILTER->%s<-%s" % (x, y) assert flatten_result(t.render(x="this is x", myfilter=myfilter, y="this is y")) == "MYFILTER->this is x<-this is y" - def test_component(self): + def test_def(self): t = Template(""" - <%component name="foo" filter="myfilter"> + <%def name="foo" filter="myfilter"> this is foo - </%component> + </%def> ${foo()} """) assert flatten_result(t.render(x="this is x", myfilter=lambda t: "MYFILTER->%s<-MYFILTER" % t)) == "MYFILTER-> this is foo <-MYFILTER" @@ -40,20 +40,20 @@ class FilterTest(unittest.TestCase): assert flatten_result(t.render()) == "http://foo.com/arg1=hi%21+this+is+a+string." class BufferTest(unittest.TestCase): - def test_buffered_component(self): + def test_buffered_def(self): t = Template(""" - <%component name="foo" buffered="True"> + <%def name="foo" buffered="True"> this is foo - </%component> + </%def> ${"hi->" + foo() + "<-hi"} """) assert flatten_result(t.render()) == "hi-> this is foo <-hi" - def test_unbuffered_component(self): + def test_unbuffered_def(self): t = Template(""" - <%component name="foo" buffered="False"> + <%def name="foo" buffered="False"> this is foo - </%component> + </%def> ${"hi->" + foo() + "<-hi"} """) assert flatten_result(t.render()) == "this is foo hi-><-hi" diff --git a/test/inheritance.py b/test/inheritance.py index 1cc4822..7836dce 100644 --- a/test/inheritance.py +++ b/test/inheritance.py @@ -14,9 +14,9 @@ class InheritanceTest(unittest.TestCase): tmpl['main'] = Template(""" <%inherit file="base"/> -<%component name="header"> +<%def name="header"> main header. -</%component> +</%def> this is the content. """, lookup=collection) @@ -30,9 +30,9 @@ body: ${self.body()} footer: ${self.footer()} -<%component name="footer"> +<%def name="footer"> this is the footer. header again ${next.header()} -</%component> +</%def> """, lookup=collection) assert result_lines(tmpl['main'].render()) == [ @@ -51,7 +51,7 @@ footer: ${self.footer()} collection.put_string('main', """ <%inherit file="layout"/> -<%component name="d">main_d</%component> +<%def name="d">main_d</%def> main_body ${parent.d()} full stack from the top: ${self.name} ${parent.name} ${parent.context['parent'].name} ${parent.context['parent'].context['parent'].name} @@ -59,7 +59,7 @@ full stack from the top: collection.put_string('layout', """ <%inherit file="general"/> -<%component name="d">layout_d</%component> +<%def name="d">layout_d</%def> layout_body parent name: ${parent.name} ${parent.d()} @@ -69,7 +69,7 @@ ${next.body()} collection.put_string('general', """ <%inherit file="base"/> -<%component name="d">general_d</%component> +<%def name="d">general_d</%def> general_body ${next.d()} ${next.context['next'].d()} @@ -80,7 +80,7 @@ base_body full stack from the base: ${self.name} ${self.context['parent'].name} ${self.context['parent'].context['parent'].name} ${self.context['parent'].context['parent'].context['parent'].name} ${next.body()} -<%component name="d">base_d</%component> +<%def name="d">base_d</%def> """) assert result_lines(collection.get_template('main').render()) == [ @@ -105,7 +105,7 @@ ${next.body()} collection = lookup.TemplateLookup() collection.put_string("base", """ - <%component name="a">base_a</%component> + <%def name="a">base_a</%def> This is the base. ${next.body()} End base. @@ -141,15 +141,15 @@ ${next.body()} collection = lookup.TemplateLookup() collection.put_string("base", """ - <%component name="a">base_a</%component> - <%component name="b">base_b</%component> + <%def name="a">base_a</%def> + <%def name="b">base_b</%def> This is the base. ${next.body()} """) collection.put_string("layout", """ <%inherit file="base"/> - <%component name="a()">layout_a</%component> + <%def name="a()">layout_a</%def> This is the layout.. ${next.body()} """) @@ -167,8 +167,8 @@ ${next.body()} collection.put_string("secondary",""" <%inherit file="layout"/> - <%component name="c">secondary_c. a is ${self.a()} b is ${self.b()} d is ${self.d()}</%component> - <%component name="d">secondary_d.</%component> + <%def name="c">secondary_c. a is ${self.a()} b is ${self.b()} d is ${self.d()}</%def> + <%def name="d">secondary_d.</%def> this is secondary. a is: ${self.a()} c is: ${self.c()} diff --git a/test/lexer.py b/test/lexer.py index a604b0c..8ca478b 100644 --- a/test/lexer.py +++ b/test/lexer.py @@ -7,32 +7,32 @@ class LexerTest(unittest.TestCase): def test_text_and_tag(self): template = """ <b>Hello world</b> - <%component name="foo"> - this is a component. - </%component> + <%def name="foo"> + this is a def. + </%def> and some more text. """ node = Lexer(template).parse() - assert repr(node) == r"""TemplateNode({}, [Text('\n<b>Hello world</b>\n ', (1, 1)), ComponentTag('component', {'name': 'foo'}, (3, 9), ["Text('\\n this is a component.\\n ', (3, 32))"]), Text('\n \n and some more text.\n', (5, 22))])""" + assert repr(node) == r"""TemplateNode({}, [Text('\n<b>Hello world</b>\n ', (1, 1)), DefTag('def', {'name': 'foo'}, (3, 9), ["Text('\\n this is a def.\\n ', (3, 26))"]), Text('\n \n and some more text.\n', (5, 16))])""" def test_unclosed_tag(self): template = """ - <%component name="foo"> + <%def name="foo"> other text """ try: nodes = Lexer(template).parse() assert False except exceptions.SyntaxException, e: - assert str(e) == "Unclosed tag: <%component> at line: 5 char: 9" + assert str(e) == "Unclosed tag: <%def> at line: 5 char: 9" def test_onlyclosed_tag(self): template = """ - <%component name="foo"> + <%def name="foo"> foo - </%component> + </%def> </%namespace> @@ -47,10 +47,10 @@ class LexerTest(unittest.TestCase): def test_unmatched_tag(self): template = """ <%namespace name="bar"> - <%component name="foo"> + <%def name="foo"> foo </%namespace> - </%component> + </%def> hi. @@ -59,7 +59,7 @@ class LexerTest(unittest.TestCase): nodes = Lexer(template).parse() assert False except exceptions.SyntaxException, e: - assert str(e) == "Closing tag </%namespace> does not match tag: <%component> at line: 5 char: 13" + assert str(e) == "Closing tag </%namespace> does not match tag: <%def> at line: 5 char: 13" def test_nonexistent_tag(self): template = """ @@ -71,11 +71,11 @@ class LexerTest(unittest.TestCase): except exceptions.CompileException, e: assert str(e) == "No such tag: 'lala' at line: 2 char: 13" - def test_component_syntax(self): + def test_def_syntax(self): template = """ - <%component lala> + <%def lala> hi - </%component> + </%def> """ try: node = Lexer(template).parse() @@ -100,14 +100,14 @@ class LexerTest(unittest.TestCase): template = """ <%namespace name="ns"> - <%component name="lala(hi, there)"> + <%def name="lala(hi, there)"> <%call expr="something()"/> - </%component> + </%def> </%namespace> """ nodes = Lexer(template).parse() - assert repr(nodes) == r"""TemplateNode({}, [Text('\n \n ', (1, 1)), NamespaceTag('namespace', {'name': 'ns'}, (3, 9), ["Text('\\n ', (3, 31))", 'ComponentTag(\'component\', {\'name\': \'lala(hi, there)\'}, (4, 13), ["Text(\'\\\\n \', (4, 48))", "CallTag(\'call\', {\'expr\': \'something()\'}, (5, 17), [])", "Text(\'\\\\n \', (5, 44))"])', "Text('\\n ', (6, 26))"]), Text('\n \n ', (7, 22))])""" + assert repr(nodes) == r"""TemplateNode({}, [Text('\n \n ', (1, 1)), NamespaceTag('namespace', {'name': 'ns'}, (3, 9), ["Text('\\n ', (3, 31))", 'DefTag(\'def\', {\'name\': \'lala(hi, there)\'}, (4, 13), ["Text(\'\\\\n \', (4, 42))", "CallTag(\'call\', {\'expr\': \'something()\'}, (5, 17), [])", "Text(\'\\\\n \', (5, 44))"])', "Text('\\n ', (6, 20))"]), Text('\n \n ', (7, 22))])""" def test_code(self): template = """ @@ -132,12 +132,12 @@ class LexerTest(unittest.TestCase): def test_code_and_tags(self): template = """ <%namespace name="foo"> - <%component name="x"> + <%def name="x"> this is x - </%component> - <%component name="y"> + </%def> + <%def name="y"> this is y - </%component> + </%def> </%namespace> <% @@ -150,19 +150,19 @@ class LexerTest(unittest.TestCase): result: <%call expr="foo.x(result)"/> """ nodes = Lexer(template).parse() - assert repr(nodes) == r"""TemplateNode({}, [Text('\n', (1, 1)), NamespaceTag('namespace', {'name': 'foo'}, (2, 1), ["Text('\\n ', (2, 24))", 'ComponentTag(\'component\', {\'name\': \'x\'}, (3, 5), ["Text(\'\\\\n this is x\\\\n \', (3, 26))"])', "Text('\\n ', (5, 18))", 'ComponentTag(\'component\', {\'name\': \'y\'}, (6, 5), ["Text(\'\\\\n this is y\\\\n \', (6, 26))"])', "Text('\\n', (8, 18))"]), Text('\n\n', (9, 14)), Code('\nresult = []\ndata = get_data()\nfor x in data:\n result.append(x+7)\n\n', False, (11, 1)), Text('\n\n result: ', (16, 3)), CallTag('call', {'expr': 'foo.x(result)'}, (18, 13), []), Text('\n', (18, 42))])""" + assert repr(nodes) == r"""TemplateNode({}, [Text('\n', (1, 1)), NamespaceTag('namespace', {'name': 'foo'}, (2, 1), ["Text('\\n ', (2, 24))", 'DefTag(\'def\', {\'name\': \'x\'}, (3, 5), ["Text(\'\\\\n this is x\\\\n \', (3, 26))"])', "Text('\\n ', (5, 18))", 'DefTag(\'def\', {\'name\': \'y\'}, (6, 5), ["Text(\'\\\\n this is y\\\\n \', (6, 26))"])', "Text('\\n', (8, 18))"]), Text('\n\n', (9, 14)), Code('\nresult = []\ndata = get_data()\nfor x in data:\n result.append(x+7)\n\n', False, (11, 1)), Text('\n\n result: ', (16, 3)), CallTag('call', {'expr': 'foo.x(result)'}, (18, 13), []), Text('\n', (18, 42))])""" def test_expression(self): template = """ this is some ${text} and this is ${textwith | escapes, moreescapes} - <%component name="hi"> + <%def name="hi"> give me ${foo()} and ${bar()} - </%component> + </%def> ${hi()} """ nodes = Lexer(template).parse() - assert repr(nodes) == r"""TemplateNode({}, [Text('\n this is some ', (1, 1)), Expression('text', [], (2, 22)), Text(' and this is ', (2, 29)), Expression('textwith ', ['escapes', 'moreescapes'], (2, 42)), Text('\n ', (2, 76)), ComponentTag('component', {'name': 'hi'}, (3, 9), ["Text('\\n give me ', (3, 31))", "Expression('foo()', [], (4, 21))", "Text(' and ', (4, 29))", "Expression('bar()', [], (4, 34))", "Text('\\n ', (4, 42))"]), Text('\n ', (5, 22)), Expression('hi()', [], (6, 9)), Text('\n', (6, 16))])""" + assert repr(nodes) == r"""TemplateNode({}, [Text('\n this is some ', (1, 1)), Expression('text', [], (2, 22)), Text(' and this is ', (2, 29)), Expression('textwith ', ['escapes', 'moreescapes'], (2, 42)), Text('\n ', (2, 76)), DefTag('def', {'name': 'hi'}, (3, 9), ["Text('\\n give me ', (3, 31))", "Expression('foo()', [], (4, 21))", "Text(' and ', (4, 29))", "Expression('bar()', [], (4, 34))", "Text('\\n ', (4, 42))"]), Text('\n ', (5, 22)), Expression('hi()', [], (6, 9)), Text('\n', (6, 16))])""" def test_control_lines(self): template = """ @@ -230,12 +230,12 @@ text text la la # inherit from foobar.html <%inherit file="foobar.html"/> -<%component name="header"> +<%def name="header"> <div>header</div> -</%component> -<%component name="footer"> +</%def> +<%def name="footer"> <div> footer</div> -</%component> +</%def> <table> % for j in data(): @@ -248,7 +248,7 @@ text text la la </table> """ nodes = Lexer(template).parse() - assert repr(nodes) == r"""TemplateNode({}, [NamespaceTag('namespace', {'name': 'foo', 'file': 'somefile.html'}, (1, 1), []), Text('\n', (1, 46)), Comment('inherit from foobar.html', (2, 1)), InheritTag('inherit', {'file': 'foobar.html'}, (3, 1), []), Text('\n\n', (3, 31)), ComponentTag('component', {'name': 'header'}, (5, 1), ["Text('\\n <div>header</div>\\n', (5, 27))"]), Text('\n', (7, 14)), ComponentTag('component', {'name': 'footer'}, (8, 1), ["Text('\\n <div> footer</div>\\n', (8, 27))"]), Text('\n\n<table>\n', (10, 14)), ControlLine('for', 'for j in data():', False, (13, 1)), Text(' <tr>\n', (14, 1)), ControlLine('for', 'for x in j:', False, (15, 1)), Text(' <td>Hello ', (16, 1)), Expression('x', ['h'], (16, 23)), Text('</td>\n', (16, 30)), ControlLine('for', 'endfor', True, (17, 1)), Text(' </tr>\n', (18, 1)), ControlLine('for', 'endfor', True, (19, 1)), Text('</table>\n', (20, 1))])""" + assert repr(nodes) == r"""TemplateNode({}, [NamespaceTag('namespace', {'name': 'foo', 'file': 'somefile.html'}, (1, 1), []), Text('\n', (1, 46)), Comment('inherit from foobar.html', (2, 1)), InheritTag('inherit', {'file': 'foobar.html'}, (3, 1), []), Text('\n\n', (3, 31)), DefTag('def', {'name': 'header'}, (5, 1), ["Text('\\n <div>header</div>\\n', (5, 27))"]), Text('\n', (7, 14)), DefTag('def', {'name': 'footer'}, (8, 1), ["Text('\\n <div> footer</div>\\n', (8, 27))"]), Text('\n\n<table>\n', (10, 14)), ControlLine('for', 'for j in data():', False, (13, 1)), Text(' <tr>\n', (14, 1)), ControlLine('for', 'for x in j:', False, (15, 1)), Text(' <td>Hello ', (16, 1)), Expression('x', ['h'], (16, 23)), Text('</td>\n', (16, 30)), ControlLine('for', 'endfor', True, (17, 1)), Text(' </tr>\n', (18, 1)), ControlLine('for', 'endfor', True, (19, 1)), Text('</table>\n', (20, 1))])""" if __name__ == '__main__': unittest.main() diff --git a/test/namespace.py b/test/namespace.py index 34a6efb..d06d2f5 100644 --- a/test/namespace.py +++ b/test/namespace.py @@ -7,12 +7,12 @@ class NamespaceTest(unittest.TestCase): def test_inline(self): t = Template(""" <%namespace name="x"> - <%component name="a"> + <%def name="a"> this is x a - </%component> - <%component name="b"> + </%def> + <%def name="b"> this is x b, and heres ${a()} - </%component> + </%def> </%namespace> ${x.a()} @@ -25,20 +25,20 @@ class NamespaceTest(unittest.TestCase): collection = lookup.TemplateLookup() collection.put_string('main.html', """ - <%namespace name="comp" file="components.html"/> + <%namespace name="comp" file="defs.html"/> this is main. ${comp.def1("hi")} ${comp.def2("there")} """) - collection.put_string('components.html', """ - <%component name="def1(s)"> + collection.put_string('defs.html', """ + <%def name="def1(s)"> def1: ${s} - </%component> + </%def> - <%component name="def2(x)"> + <%def name="def2(x)"> def2: ${x} - </%component> + </%def> """) assert flatten_result(collection.get_template('main.html').render()) == "this is main. def1: hi def2: there" @@ -47,24 +47,24 @@ class NamespaceTest(unittest.TestCase): collection = lookup.TemplateLookup() collection.put_string('main.html', """ - <%namespace name="comp" file="components.html"> - <%component name="def1(x, y)"> + <%namespace name="comp" file="defs.html"> + <%def name="def1(x, y)"> overridden def1 ${x}, ${y} - </%component> + </%def> </%namespace> this is main. ${comp.def1("hi", "there")} ${comp.def2("there")} """) - collection.put_string('components.html', """ - <%component name="def1(s)"> + collection.put_string('defs.html', """ + <%def name="def1(s)"> def1: ${s} - </%component> + </%def> - <%component name="def2(x)"> + <%def name="def2(x)"> def2: ${x} - </%component> + </%def> """) assert flatten_result(collection.get_template('main.html').render()) == "this is main. overridden def1 hi, there def2: there" -- GitLab