diff --git a/doc/build/genhtml.py b/doc/build/genhtml.py
index d72b93b950bdc380e6759347bd3be8b71818a8f4..2e08c092e0a62da5272ad7bd8505b6570fc71513 100644
--- a/doc/build/genhtml.py
+++ b/doc/build/genhtml.py
@@ -35,13 +35,10 @@ def genfile(name, toc):
     outname = os.path.join(os.getcwd(), '../', name + ".html")
     outfile = file(outname, 'w')
     print infile, '->', outname
-#    outfile.write(lookup.get_template(infile).render(toc=toc, extension='html'))
+    outfile.write(lookup.get_template(infile).render(toc=toc, extension='html'))
     
-try:
-    for filename in files:
-        genfile(filename, root)
-except exception.Error, e:
-    sys.stderr.write(e.textformat())
+for filename in files:
+    genfile(filename, root)
 
 
         
diff --git a/doc/build/read_markdown.py b/doc/build/read_markdown.py
index a7f5d74354a5502ea1296852f518c1d641a51e30..5bf68688fcabdc19e0e861278fc6465ae81c3bb7 100644
--- a/doc/build/read_markdown.py
+++ b/doc/build/read_markdown.py
@@ -34,22 +34,15 @@ def dump_tree(elem, stream):
 
 def dump_mako_tag(elem, stream):
     tag = elem.tag[5:]
-    params = ', '.join(['%s=%s' % i for i in elem.items()])
-    pipe = ''
-    if elem.text or len(elem):
-        pipe = '|'
-    comma = ''
-    if params:
-        comma = ', '
-    stream.write('<&%s%s%s%s&>' % (pipe, tag, comma, params))
-    if pipe:
-        if elem.text:
-            stream.write(elem.text)
-        for n in elem:
-            dump_tree(n, stream)
-            if n.tail:
-                stream.write(n.tail)
-        stream.write("</&>")
+    params = ','.join(['%s=%s' % i for i in elem.items()])
+    stream.write('<%%call expr="%s(%s)">' % (tag, params))
+    if elem.text:
+        stream.write(elem.text)
+    for n in elem:
+        dump_tree(n, stream)
+        if n.tail:
+            stream.write(n.tail)
+    stream.write("</%call>")
 
 def create_toc(filename, tree, tocroot):
     title = [None]
@@ -81,7 +74,7 @@ def create_toc(filename, tree, tocroot):
 
             level[0] = taglevel
 
-            tag = et.Element("MAKO:formatting.section", path=literal(current[0].path), toc="toc")
+            tag = et.Element("MAKO:self.formatting.section", path=repr(current[0].path), toc="toc")
             tag.text = (node.tail or "") + '\n'
             tag.tail = '\n'
             tag[:] = content
@@ -92,9 +85,6 @@ def create_toc(filename, tree, tocroot):
     process(tree)
     return (title[0], tocroot.get_by_file(filename))
 
-def literal(s):
-    return '"%s"' % s
-    
 def index(parent, item):
     for n, i in enumerate(parent):
         if i is item:
@@ -124,9 +114,9 @@ def process_rel_href(tree):
             (bold, path) = m.group(1,2)
             text = a.text
             if text == path:
-                tag = et.Element("MAKO:nav.toclink", path=literal(path), toc="toc", extension="extension")
+                tag = et.Element("MAKO:self.nav.toclink", path=repr(path), toc="toc", extension="extension")
             else:
-                tag = et.Element("MAKO:nav.toclink", path=literal(path), description=literal(text), toc="toc", extension="extension")
+                tag = et.Element("MAKO:self.nav.toclink", path=repr(path), description=repr(text), toc="toc", extension="extension")
             a_parent = parent[a]
             if bold:
                 bold = et.Element('strong')
@@ -138,50 +128,30 @@ def process_rel_href(tree):
                 a_parent[index(a_parent, a)] = tag
 
 def replace_pre_with_mako(tree):
-    def splice_code_tag(pre, text, type=None, title=None):
-        doctest_directives = re.compile(r'#\s*doctest:\s*[+-]\w+(,[+-]\w+)*\s*$', re.M)
-        text = re.sub(doctest_directives, '', text)
-        # process '>>>' to have quotes around it, to work with the mako python
-        # syntax highlighter which uses the tokenize module
-        text = re.sub(r'>>> ', r'">>>" ', text)
-
-        # indent two spaces.  among other things, this helps comment lines "#  " from being 
-        # consumed as mako comments.
-        text = re.compile(r'^(?!<&)', re.M).sub('  ', text)
-
-        use_sliders = True
-        
-        opts = {}
-        if type == 'python':
-            opts['syntaxtype'] = literal('python')
-        else:
-            opts['syntaxtype'] = None
-
-        if title is not None:
-            opts['title'] = literal(title)
-    
-        if use_sliders:
-            opts['use_sliders'] = True
-    
-        tag = et.Element("MAKO:formatting.code", **opts)
-        tag.text = text
+    parents = get_parent_map(tree)
 
-        pre_parent = parents[pre]
+    for precode in tree.findall('.//pre/code'):
+        tag = et.Element("MAKO:self.formatting.code")
+        tag.text = precode.text
+        [tag.append(x) for x in precode]
+        pre = parents[precode]
         tag.tail = pre.tail
+        
+        pre_parent = parents[pre]
         pre_parent[reverse_parent(pre_parent, pre)] = tag
-
+        
+def safety_code(tree):
     parents = get_parent_map(tree)
-
-    for precode in tree.findall('.//pre/code'):
-        m = re.match(r'\{(python|code)(?: title="(.*?)"){0,1}\}', precode.text.lstrip())
-        if m:
-            code = m.group(1)
-            title = m.group(2)
-            text = precode.text.lstrip()
-            text = re.sub(r'{(python|code).*?}(\n\s*)?', '', text)
-            splice_code_tag(parents[precode], text, type=code, title=title)
-        elif precode.text.lstrip().startswith('>>> '):
-            splice_code_tag(parents[precode], precode.text)
+    for code in tree.findall('.//code'):
+        tag = et.Element('%text')
+        tag.text = code.text
+        code.append(tag)
+        code.text = ""
+        #code.tail =None
+        #tag.text = code.text
+        #code_parent = parents[code]
+        #code_parent[reverse_parent(code_parent, code)] = tag
+        
 
 def reverse_parent(parent, item):
     for n, i in enumerate(parent):
@@ -215,6 +185,7 @@ def parse_markdown_files(toc, files):
         html = markdown.markdown(file(infile).read())
         tree = et.fromstring("<html>" + html + "</html>")
         (title, toc_element) = create_toc(inname, tree, toc)
+        safety_code(tree)
         replace_pre_with_mako(tree)
         process_rel_href(tree)
         outname = 'output/%s.html' % inname
diff --git a/doc/build/templates/base.html b/doc/build/templates/base.html
index 2163c42859ce7b2d2484fda018e23fa4dbf71f61..c272b1482e23cc1991197dd5a12845184d688b04 100644
--- a/doc/build/templates/base.html
+++ b/doc/build/templates/base.html
@@ -1,15 +1,13 @@
 # base.html - common to all documentation pages. intentionally separate 
 # from autohandler, which can be swapped out for a different one
 <%
-    if m.cache_self(key=m.request_component.file):
-        return
     # bootstrap TOC structure from request args, or pickled file if not present.
     import cPickle as pickle
     import os, time
     print "base.myt generating from table of contents for file %s" % ("<todo: get the file>")
     toc = context.get('toc')
     if toc is None:
-        filename = os.path.join(os.path.dirname(m.request_component.file), 'table_of_contents.pickle')
+        filename = os.path.join(os.path.dirname(self.template.filename), 'table_of_contents.pickle')
         toc = pickle.load(file(filename))
     version = toc.version
     last_updated = toc.last_updated
@@ -29,7 +27,7 @@
 <div class="">Version: <% version %>   Last Updated: <% time.strftime('%x %X', time.localtime(last_updated)) %></div>
 </div>
 
-% m.call_next(toc=toc, extension=extension)
+${next.body(toc=toc)}
 
 </div>
 
diff --git a/doc/build/templates/content_layout.html b/doc/build/templates/content_layout.html
index 252515559d69a0516b096183e085f65bec7f5118..fa354d23370fb5356aebd2c2bb3e0b4d0a5332f3 100644
--- a/doc/build/templates/content_layout.html
+++ b/doc/build/templates/content_layout.html
@@ -1,11 +1,11 @@
 # defines the default layout for normal documentation pages (not including the index)
-<%inherit file="base.html">
+<%inherit file="root.html"/>
 <%
     current = toc.get_by_file(self.template.module.filename)
 %>
 
 <A name="<% current.path %>"></a>
-<& nav.myt:topnav, item=current, extension=extension &>
+${self.nav.topnav(item=current)}
 <div class="sectioncontent">
-% m.call_next(toc=toc, extension=extension)
+${next.body(toc=toc)}
 </div>
diff --git a/doc/build/templates/formatting.html b/doc/build/templates/formatting.html
index da1c81df05b265432fc2c485a99c4acf7d32b7a2..d7a42f1e15d76149e1e2c265318fd719721d0593 100644
--- a/doc/build/templates/formatting.html
+++ b/doc/build/templates/formatting.html
@@ -1,80 +1,65 @@
-<%doc>formatting.myt - Provides section formatting elements, syntax-highlighted code blocks, and other special filters.</%doc>
-
-<%global>
+# formatting.myt - Provides section formatting elements, syntax-highlighted code blocks, and other special filters.
+<%!
     import string, re
-    import highlight
-</%global>
-
-<%method section>
-<%doc>Main section formatting element.</%doc>
-<%args>
-    toc
-    path
-    description=None
-</%args>
-<%init>
+    #import highlight
+    
+    def plainfilter(f):
+        f = re.sub(r'\n[\s\t]*\n[\s\t]*', '</p>\n<p>', f)
+        f = "<p>" + f + "</p>"
+        return f
+    
+%>
+
+<%def name="section(toc, path, description=None)">
+# Main section formatting element.
+<%
     item = toc.get_by_path(path)
     if item is None:
         raise "path: " + path
-</%init>
+%>
 
-<A name="<% item.path %>"></a>
+<A name="${item.path}"></a>
 
-<div class="subsection" style="margin-left:<% repr(item.depth * 10) %>px;">
+<div class="subsection" style="margin-left:${repr(item.depth * 10)}px;">
 
-<%python>
-    content = m.content()
+<%
+    content = caller.body()
     re2 = re.compile(r"'''PYESC(.+?)PYESC'''", re.S)
     content = re2.sub(lambda m: m.group(1), content)
-</%python>
+%>
 
 % if item.depth > 1:
-<h3><% description or item.description %></h3>
-%
+<h3>${description or item.description}</h3>
+% endif
 
     <div class="sectiontext">
-    <% content %>
+    ${content}
     </div>
 
 % if item.depth > 1:
 %   if (item.next and item.next.depth >= item.depth):
-    <a href="#<% item.get_page_root().path %>" class="toclink">back to section top</a>
-%
+    <a href="#${ item.get_page_root().path }" class="toclink">back to section top</a>
+%   endif
 % else:
-    <a href="#<% item.get_page_root().path %>" class="toclink">back to section top</a>
-    <& nav.myt:pagenav, item=item &>
-% 
+    <a href="#${ item.get_page_root().path }" class="toclink">back to section top</a>
+    ${nav.pagenav(item=item)}
+% endif
 </div>
 
-</%method>
-
-
-<%method formatplain>
-    <%filter>
-        import re
-        f = re.sub(r'\n[\s\t]*\n[\s\t]*', '</p>\n<p>', f)
-        f = "<p>" + f + "</p>"
-        return f
-    </%filter>
-<% m.content() | h%>
-</%method>
-
+</%def>
 
 
+<%def name="formatplain" filter="plainfilter">
+${ caller.body() | h}
+</%def>
 
-<%method codeline trim="both">
-<span class="codeline"><% m.content() %></span>
-</%method>
 
-<%method code autoflush=False>
-<%args>
-    title = None
-    syntaxtype = 'python'
-    html_escape = False
-    use_sliders = False
-</%args>
+<%def name="codeline" filter="trim">
+<span class="codeline">${ m.content() }</span>
+</%def>
 
-<%init>
+<%def name="code(title=None, syntaxtype='python', html_escape=False, use_sliders=False)">
+<%
     def fix_indent(f):
         f =string.expandtabs(f, 4)
         g = ''
@@ -98,68 +83,17 @@
     p = re.compile(r'<pre>(.*?)</pre>', re.S)
     def hlight(match):
         return "<pre>" + highlight.highlight(fix_indent(match.group(1)), html_escape = html_escape, syntaxtype = syntaxtype) + "</pre>"
-    content = p.sub(hlight, "<pre>" + m.content() + "</pre>")
-</%init>
-<div class="<% use_sliders and "sliding_code" or "code" %>">
+    #content = p.sub(hlight, "<pre>" + capture(caller.body) + "</pre>")
+    content = "<pre>" + capture(caller.body) + "</pre>"
+%>
+
+<div class="${ use_sliders and "sliding_code" or "code" }">
 % if title is not None:
-    <div class="codetitle"><% title %></div>
-%
-<% content %></div>
-</%method>
-
-
-
-
-<%method popboxlink trim="both"> 
-    <%args>
-        name=None
-        show='show'
-        hide='hide'
-    </%args>
-    <%init>
-        if name is None:
-            name = m.attributes.setdefault('popbox_name', 0)
-        name += 1
-        m.attributes['popbox_name'] = name
-        name = "popbox_" + repr(name)
-    </%init>
-javascript:togglePopbox('<% name %>', '<% show %>', '<% hide %>')
-</%method>
-
-<%method popbox trim="both">
-<%args>
-    name = None
-    class_ = None
-</%args>
-<%init>
-    if name is None:
-        name = 'popbox_' + repr(m.attributes['popbox_name'])
-</%init>
-<div id="<% name %>_div" class="<% class_ %>" style="display:none;"><% m.content().strip() %></div>
-</%method>
-
-<%method poplink trim="both">
-    <%args>
-        link='sql'
-    </%args>
-    <%init>
-        href = m.scomp('SELF:popboxlink')
-    </%init>
-    '''PYESC<& nav.myt:link, href=href, text=link, class_="codepoplink" &>PYESC'''
-</%method>
-
-<%method codepopper trim="both">
-	<%init>
-		c = m.content()
-		c = re.sub(r'\n', '<br/>\n', c.strip())
-	</%init>
-    </pre><&|SELF:popbox, class_="codepop" &><% c %></&><pre>
-</%method>
-
-<%method poppedcode trim="both">
-	<%init>
-		c = m.content()
-		c = re.sub(r'\n', '<br/>\n', c.strip())
-	</%init>
-    </pre><div class="codepop"><% c %></div><pre>
-</%method>
+    <div class="codetitle">${ title }</div>
+% endif
+${ content }</div>
+</%def>
+
+
+
+
diff --git a/doc/build/templates/nav.html b/doc/build/templates/nav.html
index a045df8ce74b32deb927976a3a8e63f56eb911c5..82c8cf0c16363be34b85844bb50252fd1a0eaecb 100644
--- a/doc/build/templates/nav.html
+++ b/doc/build/templates/nav.html
@@ -1,106 +1,88 @@
-<%doc>nav.myt - Provides page navigation elements that are derived from toc.TOCElement structures, including
-individual hyperlinks as well as navigational toolbars and table-of-content listings.</%doc>
-
-<%method itemlink trim="both">
-    <%args>
-    item
-    anchor=True
-    </%args>
-    <%args scope="request">
-        extension='myt'
-    </%args>
-    <a href="<% item.get_link(extension=extension, anchor=anchor) %>"><% item.description %></a>
-</%method>
-
-<%method toclink trim="both">
-    <%args>
-        toc 
-        path
-        description=None
-        extension
-    </%args>
-    <%init>
+# nav.myt - Provides page navigation elements that are derived from toc.TOCElement structures, including
+# individual hyperlinks as well as navigational toolbars and table-of-content listings.
+
+<%namespace name="tocns" file="toc.html"/>
+
+<%def name="itemlink(item, anchor=True)" filter="trim">
+    <a href="${ item.get_link(extension=extension, anchor=anchor) }">${ item.description }</a>
+</%def>
+
+<%def name="toclink(toc, path, description=None)" filter="trim">
+    <%
         item = toc.get_by_path(path)
         if description is None:
             if item:
                 description = item.description
             else:
                 description = path
-    </%init>
+    %>
 % if item:
-    <a href="<% item.get_link(extension=extension) %>"><% description %></a>
+    <a href="${ item.get_link(extension=extension) }">${ description }</a>
 % else:
-    <b><% description %></b>
-%
-</%method>
-
-
-<%method link trim="both">
-    <%args>
-        href
-        text
-        class_
-    </%args>
-    <a href="<% href %>" <% class_ and (('class=\"%s\"' % class_) or '')%>><% text %></a>
-</%method>
-
-<%method topnav>
-	<%args>
-		item
-		extension
-	</%args>
+    <b>${ description }</b>
+% endif
+</%def>
+
+
+<%def name="link" filter="trim(href, text, class_)">
+    <a href="${ href }" ${ class_ and (('class=\"%s\"' % class_) or '')}>${ text }</a>
+</%def>
+
+<%def name="topnav(item)">
 <div class="topnav">
 
 <div class="topnavsectionlink">
 
-<a href="index.<% extension %>">Table of Contents</a>
+<a href="index.${ extension }">Table of Contents</a>
 
 <div class="prevnext">
 % if item.previous is not None:
-Previous: <& itemlink, item=item.previous, anchor=False &>
-%
+Previous: ${itemlink(item=item.previous, anchor=False)}
+% endif
 
 % if item.previous is not None and item.next is not None:
 &nbsp; | &nbsp;
-%
+% endif
 
 % if item.next is not None:
 
-Next: <& itemlink, item=item.next, anchor=False &>
-%
+Next: ${itemlink(item=item.next, anchor=False)}
+% endif
 
 </div>
 </div>
 
 <div class="topnavmain">
-	<div class="topnavheader"><% item.description %></div>
+	<div class="topnavheader">${ item.description }</div>
 	<div class="topnavitems">
-	<& toc.myt:printtoc, root=item, current=None, full=True, extension=extension, anchor_toplevel=True &>
+	% if tocns is UNDEFINED:
+	    <%
+	        raise "its undefined"
+	    %>
+	% endif
+	${tocns.printtoc(root=item, current=None, full=True, anchor_toplevel=True)}
 	</div>
 </div>
 
 </div>
-</%method>
+</%def>
 
-<%method pagenav>
-<%args>
-    item
-</%args>
+<%def name="pagenav(item)">
 <div class="sectionnavblock">
 <div class="sectionnav">
 
 %       if item.previous is not None:
-        Previous: <& itemlink, item=item.previous &>
-%       # end if
+        Previous: ${itemlink(item=item.previous)}
+%       endif
 
 %       if item.next is not None:
 %               if item.previous is not None:
                 |
-%               # end if
+%               endif
 
-        Next: <& itemlink, item=item.next &>
-%       # end if
+        Next: ${itemlink(item=item.next)}
+%       endif
 
 </div>
 </div>
-</%method>
+</%def>
diff --git a/doc/build/templates/root.html b/doc/build/templates/root.html
index 1b7db5a57c4217b89a1d924b926ced618334f7fb..e801e0635a41ddac154257300d85c2ecd675ad9e 100644
--- a/doc/build/templates/root.html
+++ b/doc/build/templates/root.html
@@ -1,3 +1,4 @@
+<%inherit file="base.html"/>
 <html>
 <head>
 	<title>${self.title()}</title>
@@ -8,7 +9,7 @@
     <script src="scripts.js"></script>
 </head>
 <body>
-${self.next()}
+${next.body()}
 
 </body>
 </html>
diff --git a/doc/build/templates/toc.html b/doc/build/templates/toc.html
index 6580a39c5021807c84d8d82d2bd1e20c4e368396..7fb77194e75413b1098645ef49cf836285321503 100644
--- a/doc/build/templates/toc.html
+++ b/doc/build/templates/toc.html
@@ -1,12 +1,6 @@
-<%doc>toc.myt - prints full table of contents listings given toc.TOCElement strucures</%doc>
+# toc.myt - prints full table of contents listings given toc.TOCElement strucures
 
-<%method toc>
-	<%args>
-		toc
-		extension
-	</%args>
-	
-	
+<%def name="toc(toc)">
 	<div class="maintoc">
 
 	<a name="table_of_contents"></a>
@@ -16,12 +10,11 @@
 	<br/><br/>
 	
 	<div style="margin-left:50px;">
-	<& printtoc, root = toc, current = None, full = False, children=False, extension=extension, anchor_toplevel=False &>
+	${printtoc(root=toc,current=None,full=False,children=False,anchor_toplevel=False)}
 	</div>
 
 	</div>
 
-
 	<div class="maintoc">
 	<a name="full_index"></a>
 	<h2>Table of Contents: Full</h2>
@@ -30,66 +23,43 @@
 	<br/><br/>
 
 	<div style="margin-left:50px;">
-	<& printtoc, root = toc, current = None, full = True, children=True, extension=extension, anchor_toplevel=False &>
+	${printtoc(root=toc,current=None,full=True,children=True,anchor_toplevel=False)}
 	</div>
 
 	</div>
-</%method>
-
+</%def>
 
-<%method printtoc>
-<%args> 
-    root
-    current = None
-    full = False
-    children = True
-    extension
-    anchor_toplevel=False
-</%args>
 
-<ul class="toc_list">
-% for i in root.children:
-    <& printtocelement, item=i, bold = (i == current), full = full, children=children, extension=extension, anchor_toplevel=anchor_toplevel &>
-%
-</ul>
-</%method>
+<%def name="printtoc(root,current=None,full=False,children=True,anchor_toplevel=False)">
+    <ul class="toc_list">
+    % for i in root.children:
+        ${printtocelement(item=i, bold = (i == current), full = full, children=children, anchor_toplevel=anchor_toplevel)}
+    % endfor
+    </ul>
+</%def>
 
-<%def printtocelement>
-<%doc>prints a TOCElement as a table of contents item and prints its immediate child items</%doc>
-    <%args>
-        item
-        bold = False
-        full = False
-        children = True
-        extension
-        anchor_toplevel
-    </%args>
-    
-        <li><A style="<% bold and "font-weight:bold;" or "" %>" href="<% item.get_link(extension=extension, anchor=anchor_toplevel) %>"><% item.description %></a></li>
+<%def name="printtocelement(item, anchor_toplevel, bold=False, full=False, children=True)">
+    # prints a TOCElement as a table of contents item and prints its immediate child items
+    <li><A style="${bold and "font-weight:bold;" or "" }" href="${item.get_link(extension=extension, anchor=anchor_toplevel) }">${item.description}</a></li>
     
-% if children:  
-    <ul class="small_toc_list">
-%   for i in item.children:
-        <& printsmtocelem, item=i, children=full, extension=extension &>
-%
-    </ul>
-%
+    % if children:  
+        <ul class="small_toc_list">
+        % for i in item.children:
+            ${printsmtocelem(item=i, children=full)}
+        % endfor
+        </ul>
+    % endif
 </%def>
 
-<%def printsmtocelem>
-    <%args>
-        item
-        children = False
-        extension
-    </%args>    
-    <li><A href="<% item.get_link(extension=extension) %>"><% item.description %></a></li>
+<%def name="printsmtocelem(item, children=False)">
+    <li><A href="${item.get_link(extension=extension)}">${item.description}</a></li>
 
-% if children:
-    <ul class="small_toc_list">
-%   for i in item.children:
-        <& printsmtocelem, item = i, extension=extension &>
-%
-    </ul>
-%
+    % if children:
+        <ul class="small_toc_list">
+      % for i in item.children:
+            ${printsmtocelem(item=i)}
+      % endfor
+        </ul>
+    % endif
 
 </%def>
diff --git a/lib/mako/ast.py b/lib/mako/ast.py
index 43a36ec0aaef0eec3392e1baf389e7d8e2b09b0b..489d219a7efe3253fe0352fffe5ba9b2e2931aff 100644
--- a/lib/mako/ast.py
+++ b/lib/mako/ast.py
@@ -6,14 +6,21 @@
 
 """utilities for analyzing expressions and blocks of Python code, as well as generating Python from AST nodes"""
 
-from compiler import ast, parse, visitor
+from compiler import ast, visitor
+from compiler import parse as compiler_parse
 from mako import util, exceptions
 from StringIO import StringIO
 import re
 
+def parse(code, mode, lineno, pos, filename):
+    try:
+        return compiler_parse(code, mode)
+    except SyntaxError, e:
+        raise exceptions.SyntaxException("(%s) %s" % (e.__class__.__name__, str(e)), lineno, pos, filename)
+    
 class PythonCode(object):
     """represents information about a string containing Python code"""
-    def __init__(self, code, lineno, pos):
+    def __init__(self, code, lineno, pos, filename):
         self.code = code
         
         # represents all identifiers which are assigned to at some point in the code
@@ -29,7 +36,7 @@ class PythonCode(object):
         # - AST is less likely to break with version changes (for example, the behavior of co_names changed a little bit
         # in python version 2.5)
         if isinstance(code, basestring):
-            expr = parse(code, "exec")
+            expr = parse(code.lstrip(), "exec", lineno, pos, filename)
         else:
             expr = code
             
@@ -72,14 +79,14 @@ class PythonCode(object):
                         self.declared_identifiers.add(alias)
                     else:
                         if mod == '*':
-                            raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared.  Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", lineno, pos)
+                            raise exceptions.CompileException("'import *' is not supported, since all identifier names must be explicitly declared.  Please use the form 'from <modulename> import <name1>, <name2>, ...' instead.", lineno, pos, filename)
                         self.declared_identifiers.add(mod)
         f = FindIdentifiers()
         visitor.walk(expr, f) #, walker=walker())
 
 class ArgumentList(object):
     """parses a fragment of code as a comma-separated list of expressions"""
-    def __init__(self, code, lineno, pos):
+    def __init__(self, code, lineno, pos, filename):
         self.codeargs = []
         self.args = []
         self.declared_identifiers = util.Set()
@@ -87,7 +94,7 @@ class ArgumentList(object):
         class FindTuple(object):
             def visitTuple(s, node, *args):
                 for n in node.nodes:
-                    p = PythonCode(n, lineno, pos)
+                    p = PythonCode(n, lineno, pos, filename)
                     self.codeargs.append(p)
                     self.args.append(ExpressionGenerator(n).value())
                     self.declared_identifiers = self.declared_identifiers.union(p.declared_identifiers)
@@ -97,7 +104,7 @@ class ArgumentList(object):
                 # if theres text and no trailing comma, insure its parsed
                 # as a tuple by adding a trailing comma
                 code  += ","
-            expr = parse(code, "exec")
+            expr = parse(code, "exec", lineno, pos, filename)
         else:
             expr = code
 
@@ -113,10 +120,10 @@ class PythonFragment(PythonCode):
         except (MyException, e):
     etc.
     """
-    def __init__(self, code, lineno, pos):
-        m = re.match(r'^(\w+)(?:\s+(.*?))?:$', code)
+    def __init__(self, code, lineno, pos, filename):
+        m = re.match(r'^(\w+)(?:\s+(.*?))?:$', code.strip())
         if not m:
-            raise exceptions.CompileException("Fragment '%s' is not a partial control statement" % code, lineno, pos)
+            raise exceptions.CompileException("Fragment '%s' is not a partial control statement" % code, lineno, pos, filename)
         (keyword, expr) = m.group(1,2)
         if keyword in ['for','if', 'while']:
             code = code + "pass"
@@ -127,8 +134,8 @@ class PythonFragment(PythonCode):
         elif keyword == 'except':
             code = "try:pass\n" + code + "pass"
         else:
-            raise exceptions.CompileException("Unsupported control keyword: '%s'" % keyword, lineno, pos)
-        super(PythonFragment, self).__init__(code, lineno, pos)
+            raise exceptions.CompileException("Unsupported control keyword: '%s'" % keyword, lineno, pos, filename)
+        super(PythonFragment, self).__init__(code, lineno, pos, filename)
         
 class walker(visitor.ASTVisitor):
     def dispatch(self, node, *args):
@@ -138,9 +145,9 @@ class walker(visitor.ASTVisitor):
         
 class FunctionDecl(object):
     """function declaration"""
-    def __init__(self, code, lineno, pos):
+    def __init__(self, code, lineno, pos, filename):
         self.code = code
-        expr = parse(code, "exec")
+        expr = parse(code, "exec", lineno, pos, filename)
         class ParseFunc(object):
             def visitFunction(s, node, *args):
                 self.funcname = node.name
@@ -152,7 +159,7 @@ class FunctionDecl(object):
         f = ParseFunc()
         visitor.walk(expr, f)
         if not hasattr(self, 'funcname'):
-            raise exceptions.CompileException("Code '%s' is not a function declaration" % code, lineno, pos)
+            raise exceptions.CompileException("Code '%s' is not a function declaration" % code, lineno, pos, filename)
     def get_argument_expressions(self, include_defaults=True):
         """return the argument declarations of this FunctionDecl as a printable list."""
         namedecls = []
diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 6ce1d9a39ff7d82ed8bfb3788ec167da380ff08c..7095627037c938f2ed86bc9ea80d3e60f8317f01 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -81,9 +81,9 @@ class _GenerateRenderMethod(object):
             buffered = filtered = False
             
         if args is None:
-            args = ['context']
+            args = ['context', '**kwargs']
         else:
-            args = [a for a in ['context'] + args]
+            args = [a for a in ['context'] + args + ['**kwargs']]
 
         if not self.in_def:
             self._inherit()
@@ -97,13 +97,13 @@ class _GenerateRenderMethod(object):
         if len(self.identifiers.locally_assigned) > 0:
             printer.writeline("__locals = {}")
 
-        self.write_variable_declares(self.identifiers)
+        self.write_variable_declares(self.identifiers, first="kwargs")
 
         for n in node.nodes:
             n.accept_visitor(self)
 
         self.write_def_finish(node, buffered, filtered)
-
+        printer.writeline(None)
         printer.write("\n\n")
 
     def _inherit(self):
@@ -196,6 +196,7 @@ class _GenerateRenderMethod(object):
             n.accept_visitor(self)
 
         self.write_def_finish(node, buffered, filtered)
+        self.printer.writeline(None)
         
     def write_def_finish(self, node, buffered, filtered):
         if not buffered:
@@ -210,7 +211,7 @@ class _GenerateRenderMethod(object):
                 self.printer.writeline("return %s" % s)
             else:
                 self.printer.writeline("context.write(%s)" % s)
-        self.printer.writeline(None)
+            self.printer.writeline(None)
     
     def create_filter_callable(self, args, target):
         d = dict([(k, "filters." + v.func_name) for k, v in filters.DEFAULT_ESCAPES.iteritems()])
@@ -241,33 +242,40 @@ class _GenerateRenderMethod(object):
             self.write_source_comment(node)
             self.printer.write_indented_block(node.text)
 
-            if not self.in_def:
+            if not self.in_def and len(self.identifiers.locally_assigned) > 0:
                 # 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()])))
-
+                #self.printer.writeline('__locals.update(%s)' % (",".join(["%s=%s" % (x, x) for x in node.declared_identifiers()])))
+                self.printer.writeline('__locals.update(dict([(k, v) for k, v in locals().iteritems() if k in [%s]]))' % ','.join([repr(x) for x in node.declared_identifiers()]))
+                
     def visitIncludeTag(self, node):
         self.write_source_comment(node)
         self.printer.writeline("runtime.include_file(context, %s, import_symbols=%s)" % (node.parsed_attributes['file'], repr(node.attributes.get('import', False))))
 
     def visitNamespaceTag(self, node):
         self.write_source_comment(node)
-        self.printer.writeline("def make_namespace():")
-        export = []
-        identifiers = self.identifiers.branch(node)
-        class NSDefVisitor(object):
-            def visitDefTag(s, node):
-                self.write_inline_def(node, identifiers)
-                export.append(node.name)
-        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')))
+        if len(node.nodes):
+            self.printer.writeline("def make_namespace():")
+            export = []
+            identifiers = self.identifiers.branch(node)
+            class NSDefVisitor(object):
+                def visitDefTag(s, node):
+                    self.write_inline_def(node, identifiers)
+                    export.append(node.name)
+            vis = NSDefVisitor()
+            for n in node.nodes:
+                n.accept_visitor(vis)
+            self.printer.writeline("return [%s]" % (','.join(export)))
+            self.printer.writeline(None)
+            callable_name = "make_namespace()"
+        else:
+            callable_name = "None"
+        self.printer.writeline("%s = runtime.Namespace(%s, context.clean_inheritance_tokens(), templateuri=%s, callables=%s)" % (node.name, repr(node.name), node.parsed_attributes.get('file', 'None'), callable_name))
         if eval(node.attributes.get('inheritable', "False")):
             self.printer.writeline("self.%s = %s" % (node.name, node.name))
-        
+        if not self.in_def:
+            self.printer.writeline("__locals[%s] = %s" % (repr(node.name), node.name))
+            
     def visitDefTag(self, node):
         pass
 
@@ -285,10 +293,15 @@ class _GenerateRenderMethod(object):
             n.accept_visitor(vis)
         self.printer.writeline("def body(**kwargs):")
         body_identifiers = identifiers.branch(node, includedefs=False, includenode=False)
+        # TODO: figure out best way to specify buffering/nonbuffering (at call time would be better)
+        buffered = False
+        if buffered:
+            self.printer.writeline("context.push_buffer()")
+            self.printer.writeline("try:")
         self.write_variable_declares(body_identifiers, first="kwargs")
         for n in node.nodes:
             n.accept_visitor(self)
-        self.printer.writeline("return ''")
+        self.write_def_finish(node, buffered, False)
         self.printer.writeline(None)
         self.printer.writeline("return [%s]" % (','.join(export)))
         self.printer.writeline(None)
@@ -384,6 +397,8 @@ class _Identifiers(object):
         self.check_declared(node)
     def visitNamespaceTag(self, node):
         self.check_declared(node)
+        self.locally_declared.add(node.name)
+        self.locally_assigned.add(node.name)
         if node is self.node:
             for n in node.nodes:
                 n.accept_visitor(self)
diff --git a/lib/mako/exceptions.py b/lib/mako/exceptions.py
index a2bc255c117d69151e424ba6851550417ce17e4b..b15f7370f63e0982f650783f1c2542dedae0d094 100644
--- a/lib/mako/exceptions.py
+++ b/lib/mako/exceptions.py
@@ -11,18 +11,25 @@ class MakoException(Exception):
 
 class RuntimeException(MakoException):
     pass
+
+def _format_filepos(lineno, pos, filename):
+    if filename is None:
+        return " at line: %d char: %d" % (lineno, pos)
+    else:
+        return " in file '%s' at line: %d char: %d" % (filename, lineno, pos)     
 class CompileException(MakoException):
-    def __init__(self, message, lineno, pos):
-        MakoException.__init__(self, message + " at line: %d char: %d" % (lineno, pos))
+    def __init__(self, message, lineno, pos, filename):
+        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
         self.lineno =lineno
         self.pos = pos
-
+        self.filename = filename
                     
 class SyntaxException(MakoException):
-    def __init__(self, message, lineno, pos):
-        MakoException.__init__(self, message + " at line: %d char: %d" % (lineno, pos))
+    def __init__(self, message, lineno, pos, filename):
+        MakoException.__init__(self, message + _format_filepos(lineno, pos, filename))
         self.lineno =lineno
         self.pos = pos
+        self.filename = filename
         
 class TemplateLookupException(MakoException):
     pass
\ No newline at end of file
diff --git a/lib/mako/filters.py b/lib/mako/filters.py
index 880cd99afb494f4720f60514b922535f26871226..1369dc5b503736f14fe18f84e542eadf3e960e52 100644
--- a/lib/mako/filters.py
+++ b/lib/mako/filters.py
@@ -35,11 +35,15 @@ def url_unescape(string):
         text = text.decode("utf8")
     return text
 
+def trim(string):
+    return string.strip()
+    
 # TODO: options to make this dynamic per-compilation will be added in a later release
 DEFAULT_ESCAPES = {
     'x':xml_escape,
     'h':html_escape,
-    'u':url_escape
+    'u':url_escape,
+    'trim':trim,
 }
 
 _ASCII_re = re.compile(r'\A[\x00-\x7f]*\Z')
diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py
index 4b59c269e300ad4a4cc945aa669cd642ced8fc08..e487852be5b043ca7b383c21ea2ad2cfe65c4cf9 100644
--- a/lib/mako/lexer.py
+++ b/lib/mako/lexer.py
@@ -11,9 +11,10 @@ from mako import parsetree, exceptions
 from mako.pygen import adjust_whitespace
 
 class Lexer(object):
-    def __init__(self, text):
+    def __init__(self, text, filename=None):
         self.text = text
-        self.template = parsetree.TemplateNode()
+        self.filename = filename
+        self.template = parsetree.TemplateNode(self.filename)
         self.matched_lineno = 1
         self.matched_charpos = 0
         self.lineno = 1
@@ -51,6 +52,7 @@ class Lexer(object):
     def append_node(self, nodecls, *args, **kwargs):
         kwargs['lineno'] = self.matched_lineno
         kwargs['pos'] = self.matched_charpos
+        kwargs['filename'] = self.filename
         node = nodecls(*args, **kwargs)
         if len(self.tag):
             self.tag[-1].nodes.append(node)
@@ -66,7 +68,7 @@ class Lexer(object):
             elif node.is_primary:
                 self.control_line.append(node)
             elif len(self.control_line) and not self.control_line[-1].is_ternary(node.keyword):
-                raise exceptions.SyntaxException("Keyword '%s' not a legal ternary for keyword '%s'" % (node.keyword, self.control_line[-1].keyword), self.matched_lineno, self.matched_charpos)
+                raise exceptions.SyntaxException("Keyword '%s' not a legal ternary for keyword '%s'" % (node.keyword, self.control_line[-1].keyword), self.matched_lineno, self.matched_charpos, self.filename)
 
     def parse(self):
         length = len(self.text)
@@ -94,7 +96,7 @@ class Lexer(object):
             raise "assertion failed"
             
         if len(self.tag):
-            raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, self.matched_lineno, self.matched_charpos)
+            raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, self.matched_lineno, self.matched_charpos, self.filename)
         return self.template
 
     def match_tag_start(self):
@@ -128,7 +130,7 @@ class Lexer(object):
                 if keyword == 'text':
                     match = self.match(r'.*?(?=\</%text>)',  re.S)
                     if not match:
-                        raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, self.matched_lineno, self.matched_charpos)
+                        raise exceptions.SyntaxException("Unclosed tag: <%%%s>" % self.tag[-1].keyword, self.matched_lineno, self.matched_charpos, self.filename)
                     return self.match_tag_end()
             return True
         else: 
@@ -138,9 +140,9 @@ class Lexer(object):
         match = self.match(r'\</%\s*(.+?)\s*>')
         if match:
             if not len(self.tag):
-                raise exceptions.SyntaxException("Closing tag without opening tag: </%%%s>" % match.group(1), self.matched_lineno, self.matched_charpos)
+                raise exceptions.SyntaxException("Closing tag without opening tag: </%%%s>" % match.group(1), self.matched_lineno, self.matched_charpos, self.filename)
             elif self.tag[-1].keyword != match.group(1):
-                raise exceptions.SyntaxException("Closing tag </%%%s> does not match tag: <%%%s>" % (match.group(1), self.tag[-1].keyword), self.matched_lineno, self.matched_charpos)
+                raise exceptions.SyntaxException("Closing tag </%%%s> does not match tag: <%%%s>" % (match.group(1), self.tag[-1].keyword), self.matched_lineno, self.matched_charpos, self.filename)
             self.tag.pop()
             return True
         else:
@@ -206,15 +208,15 @@ class Lexer(object):
             if operator == '%':
                 m2 = re.match(r'(end)?(\w+)\s*(.*)', text)
                 if not m2:
-                    raise exceptions.SyntaxException("Invalid control line: '%s'" % text, self.matched_lineno, self.matched_charpos)
+                    raise exceptions.SyntaxException("Invalid control line: '%s'" % text, self.matched_lineno, self.matched_charpos, self.filename)
                 (isend, keyword) = m2.group(1, 2)
                 isend = (isend is not None)
                 
                 if isend:
                     if not len(self.control_line):
-                        raise exceptions.SyntaxException("No starting keyword '%s' for '%s'" % (keyword, text), self.matched_lineno, self.matched_charpos)
+                        raise exceptions.SyntaxException("No starting keyword '%s' for '%s'" % (keyword, text), self.matched_lineno, self.matched_charpos, self.filename)
                     elif self.control_line[-1].keyword != keyword:
-                        raise exceptions.SyntaxException("Keyword '%s' doesn't match keyword '%s'" % (text, self.control_line[-1].keyword), self.matched_lineno, self.matched_charpos)
+                        raise exceptions.SyntaxException("Keyword '%s' doesn't match keyword '%s'" % (text, self.control_line[-1].keyword), self.matched_lineno, self.matched_charpos, self.filename)
                 self.append_node(parsetree.ControlLine, keyword, isend, text)
             else:
                 self.append_node(parsetree.Comment, text)
diff --git a/lib/mako/parsetree.py b/lib/mako/parsetree.py
index 45e696dff82133f1fd8dd8456d0a5b73b6d9d7f0..f3dfded5a980f700aa7865acfcbd1ff86de84f90 100644
--- a/lib/mako/parsetree.py
+++ b/lib/mako/parsetree.py
@@ -11,9 +11,10 @@ import re
 
 class Node(object):
     """base class for a Node in the parse tree."""
-    def __init__(self, lineno, pos):
+    def __init__(self, lineno, pos, filename):
         self.lineno = lineno
         self.pos = pos
+        self.filename = filename
     def get_children(self):
         return []
     def accept_visitor(self, visitor):
@@ -25,8 +26,8 @@ class Node(object):
 
 class TemplateNode(Node):
     """a 'container' node that stores the overall collection of nodes."""
-    def __init__(self):
-        super(TemplateNode, self).__init__(0, 0)
+    def __init__(self, filename):
+        super(TemplateNode, self).__init__(0, 0, filename)
         self.nodes = []
         self.page_attributes = {}
     def get_children(self):
@@ -51,7 +52,7 @@ class ControlLine(Node):
             self._declared_identifiers = []
             self._undeclared_identifiers = []
         else:
-            code = ast.PythonFragment(text, self.lineno, self.pos)
+            code = ast.PythonFragment(text, self.lineno, self.pos, self.filename)
             (self._declared_identifiers, self._undeclared_identifiers) = (code.declared_identifiers, code.undeclared_identifiers)
     def declared_identifiers(self):
         return self._declared_identifiers
@@ -93,7 +94,7 @@ class Code(Node):
         super(Code, self).__init__(**kwargs)
         self.text = text
         self.ismodule = ismodule
-        self.code = ast.PythonCode(text, self.lineno, self.pos)
+        self.code = ast.PythonCode(text, self.lineno, self.pos, self.filename)
     def declared_identifiers(self):
         return self.code.declared_identifiers
     def undeclared_identifiers(self):
@@ -123,8 +124,8 @@ class Expression(Node):
         super(Expression, self).__init__(**kwargs)
         self.text = text
         self.escapes = escapes
-        self.escapes_code = ast.ArgumentList(escapes, self.lineno, self.pos)
-        self.code = ast.PythonCode(text, self.lineno, self.pos)
+        self.escapes_code = ast.ArgumentList(escapes, self.lineno, self.pos, self.filename)
+        self.code = ast.PythonCode(text, self.lineno, self.pos, self.filename)
     def declared_identifiers(self):
         return []
     def undeclared_identifiers(self):
@@ -144,7 +145,7 @@ class _TagMeta(type):
         try:
             cls = _TagMeta._classmap[keyword]
         except KeyError:
-            raise exceptions.CompileException("No such tag: '%s'" % keyword, kwargs['lineno'], kwargs['pos'])
+            raise exceptions.CompileException("No such tag: '%s'" % keyword, kwargs['lineno'], kwargs['pos'], kwargs['filename'])
         return type.__call__(cls, keyword, attributes, **kwargs)
         
 class Tag(Node):
@@ -178,7 +179,7 @@ class Tag(Node):
         self._parse_attributes(expressions, nonexpressions)
         missing = [r for r in required if r not in self.parsed_attributes]
         if len(missing):
-            raise exceptions.CompileException("Missing attribute(s): %s" % ",".join([repr(m) for m in missing]), self.lineno, self.pos)
+            raise exceptions.CompileException("Missing attribute(s): %s" % ",".join([repr(m) for m in missing]), self.lineno, self.pos, self.filename)
         self.parent = None
         self.nodes = []
     def is_root(self):
@@ -194,7 +195,7 @@ class Tag(Node):
                 for x in re.split(r'(\${.+?})', self.attributes[key]):
                     m = re.match(r'^\${(.+?)}$', x)
                     if m:
-                        code = ast.PythonCode(m.group(1), self.lineno, self.pos)
+                        code = ast.PythonCode(m.group(1), self.lineno, self.pos, self.filename)
                         undeclared_identifiers = undeclared_identifiers.union(code.undeclared_identifiers)
                         expr.append(m.group(1))
                     else:
@@ -202,10 +203,10 @@ class Tag(Node):
                 self.parsed_attributes[key] = " + ".join(expr)
             elif key in nonexpressions:
                 if re.search(r'${.+?}', self.attributes[key]):
-                    raise exceptions.CompileException("Attibute '%s' in tag '%s' does not allow embedded expressions"  %(key, self.keyword), self.lineno, self.pos)
+                    raise exceptions.CompileException("Attibute '%s' in tag '%s' does not allow embedded expressions"  %(key, self.keyword), self.lineno, self.pos, self.filename)
                 self.parsed_attributes[key] = repr(self.attributes[key])
             else:
-                raise exceptions.CompileException("Invalid attribute for tag '%s': '%s'" %(self.keyword, key), self.lineno, self.pos)
+                raise exceptions.CompileException("Invalid attribute for tag '%s': '%s'" %(self.keyword, key), self.lineno, self.pos, self.filename)
         self.expression_undeclared_identifiers = undeclared_identifiers
     def declared_identifiers(self):
         return []
@@ -225,7 +226,7 @@ class NamespaceTag(Tag):
         super(NamespaceTag, self).__init__(keyword, attributes, ('file',), ('name','inheritable'), ('name',), **kwargs)
         self.name = attributes['name']
     def declared_identifiers(self):
-        return [self.name]
+        return []
 
 class TextTag(Tag):
     __keyword__ = 'text'
@@ -239,22 +240,22 @@ class DefTag(Tag):
         name = attributes['name']
         if re.match(r'^[\w_]+$',name):
             name = name + "()"
-        self.function_decl = ast.FunctionDecl("def " + name + ":pass", self.lineno, self.pos)
+        self.function_decl = ast.FunctionDecl("def " + name + ":pass", self.lineno, self.pos, self.filename)
         self.name = self.function_decl.funcname
-        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), self.lineno, self.pos)
+        self.filter_args = ast.ArgumentList(attributes.get('filter', ''), self.lineno, self.pos, self.filename)
     def declared_identifiers(self):
         return self.function_decl.argnames
     def undeclared_identifiers(self):
         res = []
         for c in self.function_decl.defaults:
-            res += list(ast.PythonCode(c, self.lineno, self.pos).undeclared_identifiers)
+            res += list(ast.PythonCode(c, self.lineno, self.pos, self.filename).undeclared_identifiers)
         return res + list(self.filter_args.undeclared_identifiers.difference(util.Set(filters.DEFAULT_ESCAPES.keys())))
 
 class CallTag(Tag):
     __keyword__ = 'call'
     def __init__(self, keyword, attributes, **kwargs):
         super(CallTag, self).__init__(keyword, attributes, (), ('expr',), ('expr',), **kwargs)
-        self.code = ast.PythonCode(attributes['expr'], self.lineno, self.pos)
+        self.code = ast.PythonCode(attributes['expr'], self.lineno, self.pos, self.filename)
     def declared_identifiers(self):
         return self.code.declared_identifiers
     def undeclared_identifiers(self):
diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py
index 1941ba6051218f5833a21c683e14f9e7b550f76f..34975fbb9b4795670e6601fa2e28d74761c9acb1 100644
--- a/lib/mako/runtime.py
+++ b/lib/mako/runtime.py
@@ -14,7 +14,8 @@ class Context(object):
         self._buffer_stack = [buffer]
         self._argstack = [data]
         self._with_template = None
-        data['args'] = _AttrFacade(self)
+        #data['args'] = _AttrFacade(self)
+        data['capture'] = lambda x, *args, **kwargs: capture(self, x, *args, **kwargs)
     def keys(self):
         return self._argstack[-1].keys()
     def __getitem__(self, key):
@@ -44,7 +45,7 @@ class Context(object):
         x = self._argstack[-1].copy()
         c._argstack = [x]
         c._with_template = self._with_template
-        x['args'] = _AttrFacade(c)
+        #x['args'] = _AttrFacade(c)
         return c
     def locals_(self, d):
         """create a new Context with a copy of this Context's current state, updated with the given dictionary."""
@@ -123,7 +124,14 @@ class Namespace(object):
             return getattr(self.inherits, key)
         raise exceptions.RuntimeException("Namespace '%s' has no member '%s'" % (self.name, key))
 
-
+def capture(context, callable_, *args, **kwargs):
+    context.push_buffer()
+    try:
+        callable_(*args, **kwargs)
+    finally:
+        buf = context.pop_buffer()
+        return buf.getvalue()
+        
 def include_file(context, uri, import_symbols):
     template = _lookup_template(context, uri)
     (callable_, ctx) = _populate_self_namespace(context.clean_inheritance_tokens(), template)
diff --git a/lib/mako/template.py b/lib/mako/template.py
index 0d6947ba9dc7bc7d682721593422b529467853d9..b5c06fc32043419a8d0948e0b9ce2dab8d6f0611 100644
--- a/lib/mako/template.py
+++ b/lib/mako/template.py
@@ -50,6 +50,7 @@ class Template(object):
             self._code = None
         self.module = module
         self.description = description
+        self.filename = filename
         self.callable_ = self.module.render
         self.format_exceptions = format_exceptions
         self.error_handler = error_handler
@@ -93,12 +94,12 @@ class DefTemplate(Template):
         return self.parent.get_def(name)
         
 def _compile_text(text, identifier, filename):
-    node = Lexer(text).parse()
-    source = Compiler(node).render()
-    #print source
+    node = Lexer(text, filename).parse()
+    source = Compiler(node, filename).render()
+    print source
     cid = identifier
     module = imp.new_module(cid)
-    code = compile(source, filename or cid, 'exec')
+    code = compile(source, cid, 'exec')
     exec code in module.__dict__, module.__dict__
     return (source, module)
 
diff --git a/test/ast.py b/test/ast.py
index c4211a984f9c0ba95f8f3b0a542034a4bc675ebc..3059fdd53c1815c482aee5989448e5ea6c9254c4 100644
--- a/test/ast.py
+++ b/test/ast.py
@@ -23,11 +23,11 @@ for lar in (1,2,3):
 print "hello world, ", a, b
 print "Another expr", c
 """
-        parsed = ast.PythonCode(code, 0, 0)
+        parsed = ast.PythonCode(code, 0, 0, None)
         assert parsed.declared_identifiers == util.Set(['a','b','c', 'g', 'h', 'i', 'u', 'k', 'j', 'gh', 'lar', 'x'])
         assert parsed.undeclared_identifiers == util.Set(['x', 'q', 'foo', 'gah', 'blah'])
     
-        parsed = ast.PythonCode("x + 5 * (y-z)", 0, 0)
+        parsed = ast.PythonCode("x + 5 * (y-z)", 0, 0, None)
         assert parsed.undeclared_identifiers == util.Set(['x', 'y', 'z'])
         assert parsed.declared_identifiers == util.Set()
 
@@ -41,7 +41,7 @@ data = get_data()
 for x in data:
     result.append(x+7)
 """
-        parsed = ast.PythonCode(code, 0, 0)
+        parsed = ast.PythonCode(code, 0, 0, None)
         assert parsed.undeclared_identifiers == util.Set(['get_data'])
         assert parsed.declared_identifiers == util.Set(['result', 'data', 'x', 'hoho', 'foobar', 'foo', 'yaya'])
 
@@ -54,7 +54,7 @@ for y in range(1, y):
 [z for z in range(1, z)]
 (q for q in range (1, q))
 """
-        parsed = ast.PythonCode(code, 0, 0)
+        parsed = ast.PythonCode(code, 0, 0, None)
         assert parsed.undeclared_identifiers == util.Set(['x', 'y', 'z', 'q'])
     
     def test_locate_identifiers_4(self):
@@ -64,7 +64,7 @@ print y
 def mydef(mydefarg):
     print "mda is", mydefarg
 """    
-        parsed = ast.PythonCode(code, 0, 0)
+        parsed = ast.PythonCode(code, 0, 0, None)
         assert parsed.undeclared_identifiers == util.Set(['y'])
         assert parsed.declared_identifiers == util.Set(['mydef', 'x'])
         
@@ -74,41 +74,41 @@ from foo import *
 import x as bar
 """
         try:
-            parsed = ast.PythonCode(code, 0, 0)
+            parsed = ast.PythonCode(code, 0, 0, None)
             assert False
         except exceptions.CompileException, e:
             assert str(e).startswith("'import *' is not supported")
             
     def test_python_fragment(self):
-        parsed = ast.PythonFragment("for x in foo:", 0, 0)
+        parsed = ast.PythonFragment("for x in foo:", 0, 0, None)
         assert parsed.declared_identifiers == util.Set(['x'])
         assert parsed.undeclared_identifiers == util.Set(['foo'])
         
-        parsed = ast.PythonFragment("try:", 0, 0)
+        parsed = ast.PythonFragment("try:", 0, 0, None)
 
-        parsed = ast.PythonFragment("except (MyException, e):", 0, 0)
+        parsed = ast.PythonFragment("except (MyException, e):", 0, 0, None)
         assert parsed.declared_identifiers == util.Set(['e'])
         assert parsed.undeclared_identifiers == util.Set()
     
     def test_argument_list(self):
-        parsed = ast.ArgumentList("3, 5, 'hi', x+5, context.get('lala')", 0, 0)
+        parsed = ast.ArgumentList("3, 5, 'hi', x+5, context.get('lala')", 0, 0, None)
         assert parsed.undeclared_identifiers == util.Set(['x', 'context'])
         assert [x for x in parsed.args] == ["3", "5", "'hi'", "(x + 5)", "context.get('lala')"]
 
-        parsed = ast.ArgumentList("h", 0, 0)
+        parsed = ast.ArgumentList("h", 0, 0, None)
         assert parsed.args == ["h"]
 
     def test_function_decl(self):
         """test getting the arguments from a function"""
         code = "def foo(a, b, c=None, d='hi', e=x, f=y+7):pass"
-        parsed = ast.FunctionDecl(code, 0, 0)
+        parsed = ast.FunctionDecl(code, 0, 0, None)
         assert parsed.funcname=='foo'
         assert parsed.argnames==['a', 'b', 'c', 'd', 'e', 'f']
 
     def test_function_decl_2(self):
         """test getting the arguments from a function"""
         code = "def foo(a, b, c=None, *args, **kwargs):pass"
-        parsed = ast.FunctionDecl(code, 0, 0)
+        parsed = ast.FunctionDecl(code, 0, 0, None)
         assert parsed.funcname=='foo'
         assert parsed.argnames==['a', 'b', 'c', 'args', 'kwargs']
     
diff --git a/test/filters.py b/test/filters.py
index 43e9c5880b7419943f48e5751b5cba5716ece422..016bf84b014693e48b886ad5c2527e61331255e8 100644
--- a/test/filters.py
+++ b/test/filters.py
@@ -58,7 +58,15 @@ class BufferTest(unittest.TestCase):
 """)
         assert flatten_result(t.render()) == "this is foo hi-><-hi"
 
-
+    def test_capture(self):
+        t = Template("""
+            <%def name="foo" buffered="False">
+                this is foo
+            </%def>
+            ${"hi->" + capture(foo) + "<-hi"}
+""")
+        assert flatten_result(t.render()) == "hi-> this is foo <-hi"
+        
 
 if __name__ == '__main__':
     unittest.main()
\ No newline at end of file
diff --git a/test/inheritance.py b/test/inheritance.py
index 7836dce6a750214edbb29527eb10baa206f2053e..3dc9f5d9b576f821dcd9ce5c5cbb855421fc3516 100644
--- a/test/inheritance.py
+++ b/test/inheritance.py
@@ -99,7 +99,6 @@ ${next.body()}
              'self:main self:layout self:general self:base'
         ]
         
-
     def test_includes(self):
         """test that an included template also has its full hierarchy invoked."""
         collection = lookup.TemplateLookup()
diff --git a/test/namespace.py b/test/namespace.py
index d06d2f59cb12841bb692b2dee7fe163b784329ea..282212bddf46ff68bbc6c33d72f775f2c12d949b 100644
--- a/test/namespace.py
+++ b/test/namespace.py
@@ -68,6 +68,25 @@ class NamespaceTest(unittest.TestCase):
     """)
 
         assert flatten_result(collection.get_template('main.html').render()) == "this is main. overridden def1 hi, there def2: there"
+
+    def test_in_def(self):
+        collection = lookup.TemplateLookup()
+        collection.put_string("main.html", """
+            <%namespace name="foo" file="ns.html"/>
+            
+            this is main.  ${bar()}
+            <%def name="bar">
+                this is bar, foo is ${foo.bar()}
+            </%def>
+        """)
+        
+        collection.put_string("ns.html", """
+            <%def name="bar">
+                this is ns.html->bar
+            </%def>
+        """)
+
+        print collection.get_template("main.html").render()
         
 if __name__ == '__main__':
     unittest.main()