diff --git a/CHANGES b/CHANGES
index 53727dc74757ac3e6a4986e4614f4af957188114..5403c806b7b9bd315ed805b43e30c97f4cb1f931 100644
--- a/CHANGES
+++ b/CHANGES
@@ -8,6 +8,14 @@ file
 (takes filename, uri arguments).  used for [ticket:14]
 - added optional input_encoding flag to Template, to allow sending a unicode() object with no
 magic encoding comment
+- "expression_filter" argument in <%page> applies only to expressions
+- added "default_filters" argument to Template, TemplateLookup.  applies only to expressions,
+gets prepended to "expression_filter" arg from <%page>.  defaults to ["unicode"], so that 
+all expressions get stringified into u'' by default (this is what Mako already does).
+By setting to [], expressions are passed through raw.
+- added "imports" argument to Template, TemplateLookup.  so you can predefine a list of
+import statements at the top of the template.  can be used in conjunction with 
+default_filters.
 
 0.1.1
 - buffet plugin supports string-based templates, allows ToscaWidgets to work [ticket:8]
diff --git a/lib/mako/codegen.py b/lib/mako/codegen.py
index 95e1ba2eb26bd1070ff8f40968cb9ed225028c3d..ba83f1baf711e22e3c1ce43a443cd4f5baa269cb 100644
--- a/lib/mako/codegen.py
+++ b/lib/mako/codegen.py
@@ -14,17 +14,19 @@ from mako import util, ast, parsetree, filters
 MAGIC_NUMBER = 1
 
 
-def compile(node, uri, filename=None):
+def compile(node, uri, filename=None, default_filters=None, imports=None):
     """generate module source code given a parsetree node, uri, and optional source filename"""
     buf = util.FastEncodingBuffer()
     printer = PythonPrinter(buf)
-    _GenerateRenderMethod(printer, _CompileContext(uri, filename), node)
+    _GenerateRenderMethod(printer, _CompileContext(uri, filename, default_filters, imports), node)
     return buf.getvalue()
 
 class _CompileContext(object):
-    def __init__(self, uri, filename):
+    def __init__(self, uri, filename, default_filters, imports):
         self.uri = uri
         self.filename = filename
+        self.default_filters = default_filters
+        self.imports = imports
         
 class _GenerateRenderMethod(object):
     """a template visitor object which generates the full module source for a template."""
@@ -113,10 +115,21 @@ class _GenerateRenderMethod(object):
         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)")
+        if self.compiler.imports:
+            buf = ''
+            for imp in self.compiler.imports:
+                buf += imp + "\n"
+                self.printer.writeline(imp)
+            impcode = ast.PythonCode(buf, 0, 0, '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"]]
+        if impcode:
+            [module_identifiers.declared.add(x) for x in 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.write("\n\n")
@@ -331,7 +344,7 @@ class _GenerateRenderMethod(object):
             self.printer.writeline("_buf = context.pop_buffer()")
             s = "_buf.getvalue()"
             if filtered:
-                s = self.create_filter_callable(node.filter_args.args, s)
+                s = self.create_filter_callable(node.filter_args.args, s, False)
             self.printer.writeline(None)
             if buffered or cached:
                 self.printer.writeline("return %s" % s)
@@ -376,13 +389,15 @@ class _GenerateRenderMethod(object):
                 None
             )
 
-    def create_filter_callable(self, args, target):
+    def create_filter_callable(self, args, target, is_expression):
         """write a filter-applying expression based on the filters present in the given 
         filter names, adjusting for the global 'default' filter aliases as needed."""
-        d = dict([(k, "filters." + v.func_name) for k, v in filters.DEFAULT_ESCAPES.iteritems()])
+        d = dict([(k, (v is unicode and 'unicode' or "filters." + v.func_name)) for k, v in filters.DEFAULT_ESCAPES.iteritems()])
         
-        if self.compiler.pagetag:
-            args += self.compiler.pagetag.filter_args.args
+        if is_expression and self.compiler.pagetag:
+            args = self.compiler.pagetag.filter_args.args + args
+        if is_expression and self.compiler.default_filters:
+            args = self.compiler.default_filters + args
         for e in args:
             # if filter given as a function, get just the identifier portion
             m = re.match(r'(.+?)(\(.*\))', e)
@@ -397,11 +412,11 @@ class _GenerateRenderMethod(object):
         
     def visitExpression(self, node):
         self.write_source_comment(node)
-        if len(node.escapes) or (self.compiler.pagetag is not None and len(self.compiler.pagetag.filter_args.args)):
-            s = self.create_filter_callable(node.escapes_code.args, "unicode(%s)" % node.text)
+        if len(node.escapes) or (self.compiler.pagetag is not None and len(self.compiler.pagetag.filter_args.args)) or len(self.compiler.default_filters):
+            s = self.create_filter_callable(node.escapes_code.args, "%s" % node.text, True)
             self.printer.writeline("context.write(%s)" % s)
         else:
-            self.printer.writeline("context.write(unicode(%s))" % node.text)
+            self.printer.writeline("context.write(%s)" % node.text)
             
     def visitControlLine(self, node):
         if node.isend:
@@ -425,7 +440,7 @@ class _GenerateRenderMethod(object):
             self.printer.writelines(
                 "finally:",
                 "_buf = context.pop_buffer()",
-                "context.write(%s)" % self.create_filter_callable(node.filter_args.args, "_buf.getvalue()"),
+                "context.write(%s)" % self.create_filter_callable(node.filter_args.args, "_buf.getvalue()", False),
                 None
                 )
         
diff --git a/lib/mako/filters.py b/lib/mako/filters.py
index 5e35e340b7eeb68030d0b5a4c9f7b027a0931cfb..5d782eefb247f0fedd062ce87b45bf649a53a2be 100644
--- a/lib/mako/filters.py
+++ b/lib/mako/filters.py
@@ -147,6 +147,7 @@ DEFAULT_ESCAPES = {
     'u':url_escape,
     'trim':trim,
     'entity':html_entities_escape,
+    'unicode':unicode
 }
     
 
diff --git a/lib/mako/lookup.py b/lib/mako/lookup.py
index 1c910cfe0af0e90d4db7bf7d7aabed120f488119..0f6730a82bf08b288305ef3d617a6468f3fb445d 100644
--- a/lib/mako/lookup.py
+++ b/lib/mako/lookup.py
@@ -37,7 +37,7 @@ class TemplateCollection(object):
         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, output_encoding=None, cache_type=None, cache_dir=None, modulename_callable=None):
+    def __init__(self, directories=None, module_directory=None, filesystem_checks=True, collection_size=-1, format_exceptions=False, error_handler=None, output_encoding=None, cache_type=None, cache_dir=None, modulename_callable=None, default_filters=['unicode'], imports=None):
         if isinstance(directories, basestring):
             directories = [directories]        
         self.directories = [posixpath.normpath(d) for d in directories or []]
@@ -45,7 +45,7 @@ class TemplateLookup(TemplateCollection):
         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, 'output_encoding':output_encoding, 'module_directory':module_directory, 'cache_type':cache_type, 'cache_dir':cache_dir or module_directory}
+        self.template_args = {'format_exceptions':format_exceptions, 'error_handler':error_handler, 'output_encoding':output_encoding, 'module_directory':module_directory, 'cache_type':cache_type, 'cache_dir':cache_dir or module_directory, 'default_filters':default_filters, 'imports':imports}
         if collection_size == -1:
             self.__collection = {}
             self._uri_cache = {}
diff --git a/lib/mako/template.py b/lib/mako/template.py
index a3c4ea4d064c1b23e9dfcb84729c5db7f857e538..40a0872d4835d956b55ed7d687be50cc12c2f327 100644
--- a/lib/mako/template.py
+++ b/lib/mako/template.py
@@ -16,7 +16,7 @@ import imp, time, weakref, tempfile, shutil,  os, stat, sys, re
     
 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, module_directory=None, cache_type=None, cache_dir=None, module_filename=None, input_encoding=None):
+    def __init__(self, text=None, filename=None, uri=None, format_exceptions=False, error_handler=None, lookup=None, output_encoding=None, module_directory=None, cache_type=None, cache_dir=None, module_filename=None, input_encoding=None, default_filters=['unicode'], imports=None):
         """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
@@ -38,9 +38,13 @@ class Template(object):
             self.module_id = "memory:" + hex(id(self))
             self.uri = self.module_id
         
+        self.default_filters = default_filters
+        self.input_encoding = input_encoding
+        self.imports = imports
+        
         # if plain text, compile code in memory only
         if text is not None:
-            (code, module) = _compile_text(text, self.module_id, filename, self.uri, input_encoding)
+            (code, module) = _compile_text(self, text, filename)
             self._code = code
             self._source = text
             ModuleInfo(module, None, self, filename, code, text)
@@ -60,18 +64,18 @@ class Template(object):
                 util.verify_directory(os.path.dirname(path))
                 filemtime = os.stat(filename)[stat.ST_MTIME]
                 if not os.access(path, os.F_OK) or os.stat(path)[stat.ST_MTIME] < filemtime:
-                    _compile_module_file(file(filename).read(), self.module_id, filename, path, self.uri, input_encoding)
+                    _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(file(filename).read(), self.module_id, filename, path, self.uri, input_encoding)
+                    _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(file(filename).read(), self.module_id, filename, self.uri, input_encoding)
+                (code, module) = _compile_text(self, file(filename).read(), filename)
                 self._source = None
                 self._code = code
                 ModuleInfo(module, None, self, filename, code, None)
@@ -153,19 +157,21 @@ class ModuleInfo(object):
             return file(self.template_filename).read()
     source = property(_get_source)
         
-def _compile_text(text, identifier, filename, uri, input_encoding):
-    node = Lexer(text, filename, input_encoding=input_encoding).parse()
-    source = codegen.compile(node, uri, filename)
+def _compile_text(template, text, filename):
+    identifier = template.module_id
+    node = Lexer(text, filename, input_encoding=template.input_encoding).parse()
+    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, imports=template.imports)
     cid = identifier
     module = imp.new_module(cid)
     code = compile(source, cid, 'exec')
     exec code in module.__dict__, module.__dict__
     return (source, module)
 
-def _compile_module_file(text, identifier, filename, outputpath, uri, input_encoding):
+def _compile_module_file(template, text, filename, outputpath):
+    identifier = template.module_id
     (dest, name) = tempfile.mkstemp()
-    node = Lexer(text, filename, input_encoding=input_encoding).parse()
-    source = codegen.compile(node, uri, filename)
+    node = Lexer(text, filename, input_encoding=template.input_encoding).parse()
+    source = codegen.compile(node, template.uri, filename, default_filters=template.default_filters, imports=template.imports)
     os.write(dest, source)
     os.close(dest)
     shutil.move(name, outputpath)
diff --git a/test/filters.py b/test/filters.py
index 8033ee4d78404965233aaa0be294aaa6ebaff515..d9ecb254c603f0e6c6d2f490babaf0f002dddc3b 100644
--- a/test/filters.py
+++ b/test/filters.py
@@ -46,6 +46,24 @@ class FilterTest(unittest.TestCase):
 
         assert t.render().strip()=="trim this string: some string to trim continue"
     
+    def test_import_2(self):
+        t = Template("""
+        trim this string: ${"  some string to trim   " | filters.trim} continue\
+        """, imports=["from mako import filters"])
+        print t.code
+        assert t.render().strip()=="trim this string: some string to trim continue"
+
+    def test_custom_default(self):
+        t = Template("""
+        <%!
+            def myfilter(x):
+                return "->" + x + "<-"
+        %>
+        
+            hi ${'there'}
+        """, default_filters=['myfilter'])
+        assert t.render().strip()=="hi ->there<-"
+        
     def test_global(self):
         t = Template("""
             <%page expression_filter="h"/>
diff --git a/test/template.py b/test/template.py
index aca42ed3ce6058870e5c0442d9ed631b7c39d9d8..88f61e384aac3034288d1242a85b78d753f3bd21 100644
--- a/test/template.py
+++ b/test/template.py
@@ -67,7 +67,15 @@ class EncodingTest(unittest.TestCase):
         res = Template(s2).render_unicode(f=lambda x:x)
         assert res == u"hello śląsk"
 
-            
+    def test_raw_strings(self):
+        """test that raw strings go straight thru with default_filters turned off"""
+        g = 'śląsk'
+        s = u"# -*- coding: utf-8 -*-\nhello ${x}"
+        t = Template(s, default_filters=[])
+        y = t.render(x=g)
+        print t.code
+        assert y == "hello śląsk"
+        
     def test_encoding(self):
         val = u"""Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petit voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »"""
         template = Template(val, output_encoding='utf-8')
@@ -101,7 +109,7 @@ class PageArgsTest(unittest.TestCase):
 
             this is page, ${x}, ${y}, ${z}, ${w}
 """)
-
+        print template.code
         assert flatten_result(template.render(x=5, y=10, w=17)) == "this is page, 5, 10, 7, 17"
 
     def test_overrides_builtins(self):