- 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' )