From 56c690b9efdb009ab44f3112b6c301d7d393f07e Mon Sep 17 00:00:00 2001 From: Renard Date: Sun, 29 Mar 2020 18:43:36 -0300 Subject: Formateo de python con pep8 --- cgi/tenjin.py | 839 +++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 507 insertions(+), 332 deletions(-) (limited to 'cgi/tenjin.py') diff --git a/cgi/tenjin.py b/cgi/tenjin.py index db8cdde..ddc12bb 100644 --- a/cgi/tenjin.py +++ b/cgi/tenjin.py @@ -1,26 +1,26 @@ ## -## $Release: 1.1.1 $ -## $Copyright: copyright(c) 2007-2012 kuwata-lab.com all rights reserved. $ -## $License: MIT License $ +# $Release: 1.1.1 $ +# $Copyright: copyright(c) 2007-2012 kuwata-lab.com all rights reserved. $ +# $License: MIT License $ ## -## Permission is hereby granted, free of charge, to any person obtaining -## a copy of this software and associated documentation files (the -## "Software"), to deal in the Software without restriction, including -## without limitation the rights to use, copy, modify, merge, publish, -## distribute, sublicense, and/or sell copies of the Software, and to -## permit persons to whom the Software is furnished to do so, subject to -## the following conditions: +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: ## -## The above copyright notice and this permission notice shall be -## included in all copies or substantial portions of the Software. +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. ## -## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -## EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -## MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -## NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -## LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -## OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -## WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ## """Very fast and light-weight template engine based embedded Python. @@ -29,15 +29,19 @@ http://www.kuwata-lab.com/tenjin/pytenjin-examples.html """ -__version__ = "$Release: 1.1.1 $"[10:-2] -__license__ = "$License: MIT License $"[10:-2] -__all__ = ('Template', 'Engine', ) +__version__ = "$Release: 1.1.1 $"[10:-2] +__license__ = "$License: MIT License $"[10:-2] +__all__ = ('Template', 'Engine', ) -import sys, os, re, time, marshal -from time import time as _time -from os.path import getmtime as _getmtime from os.path import isfile as _isfile +from os.path import getmtime as _getmtime +from time import time as _time +import sys +import os +import re +import time +import marshal random = pickle = unquote = None # lazy import python3 = sys.version_info[0] == 3 python2 = sys.version_info[0] == 2 @@ -46,12 +50,13 @@ logger = None ## -## utilities +# utilities ## def _write_binary_file(filename, content): global random - if random is None: from random import random + if random is None: + from random import random tmpfile = filename + str(random())[1:] f = open(tmpfile, 'w+b') # on windows, 'w+b' is preffered than 'wb' try: @@ -62,9 +67,11 @@ def _write_binary_file(filename, content): try: os.rename(tmpfile, filename) except: - os.remove(filename) # on windows, existing file should be removed before renaming + # on windows, existing file should be removed before renaming + os.remove(filename) os.rename(tmpfile, filename) + def _read_binary_file(filename): f = open(filename, 'rb') try: @@ -72,25 +79,32 @@ def _read_binary_file(filename): finally: f.close() + codecs = None # lazy import + def _read_text_file(filename, encoding=None): global codecs - if not codecs: import codecs + if not codecs: + import codecs f = codecs.open(filename, encoding=(encoding or 'utf-8')) try: return f.read() finally: f.close() + def _read_template_file(filename, encoding=None): - s = _read_binary_file(filename) ## binary(=str) - if encoding: s = s.decode(encoding) ## binary(=str) to unicode + s = _read_binary_file(filename) # binary(=str) + if encoding: + s = s.decode(encoding) # binary(=str) to unicode return s + _basestring = basestring -_unicode = unicode -_bytes = str +_unicode = unicode +_bytes = str + def _ignore_not_found_error(f, default=None): try: @@ -100,6 +114,7 @@ def _ignore_not_found_error(f, default=None): return default raise + def create_module(module_name, dummy_func=None, **kwargs): """ex. mod = create_module('tenjin.util')""" try: @@ -116,12 +131,13 @@ def create_module(module_name, dummy_func=None, **kwargs): exec(dummy_func.func_code, mod.__dict__) return mod + def _raise(exception_class, *args): raise exception_class(*args) ## -## helper method's module +# helper method's module ## def _dummy(): @@ -142,13 +158,16 @@ def _dummy(): """ if encode: if decode: - raise ValueError("can't specify both encode and decode encoding.") + raise ValueError( + "can't specify both encode and decode encoding.") else: def to_str(val, _str=str, _unicode=unicode, _isa=isinstance, _encode=encode): """Convert val into string or return '' if None. Unicode will be encoded into binary(=str).""" - if _isa(val, _str): return val - if val is None: return '' - #if _isa(val, _unicode): return val.encode(_encode) # unicode to binary(=str) + if _isa(val, _str): + return val + if val is None: + return '' + # if _isa(val, _unicode): return val.encode(_encode) # unicode to binary(=str) if _isa(val, _unicode): return val.encode(_encode) # unicode to binary(=str) return _str(val) @@ -156,18 +175,23 @@ def _dummy(): if decode: def to_str(val, _str=str, _unicode=unicode, _isa=isinstance, _decode=decode): """Convert val into string or return '' if None. Binary(=str) will be decoded into unicode.""" - #if _isa(val, _str): return val.decode(_decode) # binary(=str) to unicode + # if _isa(val, _str): return val.decode(_decode) # binary(=str) to unicode if _isa(val, _str): return val.decode(_decode) - if val is None: return '' - if _isa(val, _unicode): return val + if val is None: + return '' + if _isa(val, _unicode): + return val return _unicode(val) else: def to_str(val, _str=str, _unicode=unicode, _isa=isinstance): """Convert val into string or return '' if None. Both binary(=str) and unicode will be retruned as-is.""" - if _isa(val, _str): return val - if val is None: return '' - if _isa(val, _unicode): return val + if _isa(val, _str): + return val + if val is None: + return '' + if _isa(val, _unicode): + return val return _str(val) return to_str @@ -197,21 +221,21 @@ def _dummy(): class CaptureContext(object): def __init__(self, name, store_to_context=True, lvars=None): - self.name = name + self.name = name self.store_to_context = store_to_context self.lvars = lvars or sys._getframe(1).f_locals def __enter__(self): lvars = self.lvars self._buf_orig = lvars['_buf'] - lvars['_buf'] = _buf = [] + lvars['_buf'] = _buf = [] lvars['_extend'] = _buf.extend return self def __exit__(self, *args): lvars = self.lvars _buf = lvars['_buf'] - lvars['_buf'] = self._buf_orig + lvars['_buf'] = self._buf_orig lvars['_extend'] = self._buf_orig.extend lvars[self.name] = self.captured = ''.join(_buf) if self.store_to_context and '_context' in lvars: @@ -236,7 +260,8 @@ def _dummy(): lvars = sys._getframe(_depth).f_locals capture_context = lvars.pop('_capture_context', None) if not capture_context: - raise Exception('stop_capture(): start_capture() is not called before.') + raise Exception( + 'stop_capture(): start_capture() is not called before.') capture_context.store_to_context = store_to_context capture_context.__exit__() return capture_context.captured @@ -270,19 +295,25 @@ def _dummy(): global unquote if unquote is None: from urllib import unquote - dct = { 'lt':'<', 'gt':'>', 'amp':'&', 'quot':'"', '#039':"'", } + dct = {'lt': '<', 'gt': '>', 'amp': '&', 'quot': '"', '#039': "'", } + def unescape(s): - #return s.replace('<', '<').replace('>', '>').replace('"', '"').replace(''', "'").replace('&', '&') - return re.sub(r'&(lt|gt|quot|amp|#039);', lambda m: dct[m.group(1)], s) + # return s.replace('<', '<').replace('>', '>').replace('"', '"').replace(''', "'").replace('&', '&') + return re.sub(r'&(lt|gt|quot|amp|#039);', lambda m: dct[m.group(1)], s) s = to_str(s) - s = re.sub(r'%3C%60%23(.*?)%23%60%3E', lambda m: '#{%s}' % unquote(m.group(1)), s) - s = re.sub(r'%3C%60%24(.*?)%24%60%3E', lambda m: '${%s}' % unquote(m.group(1)), s) - s = re.sub(r'<`#(.*?)#`>', lambda m: '#{%s}' % unescape(m.group(1)), s) - s = re.sub(r'<`\$(.*?)\$`>', lambda m: '${%s}' % unescape(m.group(1)), s) + s = re.sub(r'%3C%60%23(.*?)%23%60%3E', + lambda m: '#{%s}' % unquote(m.group(1)), s) + s = re.sub(r'%3C%60%24(.*?)%24%60%3E', + lambda m: '${%s}' % unquote(m.group(1)), s) + s = re.sub(r'<`#(.*?)#`>', + lambda m: '#{%s}' % unescape(m.group(1)), s) + s = re.sub(r'<`\$(.*?)\$`>', + lambda m: '${%s}' % unescape(m.group(1)), s) s = re.sub(r'<`#(.*?)#`>', r'#{\1}', s) s = re.sub(r'<`\$(.*?)\$`>', r'${\1}', s) return s + helpers = create_module('tenjin.helpers', _dummy, sys=sys, re=re) helpers.__all__ = ['to_str', 'escape', 'echo', 'new_cycle', 'generate_tostrfunc', 'start_capture', 'stop_capture', 'capture_as', 'captured_as', @@ -293,13 +324,14 @@ generate_tostrfunc = helpers.generate_tostrfunc ## -## escaped module +# escaped module ## def _dummy(): global is_escaped, as_escaped, to_escaped global Escaped, EscapedStr, EscapedUnicode global __all__ - __all__ = ('is_escaped', 'as_escaped', 'to_escaped', ) #'Escaped', 'EscapedStr', + # 'Escaped', 'EscapedStr', + __all__ = ('is_escaped', 'as_escaped', 'to_escaped', ) class Escaped(object): """marking class that object is already escaped.""" @@ -319,8 +351,10 @@ def _dummy(): def as_escaped(s): """mark string as escaped, without escaping.""" - if isinstance(s, str): return EscapedStr(s) - if isinstance(s, unicode): return EscapedUnicode(s) + if isinstance(s, str): + return EscapedStr(s) + if isinstance(s, unicode): + return EscapedUnicode(s) raise TypeError("as_escaped(%r): expected str or unicode." % (s, )) def to_escaped(value): @@ -329,23 +363,24 @@ def _dummy(): if hasattr(value, '__html__'): value = value.__html__() if is_escaped(value): - #return value # EscapedUnicode should be convered into EscapedStr + # return value # EscapedUnicode should be convered into EscapedStr return as_escaped(_helpers.to_str(value)) - #if isinstance(value, _basestring): + # if isinstance(value, _basestring): # return as_escaped(_helpers.escape(value)) return as_escaped(_helpers.escape(_helpers.to_str(value))) + escaped = create_module('tenjin.escaped', _dummy, _helpers=helpers) ## -## module for html +# module for html ## def _dummy(): global escape_html, escape_xml, escape, tagattr, tagattrs, _normalize_attrs global checked, selected, disabled, nl2br, text2html, nv, js_link - #_escape_table = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' } + # _escape_table = { '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' } #_escape_pattern = re.compile(r'[&<>"]') ##_escape_callable = lambda m: _escape_table[m.group(0)] ##_escape_callable = lambda m: _escape_table.__get__(m.group(0)) @@ -353,22 +388,22 @@ def _dummy(): #_escape_callable = lambda m: _escape_get(m.group(0)) #_escape_sub = _escape_pattern.sub - #def escape_html(s): + # def escape_html(s): # return s # 3.02 - #def escape_html(s): + # def escape_html(s): # return _escape_pattern.sub(_escape_callable, s) # 6.31 - #def escape_html(s): + # def escape_html(s): # return _escape_sub(_escape_callable, s) # 6.01 - #def escape_html(s, _p=_escape_pattern, _f=_escape_callable): + # def escape_html(s, _p=_escape_pattern, _f=_escape_callable): # return _p.sub(_f, s) # 6.27 - #def escape_html(s, _sub=_escape_pattern.sub, _callable=_escape_callable): + # def escape_html(s, _sub=_escape_pattern.sub, _callable=_escape_callable): # return _sub(_callable, s) # 6.04 - #def escape_html(s): + # def escape_html(s): # s = s.replace('&', '&') # s = s.replace('<', '<') # s = s.replace('>', '>') @@ -384,9 +419,12 @@ def _dummy(): def tagattr(name, expr, value=None, escape=True): """(experimental) Return ' name="value"' if expr is true value, else '' (empty string). If value is not specified, expr is used as value instead.""" - if not expr and expr != 0: return _escaped.as_escaped('') - if value is None: value = expr - if escape: value = _escaped.to_escaped(value) + if not expr and expr != 0: + return _escaped.as_escaped('') + if value is None: + value = expr + if escape: + value = _escaped.to_escaped(value) return _escaped.as_escaped(' %s="%s"' % (name, value)) def tagattrs(**kwargs): @@ -399,14 +437,19 @@ def _dummy(): """ kwargs = _normalize_attrs(kwargs) esc = _escaped.to_escaped - s = ''.join([ ' %s="%s"' % (k, esc(v)) for k, v in kwargs.iteritems() if v or v == 0 ]) + s = ''.join([' %s="%s"' % (k, esc(v)) + for k, v in kwargs.iteritems() if v or v == 0]) return _escaped.as_escaped(s) def _normalize_attrs(kwargs): - if 'klass' in kwargs: kwargs['class'] = kwargs.pop('klass') - if 'checked' in kwargs: kwargs['checked'] = kwargs.pop('checked') and 'checked' or None - if 'selected' in kwargs: kwargs['selected'] = kwargs.pop('selected') and 'selected' or None - if 'disabled' in kwargs: kwargs['disabled'] = kwargs.pop('disabled') and 'disabled' or None + if 'klass' in kwargs: + kwargs['class'] = kwargs.pop('klass') + if 'checked' in kwargs: + kwargs['checked'] = kwargs.pop('checked') and 'checked' or None + if 'selected' in kwargs: + kwargs['selected'] = kwargs.pop('selected') and 'selected' or None + if 'disabled' in kwargs: + kwargs['disabled'] = kwargs.pop('disabled') and 'disabled' or None return kwargs def checked(expr): @@ -432,8 +475,9 @@ def _dummy(): if not text: return _escaped.as_escaped('') s = _escaped.to_escaped(text) - if use_nbsp: s = s.replace(' ', '  ') - #return nl2br(s) + if use_nbsp: + s = s.replace(' ', '  ') + # return nl2br(s) s = s.replace('\n', '
\n') return _escaped.as_escaped(s) @@ -449,19 +493,20 @@ def _dummy(): >>> nv('rank', 'A', '.', klass='error', style='color:red') 'name="rank" value="A" id="rank.A" class="error" style="color:red"' """ - name = _escaped.to_escaped(name) + name = _escaped.to_escaped(name) value = _escaped.to_escaped(value) s = sep and 'name="%s" value="%s" id="%s"' % (name, value, name+sep+value) \ - or 'name="%s" value="%s"' % (name, value) + or 'name="%s" value="%s"' % (name, value) html = kwargs and s + tagattrs(**kwargs) or s return _escaped.as_escaped(html) def js_link(label, onclick, **kwargs): s = kwargs and tagattrs(**kwargs) or '' html = '%s' % \ - (_escaped.to_escaped(onclick), s, _escaped.to_escaped(label)) + (_escaped.to_escaped(onclick), s, _escaped.to_escaped(label)) return _escaped.as_escaped(html) + html = create_module('tenjin.html', _dummy, helpers=helpers, _escaped=escaped) helpers.escape = html.escape_html helpers.html = html # for backward compatibility @@ -469,10 +514,11 @@ sys.modules['tenjin.helpers.html'] = html ## -## utility function to set default encoding of template files +# utility function to set default encoding of template files ## _template_encoding = (None, 'utf-8') # encodings for decode and encode + def set_template_encoding(decode=None, encode=None): """Set default encoding of template files. This should be called before importing helper functions. @@ -486,9 +532,11 @@ def set_template_encoding(decode=None, encode=None): if _template_encoding == (decode, encode): return if decode and encode: - raise ValueError("set_template_encoding(): cannot specify both decode and encode.") + raise ValueError( + "set_template_encoding(): cannot specify both decode and encode.") if not decode and not encode: - raise ValueError("set_template_encoding(): decode or encode should be specified.") + raise ValueError( + "set_template_encoding(): decode or encode should be specified.") if decode: Template.encoding = decode # unicode base template helpers.to_str = helpers.generate_tostrfunc(decode=decode) @@ -499,7 +547,7 @@ def set_template_encoding(decode=None, encode=None): ## -## Template class +# Template class ## class TemplateSyntaxError(SyntaxError): @@ -510,8 +558,8 @@ class TemplateSyntaxError(SyntaxError): return self.args[0] return ''.join([ "%s:%s:%s: %s\n" % (ex.filename, ex.lineno, ex.offset, ex.msg, ), - "%4d: %s\n" % (ex.lineno, ex.text.rstrip(), ), - " %s^\n" % (' ' * ex.offset, ), + "%4d: %s\n" % (ex.lineno, ex.text.rstrip(), ), + " %s^\n" % (' ' * ex.offset, ), ]) @@ -522,21 +570,21 @@ class Template(object): http://www.kuwata-lab.com/tenjin/pytenjin-examples.html """ - ## default value of attributes - filename = None - encoding = None + # default value of attributes + filename = None + encoding = None escapefunc = 'escape' - tostrfunc = 'to_str' - indent = 4 - preamble = None # "_buf = []; _expand = _buf.expand; _to_str = to_str; _escape = escape" - postamble = None # "print ''.join(_buf)" - smarttrim = None - args = None - timestamp = None - trace = False # if True then '' and '' are printed + tostrfunc = 'to_str' + indent = 4 + preamble = None # "_buf = []; _expand = _buf.expand; _to_str = to_str; _escape = escape" + postamble = None # "print ''.join(_buf)" + smarttrim = None + args = None + timestamp = None + trace = False # if True then '' and '' are printed def __init__(self, filename=None, encoding=None, input=None, escapefunc=None, tostrfunc=None, - indent=None, preamble=None, postamble=None, smarttrim=None, trace=None): + indent=None, preamble=None, postamble=None, smarttrim=None, trace=None): """Initailizer of Template class. filename:str (=None) @@ -565,29 +613,40 @@ class Template(object): If True then "
\\n#{_context}\\n
" is parsed as "
\\n#{_context}
". """ - if encoding is not None: self.encoding = encoding - if escapefunc is not None: self.escapefunc = escapefunc - if tostrfunc is not None: self.tostrfunc = tostrfunc - if indent is not None: self.indent = indent - if preamble is not None: self.preamble = preamble - if postamble is not None: self.postamble = postamble - if smarttrim is not None: self.smarttrim = smarttrim - if trace is not None: self.trace = trace + if encoding is not None: + self.encoding = encoding + if escapefunc is not None: + self.escapefunc = escapefunc + if tostrfunc is not None: + self.tostrfunc = tostrfunc + if indent is not None: + self.indent = indent + if preamble is not None: + self.preamble = preamble + if postamble is not None: + self.postamble = postamble + if smarttrim is not None: + self.smarttrim = smarttrim + if trace is not None: + self.trace = trace # - if preamble is True: self.preamble = "_buf = []" - if postamble is True: self.postamble = "print(''.join(_buf))" + if preamble is True: + self.preamble = "_buf = []" + if postamble is True: + self.postamble = "print(''.join(_buf))" if input: self.convert(input, filename) - self.timestamp = False # False means 'file not exist' (= Engine should not check timestamp of file) + # False means 'file not exist' (= Engine should not check timestamp of file) + self.timestamp = False elif filename: self.convert_file(filename) else: self._reset() def _reset(self, input=None, filename=None): - self.script = None + self.script = None self.bytecode = None - self.input = input + self.input = input self.filename = filename if input != None: i = input.find("\n") @@ -648,7 +707,8 @@ class Template(object): return pat def parse_stmts(self, buf, input): - if not input: return + if not input: + return rexp = self.stmt_pattern() is_bol = True index = 0 @@ -658,7 +718,7 @@ class Template(object): #code = input[m.start()+4+len(mspace):m.end()-len(close)-(rspace and len(rspace) or 0)] text = input[index:m.start()] index = m.end() - ## detect spaces at beginning of line + # detect spaces at beginning of line lspace = None if text == '': if is_bol: @@ -675,13 +735,13 @@ class Template(object): if s.isspace(): lspace, text = s, text[:rindex+1] #is_bol = rspace is not None - ## add text, spaces, and statement + # add text, spaces, and statement self.parse_exprs(buf, text, is_bol) is_bol = rspace is not None - #if mspace == "\n": + # if mspace == "\n": if mspace and mspace.endswith("\n"): code = "\n" + (code or "") - #if rspace == "\n": + # if rspace == "\n": if rspace and rspace.endswith("\n"): code = (code or "") + "\n" if code: @@ -708,10 +768,12 @@ class Template(object): def _add_args_declaration(self, buf, m): arr = (m.group(1) or '').split(',') - args = []; declares = [] + args = [] + declares = [] for s in arr: arg = s.strip() - if not s: continue + if not s: + continue if not re.match('^[a-zA-Z_]\w*$', arg): raise ValueError("%r: invalid template argument." % arg) args.append(arg) @@ -722,7 +784,8 @@ class Template(object): buf.append(''.join(declares) + "\n") s = '(?:\{.*?\}.*?)*' - EXPR_PATTERN = (r'#\{(.*?'+s+r')\}|\$\{(.*?'+s+r')\}|\{=(?:=(.*?)=|(.*?))=\}', re.S) + EXPR_PATTERN = ( + r'#\{(.*?'+s+r')\}|\$\{(.*?'+s+r')\}|\{=(?:=(.*?)=|(.*?))=\}', re.S) del s def expr_pattern(self): @@ -733,10 +796,14 @@ class Template(object): def get_expr_and_flags(self, match): expr1, expr2, expr3, expr4 = match.groups() - if expr1 is not None: return expr1, (False, True) # not escape, call to_str - if expr2 is not None: return expr2, (True, True) # call escape, call to_str - if expr3 is not None: return expr3, (False, True) # not escape, call to_str - if expr4 is not None: return expr4, (True, True) # call escape, call to_str + if expr1 is not None: + return expr1, (False, True) # not escape, call to_str + if expr2 is not None: + return expr2, (True, True) # call escape, call to_str + if expr3 is not None: + return expr3, (False, True) # not escape, call to_str + if expr4 is not None: + return expr4, (True, True) # call escape, call to_str def parse_exprs(self, buf, input, is_bol=False): buf2 = [] @@ -745,17 +812,18 @@ class Template(object): buf.append(''.join(buf2)) def _parse_exprs(self, buf, input, is_bol=False): - if not input: return + if not input: + return self.start_text_part(buf) rexp = self.expr_pattern() smarttrim = self.smarttrim nl = self.newline - nl_len = len(nl) + nl_len = len(nl) pos = 0 for m in rexp.finditer(input): start = m.start() - text = input[pos:start] - pos = m.end() + text = input[pos:start] + pos = m.end() expr, flags = self.get_expr_and_flags(m) # if text: @@ -763,7 +831,8 @@ class Template(object): self.add_expr(buf, expr, *flags) # if smarttrim: - flag_bol = text.endswith(nl) or not text and (start > 0 or is_bol) + flag_bol = text.endswith( + nl) or not text and (start > 0 or is_bol) if flag_bol and not flags[0] and input[pos:pos+nl_len] == nl: pos += nl_len buf.append("\n") @@ -779,7 +848,7 @@ class Template(object): def start_text_part(self, buf): self._add_localvars_assignments_to_text(buf) - #buf.append("_buf.extend((") + # buf.append("_buf.extend((") buf.append("_extend((") def _add_localvars_assignments_to_text(self, buf): @@ -796,30 +865,43 @@ class Template(object): return text def add_text(self, buf, text, encode_newline=False): - if not text: return + if not text: + return use_unicode = self.encoding and python2 buf.append(use_unicode and "u'''" or "'''") text = self._quote_text(text) - if not encode_newline: buf.extend((text, "''', ")) - elif text.endswith("\r\n"): buf.extend((text[0:-2], "\\r\\n''', ")) - elif text.endswith("\n"): buf.extend((text[0:-1], "\\n''', ")) - else: buf.extend((text, "''', ")) + if not encode_newline: + buf.extend((text, "''', ")) + elif text.endswith("\r\n"): + buf.extend((text[0:-2], "\\r\\n''', ")) + elif text.endswith("\n"): + buf.extend((text[0:-1], "\\n''', ")) + else: + buf.extend((text, "''', ")) _add_text = add_text def add_expr(self, buf, code, *flags): - if not code or code.isspace(): return + if not code or code.isspace(): + return flag_escape, flag_tostr = flags - if not self.tostrfunc: flag_tostr = False - if not self.escapefunc: flag_escape = False - if flag_tostr and flag_escape: s1, s2 = "_escape(_to_str(", ")), " - elif flag_tostr: s1, s2 = "_to_str(", "), " - elif flag_escape: s1, s2 = "_escape(", "), " - else: s1, s2 = "(", "), " + if not self.tostrfunc: + flag_tostr = False + if not self.escapefunc: + flag_escape = False + if flag_tostr and flag_escape: + s1, s2 = "_escape(_to_str(", ")), " + elif flag_tostr: + s1, s2 = "_to_str(", "), " + elif flag_escape: + s1, s2 = "_escape(", "), " + else: + s1, s2 = "(", "), " buf.extend((s1, code, s2, )) def add_stmt(self, buf, code): - if not code: return + if not code: + return lines = code.splitlines(True) # keep "\n" if lines[-1][-1] != "\n": lines[-1] = lines[-1] + "\n" @@ -840,59 +922,64 @@ class Template(object): else: buf[index] = self._localvars_assignments() + buf[index] - - _START_WORDS = dict.fromkeys(('for', 'if', 'while', 'def', 'try:', 'with', 'class'), True) - _END_WORDS = dict.fromkeys(('#end', '#endfor', '#endif', '#endwhile', '#enddef', '#endtry', '#endwith', '#endclass'), True) - _CONT_WORDS = dict.fromkeys(('elif', 'else:', 'except', 'except:', 'finally:'), True) - _WORD_REXP = re.compile(r'\S+') + _START_WORDS = dict.fromkeys( + ('for', 'if', 'while', 'def', 'try:', 'with', 'class'), True) + _END_WORDS = dict.fromkeys(('#end', '#endfor', '#endif', '#endwhile', + '#enddef', '#endtry', '#endwith', '#endclass'), True) + _CONT_WORDS = dict.fromkeys( + ('elif', 'else:', 'except', 'except:', 'finally:'), True) + _WORD_REXP = re.compile(r'\S+') depth = -1 ## - ## ex. - ## input = r""" - ## if items: + # ex. + # input = r""" + # if items: ## _buf.extend(('\n', )) - ## #endif - ## """[1:] + # endif + # """[1:] ## lines = input.splitlines(True) ## block = self.parse_lines(lines) - ## #=> [ "if items:\n", - ## [ "_buf.extend(('