aboutsummaryrefslogtreecommitdiffstats
path: root/test/test_template.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-02-05 21:32:07 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2010-02-05 21:32:07 +0000
commitd190169d0b0059b312ba9adad7011ecdff177188 (patch)
tree352d6cf60e4798fb68ee8146323ea2c1ff61e5be /test/test_template.py
parent9354a7e5e9ec515e6884464edef73302d7aa93ac (diff)
downloadexternal_python_mako-d190169d0b0059b312ba9adad7011ecdff177188.tar.gz
external_python_mako-d190169d0b0059b312ba9adad7011ecdff177188.tar.bz2
external_python_mako-d190169d0b0059b312ba9adad7011ecdff177188.zip
- Unit tests now run with nose. [ticket:127]
Diffstat (limited to 'test/test_template.py')
-rw-r--r--test/test_template.py479
1 files changed, 479 insertions, 0 deletions
diff --git a/test/test_template.py b/test/test_template.py
new file mode 100644
index 0000000..a5755d0
--- /dev/null
+++ b/test/test_template.py
@@ -0,0 +1,479 @@
+# -*- coding: utf-8 -*-
+
+from mako.template import Template, ModuleTemplate
+from mako.lookup import TemplateLookup
+from mako.ext.preprocessors import convert_comments
+from mako import exceptions
+import unittest, re, os
+from util import flatten_result, result_lines
+import codecs
+
+if not os.access('./test_htdocs', os.F_OK):
+ os.mkdir('./test_htdocs')
+if not os.access('./test_htdocs/subdir', os.F_OK):
+ os.mkdir('./test_htdocs/subdir')
+file('./test_htdocs/unicode.html', 'w').write("""## -*- coding: utf-8 -*-
+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! »""")
+file('./test_htdocs/unicode_syntax_error.html', 'w').write("""## -*- coding: utf-8 -*-
+<% print '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! » %>""")
+file('./test_htdocs/unicode_runtime_error.html', 'w').write("""## -*- coding: utf-8 -*-
+<% print '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! »' + int(5/0) %>""")
+
+file('./test_htdocs/bommagic.html', 'w').write(codecs.BOM_UTF8 + """## -*- coding: utf-8 -*-
+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! »""")
+file('./test_htdocs/badbom.html', 'w').write(codecs.BOM_UTF8 + """## -*- coding: ascii -*-
+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! »""")
+file('./test_htdocs/bom.html', 'w').write(codecs.BOM_UTF8 + """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! »""")
+
+class EncodingTest(unittest.TestCase):
+ def test_unicode(self):
+ template = Template(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! »""")
+ assert template.render_unicode() == 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! »"""
+
+ def test_encoding_doesnt_conflict(self):
+ template = Template(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! »""", output_encoding='utf-8')
+ assert template.render_unicode() == 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! »"""
+
+ def test_unicode_arg(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}")
+ assert template.render_unicode(val=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! »"""
+
+ def test_unicode_file(self):
+ template = Template(filename='./test_htdocs/unicode.html', module_directory='./test_htdocs')
+ assert template.render_unicode() == 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! »"""
+
+ def test_unicode_file_lookup(self):
+ lookup = TemplateLookup(directories=['./test_htdocs'], output_encoding='utf-8', default_filters=['decode.utf8'])
+ template = lookup.get_template('/chs_unicode.html')
+ assert flatten_result(template.render(name='毛泽东')) == '毛泽东 是 新中国的主席<br/> Welcome 你 to 北京.'
+
+ def test_unicode_bom(self):
+ template = Template(filename='./test_htdocs/bom.html', module_directory='./test_htdocs')
+ assert template.render_unicode() == 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(filename='./test_htdocs/bommagic.html', module_directory='./test_htdocs')
+ assert template.render_unicode() == 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! »"""
+
+ try:
+ template = Template(filename='./test_htdocs/badbom.html', module_directory='./test_htdocs')
+ assert False
+ except exceptions.CompileException:
+ assert True
+
+ def test_unicode_memory(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! »"""
+ val = "## coding: utf-8\n" + val.encode('utf-8')
+ template = Template(val)
+ assert isinstance(template.code, unicode)
+ assert template.render_unicode() == 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! »"""
+
+ def test_unicode_text(self):
+ val = u"""<%text>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! »</%text>"""
+ val = "## -*- coding: utf-8 -*-\n" + val.encode('utf-8')
+ template = Template(val)
+ #print template.code
+ assert template.render_unicode() == 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! »"""
+
+ def test_unicode_text_ccall(self):
+ val = u"""
+ <%def name="foo()">
+ ${capture(caller.body)}
+ </%def>
+ <%call expr="foo()">
+ <%text>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! »</%text>
+ </%call>"""
+ val = "## -*- coding: utf-8 -*-\n" + val.encode('utf-8')
+ template = Template(val)
+ #print template.code
+ assert flatten_result(template.render_unicode()) == 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! »"""
+
+ def test_unicode_literal_in_expr(self):
+ template = Template(u"""## -*- coding: utf-8 -*-
+ ${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! »"}
+ """.encode('utf-8'))
+ assert template.render_unicode().strip() == 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! »"""
+
+ def test_unicode_literal_in_code(self):
+ template = Template(u"""## -*- coding: utf-8 -*-
+ <%
+ context.write(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! »")
+ %>
+ """.encode('utf-8'))
+ assert template.render_unicode().strip() == 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! »"""
+
+ def test_unicode_literal_in_controlline(self):
+ template = Template(u"""## -*- coding: utf-8 -*-
+ <%
+ x = u"drôle de petit voix m’a réveillé."
+ %>
+ % if x==u"drôle de petit voix m’a réveillé.":
+ hi, ${x}
+ % endif
+ """.encode('utf-8'))
+ assert template.render_unicode().strip() == u"""hi, drôle de petit voix m’a réveillé."""
+
+ def test_unicode_literal_in_def(self):
+ template = Template(u"""## -*- coding: utf-8 -*-
+ <%def name="bello(foo, bar)">
+ Foo: ${ foo }
+ Bar: ${ bar }
+ </%def>
+ <%call expr="bello(foo=u'árvíztűrő tükörfúrógép', bar=u'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')">
+ </%call>""".encode('utf-8'))
+ assert flatten_result(template.render_unicode()) == u"""Foo: árvíztűrő tükörfúrógép Bar: ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP"""
+
+ template = Template(u"""## -*- coding: utf-8 -*-
+ <%def name="hello(foo=u'árvíztűrő tükörfúrógép', bar=u'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')">
+ Foo: ${ foo }
+ Bar: ${ bar }
+ </%def>
+ ${ hello() }""".encode('utf-8'))
+ assert flatten_result(template.render_unicode()) == u"""Foo: árvíztűrő tükörfúrógép Bar: ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP"""
+
+ def test_input_encoding(self):
+ """test the 'input_encoding' flag on Template, and that unicode objects arent double-decoded"""
+ s2 = u"hello ${f(u'śląsk')}"
+ res = Template(s2, input_encoding='utf-8').render_unicode(f=lambda x:x)
+ assert res == u"hello śląsk"
+
+ s2 = u"## -*- coding: utf-8 -*-\nhello ${f(u'śląsk')}"
+ 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)
+ assert y == "hello śląsk"
+
+ # now, the way you *should* be doing it....
+ q = g.decode('utf-8')
+ y = t.render_unicode(x=q)
+ assert y == u"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')
+ assert template.render() == val.encode('utf-8')
+
+ def test_encoding_errors(self):
+ val = u"""KGB (transliteration of "КГБ") is the Russian-language abbreviation for Committee for State Security, (Russian: Комит́ет Госуд́арственной Безоп́асности (help·info); Komitet Gosudarstvennoy Bezopasnosti)"""
+ template = Template(val, output_encoding='iso-8859-1', encoding_errors='replace')
+ assert template.render() == val.encode('iso-8859-1', 'replace')
+
+ def test_read_unicode(self):
+ lookup = TemplateLookup(directories=['./test_htdocs'], filesystem_checks=True, output_encoding='utf-8')
+ template = lookup.get_template('/read_unicode.html')
+ data = template.render(path=os.path.join('./test_htdocs', 'internationalization.html'))
+
+ def test_bytestring_passthru(self):
+ lookup = TemplateLookup(directories=['./test_htdocs'], default_filters=[], disable_unicode=True)
+ template = lookup.get_template('/chs_utf8.html')
+ self.assertEquals(flatten_result(template.render(name='毛泽东')), '毛泽东 是 新中国的主席<br/> Welcome 你 to 北京. Welcome 你 to 北京.')
+
+ lookup = TemplateLookup(directories=['./test_htdocs'], disable_unicode=True)
+ template = lookup.get_template('/chs_utf8.html')
+ self.assertEquals(flatten_result(template.render(name='毛泽东')), '毛泽东 是 新中国的主席<br/> Welcome 你 to 北京. Welcome 你 to 北京.')
+
+ self.assertRaises(UnicodeDecodeError, template.render_unicode, name='毛泽东')
+
+ template = Template("""${'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! »'}""", disable_unicode=True, input_encoding='utf-8')
+ assert template.render() == """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("""${'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! »'}""", input_encoding='utf8', output_encoding='utf8', disable_unicode=False, default_filters=[])
+ self.assertRaises(UnicodeDecodeError, template.render) # raises because expression contains an encoded bytestring which cannot be decoded
+
+
+class PageArgsTest(unittest.TestCase):
+ def test_basic(self):
+ template = Template("""
+ <%page args="x, y, z=7"/>
+
+ this is page, ${x}, ${y}, ${z}
+""")
+
+ assert flatten_result(template.render(x=5, y=10)) == "this is page, 5, 10, 7"
+ assert flatten_result(template.render(x=5, y=10, z=32)) == "this is page, 5, 10, 32"
+ try:
+ template.render(y=10)
+ assert False
+ except TypeError, e:
+ assert True
+
+ def test_with_context(self):
+ template = Template("""
+ <%page args="x, y, z=7"/>
+
+ 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):
+ template = Template("""
+ <%page args="id"/>
+
+ this is page, id is ${id}
+ """)
+
+ assert flatten_result(template.render(id="im the id")) == "this is page, id is im the id"
+
+ def test_canuse_builtin_names(self):
+ template = Template("""
+ exception: ${Exception}
+ id: ${id}
+ """)
+ assert flatten_result(template.render(id='some id', Exception='some exception')) == "exception: some exception id: some id"
+
+ def test_builtin_names_dont_clobber_defaults_in_includes(self):
+ lookup = TemplateLookup()
+ lookup.put_string("test.mako",
+ """
+ <%include file="test1.mako"/>
+
+ """)
+
+ lookup.put_string("test1.mako", """
+ <%page args="id='foo'"/>
+
+ ${id}
+ """)
+
+ for template in ("test.mako", "test1.mako"):
+ assert flatten_result(lookup.get_template(template).render()) == "foo"
+ assert flatten_result(lookup.get_template(template).render(id=5)) == "5"
+ assert flatten_result(lookup.get_template(template).render(id=id)) == "<built-in function id>"
+
+ def test_dict_locals(self):
+ template = Template("""
+ <%
+ dict = "this is dict"
+ locals = "this is locals"
+ %>
+ dict: ${dict}
+ locals: ${locals}
+ """)
+ assert flatten_result(template.render()) == "dict: this is dict locals: this is locals"
+
+class IncludeTest(unittest.TestCase):
+ def test_basic(self):
+ lookup = TemplateLookup()
+ lookup.put_string("a", """
+ this is a
+ <%include file="b" args="a=3,b=4,c=5"/>
+ """)
+ lookup.put_string("b", """
+ <%page args="a,b,c"/>
+ this is b. ${a}, ${b}, ${c}
+ """)
+ assert flatten_result(lookup.get_template("a").render()) == "this is a this is b. 3, 4, 5"
+
+ def test_localargs(self):
+ lookup = TemplateLookup()
+ lookup.put_string("a", """
+ this is a
+ <%include file="b" args="a=a,b=b,c=5"/>
+ """)
+ lookup.put_string("b", """
+ <%page args="a,b,c"/>
+ this is b. ${a}, ${b}, ${c}
+ """)
+ assert flatten_result(lookup.get_template("a").render(a=7,b=8)) == "this is a this is b. 7, 8, 5"
+
+ def test_viakwargs(self):
+ lookup = TemplateLookup()
+ lookup.put_string("a", """
+ this is a
+ <%include file="b" args="c=5, **context.kwargs"/>
+ """)
+ lookup.put_string("b", """
+ <%page args="a,b,c"/>
+ this is b. ${a}, ${b}, ${c}
+ """)
+ #print lookup.get_template("a").code
+ assert flatten_result(lookup.get_template("a").render(a=7,b=8)) == "this is a this is b. 7, 8, 5"
+
+ def test_include_withargs(self):
+ lookup = TemplateLookup()
+ lookup.put_string("a", """
+ this is a
+ <%include file="${i}" args="c=5, **context.kwargs"/>
+ """)
+ lookup.put_string("b", """
+ <%page args="a,b,c"/>
+ this is b. ${a}, ${b}, ${c}
+ """)
+ assert flatten_result(lookup.get_template("a").render(a=7,b=8,i='b')) == "this is a this is b. 7, 8, 5"
+
+ def test_within_ccall(self):
+ lookup = TemplateLookup()
+ lookup.put_string("a", """this is a""")
+ lookup.put_string("b", """
+ <%def name="bar()">
+ bar: ${caller.body()}
+ <%include file="a"/>
+ </%def>
+ """)
+ lookup.put_string("c", """
+ <%namespace name="b" file="b"/>
+ <%b:bar>
+ calling bar
+ </%b:bar>
+ """)
+ assert flatten_result(lookup.get_template("c").render()) == "bar: calling bar this is a"
+
+class ControlTest(unittest.TestCase):
+ def test_control(self):
+ t = Template("""
+ ## this is a template.
+ % for x in y:
+ % if x.has_key('test'):
+ yes x has test
+ % else:
+ no x does not have test
+ %endif
+ %endfor
+""")
+ assert result_lines(t.render(y=[{'test':'one'}, {'foo':'bar'}, {'foo':'bar', 'test':'two'}])) == [
+ "yes x has test",
+ "no x does not have test",
+ "yes x has test"
+ ]
+
+ def test_multiline_control(self):
+ t = Template("""
+ % for x in \\
+ [y for y in [1,2,3]]:
+ ${x}
+ % endfor
+""")
+ #print t.code
+ assert flatten_result(t.render()) == "1 2 3"
+
+class GlobalsTest(unittest.TestCase):
+ def test_globals(self):
+ t= Template("""
+ <%!
+ y = "hi"
+ %>
+ y is ${y}
+""")
+ assert t.render().strip() == "y is hi"
+
+class RichTracebackTest(unittest.TestCase):
+ def _do_test_traceback(self, utf8, memory, syntax):
+ if memory:
+ if syntax:
+ source = u'## coding: utf-8\n<% print "m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! » %>'
+ else:
+ source = u'## coding: utf-8\n<% print u"m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »" + str(5/0) %>'
+ if utf8:
+ source = source.encode('utf-8')
+ else:
+ source = source
+ templateargs = {'text':source}
+ else:
+ if syntax:
+ filename = './test_htdocs/unicode_syntax_error.html'
+ else:
+ filename = './test_htdocs/unicode_runtime_error.html'
+ source = file(filename).read()
+ if not utf8:
+ source = source.decode('utf-8')
+ templateargs = {'filename':filename}
+ try:
+ template = Template(**templateargs)
+ if not syntax:
+ template.render_unicode()
+ assert False
+ except Exception, e:
+ tback = exceptions.RichTraceback()
+ if utf8:
+ assert tback.source == source.decode('utf-8')
+ else:
+ assert tback.source == source
+
+for utf8 in (True, False):
+ for memory in (True, False):
+ for syntax in (True, False):
+ def _do_test(self):
+ self._do_test_traceback(utf8, memory, syntax)
+ name = 'test_%s_%s_%s' % (utf8 and 'utf8' or 'unicode', memory and 'memory' or 'file', syntax and 'syntax' or 'runtime')
+ try:
+ _do_test.__name__ = name
+ except:
+ pass
+ setattr(RichTracebackTest, name, _do_test)
+ del _do_test
+
+
+class ModuleDirTest(unittest.TestCase):
+ def test_basic(self):
+ file('./test_htdocs/modtest.html', 'w').write("""this is a test""")
+ file('./test_htdocs/subdir/modtest.html', 'w').write("""this is a test""")
+ t = Template(filename='./test_htdocs/modtest.html', module_directory='./test_htdocs/modules')
+ t2 = Template(filename='./test_htdocs/subdir/modtest.html', module_directory='./test_htdocs/modules')
+ assert t.module.__file__ == os.path.abspath('./test_htdocs/modules/test_htdocs/modtest.html.py')
+ assert t2.module.__file__ == os.path.abspath('./test_htdocs/modules/test_htdocs/subdir/modtest.html.py')
+ def test_callable(self):
+ file('./test_htdocs/modtest.html', 'w').write("""this is a test""")
+ file('./test_htdocs/subdir/modtest.html', 'w').write("""this is a test""")
+ def get_modname(filename, uri):
+ return os.path.dirname(filename) + "/foo/" + os.path.basename(filename) + ".py"
+ lookup = TemplateLookup('./test_htdocs', modulename_callable=get_modname)
+ t = lookup.get_template('/modtest.html')
+ t2 = lookup.get_template('/subdir/modtest.html')
+ assert t.module.__file__ == 'test_htdocs/foo/modtest.html.py'
+ assert t2.module.__file__ == 'test_htdocs/subdir/foo/modtest.html.py'
+
+class ModuleTemplateTest(unittest.TestCase):
+ def test_module_roundtrip(self):
+ lookup = TemplateLookup()
+
+ template = Template("""
+ <%inherit file="base.html"/>
+
+ % for x in range(5):
+ ${x}
+ % endfor
+""", lookup=lookup)
+
+ base = Template("""
+ This is base.
+ ${self.body()}
+""", lookup=lookup)
+
+ lookup.put_template("base.html", base)
+ lookup.put_template("template.html", template)
+
+ assert result_lines(template.render()) == [
+ "This is base.", "0", "1", "2", "3", "4"
+ ]
+
+ lookup = TemplateLookup()
+ template = ModuleTemplate(template.module, lookup=lookup)
+ base = ModuleTemplate(base.module, lookup=lookup)
+
+ lookup.put_template("base.html", base)
+ lookup.put_template("template.html", template)
+
+ assert result_lines(template.render()) == [
+ "This is base.", "0", "1", "2", "3", "4"
+ ]
+
+
+class PreprocessTest(unittest.TestCase):
+ def test_old_comments(self):
+ t = Template("""
+ im a template
+# old style comment
+ # more old style comment
+
+ ## new style comment
+ - # not a comment
+ - ## not a comment
+""", preprocessor=convert_comments)
+
+ assert flatten_result(t.render()) == "im a template - # not a comment - ## not a comment"