- the "ascii encoding by default" approach doesn't work in Py3K,
because a string and an ascii encoded string are of course
different things, and we'd like render() by default to return a
string.   So go the other way, use FEB in all cases,
 add a new flag bytestring_passthrough which goes back to StringIO,
to support that one guy who wanted to force a bytestring through
in an expression.
diff --git a/CHANGES b/CHANGES
index e74bb62..bde5841 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,20 +1,37 @@
 0.4.0
-- The "output encoding" now defaults
-  to "ascii", whereas previously
-  it was set to None.  This has the effect
-  of FastEncodingBuffer being used internally
-  by default when render() is called, instead 
-  of cStringIO or StringIO, which are 
-  slower, but allow bytestrings with 
-  unknown encoding to pass right through.  
-  It is of course not recommended to use 
-  bytestrings of unknown encoding. Usage of
-  the "disable_unicode" mode also requires
-  that output_encoding be set to None.
+- A 20% speedup for a basic two-page 
+  inheritance setup rendering
+  a table of escaped data
+  (see http://techspot.zzzeek.org/2010/11/19/quick-mako-vs.-jinja-speed-test/).
+  A few configurational changes which
+  affect those in the I-don't-do-unicode 
+  camp should be noted below.
+
+- The FastEncodingBuffer is now used
+  by default instead of cStringIO or StringIO,
+  regardless of whether output_encoding
+  is set to None or not.  FEB is faster than
+  both.  Only StringIO allows bytestrings
+  of unknown encoding to pass right 
+  through, however - while it is of course 
+  not recommended to send bytestrings of unknown 
+  encoding to the output stream, this
+  mode of usage can be re-enabled by
+  setting the flag bytestring_passthrough
+  to True.
+
+- disable_unicode mode requires that 
+  output_encoding be set to None - it also
+  forces the bytestring_passthrough flag
+  to True.
 
 - the <%namespace> tag raises an error
   if the 'template' and 'module' attributes
-  are specified at the same time.
+  are specified at the same time in 
+  one tag.  A different class is used 
+  for each case which allows a reduction in 
+  runtime conditional logic and function
+  call overhead. [ticket:156]
 
 - the keys() in the Context, as well as 
   it's internal _data dictionary, now
@@ -22,6 +39,8 @@
   render() as well as Mako builtins
   'caller', 'capture'.  The contents
   of __builtin__ are no longer copied.
+  Thanks to Daniel Lopez for pointing
+  this out. [ticket:159]
 
 0.3.6
 - Documentation is on Sphinx.
diff --git a/mako/lookup.py b/mako/lookup.py
index 3ca289a..b397d21 100644
--- a/mako/lookup.py
+++ b/mako/lookup.py
@@ -148,7 +148,8 @@
                         format_exceptions=False, 
                         error_handler=None, 
                         disable_unicode=False, 
-                        output_encoding='ascii', 
+                        bytestring_passthrough=False,
+                        output_encoding=None, 
                         encoding_errors='strict', 
                         cache_type=None, 
                         cache_dir=None, cache_url=None,
@@ -173,6 +174,7 @@
             'format_exceptions':format_exceptions, 
             'error_handler':error_handler, 
             'disable_unicode':disable_unicode, 
+            'bytestring_passthrough':bytestring_passthrough,
             'output_encoding':output_encoding, 
             'encoding_errors':encoding_errors, 
             'input_encoding':input_encoding, 
diff --git a/mako/runtime.py b/mako/runtime.py
index f57087f..dfd701a 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -645,13 +645,13 @@
 
     if as_unicode:
         buf = util.FastEncodingBuffer(unicode=True)
-    elif template.output_encoding:
+    elif template.bytestring_passthrough:
+        buf = util.StringIO()
+    else:
         buf = util.FastEncodingBuffer(
                         unicode=as_unicode, 
                         encoding=template.output_encoding, 
                         errors=template.encoding_errors)
-    else:
-        buf = util.StringIO()
     context = Context(buf, **data)
     context._outputting_as_unicode = as_unicode
     context._with_template = template
diff --git a/mako/template.py b/mako/template.py
index 6166895..903dc42 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -38,13 +38,22 @@
      creation of default expression filters that let the output
      of return-valued %defs "opt out" of that filtering via
      passing special attributes or objects.
- 
+
+    :param bytestring_passthrough: When True, and output_encoding is 
+     set to None, and :meth:`.Template.render` is used to render,
+     the StringIO or cStringIO buffer will be used instead of the
+     default "fast" buffer.   This allows raw bytestrings in the
+     output stream, such as in expressions, to pass straight
+     through to the buffer.   New in 0.4 to provide the same
+     behavior as that of the previous series.  This flag is forced
+     to True if disable_unicode is also configured.
+
     :param cache_dir: Filesystem directory where cache files will be
      placed.  See :ref:`caching_toplevel`.
- 
+
     :param cache_enabled: Boolean flag which enables caching of this
      template.  See :ref:`caching_toplevel`.
- 
+
     :param cache_type: Type of Beaker caching to be applied to the 
      template. See :ref:`caching_toplevel`.
  
@@ -96,7 +105,7 @@
      Python module file. For advanced usage only.
  
     :param output_encoding: The encoding to use when :meth:`.render` 
-     is called.  Defaults to ``ascii`` as of Mako 0.4.0.  
+     is called.  
      See :ref:`usage_unicode` as well as :ref:`unicode_toplevel`.
  
     :param preprocessor: Python callable which will be passed 
@@ -127,7 +136,7 @@
                     format_exceptions=False, 
                     error_handler=None, 
                     lookup=None, 
-                    output_encoding='ascii', 
+                    output_encoding=None, 
                     encoding_errors='strict', 
                     module_directory=None, 
                     cache_type=None, 
@@ -135,7 +144,8 @@
                     cache_url=None, 
                     module_filename=None, 
                     input_encoding=None, 
-                    disable_unicode=False, 
+                    disable_unicode=False,
+                    bytestring_passthrough=False, 
                     default_filters=None, 
                     buffer_filters=(), 
                     strict_undefined=False,
@@ -158,6 +168,7 @@
         self.output_encoding = output_encoding
         self.encoding_errors = encoding_errors
         self.disable_unicode = disable_unicode
+        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
         self.strict_undefined = strict_undefined
 
         if util.py3k and disable_unicode:
@@ -348,6 +359,7 @@
                         output_encoding=None, 
                         encoding_errors='strict',
                         disable_unicode=False, 
+                        bytestring_passthrough=False,
                         format_exceptions=False,
                         error_handler=None, 
                         lookup=None, 
@@ -362,6 +374,17 @@
         self.output_encoding = output_encoding
         self.encoding_errors = encoding_errors
         self.disable_unicode = disable_unicode
+        self.bytestring_passthrough = bytestring_passthrough or disable_unicode
+
+        if util.py3k and disable_unicode:
+            raise exceptions.UnsupportedError(
+                                    "Mako for Python 3 does not "
+                                    "support disabling Unicode")
+        elif output_encoding and disable_unicode:
+            raise exceptions.UnsupportedError(
+                                    "output_encoding must be set to "
+                                    "None when disable_unicode is used.")
+
         self.module = module
         self.filename = template_filename
         ModuleInfo(module, 
@@ -393,6 +416,7 @@
         self.format_exceptions = parent.format_exceptions
         self.error_handler = parent.error_handler
         self.lookup = parent.lookup
+        self.bytestring_passthrough = parent.bytestring_passthrough
 
     def get_def(self, name):
         return self.parent.get_def(name)
diff --git a/test/test_template.py b/test/test_template.py
index 2ac4ad3..e8fd6ed 100644
--- a/test/test_template.py
+++ b/test/test_template.py
@@ -283,7 +283,10 @@
             )
 
     def test_raw_strings(self):
-        """test that raw strings go straight thru with default_filters turned off"""
+        """test that raw strings go straight thru with default_filters turned off,
+        bytestring_passthrough enabled.
+        
+        """
 
         self._do_memory_test(
             u"## -*- coding: utf-8 -*-\nhello ${x}",
@@ -291,6 +294,7 @@
             default_filters=[],
             template_args={'x':'śląsk'},
             unicode_=False,
+            bytestring_passthrough=True,
             output_encoding=None #'ascii'
         )