diff --git a/CHANGES b/CHANGES index 840887886f4e0591089a4ee4b37c76af9a7a84f1..83cdf9345ce19028dc5fb64ae1bdce0794d714d0 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ cant handle those files, setuptools not very good at "pruning" certain directori - fix to expression filters so that string conversion (actually unicode) properly occurs before filtering - better error message when a lookup is attempted with a template that has no lookup +- implemented "module" attribute for namespace 0.1.0 diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py index efb67ccf34db0eca9293fcbdb8580b2742270daa..f54df0de1c30511ba396f3a2cc45adac8b5c8e6b 100644 --- a/lib/mako/codegen.py +++ b/lib/mako/codegen.py @@ -204,7 +204,7 @@ class _GenerateRenderMethod(object): callable_name = "make_namespace()" else: callable_name = "None" - self.printer.writeline("ns = runtime.Namespace(%s, context._clean_inheritance_tokens(), templateuri=%s, callables=%s, calling_uri=_template_uri)" % (repr(node.name), node.parsed_attributes.get('file', 'None'), callable_name)) + self.printer.writeline("ns = runtime.Namespace(%s, context._clean_inheritance_tokens(), templateuri=%s, callables=%s, calling_uri=_template_uri, module=%s)" % (repr(node.name), node.parsed_attributes.get('file', 'None'), callable_name, node.parsed_attributes.get('module', 'None'))) if eval(node.attributes.get('inheritable', "False")): self.printer.writeline("context['self'].%s = ns" % (node.name)) self.printer.writeline("context.namespaces[(__name__, %s)] = ns" % repr(node.name)) diff --git a/lib/mako/parsetree.py b/lib/mako/parsetree.py index 7038f45e63f9cc026c969fc033ed65a59ed854f5..9780975a41d300f6afe55107eb1843a8eeed1e9e 100644 --- a/lib/mako/parsetree.py +++ b/lib/mako/parsetree.py @@ -224,7 +224,7 @@ class IncludeTag(Tag): class NamespaceTag(Tag): __keyword__ = 'namespace' def __init__(self, keyword, attributes, **kwargs): - super(NamespaceTag, self).__init__(keyword, attributes, (), ('name','inheritable','file','import'), (), **kwargs) + super(NamespaceTag, self).__init__(keyword, attributes, (), ('name','inheritable','file','import','module'), (), **kwargs) self.name = attributes.get('name', '__anon_%s' % hex(abs(id(self)))) if not 'name' in attributes and not 'import' in attributes: raise exceptions.CompileException("'name' and/or 'import' attributes are required for <%namespace>", self.lineno, self.pos, self.filename) diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py index c91f54859948f4fcee2bfe730fdeeadd551eb8d2..4b33e67d5036bf7d589f6bdf50cb9b396281e012 100644 --- a/lib/mako/runtime.py +++ b/lib/mako/runtime.py @@ -83,7 +83,13 @@ class Namespace(object): """provides access to collections of rendering methods, which can be local, from other templates, or from imported modules""" def __init__(self, name, context, module=None, template=None, templateuri=None, callables=None, inherits=None, populate_self=True, calling_uri=None): self.name = name - self._module = module + if module is not None: + mod = __import__(module) + for token in module.split('.')[1:]: + mod = getattr(mod, token) + self._module = mod + else: + self._module = None if templateuri is not None: self.template = _lookup_template(context, templateuri, calling_uri) self._templateuri = self.template.module._template_uri @@ -149,10 +155,13 @@ class Namespace(object): return lambda *args, **kwargs:callable_(self.context, *args, **kwargs) for k in self.template.module._exports: yield (k, get(k)) - if self.module is not None: - for k in dir(self.module): + if self._module is not None: + def get(key): + callable_ = getattr(self._module, key) + return lambda *args, **kwargs:callable_(self.context, *args, **kwargs) + for k in dir(self._module): if k[0] != '_': - yield (k, getattr(self.module, k)) + yield (k, get(k)) def __getattr__(self, key): if self.callables is not None: diff --git a/test/foo/__init__.py b/test/foo/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/test/foo/test_ns.py b/test/foo/test_ns.py new file mode 100644 index 0000000000000000000000000000000000000000..084fe97225049e66b79a052aa2d5aa549e43c63c --- /dev/null +++ b/test/foo/test_ns.py @@ -0,0 +1,7 @@ +def foo1(context): + context.write("this is foo1.") + return '' + +def foo2(context, x): + context.write("this is foo2, x is " + x) + return '' \ No newline at end of file diff --git a/test/namespace.py b/test/namespace.py index f39cdee70c89c940c743472603891da89d325ac3..ef42bf72c2e89ffe1f5cdf715a8f2a75dcb83d8f 100644 --- a/test/namespace.py +++ b/test/namespace.py @@ -43,6 +43,54 @@ class NamespaceTest(unittest.TestCase): assert flatten_result(collection.get_template('main.html').render()) == "this is main. def1: hi def2: there" + def test_module(self): + collection = lookup.TemplateLookup() + + collection.put_string('main.html', """ + <%namespace name="comp" module="test_namespace"/> + + this is main. ${comp.foo1()} + ${comp.foo2("hi")} +""") + + assert flatten_result(collection.get_template('main.html').render()) == "this is main. this is foo1. this is foo2, x is hi" + + def test_module_2(self): + collection = lookup.TemplateLookup() + + collection.put_string('main.html', """ + <%namespace name="comp" module="foo.test_ns"/> + + this is main. ${comp.foo1()} + ${comp.foo2("hi")} +""") + + assert flatten_result(collection.get_template('main.html').render()) == "this is main. this is foo1. this is foo2, x is hi" + + def test_module_imports(self): + collection = lookup.TemplateLookup() + + collection.put_string('main.html', """ + <%namespace import="*" module="foo.test_ns"/> + + this is main. ${foo1()} + ${foo2("hi")} +""") + + assert flatten_result(collection.get_template('main.html').render()) == "this is main. this is foo1. this is foo2, x is hi" + + def test_module_imports_2(self): + collection = lookup.TemplateLookup() + + collection.put_string('main.html', """ + <%namespace import="foo1, foo2" module="foo.test_ns"/> + + this is main. ${foo1()} + ${foo2("hi")} +""") + + assert flatten_result(collection.get_template('main.html').render()) == "this is main. this is foo1. this is foo2, x is hi" + def test_context(self): """test that namespace callables get access to the current context""" collection = lookup.TemplateLookup() diff --git a/test/test_namespace.py b/test/test_namespace.py new file mode 100644 index 0000000000000000000000000000000000000000..084fe97225049e66b79a052aa2d5aa549e43c63c --- /dev/null +++ b/test/test_namespace.py @@ -0,0 +1,7 @@ +def foo1(context): + context.write("this is foo1.") + return '' + +def foo2(context, x): + context.write("this is foo2, x is " + x) + return '' \ No newline at end of file