def test_option_tostrfunc(self): input = "<p>Hello #{name}!</p>" if "passed tostrfunc option then use it": globals()['my_str'] = lambda s: s.upper() t = tenjin.Template(None, input=input, tostrfunc='my_str') output = t.render({'name': 'Haruhi'}) ok (output) == "<p>Hello HARUHI!</p>" ok (t.script) == self.lvars.replace('=to_str', '=my_str') + \ "_extend(('''<p>Hello ''', _to_str(name), '''!</p>''', ));" globals().pop('my_str') # t = tenjin.Template(None, input=input, tostrfunc='str') output = t.render({'name': None}) ok (output) == "<p>Hello None!</p>" # t = tenjin.Template(None, input=input, tostrfunc='str.upper') output = t.render({'name': 'sos'}) ok (output) == "<p>Hello SOS!</p>" if "passed False as tostrfunc option then no function is used": t = tenjin.Template(None, input=input, tostrfunc=False) output = t.render({'name': 'Haruhi'}) ok (output) == "<p>Hello Haruhi!</p>" ok (t.script) == self.lvars.replace('=to_str', '=False') + \ "_extend(('''<p>Hello ''', (name), '''!</p>''', ));" # def f(): t.render({'name': 123}) if python2: ok (f).raises(TypeError, 'sequence item 1: expected string, int found') elif python3: ok (f).raises(TypeError, 'sequence item 1: expected str instance, int found') if "passed wrong function name as tostrfunc option then raises error": t = tenjin.Template(None, input=input, tostrfunc='johnsmith') def f(): t.render({'name': 'Haruhi'}) #ok (f).raises(TypeError, "'NoneType' object is not callable") ok (f).raises(NameError, _errmsg("name 'johnsmith' is not defined"))
def test_option_escapefunc(self): input = "<p>Hello ${name}!</p>" if "passed escapefunc option then use it": globals()['my_escape'] = lambda s: s.lower() t = tenjin.Template(None, input=input, escapefunc='my_escape') output = t.render({'name': 'Haruhi'}) ok (output) == "<p>Hello haruhi!</p>" ok (t.script) == self.lvars.replace('=escape', '=my_escape') + \ "_extend(('''<p>Hello ''', _escape(_to_str(name)), '''!</p>''', ));" globals().pop('my_escape') # global cgi import cgi t = tenjin.Template(None, input=input, escapefunc='cgi.escape') output = t.render({'name': '&<>"'}) ok (output) == "<p>Hello &<>\"!</p>" if "passed False as escapefunc option then no function is used": t = tenjin.Template(None, input=input, escapefunc=False) output = t.render({'name': 'Haru&Kyon'}) ok (output) == "<p>Hello Haru&Kyon!</p>" ok (t.script) == self.lvars.replace('=escape', '=False') + \ "_extend(('''<p>Hello ''', _to_str(name), '''!</p>''', ));" if "passed wrong function name as tostrfunc option then raises error": t = tenjin.Template(None, input=input, escapefunc='kyonsmith') def f(): t.render({'name': 'Haruhi'}) #ok (f).raises(TypeError, "'NoneType' object is not callable") ok (f).raises(NameError, _errmsg("name 'kyonsmith' is not defined"))
def test_with_unicode_template_and_binary_data(self): t = tenjin.Template(encoding='utf-8') input = "**あ**\n#{'あ'}\n" script = lvars + u"_extend((u'''**\u3042**\n''', _to_str('\u3042'), u'''\\n''', ));\n" ok (t.convert(input)) == script ## do nothing in to_str() self._test_render( template = t, to_str = tenjin.generate_tostrfunc(encode=None, decode=None), expected_buf = [u'**\u3042**\n', '\xe3\x81\x82', u'\n'], expected_errcls = UnicodeDecodeError, expected_errmsg = "'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)" ) ## encode unicode in binary in to_str() self._test_render( template = t, to_str = tenjin.generate_tostrfunc(encode='utf-8', decode=None), expected_buf = [u'**\u3042**\n', '\xe3\x81\x82', u'\n'], expected_errcls = UnicodeDecodeError, expected_errmsg = "'ascii' codec can't decode byte 0xe3 in position 0: ordinal not in range(128)" ) ## decode binary into unicode in to_str() self._test_render( template = t, to_str = tenjin.generate_tostrfunc(encode=None, decode='utf-8'), expected_buf = [u'**\u3042**\n', u'\u3042', u'\n'], expected_output = u"**あ**\nあ\n" )
def test_filename1(self): input = """<ul> <?py for i in range(0,3): ?> <li>#{i}</li> <?py #endfor ?> </ul> """ filename = 'test_filename1.tenjin' try: write_file(filename, input) template1 = tenjin.Template(filename) template2 = tenjin.Template() ok (template2.convert(input)) == template1.script ok (template2.render()) == template1.render() finally: try: os.remove(filename) except: pass
def test_trace(self): if "trace is on then prints template filename as HTML comments": filename = "test.trace.pyhtml" input = "<p>hello #{name}!</p>\n" expected = ( "<!-- ***** begin: %s ***** -->\n" "<p>hello world!</p>\n" "<!-- ***** end: %s ***** -->\n" ) % (filename, filename) t = tenjin.Template(filename, input=input, trace=True) output = t.render({'name':'world'}) ok (output) == expected
def test_add_template(self): if "template is added then it can be got by get_template()": input = """val=#{val}""" template = tenjin.Template('foo.pyhtml', input=input) engine = tenjin.Engine(postfix='.pyhtml') engine.add_template(template) ok (engine.get_template('foo.pyhtml')) == template ok (engine.get_template(':foo')) == template if "template is added then it should not create cache file": ok (engine.render(':foo', {'val': 'ABC'})) == 'val=ABC' not_ok ('foo.pyhtml').exists()
def _(self): input = """ <p>${f({'a':1})+g({'b':2})}</p> <p>#{f({'c':3})+g({'d':4})}</p> """ expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' <p>''', _escape(_to_str(f({'a':1})+g({'b':2}))), '''</p> <p>''', _to_str(f({'c':3})+g({'d':4})), '''</p>\n''', )); """ t = tenjin.Template() script = t.convert(input) ok (script) == expected
def test_get_template(self): e1 = tenjin.Engine(path=['_views/blog', '_views'], postfix='.pyhtml') filepath = '_views/blog/index.pyhtml' fullpath = os.getcwd() + filepath cachepath = fullpath + '.cache' assert not os.path.exists(cachepath) t = None if spec("return template object.") and \ spec("accept template_name such as ':index'."): t = e1.get_template(':index') ok (t).is_a(tenjin.Template) ok (t.filename) == filepath if spec("if template object is added by add_template(), return it."): tmp = tenjin.Template('foo.pyhtml', input="<<dummy>>") e1.add_template(tmp) ok (e1.get_template('foo.pyhtml')).is_(tmp) if spec("get filepath and fullpath of template"): e1._filepaths['index.pyhtml'] == (filepath, fullpath) if spec("if template file is not found then raise TemplateNotFoundError"): def f(): e1.get_template('index') ok (f).raises(tenjin.TemplateNotFoundError, "index: filename not found (path=['_views/blog', '_views']).") if spec("use full path as base of cache file path") and \ spec("get template object from cache"): ok (list(e1.cache.items.keys())) == ["%s/_views/blog/index.pyhtml.cache" % os.getcwd()] if spec("change template filename according to prefer_fullpath"): pass if spec("use full path as base of cache file path"): pass if spec("get template object from cache"): pass if spec("if template object is not found in cache or is expired..."): e1.cache.clear() ok (len(e1.cache.items)) == 0 tname = ':layout' fpath = '_views/layout.pyhtml' cpath = os.path.join(os.getcwd(), '_views/layout.pyhtml.cache') not_ok (cpath).exists() if spec("create template object."): t = e1.get_template(tname) ok (t).is_a(tenjin.Template) if spec("set timestamp and filename of template object."): ok (t.timestamp) == os.path.getmtime(filepath) ok (t.filename) == fpath delta = JYTHON and 0.03 or 0.003 ok (t._last_checked_at).in_delta(time.time(), delta) if spec("save template object into cache."): ok (cpath).exists() ok (len(e1.cache.items)) == 1 ok (e1.cache.items).contains(cpath)
def test_new_notation(self): input = r""" a=${a} b=#{b} c={=c=} d={==d==} """ expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' a=''', _escape(_to_str(a)), ''' b=''', _to_str(b), ''' c=''', _escape(_to_str(c)), ''' d=''', _to_str(d), '''\n''', )); """ t = tenjin.Template() ok (t.convert(input)) == expected
def test_import_module1(self): import base64 if python2: input = "#{base64.encodestring('tenjin')}" elif python3: if hasattr(base64, 'encodebytes'): # python 3.1 or later input = "#{base64.encodebytes(b'tenjin')}" else: # python 3.0 input = "#{base64.encodestring(b'tenjin')}" template = tenjin.Template() template.convert(input) def f1(): template.render() ok (f1).raises(NameError) #tenjin.import_module('base64') globals()['base64'] = base64 #ok (f1).not_raise() f1()
def test_import_module2(self): if python2: import rfc822 input = "#{rfc822.formatdate()}" elif python3: import email.utils input = "#{email.utils.formatdate()}" template = tenjin.Template() template.convert(input) def f1(): template.render() ok (f1).raises(NameError) if python2: #tenjin.import_module(rfc822) globals()['rfc822'] = rfc822 elif python3: globals()['email'] = email #ok (f1).not_raise() f1()
def test_input(self): input = r"""<!DOCTYPE> <ul> <?py for item in items: ?> <li>#{item}</li> <?py #endfor ?> </ul> """ script = self.lvars + r"""_extend(('''<!DOCTYPE> <ul>\n''', )); for item in items: _extend((''' <li>''', _to_str(item), '''</li>\n''', )); #endfor _extend(('''</ul>\n''', )); """ t = tenjin.Template("test.foobar.pyhtml", input=input) if "input argument is specified then regard it as template content": ok (t.script) == script if "input argument is specified then timestamp is set to False": ok (t.timestamp) == False
def test__get_template_from_cache(self): e1 = tenjin.Engine(path=['_views/blog', '_views'], postfix='.pyhtml') fpath = '_views/blog/index.pyhtml' cpath = fpath + '.cache' if spec("if template not found in cache, return None"): ret = e1._get_template_from_cache(cpath, fpath) ok (ret) == None t = tenjin.Template(fpath) e1.cache.set(fpath + '.cache', t) if spec("if checked within a sec, skip timestamp check."): #try: # t.timestamp = time.time() - 0.2 # #import pdb; pdb.set_trace() # tenjin.logger = DebugLogger() # ret = e1._get_template_from_cache(cpath, fpath) # msg = tenjin.logger.messages[0] # ok (msg.startswith("[TRACE] [tenjin.Engine] timestamp check skipped (")) == True #finally: # tenjin.logger = None pass if spec("if timestamp of template objectis same as file, return it."): t._last_checked_at = None t.timestamp = os.path.getmtime(fpath) ok (e1._get_template_from_cache(cpath, fpath)).is_(t) delta = JYTHON and 0.03 or 0.001 ok (t._last_checked_at).in_delta(time.time(), delta) if spec("if timestamp of template object is different from file, clear it"): t.timestamp = t.timestamp + 1 t._last_checked_at = None try: #import pdb; pdb.set_trace() tenjin.logger = DebugLogger() ret = e1._get_template_from_cache(cpath, fpath) msg = tenjin.logger.messages[0] ok (msg) == "[INFO] [tenjin.Engine] cache expired (filepath='_views/blog/index.pyhtml')" finally: tenjin.logger = None
def get_tenjin_tests(): if not tenjin: return [] try: import webext helpers = {'to_str': webext.to_str, 'escape': webext.escape_html} except ImportError: helpers = { 'to_str': tenjin.helpers.to_str, 'escape': tenjin.helpers.escape } tenjin_template = tenjin.Template(encoding='utf8') tenjin_template.convert("""\ <table> <?py for row in table: ?> <tr> <?py for key, value in row.items(): ?> <td>${ key }</td><td>#{ value }</td> <?py #end ?> </tr> <?py #end ?> </table> """) ctx = { 'table': TABLE_DATA, } def test_tenjin(): """tenjin template""" return tenjin_template.render(ctx, helpers) return [ test_tenjin, ]
# region: tenjin try: import tenjin except ImportError: test_tenjin = None else: try: import webext helpers = {'to_str': webext.to_str, 'escape': webext.escape_html} except ImportError: helpers = { 'to_str': tenjin.helpers.to_str, 'escape': tenjin.helpers.escape } tenjin_template = tenjin.Template(encoding='utf8') tenjin_template.convert( s("""\ <table> <?py for row in table: ?> <tr> <?py for key, value in row.items(): ?> <td>${ key }</td><td>#{ value }</td> <?py #end ?> </tr> <?py #end ?> </table> """)) def test_tenjin(): return tenjin_template.render(ctx, helpers)
#end for </table> </div> </body> </html>\ """, searchList=[dict(context)]) def test_cheetah(): unicode(cheetah_template) try: import tenjin except ImportError: test_tenjin = None else: tenjin_template = tenjin.Template() tenjin_template.convert("""\ <!doctype html> <html> <head> <title>${page_title}</title> </head> <body> <div class="header"> <h1>${page_title}</h1> </div> <ul class="navigation"> <?py for href, caption in [('index.html', 'Index'), ('downloads.html', 'Downloads'), ('products.html', 'Products')]: ?> <li><a href="${href}">${caption}</a></li> <?py #end ?> </ul>
import tenjin template = tenjin.Template('views/page.pyhtml') print(template.script) ### or: #template = tenjin.Template() #with open('views/page.pyhtml') as f: # print(template.convert(f.read(), 'views/page.pyhtml')) ### or: #engine = tenjin.Engine(path=['views']) #print(engine.get_template('page.pyhtml').script)
def _makemessages(domain, locale, localedir, extensions): sys.stdout.write("processing language %s\n" % locale) basedir = os.path.join(localedir, locale, 'LC_MESSAGES') if not os.path.isdir(basedir): os.makedirs(basedir) pofile = '%s/%s.po' % (basedir, domain) potfile = '%s/%s.pot' % (basedir, domain) if os.path.exists(potfile): os.unlink(potfile) for ff_name in find_files(domain): dirpath, f_name = os.path.split(ff_name) file_base, file_ext = os.path.splitext(f_name) if domain == 'front' \ and (file_ext == '.py' or file_ext in extensions): thefile = f_name if file_ext in extensions: thefile = '%s.py' % f_name import tenjin src = tenjin.Template(ff_name).script with open(os.path.join(dirpath, thefile), "w") as f: f.write(src) else: continue cmd = ('xgettext -d %s -L Python --keyword=gettext_noop ' '--keyword=gettext_lazy --keyword=ngettext_lazy:1,2 ' '--keyword=ugettext_noop --keyword=ugettext_lazy ' '--keyword=ungettext_lazy:1,2 --keyword=pgettext:1c,2 ' '--keyword=npgettext:1c,2,3 --keyword=pgettext_lazy:1c,2 ' '--keyword=npgettext_lazy:1c,2,3 --from-code UTF-8 ' '--add-comments=Translators -o - "%s"' % (domain, os.path.join(dirpath, thefile))) msgs, errors = _popen(cmd) if errors: if thefile != f_name: os.unlink(os.path.join(dirpath, thefile)) if os.path.exists(potfile): os.unlink(potfile) raise CommandError( "errors happened while running xgettext on %s\n%s" % (f_name, errors)) if msgs: if thefile != f_name: old = '#: ' + os.path.join(dirpath, thefile) new = '#: ' + ff_name msgs = msgs.replace(old, new) if os.path.exists(potfile): # Strip the header msgs = '\n'.join(dropwhile(len, msgs.split('\n'))) else: msgs = msgs.replace('charset=CHARSET', 'charset=UTF-8') with open(potfile, 'ab') as f: f.write(msgs) if thefile != f_name: os.unlink(os.path.join(dirpath, thefile)) if os.path.exists(potfile): msgs, errors = _popen('msguniq --to-code=utf-8 "%s"' % potfile) if errors: os.unlink(potfile) raise CommandError("errors happened while running msguniq\n%s" % errors) if os.path.exists(pofile): with open(potfile, 'w') as f: f.write(msgs) msgs, errors = _popen('msgmerge -q "%s" "%s"' % (pofile, potfile)) if errors: os.unlink(potfile) raise CommandError( "errors happened while running msgmerge\n%s" % errors) with open(pofile, 'wb') as f: f.write(msgs) os.unlink(potfile)
try: import tenjin except ImportError: test(name="tenjin") else: try: import webext helpers = {"to_str": webext.to_str, "escape": webext.escape_html} except ImportError: helpers = { "to_str": tenjin.helpers.to_str, "escape": tenjin.helpers.escape, } tenjin_template = tenjin.Template(encoding="utf8") tenjin_template.convert( s("""\ <table> <?py for row in table: ?> <tr> <?py for key, value in row.items(): ?> <td>${ key }</td><td>#{ value }</td> <?py #end ?> </tr> <?py #end ?> </table> """)) @test(40) def test_tenjin() -> str:
def test_add_expr(self): input = r""" not escape: #{var} escape: ${var} """ if spec("nothing is specified then both _to_str() and _escape() are used."): t = tenjin.Template() script = t.convert(input) expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' not escape: ''', _to_str(var), ''' escape: ''', _escape(_to_str(var)), '''\n''', )); """ ok (script) == expected if spec("when tostrfunc is False then skips _to_str()."): expected = r"""_extend=_buf.extend;_to_str=False;_escape=escape; _extend((''' not escape: ''', (var), ''' escape: ''', _escape(var), '''\n''', )); """ t = tenjin.Template(tostrfunc=False) ok (t.convert(input)) == expected if spec("escapefunc is False then skips _escape()."): expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=False; _extend((''' not escape: ''', _to_str(var), ''' escape: ''', _to_str(var), '''\n''', )); """ t = tenjin.Template(escapefunc=False) ok (t.convert(input)) == expected if spec("both tostr and escapefunc are False then skips _to_str() and _escape()."): expected = r"""_extend=_buf.extend;_to_str=False;_escape=False; _extend((''' not escape: ''', (var), ''' escape: ''', (var), '''\n''', )); """ t = tenjin.Template(tostrfunc=False, escapefunc=False) ok (t.convert(input)) == expected if spec("get_expr_and_flags() returns flag_tostr=False then ignores _escape()."): tr = Tracer() def fn(orig, *args): expr, (flag_escape, flag_tostr) = orig(*args) return expr, (flag_escape, False) expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' not escape: ''', (var), ''' escape: ''', _escape(var), '''\n''', )); """ t = tenjin.Template() tr.fake_method(t, get_expr_and_flags=fn) ok (t.convert(input)) == expected if spec("get_expr_and_flags() returns flag_escape=False then ignores _escape()."): tr = Tracer() def fn(orig, *args): expr, (flag_escape, flag_tostr) = orig(*args) return expr, (False, flag_tostr) expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' not escape: ''', _to_str(var), ''' escape: ''', _to_str(var), '''\n''', )); """ t = tenjin.Template() tr.fake_method(t, get_expr_and_flags=fn) ok (t.convert(input)) == expected if spec("get_expr_and_flags() returns both flags False then ignores both _to_str() and _escape()."): tr = Tracer() def fn(orig, *args): expr, (flag_escape, flag_tostr) = orig(*args) return expr, (False, False) expected = r"""_extend=_buf.extend;_to_str=to_str;_escape=escape; _extend((''' not escape: ''', (var), ''' escape: ''', (var), '''\n''', )); """ t = tenjin.Template() tr.fake_method(t, get_expr_and_flags=fn) ok (t.convert(input)) == expected
def f(): input = "<?py #@ARGS 1x ?>" template = tenjin.Template() template.convert(input)
def _convert(input): return tenjin.Template(input=input).script
def _test(self): input = getattr(self, 'input', None) source = getattr(self, 'source', None) expected = getattr(self, 'expected', None) exception = getattr(self, 'exception', None) errormsg = getattr(self, 'errormsg', None) options = getattr(self, 'options', {}) filename = getattr(self, 'filename', None) context = getattr(self, 'context', {}) testopts = getattr(self, 'testopts', None) disabled = getattr(self, 'disabled', None) templateclass = getattr(self, 'templateclass', None) encoding = None # if disabled: return # if testopts: if 'crchar' in testopts: ch = testopts['crchar'] if input: input = input.replace(ch, "\r") if source: source = source.replace(ch, "\r") if expected: expected = expected.replace(ch, "\r") if testopts.get('escapefunc') == 'cgi.escape': #import cgi #context['escape'] = cgi.escape pass if testopts.get('tostrfunc') == 'str': #context['to_str'] = str pass if 'encoding' in testopts: encoding = testopts.get('encoding') if 'templateclass' in testopts: templateclass = testopts.get('templateclass') # if python3: input = input.replace('urllib.quote', 'urllib.parse.quote') source = source.replace('urllib.quote', 'urllib.parse.quote') if encoding: if source: source = source.replace("u'''", "'''").replace("u'", "'") input = input.replace("u'", "'") # if JYTHON: if self._testMethodName == 'test_syntaxerr1': errormsg = r"mismatched input '\n' expecting COLON" # if PYPY: if errormsg: errormsg = _errmsg(errormsg) # if exception: try: template = tenjin.Template(**options) template.convert(input, filename) template.render(context) self.fail('%s is expected but not raised.' % exception) except Exception: ex = sys.exc_info()[1] ok (ex.__class__) == exception #ok (ex).is_a(exception) if errormsg: ## SyntaxError has 'msg' attribute instead of 'message'. Why? #ok (ex.message or ex.msg) == errormsg # failed in python2.3 ok (ex.args[0]) == errormsg if filename: ok (ex.filename) == filename else: if templateclass: templateclass = eval(templateclass) template = templateclass(**options) else: template = tenjin.Template(**options) script = template.convert(input, filename) ok (script) == source # encoding=encoding if expected: output = template.render(context) ok (output) == expected # encoding=encoding