From 86411ebded5f62970eaa2b119a215a71212cb492 Mon Sep 17 00:00:00 2001
From: Mike Bayer <mike_mp@zzzcomputing.com>
Date: Fri, 5 Feb 2010 00:04:55 +0000
Subject: [PATCH] - update copyright for 2010 - start work on #98

---
 CHANGES                |   4 +
 LICENSE                |   4 +-
 lib/mako/__init__.py   |   2 +-
 lib/mako/ast.py        |   2 +-
 lib/mako/codegen.py    |  97 +++++++++++++-----
 lib/mako/exceptions.py |   2 +-
 lib/mako/filters.py    |   2 +-
 lib/mako/lexer.py      |   2 +-
 lib/mako/lookup.py     | 127 ++++++++++++++++-------
 lib/mako/parsetree.py  |   2 +-
 lib/mako/pygen.py      |   2 +-
 lib/mako/runtime.py    |   2 +-
 lib/mako/template.py   | 225 ++++++++++++++++++++++++++++++-----------
 lib/mako/util.py       |  10 +-
 14 files changed, 352 insertions(+), 131 deletions(-)

diff --git a/CHANGES b/CHANGES
index 46aa4da..96fedad 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,7 @@
+0.3
+- Python 2.3 support is dropped (who can resist
+  @decorators)
+  
 0.2.6
 
 - Fix mako function decorators to preserve the
diff --git a/LICENSE b/LICENSE
index 9df31e9..86d4196 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,7 +1,7 @@
 This is the MIT license: http://www.opensource.org/licenses/mit-license.php
 
-Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer and contributors. Mako is a trademark of Michael
-Bayer.
+Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer and contributors.
+Mako is a trademark of Michael Bayer.
 
 Permission is hereby granted, free of charge, to any person obtaining a copy of this
 software and associated documentation files (the "Software"), to deal in the Software
diff --git a/lib/mako/__init__.py b/lib/mako/__init__.py
index c08bf6c..6a30418 100644
--- a/lib/mako/__init__.py
+++ b/lib/mako/__init__.py
@@ -1,5 +1,5 @@
 # __init__.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/ast.py b/lib/mako/ast.py
index 3ba4532..3b9f3ed 100644
--- a/lib/mako/ast.py
+++ b/lib/mako/ast.py
@@ -1,5 +1,5 @@
 # ast.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 7df2473..b3074f0 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -1,5 +1,5 @@
 # codegen.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -13,18 +13,41 @@ from mako import util, ast, parsetree, filters
 
 MAGIC_NUMBER = 5
 
-
-def compile(node, uri, filename=None, default_filters=None, buffer_filters=None, imports=None, source_encoding=None, generate_unicode=True):
-    """generate module source code given a parsetree node, uri, and optional source filename"""
+def compile(node, 
+                uri, 
+                filename=None, 
+                default_filters=None, 
+                buffer_filters=None, 
+                imports=None, 
+                source_encoding=None, 
+                generate_unicode=True):
+                
+    """Generate module source code given a parsetree node, 
+      uri, and optional source filename"""
 
     buf = util.FastEncodingBuffer(unicode=generate_unicode)
 
     printer = PythonPrinter(buf)
-    _GenerateRenderMethod(printer, _CompileContext(uri, filename, default_filters, buffer_filters, imports, source_encoding, generate_unicode), node)
+    _GenerateRenderMethod(printer, 
+                            _CompileContext(uri, 
+                                            filename, 
+                                            default_filters, 
+                                            buffer_filters,
+                                            imports, 
+                                            source_encoding,
+                                            generate_unicode), 
+                                node)
     return buf.getvalue()
 
 class _CompileContext(object):
-    def __init__(self, uri, filename, default_filters, buffer_filters, imports, source_encoding, generate_unicode):
+    def __init__(self, 
+                    uri, 
+                    filename, 
+                    default_filters, 
+                    buffer_filters, 
+                    imports, 
+                    source_encoding, 
+                    generate_unicode):
         self.uri = uri
         self.filename = filename
         self.default_filters = default_filters
@@ -34,7 +57,10 @@ class _CompileContext(object):
         self.generate_unicode = generate_unicode
         
 class _GenerateRenderMethod(object):
-    """a template visitor object which generates the full module source for a template."""
+    """A template visitor object which generates the 
+       full module source for a template.
+       
+    """
     def __init__(self, printer, compiler, node):
         self.printer = printer
         self.last_source_line = -1
@@ -70,17 +96,24 @@ class _GenerateRenderMethod(object):
         else:
             args = [a for a in ['context'] + args]
             
-        self.write_render_callable(pagetag or node, name, args, buffered, filtered, cached)
+        self.write_render_callable(
+                            pagetag or node, 
+                            name, args, 
+                            buffered, filtered, cached)
         
         if defs is not None:
             for node in defs:
                 _GenerateRenderMethod(printer, compiler, node)
     
-    identifiers = property(lambda self:self.identifier_stack[-1])
+    @property
+    def identifiers(self):
+        return self.identifier_stack[-1]
     
     def write_toplevel(self):
-        """traverse a template structure for module-level directives and generate the
-        start of module-level code."""
+        """Traverse a template structure for module-level directives and
+        generate the start of module-level code.
+        
+        """
         inherit = []
         namespaces = {}
         module_code = []
@@ -113,36 +146,50 @@ class _GenerateRenderMethod(object):
         module_identifiers.declared = module_ident
         
         # module-level names, python code
-        if not self.compiler.generate_unicode and self.compiler.source_encoding:
-            self.printer.writeline("# -*- encoding:%s -*-" % self.compiler.source_encoding)
+        if not self.compiler.generate_unicode and \
+            self.compiler.source_encoding:
+            self.printer.writeline("# -*- encoding:%s -*-" %
+                                    self.compiler.source_encoding)
             
         self.printer.writeline("from mako import runtime, filters, cache")
         self.printer.writeline("UNDEFINED = runtime.UNDEFINED")
         self.printer.writeline("__M_dict_builtin = dict")
         self.printer.writeline("__M_locals_builtin = locals")
-        self.printer.writeline("_magic_number = %s" % repr(MAGIC_NUMBER))
-        self.printer.writeline("_modified_time = %s" % repr(time.time()))
-        self.printer.writeline("_template_filename=%s" % repr(self.compiler.filename))
-        self.printer.writeline("_template_uri=%s" % repr(self.compiler.uri))
-        self.printer.writeline("_template_cache=cache.Cache(__name__, _modified_time)")
-        self.printer.writeline("_source_encoding=%s" % repr(self.compiler.source_encoding))
+        self.printer.writeline("_magic_number = %r" % MAGIC_NUMBER)
+        self.printer.writeline("_modified_time = %r" % time.time())
+        self.printer.writeline(
+                            "_template_filename=%r" % self.compiler.filename)
+        self.printer.writeline("_template_uri=%r" % self.compiler.uri)
+        self.printer.writeline(
+                    "_template_cache=cache.Cache(__name__, _modified_time)")
+        self.printer.writeline(
+                    "_source_encoding=%r" % self.compiler.source_encoding)
         if self.compiler.imports:
             buf = ''
             for imp in self.compiler.imports:
                 buf += imp + "\n"
                 self.printer.writeline(imp)
-            impcode = ast.PythonCode(buf, source='', lineno=0, pos=0, filename='template defined imports')
+            impcode = ast.PythonCode(
+                            buf, 
+                            source='', lineno=0, 
+                            pos=0, 
+                            filename='template defined imports')
         else:
             impcode = None
         
         main_identifiers = module_identifiers.branch(self.node)
-        module_identifiers.topleveldefs = module_identifiers.topleveldefs.union(main_identifiers.topleveldefs)
-        [module_identifiers.declared.add(x) for x in ["UNDEFINED"]]
+        module_identifiers.topleveldefs = \
+            module_identifiers.topleveldefs.\
+                union(main_identifiers.topleveldefs)
+        module_identifiers.declared.add("UNDEFINED")
         if impcode:
-            [module_identifiers.declared.add(x) for x in impcode.declared_identifiers]
+            module_identifiers.declared.update(impcode.declared_identifiers)
             
         self.compiler.identifiers = module_identifiers
-        self.printer.writeline("_exports = %s" % repr([n.name for n in main_identifiers.topleveldefs.values()]))
+        self.printer.writeline("_exports = %r" % 
+                            [n.name for n in
+                            main_identifiers.topleveldefs.values()]
+                        )
         self.printer.write("\n\n")
 
         if len(module_code):
@@ -156,6 +203,8 @@ class _GenerateRenderMethod(object):
 
         return main_identifiers.topleveldefs.values()
 
+##### continue [ticket:98] below ####
+
     def write_render_callable(self, node, name, args, buffered, filtered, cached):
         """write a top-level render callable.
         
diff --git a/lib/mako/exceptions.py b/lib/mako/exceptions.py
index aa529d7..dcd6a64 100644
--- a/lib/mako/exceptions.py
+++ b/lib/mako/exceptions.py
@@ -1,5 +1,5 @@
 # exceptions.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/filters.py b/lib/mako/filters.py
index 13ac622..9a5b21d 100644
--- a/lib/mako/filters.py
+++ b/lib/mako/filters.py
@@ -1,5 +1,5 @@
 # filters.py
-# Copyright (C) 2006, 2007, 2008, 2009 Geoffrey T. Dairiki <dairiki@dairiki.org> and Michael Bayer <mike_mp@zzzcomputing.com>
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Geoffrey T. Dairiki <dairiki@dairiki.org> and Michael Bayer <mike_mp@zzzcomputing.com>
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/lexer.py b/lib/mako/lexer.py
index de562cc..52a4b6d 100644
--- a/lib/mako/lexer.py
+++ b/lib/mako/lexer.py
@@ -1,5 +1,5 @@
 # lexer.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/lookup.py b/lib/mako/lookup.py
index a213973..0398c5e 100644
--- a/lib/mako/lookup.py
+++ b/lib/mako/lookup.py
@@ -1,5 +1,6 @@
 # lookup.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer 
+# mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -18,35 +19,59 @@ class TemplateCollection(object):
         try:
             self.get_template(uri)
             return True
-        except exceptions.TemplateLookupException, e:
+        except exceptions.TemplateLookupException:
             return False
+
     def get_template(self, uri, relativeto=None):
         raise NotImplementedError()
+
     def filename_to_uri(self, uri, filename):
-        """convert the given filename to a uri relative to this TemplateCollection."""
+        """Convert the given filename to a uri relative to 
+           this TemplateCollection."""
+        
         return uri
         
     def adjust_uri(self, uri, filename):
-        """adjust the given uri based on the calling filename.
+        """Adjust the given uri based on the calling filename.
+        
+        When this method is called from the runtime, the 'filename' parameter
+        is taken directly to the 'filename' attribute of the calling template.
+        Therefore a custom TemplateCollection subclass can place any string
+        identifier desired in the "filename" parameter of the Template objects
+        it constructs and have them come back here.
         
-        when this method is called from the runtime, the 'filename' parameter 
-        is taken directly to the 'filename' attribute of the calling 
-        template.  Therefore a custom TemplateCollection subclass can place any string 
-        identifier desired in the "filename" parameter of the Template objects it constructs
-        and have them come back here."""
+        """
         return uri
         
 class TemplateLookup(TemplateCollection):
-    def __init__(self, directories=None, module_directory=None, filesystem_checks=True, collection_size=-1, format_exceptions=False, 
-    error_handler=None, disable_unicode=False, output_encoding=None, encoding_errors='strict', cache_type=None, cache_dir=None, cache_url=None, 
-    cache_enabled=True, modulename_callable=None, default_filters=None, buffer_filters=[], imports=None, input_encoding=None, preprocessor=None):
-        if isinstance(directories, basestring):
-            directories = [directories]        
-        self.directories = [posixpath.normpath(d) for d in directories or []]
+    def __init__(self, 
+                        directories=None, 
+                        module_directory=None, 
+                        filesystem_checks=True, 
+                        collection_size=-1, 
+                        format_exceptions=False, 
+                        error_handler=None, 
+                        disable_unicode=False, 
+                        output_encoding=None, 
+                        encoding_errors='strict', 
+                        cache_type=None, 
+                        cache_dir=None, cache_url=None,
+                        cache_enabled=True, 
+                        modulename_callable=None, 
+                        default_filters=None, 
+                        buffer_filters=(), 
+                        imports=None, 
+                        input_encoding=None, 
+                        preprocessor=None):
+                        
+        self.directories = [posixpath.normpath(d) for d in
+                            util.to_list(directories, ())
+                            ]
         self.module_directory = module_directory
         self.modulename_callable = modulename_callable
         self.filesystem_checks = filesystem_checks
         self.collection_size = collection_size
+
         self.template_args = {
             'format_exceptions':format_exceptions, 
             'error_handler':error_handler, 
@@ -63,28 +88,30 @@ class TemplateLookup(TemplateCollection):
             'buffer_filters':buffer_filters,  
             'imports':imports, 
             'preprocessor':preprocessor}
+
         if collection_size == -1:
-            self.__collection = {}
+            self._collection = {}
             self._uri_cache = {}
         else:
-            self.__collection = util.LRUCache(collection_size)
+            self._collection = util.LRUCache(collection_size)
             self._uri_cache = util.LRUCache(collection_size)
         self._mutex = threading.Lock()
         
     def get_template(self, uri):
         try:
             if self.filesystem_checks:
-                return self.__check(uri, self.__collection[uri])
+                return self._check(uri, self._collection[uri])
             else:
-                return self.__collection[uri]
+                return self._collection[uri]
         except KeyError:
             u = re.sub(r'^\/+', '', uri)
             for dir in self.directories:
                 srcfile = posixpath.normpath(posixpath.join(dir, u))
                 if os.path.exists(srcfile):
-                    return self.__load(srcfile, uri)
+                    return self._load(srcfile, uri)
             else:
-                raise exceptions.TopLevelLookupException("Cant locate template for uri '%s'" % uri)
+                raise exceptions.TopLevelLookupException(
+                                    "Cant locate template for uri %r" % uri)
 
     def adjust_uri(self, uri, relativeto):
         """adjust the given uri based on the calling filename."""
@@ -102,12 +129,16 @@ class TemplateLookup(TemplateCollection):
         try:
             return self._uri_cache[filename]
         except KeyError:
-            value = self.__relativeize(filename)
+            value = self._relativeize(filename)
             self._uri_cache[filename] = value
             return value
                     
-    def __relativeize(self, filename):
-        """return the portion of a filename that is 'relative' to the directories in this lookup."""
+    def _relativeize(self, filename):
+        """Return the portion of a filename that is 'relative' 
+           to the directories in this lookup.
+           
+        """
+        
         filename = posixpath.normpath(filename)
         for dir in self.directories:
             if filename[0:len(dir)] == dir:
@@ -115,37 +146,57 @@ class TemplateLookup(TemplateCollection):
         else:
             return None
             
-    def __load(self, filename, uri):
+    def _load(self, filename, uri):
         self._mutex.acquire()
         try:
             try:
-                # try returning from collection one more time in case concurrent thread already loaded
-                return self.__collection[uri]
+                # try returning from collection one 
+                # more time in case concurrent thread already loaded
+                return self._collection[uri]
             except KeyError:
                 pass
             try:
-                self.__collection[uri] = Template(uri=uri, filename=posixpath.normpath(filename), lookup=self, module_filename=(self.modulename_callable is not None and self.modulename_callable(filename, uri) or None), **self.template_args)
-                return self.__collection[uri]
+                if self.modulename_callable is not None:
+                    module_filename = self.modulename_callable(filename, uri)
+                else:
+                    module_filename = None
+                self._collection[uri] = template = Template(
+                                        uri=uri,
+                                        filename=posixpath.normpath(filename),
+                                        lookup=self, 
+                                        module_filename=module_filename,
+                                        **self.template_args)
+                return template
             except:
-                self.__collection.pop(uri, None)
+                # if compilation fails etc, ensure 
+                # template is removed from collection,
+                # re-raise
+                self._collection.pop(uri, None)
                 raise
         finally:
             self._mutex.release()
             
-    def __check(self, uri, template):
+    def _check(self, uri, template):
         if template.filename is None:
             return template
         if not os.path.exists(template.filename):
-            self.__collection.pop(uri, None)
-            raise exceptions.TemplateLookupException("Cant locate template for uri '%s'" % uri)
-        elif template.module._modified_time < os.stat(template.filename)[stat.ST_MTIME]:
-            self.__collection.pop(uri, None)
-            return self.__load(template.filename, uri)
+            self._collection.pop(uri, None)
+            raise exceptions.TemplateLookupException(
+                                "Cant locate template for uri %r" % uri)
+        elif template.module._modified_time < \
+                        os.stat(template.filename)[stat.ST_MTIME]:
+            self._collection.pop(uri, None)
+            return self._load(template.filename, uri)
         else:
             return template
             
     def put_string(self, uri, text):
-        self.__collection[uri] = Template(text, lookup=self, uri=uri, **self.template_args)
+        self._collection[uri] = Template(
+                                    text, 
+                                    lookup=self, 
+                                    uri=uri, 
+                                    **self.template_args)
+        
     def put_template(self, uri, template):
-        self.__collection[uri] = template
+        self._collection[uri] = template
             
diff --git a/lib/mako/parsetree.py b/lib/mako/parsetree.py
index fd588c1..347c31a 100644
--- a/lib/mako/parsetree.py
+++ b/lib/mako/parsetree.py
@@ -1,5 +1,5 @@
 # parsetree.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/pygen.py b/lib/mako/pygen.py
index 76e6e87..914443b 100644
--- a/lib/mako/pygen.py
+++ b/lib/mako/pygen.py
@@ -1,5 +1,5 @@
 # pygen.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/runtime.py b/lib/mako/runtime.py
index ee6c5be..a475b71 100644
--- a/lib/mako/runtime.py
+++ b/lib/mako/runtime.py
@@ -1,5 +1,5 @@
 # runtime.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
diff --git a/lib/mako/template.py b/lib/mako/template.py
index 45b5403..4bf01e0 100644
--- a/lib/mako/template.py
+++ b/lib/mako/template.py
@@ -1,34 +1,55 @@
 # template.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer
+# mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""provides the Template class, a facade for parsing, generating and executing template strings,
-as well as template runtime operations."""
+"""Provides the Template class, a facade for parsing, generating and executing
+template strings, as well as template runtime operations."""
 
 from mako.lexer import Lexer
-from mako import codegen
-from mako import runtime, util, exceptions
+from mako import runtime, util, exceptions, codegen
 import imp, os, re, shutil, stat, sys, tempfile, time, types, weakref
 
     
 class Template(object):
     """a compiled template"""
-    def __init__(self, text=None, filename=None, uri=None, format_exceptions=False, error_handler=None, 
-        lookup=None, output_encoding=None, encoding_errors='strict', module_directory=None, cache_type=None, 
-        cache_dir=None, cache_url=None, module_filename=None, input_encoding=None, disable_unicode=False, default_filters=None, 
-        buffer_filters=[], imports=None, preprocessor=None, cache_enabled=True):
-        """construct a new Template instance using either literal template text, or a previously loaded template module
+    def __init__(self, 
+                    text=None, 
+                    filename=None, 
+                    uri=None, 
+                    format_exceptions=False, 
+                    error_handler=None, 
+                    lookup=None, 
+                    output_encoding=None, 
+                    encoding_errors='strict', 
+                    module_directory=None, 
+                    cache_type=None, 
+                    cache_dir=None, 
+                    cache_url=None, 
+                    module_filename=None, 
+                    input_encoding=None, 
+                    disable_unicode=False, 
+                    default_filters=None, 
+                    buffer_filters=(), 
+                    imports=None, 
+                    preprocessor=None, 
+                    cache_enabled=True):
+        """Construct a new Template instance using either literal template
+        text, or a previously loaded template module
         
-        text - textual template source, or None if a module is to be provided
+        :param text: textual template source, or None if a module is to be
+            provided
         
-        uri - the uri of this template, or some identifying string. defaults to the 
-        full filename given, or "memory:(hex id of this Template)" if no filename
+        :param uri: the uri of this template, or some identifying string.
+            defaults to the full filename given, or "memory:(hex id of this
+            Template)" if no filename
         
-        filename - filename of the source template, if any
+        :param filename: filename of the source template, if any
         
-        format_exceptions - catch exceptions and format them into an error display template
+        :param format_exceptions: catch exceptions and format them into an
+            error display template
         """
         
         if uri:
@@ -72,30 +93,48 @@ class Template(object):
                 u = self.uri
                 if u[0] == '/':
                     u = u[1:]
-                path = os.path.abspath(os.path.join(module_directory.replace('/', os.path.sep), u + ".py"))
+                path = os.path.abspath(
+                        os.path.join(
+                            module_directory.replace('/', os.path.sep), 
+                            u + ".py"
+                            )
+                        )
             else:
                 path = None    
             if path is not None:
                 util.verify_directory(os.path.dirname(path))
                 filemtime = os.stat(filename)[stat.ST_MTIME]
-                if not os.path.exists(path) or os.stat(path)[stat.ST_MTIME] < filemtime:
-                    _compile_module_file(self, file(filename).read(), filename, path)
+                if not os.path.exists(path) or \
+                            os.stat(path)[stat.ST_MTIME] < filemtime:
+                    _compile_module_file(
+                                self, 
+                                file(filename).read(), 
+                                filename, 
+                                path)
                 module = imp.load_source(self.module_id, path, file(path))
                 del sys.modules[self.module_id]
                 if module._magic_number != codegen.MAGIC_NUMBER:
-                    _compile_module_file(self, file(filename).read(), filename, path)
+                    _compile_module_file(
+                                self, 
+                                file(filename).read(), 
+                                filename, 
+                                path)
                     module = imp.load_source(self.module_id, path, file(path))
                     del sys.modules[self.module_id]
                 ModuleInfo(module, path, self, filename, None, None)
             else:
                 # template filename and no module directory, compile code
                 # in memory
-                (code, module) = _compile_text(self, file(filename).read(), filename)
+                (code, module) = _compile_text(
+                                    self, 
+                                    file(filename).read(), 
+                                    filename)
                 self._source = None
                 self._code = code
                 ModuleInfo(module, None, self, filename, code, None)
         else:
-            raise exceptions.RuntimeException("Template requires text or filename")
+            raise exceptions.RuntimeException(
+                                "Template requires text or filename")
 
         self.module = module
         self.filename = filename
@@ -107,54 +146,71 @@ class Template(object):
         self.cache_dir = cache_dir
         self.cache_url = cache_url
         self.cache_enabled = cache_enabled
-
+    
+    @property
     def source(self):
         """return the template source code for this Template."""
+        
         return _get_module_info_from_callable(self.callable_).source
-    source = property(source)
-    
+
+    @property
     def code(self):
         """return the module source code for this Template"""
+        
         return _get_module_info_from_callable(self.callable_).code
-    code = property(code)
     
+    @property
     def cache(self):
         return self.module._template_cache
-    cache = property(cache)
     
     def render(self, *args, **data):
-        """render the output of this template as a string.
+        """Render the output of this template as a string.
+        
+        if the template specifies an output encoding, the string will be
+        encoded accordingly, else the output is raw (raw output uses cStringIO
+        and can't handle multibyte characters). a Context object is created
+        corresponding to the given data. Arguments that are explictly declared
+        by this template's internal rendering method are also pulled from the
+        given \*args, \**data members.
         
-        if the template specifies an output encoding, the string will be encoded accordingly, else the output
-        is raw (raw output uses cStringIO and can't handle multibyte characters).
-        a Context object is created corresponding to the given data.  Arguments that are explictly
-        declared by this template's internal rendering method are also pulled from the given *args, **data 
-        members."""
+        """
         return runtime._render(self, self.callable_, args, data)
     
     def render_unicode(self, *args, **data):
         """render the output of this template as a unicode object."""
         
-        return runtime._render(self, self.callable_, args, data, as_unicode=True)
+        return runtime._render(self, 
+                                self.callable_, 
+                                args, 
+                                data, 
+                                as_unicode=True)
         
     def render_context(self, context, *args, **kwargs):
-        """render this Template with the given context.  
+        """Render this Template with the given context.  
         
-        the data is written to the context's buffer."""
+        the data is written to the context's buffer.
+        
+        """
         if getattr(context, '_with_template', None) is None:
             context._with_template = self
-        runtime._render_context(self, self.callable_, context, *args, **kwargs)
+        runtime._render_context(self, 
+                                self.callable_, 
+                                context, 
+                                *args, 
+                                **kwargs)
     
     def has_def(self, name):
         return hasattr(self.module, "render_%s" % name)
         
     def get_def(self, name):
-        """return a def of this template as an individual Template of its own."""
+        """Return a def of this template as a DefTemplate."""
+        
         return DefTemplate(self, getattr(self.module, "render_%s" % name))
 
     def _get_def_callable(self, name):
         return getattr(self.module, "render_%s" % name)
     
+    @property
     def last_modified(self): 
         return self.module._modified_time    
     last_modified = property(last_modified)
@@ -177,11 +233,21 @@ class ModuleTemplate(Template):
     """
     
     def __init__(self, module, 
-        module_filename=None, 
-        template=None, template_filename=None, 
-        module_source=None, template_source=None,
-        output_encoding=None, encoding_errors='strict', disable_unicode=False, format_exceptions=False,
-        error_handler=None, lookup=None, cache_type=None, cache_dir=None, cache_url=None, cache_enabled=True
+                        module_filename=None, 
+                        template=None, 
+                        template_filename=None, 
+                        module_source=None, 
+                        template_source=None,
+                        output_encoding=None, 
+                        encoding_errors='strict',
+                        disable_unicode=False, 
+                        format_exceptions=False,
+                        error_handler=None, 
+                        lookup=None, 
+                        cache_type=None,
+                        cache_dir=None, 
+                        cache_url=None, 
+                        cache_enabled=True
     ):
         self.module_id = re.sub(r'\W', "_", module._template_uri)
         self.uri = module._template_uri
@@ -191,7 +257,12 @@ class ModuleTemplate(Template):
         self.disable_unicode = disable_unicode
         self.module = module
         self.filename = template_filename
-        ModuleInfo(module, module_filename, self, template_filename, module_source, template_source)
+        ModuleInfo(module, 
+                        module_filename, 
+                        self, 
+                        template_filename, 
+                        module_source, 
+                        template_source)
         
         self.callable_ = self.module.render_body
         self.format_exceptions = format_exceptions
@@ -204,6 +275,7 @@ class ModuleTemplate(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_
@@ -218,12 +290,20 @@ class DefTemplate(Template):
         return self.parent.get_def(name)
 
 class ModuleInfo(object):
-    """stores information about a module currently loaded into memory,
+    """Stores information about a module currently loaded into memory,
     provides reverse lookups of template source, module source code based on
-    a module's identifier."""
+    a module's identifier.
+    
+    """
     _modules = weakref.WeakValueDictionary()
 
-    def __init__(self, module, module_filename, template, template_filename, module_source, template_source):
+    def __init__(self, 
+                    module, 
+                    module_filename, 
+                    template, 
+                    template_filename, 
+                    module_source, 
+                    template_source):
         self.module = module
         self.module_filename = module_filename
         self.template_filename = template_filename
@@ -232,31 +312,48 @@ class ModuleInfo(object):
         self._modules[module.__name__] = template._mmarker = self
         if module_filename:
             self._modules[module_filename] = self
-    def _get_code(self):
+    
+    @property
+    def code(self):
         if self.module_source is not None:
             return self.module_source
         else:
             return file(self.module_filename).read()
-    code = property(_get_code)
-    def _get_source(self):
+    
+    @property
+    def source(self):
         if self.template_source is not None:
-            if self.module._source_encoding and not isinstance(self.template_source, unicode):
-                return self.template_source.decode(self.module._source_encoding)
+            if self.module._source_encoding and \
+                    not isinstance(self.template_source, unicode):
+                return self.template_source.decode(
+                                self.module._source_encoding)
             else:
                 return self.template_source
         else:
             if self.module._source_encoding:
-                return file(self.template_filename).read().decode(self.module._source_encoding)
+                return file(self.template_filename).read().\
+                                decode(self.module._source_encoding)
             else:
                 return file(self.template_filename).read()
-    source = property(_get_source)
         
 def _compile_text(template, text, filename):
     identifier = template.module_id
-    lexer = Lexer(text, filename, disable_unicode=template.disable_unicode, input_encoding=template.input_encoding, preprocessor=template.preprocessor)
+    lexer = Lexer(text, 
+                    filename, 
+                    disable_unicode=template.disable_unicode,
+                    input_encoding=template.input_encoding,
+                    preprocessor=template.preprocessor)
     node = lexer.parse()
-    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, buffer_filters=template.buffer_filters, imports=template.imports, source_encoding=lexer.encoding, generate_unicode=not template.disable_unicode)
-    #print source
+    
+    source = codegen.compile(node, 
+                            template.uri, 
+                            filename,
+                            default_filters=template.default_filters,
+                            buffer_filters=template.buffer_filters, 
+                            imports=template.imports, 
+                            source_encoding=lexer.encoding,
+                            generate_unicode=not template.disable_unicode)
+
     cid = identifier
     if isinstance(cid, unicode):
         cid = cid.encode()
@@ -267,9 +364,21 @@ def _compile_text(template, text, filename):
 
 def _compile_module_file(template, text, filename, outputpath):
     identifier = template.module_id
-    lexer = Lexer(text, filename, disable_unicode=template.disable_unicode, input_encoding=template.input_encoding, preprocessor=template.preprocessor)
+    lexer = Lexer(text, 
+                    filename, 
+                    disable_unicode=template.disable_unicode,
+                    input_encoding=template.input_encoding,
+                    preprocessor=template.preprocessor)
+                    
     node = lexer.parse()
-    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, buffer_filters=template.buffer_filters, imports=template.imports, source_encoding=lexer.encoding, generate_unicode=not template.disable_unicode)
+    source = codegen.compile(node, 
+                                template.uri, 
+                                filename,
+                                default_filters=template.default_filters,
+                                buffer_filters=template.buffer_filters,
+                                imports=template.imports,
+                                source_encoding=lexer.encoding,
+                                generate_unicode=not template.disable_unicode)
     (dest, name) = tempfile.mkstemp()
     os.write(dest, source)
     os.close(dest)
diff --git a/lib/mako/util.py b/lib/mako/util.py
index ed308f6..1f9f3d4 100644
--- a/lib/mako/util.py
+++ b/lib/mako/util.py
@@ -1,5 +1,5 @@
 # util.py
-# Copyright (C) 2006, 2007, 2008, 2009 Michael Bayer mike_mp@zzzcomputing.com
+# Copyright (C) 2006, 2007, 2008, 2009, 2010 Michael Bayer mike_mp@zzzcomputing.com
 #
 # This module is part of Mako and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -43,6 +43,14 @@ def verify_directory(dir):
             if tries > 5:
                 raise
 
+def to_list(x, default=None):
+    if x is None:
+        return default
+    if not isinstance(x, (list, tuple)):
+        return [x]
+    else:
+        return x
+
 class SetLikeDict(dict):
     """a dictionary that has some setlike methods on it"""
     def union(self, other):
-- 
GitLab