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