15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)A small templating language 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)This implements a small templating language. This language implements 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if/elif/else, for/continue/break, expressions, and blocks of Python 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)code. The syntax is:: 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{any expression (function calls etc)}} 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{any expression | filter}} 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{for x in y}}...{{endfor}} 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{if x}}x{{elif y}}y{{else}}z{{endif}} 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{py:x=1}} 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{py: 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def foo(bar): 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 'baz' 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) }} 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{default var = default_value}} 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) {{# comment}} 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)You use this with the ``Template`` class or the ``sub`` shortcut. 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)The ``Template`` class takes the template string and the name of 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)the template (for errors) and a default namespace. Then (like 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)``string.Template``) you can call the ``tmpl.substitute(**kw)`` 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)method to make a substitution (or ``tmpl.substitute(a_dict)``). 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)``sub(content, **kw)`` substitutes the template immediately. You 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)can use ``__name='tmpl.html'`` to set the name of the template. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)If there are syntax errors ``TemplateError`` will be raised. 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import re 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import sys 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import cgi 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)try: 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from urllib import quote as url_quote 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)except ImportError: # Py3 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from urllib.parse import quote as url_quote 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import os 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)import tokenize 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)try: 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from io import StringIO 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)except ImportError: 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from cStringIO import StringIO 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Tempita._looper import looper 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)from Cython.Tempita.compat3 import bytes, basestring_, next, is_unicode, coerce_text 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate', 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'sub_html', 'html', 'bunch'] 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)in_re = re.compile(r'\s+in\s+') 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I) 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplateError(Exception): 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Exception raised while parsing a template 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, message, position, name=None): 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Exception.__init__(self, message) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.position = position 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.name = name 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __str__(self): 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg = ' '.join(self.args) 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.position: 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg = '%s at line %s column %s' % ( 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg, self.position[0], self.position[1]) 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.name: 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg += ' in %s' % self.name 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return msg 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class _TemplateContinue(Exception): 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class _TemplateBreak(Exception): 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def get_file_template(name, from_template): 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) path = os.path.join(os.path.dirname(from_template.name), name) 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return from_template.__class__.from_filename( 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) path, namespace=from_template.namespace, 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get_template=from_template.get_template) 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class Template(object): 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_namespace = { 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'start_braces': '{{', 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'end_braces': '}}', 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'looper': looper, 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_encoding = 'utf8' 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_inherit = None 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, content, name=None, namespace=None, stacklevel=None, 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) get_template=None, default_inherit=None, line_offset=0, 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delimeters=None): 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.content = content 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # set delimeters 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if delimeters is None: 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delimeters = (self.default_namespace['start_braces'], 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.default_namespace['end_braces']) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) #assert len(delimeters) == 2 and all([isinstance(delimeter, basestring) 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # for delimeter in delimeters]) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.default_namespace = self.__class__.default_namespace.copy() 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.default_namespace['start_braces'] = delimeters[0] 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.default_namespace['end_braces'] = delimeters[1] 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.delimeters = delimeters 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._unicode = is_unicode(content) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name is None and stacklevel is not None: 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) caller = sys._getframe(stacklevel) 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except ValueError: 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pass 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) globals = caller.f_globals 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lineno = caller.f_lineno 1265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '__file__' in globals: 1275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = globals['__file__'] 1285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name.endswith('.pyc') or name.endswith('.pyo'): 1295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = name[:-1] 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif '__name__' in globals: 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = globals['__name__'] 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = '<string>' 1345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if lineno: 1355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name += ':%s' % lineno 1365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.name = name 1375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._parsed = parse(content, name=name, line_offset=line_offset, delimeters=self.delimeters) 1385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if namespace is None: 1395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) namespace = {} 1405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.namespace = namespace 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.get_template = get_template 1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if default_inherit is not None: 1435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.default_inherit = default_inherit 1445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def from_filename(cls, filename, namespace=None, encoding=None, 1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_inherit=None, get_template=get_file_template): 1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f = open(filename, 'rb') 1485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) c = f.read() 1495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f.close() 1505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if encoding: 1515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) c = c.decode(encoding) 1525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return cls(content=c, name=filename, namespace=namespace, 1535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_inherit=default_inherit, get_template=get_template) 1545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) from_filename = classmethod(from_filename) 1565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 1585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<%s %s name=%r>' % ( 1595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.__class__.__name__, 1605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) hex(id(self))[2:], self.name) 1615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def substitute(self, *args, **kw): 1635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if args: 1645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if kw: 1655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 1665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "You can only give positional *or* keyword arguments") 1675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) > 1: 1685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 1695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "You can only give one positional argument") 1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not hasattr(args[0], 'items'): 1715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "If you pass in a single argument, you must pass in a dictionary-like object (with a .items() method); you gave %r" 1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) % (args[0],)) 1745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kw = args[0] 1755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns = kw 1765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns['__template_name__'] = self.name 1775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.namespace: 1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns.update(self.namespace) 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result, defs, inherit = self._interpret(ns) 1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not inherit: 1815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inherit = self.default_inherit 1825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if inherit: 1835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = self._interpret_inherit(result, defs, inherit, ns) 1845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result 1855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret(self, ns): 1875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 1885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = [] 1895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) defs = {} 1905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_codes(self._parsed, ns, out=parts, defs=defs) 1915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '__inherit__' in defs: 1925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inherit = defs.pop('__inherit__') 1935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 1945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) inherit = None 1955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ''.join(parts), defs, inherit 1965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret_inherit(self, body, defs, inherit_template, ns): 1985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 1995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self.get_template: 2005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 2015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'You cannot use inheritance without passing in get_template', 2025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=None, name=self.name) 2035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) templ = self.get_template(inherit_template, self) 2045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self_ = TemplateObject(self.name) 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value in defs.iteritems(): 2065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) setattr(self_, name, value) 2075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self_.body = body 2085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns = ns.copy() 2095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns['self'] = self_ 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return templ.substitute(ns) 2115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret_codes(self, codes, ns, out, defs): 2135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 2145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for item in codes: 2155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(item, basestring_): 2165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) out.append(item) 2175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_code(item, ns, out, defs) 2195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret_code(self, code, ns, out, defs): 2215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 2225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name, pos = code[0], code[1] 2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name == 'py': 2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._exec(code[2], ns, pos) 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'continue': 2265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise _TemplateContinue() 2275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'break': 2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise _TemplateBreak() 2295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'for': 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars, expr, content = code[2], code[3], code[4] 2315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = self._eval(expr, ns, pos) 2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_for(vars, expr, content, ns, out, defs) 2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'cond': 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = code[2:] 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_if(parts, ns, out, defs) 2365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'expr': 2375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = code[2].split('|') 2385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = self._eval(parts[0], ns, pos) 2395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for part in parts[1:]: 2405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func = self._eval(part, ns, pos) 2415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) base = func(base) 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) out.append(self._repr(base, pos)) 2435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'default': 2445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var, expr = code[2], code[3] 2455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if var not in ns: 2465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = self._eval(expr, ns, pos) 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns[var] = result 2485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'inherit': 2495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = code[2] 2505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = self._eval(expr, ns, pos) 2515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) defs['__inherit__'] = value 2525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'def': 2535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = code[2] 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) signature = code[3] 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = code[4] 2565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns[name] = defs[name] = TemplateDef(self, name, signature, body=parts, ns=ns, 2575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos=pos) 2585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif name == 'comment': 2595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 2605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert 0, "Unknown code: %r" % name 2625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret_for(self, vars, expr, content, ns, out, defs): 2645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 2655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for item in expr: 2665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(vars) == 1: 2675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns[vars[0]] = item 2685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(vars) != len(item): 2705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise ValueError( 2715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Need %i items to unpack (got %i items)' 2725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) % (len(vars), len(item))) 2735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value in zip(vars, item): 2745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns[name] = value 2755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 2765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_codes(content, ns, out, defs) 2775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except _TemplateContinue: 2785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except _TemplateBreak: 2805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _interpret_if(self, parts, ns, out, defs): 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # @@: if/else/else gets through 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for part in parts: 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert not isinstance(part, basestring_) 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name, pos = part[0], part[1] 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name == 'else': 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = True 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = self._eval(part[2], ns, pos) 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if result: 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._interpret_codes(part[3], ns, out, defs) 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _eval(self, code, ns, pos): 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 2995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = eval(code, self.default_namespace, ns) 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except SyntaxError, e: 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise SyntaxError( 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'invalid syntax in expression: %s' % code) 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except: 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exc_info = sys.exc_info() 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e = exc_info[1] 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if getattr(e, 'args', None): 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg0 = e.args[0] 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) arg0 = coerce_text(e) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.args = (self._add_line_info(arg0, pos),) 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise exc_info[0], e, exc_info[2] 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _exec(self, code, ns, pos): 3165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 3175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exec code in self.default_namespace, ns 3195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except: 3205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exc_info = sys.exc_info() 3215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e = exc_info[1] 3225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if e.args: 3235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.args = (self._add_line_info(e.args[0], pos),) 3245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 3255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.args = (self._add_line_info(None, pos),) 3265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise exc_info[0], e, exc_info[2] 3275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _repr(self, value, pos): 3295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __traceback_hide__ = True 3305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 3315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value is None: 3325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '' 3335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._unicode: 3345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 3355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = unicode(value) 3365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except UnicodeDecodeError: 3375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = bytes(value) 3385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 3395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(value, basestring_): 3405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = coerce_text(value) 3415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (is_unicode(value) 3425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and self.default_encoding): 3435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.encode(self.default_encoding) 3445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except: 3455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) exc_info = sys.exc_info() 3465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e = exc_info[1] 3475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.args = (self._add_line_info(e.args[0], pos),) 3485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise exc_info[0], e, exc_info[2] 3495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 3505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._unicode and isinstance(value, bytes): 3515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self.default_encoding: 3525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise UnicodeDecodeError( 3535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Cannot decode bytes value %r into unicode ' 3545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '(no default_encoding provided)' % value) 3555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 3565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.decode(self.default_encoding) 3575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except UnicodeDecodeError, e: 3585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise UnicodeDecodeError( 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.encoding, 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.object, 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.start, 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.end, 3635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) e.reason + ' in string %r' % value) 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not self._unicode and is_unicode(value): 3655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not self.default_encoding: 3665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise UnicodeEncodeError( 3675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Cannot encode unicode value %r into bytes ' 3685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '(no default_encoding provided)' % value) 3695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.encode(self.default_encoding) 3705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value 3715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _add_line_info(self, msg, pos): 3735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg = "%s at line %s column %s" % ( 3745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg, pos[0], pos[1]) 3755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self.name: 3765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) msg += " in file %s" % self.name 3775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return msg 3785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def sub(content, delimeters=None, **kw): 3815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = kw.get('__name') 3825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tmpl = Template(content, name=name, delimeters=delimeters) 3835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tmpl.substitute(kw) 3845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def paste_script_template_renderer(content, vars, filename=None): 3875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tmpl = Template(content, name=filename) 3885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tmpl.substitute(vars) 3895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class bunch(dict): 3925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, **kw): 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value in kw.iteritems(): 3955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) setattr(self, name, value) 3965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __setattr__(self, name, value): 3985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self[name] = value 3995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __getattr__(self, name): 4015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self[name] 4035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except KeyError: 4045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise AttributeError(name) 4055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __getitem__(self, key): 4075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if 'default' in self: 4085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 4095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dict.__getitem__(self, key) 4105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except KeyError: 4115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dict.__getitem__(self, 'default') 4125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return dict.__getitem__(self, key) 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 4165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) items = [ 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (k, v) for k, v in self.iteritems()] 4185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) items.sort() 4195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<%s %s>' % ( 4205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.__class__.__name__, 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ' '.join(['%s=%r' % (k, v) for k, v in items])) 4225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)############################################################ 4245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)## HTML Templating 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)############################################################ 4265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class html(object): 4295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, value): 4315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.value = value 4325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __str__(self): 4345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.value 4355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __html__(self): 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.value 4385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 4405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<%s %r>' % ( 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.__class__.__name__, self.value) 4425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def html_quote(value, force=True): 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not force and hasattr(value, '__html__'): 4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value.__html__() 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value is None: 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '' 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not isinstance(value, basestring_): 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = coerce_text(value) 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if sys.version >= "3" and isinstance(value, bytes): 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = cgi.escape(value.decode('latin1'), 1) 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.encode('latin1') 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = cgi.escape(value, 1) 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if sys.version < "3": 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unicode(value): 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.encode('ascii', 'xmlcharrefreplace') 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return value 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def url(v): 4635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) v = coerce_text(v) 4645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if is_unicode(v): 4655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) v = v.encode('utf8') 4665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return url_quote(v) 4675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def attr(**kw): 4705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kw = list(kw.iteritems()) 4715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kw.sort() 4725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = [] 4735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value in kw: 4745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if value is None: 4755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name.endswith('_'): 4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = name[:-1] 4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts.append('%s="%s"' % (html_quote(name), html_quote(value))) 4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return html(' '.join(parts)) 4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class HTMLTemplate(Template): 4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_namespace = Template.default_namespace.copy() 4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_namespace.update(dict( 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) html=html, 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) attr=attr, 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) url=url, 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) html_quote=html_quote, 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) )) 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _repr(self, value, pos): 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if hasattr(value, '__html__'): 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = value.__html__() 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) quote = False 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) quote = True 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) plain = Template._repr(self, value, pos) 4995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if quote: 5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return html_quote(plain) 5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return plain 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def sub_html(content, **kw): 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = kw.get('__name') 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tmpl = HTMLTemplate(content, name=name) 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tmpl.substitute(kw) 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplateDef(object): 5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, template, func_name, func_signature, 5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) body, ns, pos, bound_self=None): 5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._template = template 5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._func_name = func_name 5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._func_signature = func_signature 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._body = body 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._ns = ns 5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._pos = pos 5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._bound_self = bound_self 5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<tempita function %s(%s) at %s:%s>' % ( 5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._func_name, self._func_signature, 5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._template.name, self._pos) 5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __str__(self): 5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self() 5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __call__(self, *args, **kw): 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values = self._parse_signature(args, kw) 5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns = self._ns.copy() 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns.update(values) 5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if self._bound_self is not None: 5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ns['self'] = self._bound_self 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) out = [] 5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) subdefs = {} 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._template._interpret_codes(self._body, ns, out, subdefs) 5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ''.join(out) 5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __get__(self, obj, type=None): 5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if obj is None: 5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self 5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self.__class__( 5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._template, self._func_name, self._func_signature, 5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self._body, self._ns, self._pos, bound_self=obj) 5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def _parse_signature(self, args, kw): 5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values = {} 5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args, var_args, var_kw, defaults = self._func_signature 5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extra_kw = {} 5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value in kw.iteritems(): 5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not var_kw and name not in sig_args: 5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Unexpected argument %s' % name) 5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name in sig_args: 5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values[sig_args] = value 5585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 5595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) extra_kw[name] = value 5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = list(args) 5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args = list(sig_args) 5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while args: 5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while sig_args and sig_args[0] in values: 5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args.pop(0) 5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if sig_args: 5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = sig_args.pop(0) 5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values[name] = args.pop(0) 5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif var_args: 5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values[var_args] = tuple(args) 5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Extra position arguments: %s' 5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) % ', '.join([repr(v) for v in args])) 5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name, value_expr in defaults.iteritems(): 5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name not in values: 5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values[name] = self._template._eval( 5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value_expr, self._ns, self._pos) 5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for name in sig_args: 5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name not in values: 5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TypeError( 5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Missing argument: %s' % name) 5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if var_kw: 5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) values[var_kw] = extra_kw 5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return values 5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplateObject(object): 5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, name): 5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.__name = name 5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.get = TemplateObjectGetter(self) 5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<%s %s>' % (self.__class__.__name__, self.__name) 5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class TemplateObjectGetter(object): 5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __init__(self, template_obj): 6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) self.__template_obj = template_obj 6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __getattr__(self, attr): 6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return getattr(self.__template_obj, attr, Empty) 6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '<%s around %r>' % (self.__class__.__name__, self.__template_obj) 6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)class _Empty(object): 6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __call__(self, *args, **kw): 6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return self 6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __str__(self): 6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return '' 6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __repr__(self): 6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return 'Empty' 6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __unicode__(self): 6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return u'' 6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __iter__(self): 6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return iter(()) 6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def __bool__(self): 6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return False 6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if sys.version < "3": 6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) __nonzero__ = __bool__ 6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Empty = _Empty() 6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)del _Empty 6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)############################################################ 6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)## Lexing and Parsing 6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)############################################################ 6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def lex(s, name=None, trim_whitespace=True, line_offset=0, delimeters=None): 6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Lex a string into chunks: 6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> lex('hey') 6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ['hey'] 6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> lex('hey {{you}}') 6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ['hey ', ('you', (1, 7))] 6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> lex('hey {{') 6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: No }} to finish last expression at line 1 column 7 6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> lex('hey }}') 6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: }} outside expression at line 1 column 7 6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> lex('hey {{ {{') 6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: {{ inside expression at line 1 column 10 6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 6625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if delimeters is None: 6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delimeters = ( Template.default_namespace['start_braces'], 6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Template.default_namespace['end_braces'] ) 6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) in_expr = False 6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) chunks = [] 6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last = 0 6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_pos = (line_offset + 1, 1) 6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) token_re = re.compile(r'%s|%s' % (re.escape(delimeters[0]), 6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) re.escape(delimeters[1]))) 6725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for match in token_re.finditer(s): 6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = match.group(0) 6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pos = find_position(s, match.end(), last, last_pos) 6755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expr == delimeters[0] and in_expr: 6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('%s inside expression' % delimeters[0], 6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, 6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name=name) 6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr == delimeters[1] and not in_expr: 6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('%s outside expression' % delimeters[1], 6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, 6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name=name) 6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expr == delimeters[0]: 6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) part = s[last:match.start()] 6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if part: 6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) chunks.append(part) 6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) in_expr = True 6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) chunks.append((s[last:match.start()], last_pos)) 6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) in_expr = False 6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last = match.end() 6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_pos = pos 6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if in_expr: 6945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('No %s to finish last expression' % delimeters[1], 6955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name=name, position=last_pos) 6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) part = s[last:] 6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if part: 6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) chunks.append(part) 6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if trim_whitespace: 7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) chunks = trim_lex(chunks) 7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return chunks 7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)statement_re = re.compile(r'^(?:if |elif |for |def |inherit |default |py:)') 7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)single_statements = ['else', 'endif', 'endfor', 'enddef', 'continue', 'break'] 7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)trail_whitespace_re = re.compile(r'\n\r?[\t ]*$') 7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)lead_whitespace_re = re.compile(r'^[\t ]*\n') 7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def trim_lex(tokens): 7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) r""" 7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Takes a lexed set of tokens, and removes whitespace when there is 7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) a directive on a line by itself: 7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False) 7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> tokens 7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny'] 7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> trim_lex(tokens) 7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y'] 7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_trim = None 7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for i, current in enumerate(tokens): 7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(current, basestring_): 7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # we don't trim this 7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) item = current[0] 7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not statement_re.search(item) and item not in single_statements: 7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not i: 7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev = '' 7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev = tokens[i - 1] 7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if i + 1 >= len(tokens): 7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk = '' 7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk = tokens[i + 1] 7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (not isinstance(next_chunk, basestring_) 7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or not isinstance(prev, basestring_)): 7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev_ok = not prev or trail_whitespace_re.search(prev) 7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if i == 1 and not prev.strip(): 7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev_ok = True 7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if last_trim is not None and last_trim + 2 == i and not prev.strip(): 7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev_ok = 'last' 7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (prev_ok 7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and (not next_chunk or lead_whitespace_re.search(next_chunk) 7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or (i == len(tokens) - 2 and not next_chunk.strip()))): 7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if prev: 7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((i == 1 and not prev.strip()) 7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or prev_ok == 'last'): 7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens[i - 1] = '' 7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) m = trail_whitespace_re.search(prev) 7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # +1 to leave the leading \n on: 7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) prev = prev[:m.start() + 1] 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens[i - 1] = prev 7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if next_chunk: 7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) last_trim = i 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if i == len(tokens) - 2 and not next_chunk.strip(): 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens[i + 1] = '' 7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) m = lead_whitespace_re.search(next_chunk) 7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk = next_chunk[m.end():] 7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens[i + 1] = next_chunk 7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tokens 7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def find_position(string, index, last_index, last_pos): 7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """Given a string and index, return (line, column)""" 7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lines = string.count('\n', last_index, index) 7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if lines > 0: 7715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) column = index - string.rfind('\n', last_index, index) 7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) column = last_pos[1] + (index - last_index) 7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (last_pos[0] + lines, column) 7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse(s, name=None, line_offset=0, delimeters=None): 7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) r""" 7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Parses a string into a kind of AST 7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{x}}') 7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('expr', (1, 3), 'x')] 7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('foo') 7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ['foo'] 7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{if x}}test{{endif}}') 7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))] 7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('series->{{for x in y}}x={{x}}{{endfor}}') 7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])] 7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}') 7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])] 7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{py:x=1}}') 7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('py', (1, 3), 'x=1')] 7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}') 7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))] 7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Some exceptions:: 7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{continue}}') 7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: continue outside of for loop at line 1 column 3 8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{if x}}foo') 8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: No {{endif}} at line 1 column 3 8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{else}}') 8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: else outside of an if block at line 1 column 3 8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}') 8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: Unexpected endif at line 1 column 25 8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{if}}{{endif}}') 8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: if with no expression at line 1 column 3 8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{for x y}}{{endfor}}') 8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: Bad for (no "in") in 'x y' at line 1 column 3 8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) >>> parse('{{py:x=1\ny=2}}') 8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Traceback (most recent call last): 8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ... 8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateError: Multi-line py blocks must start with a newline at line 1 column 3 8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) """ 8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if delimeters is None: 8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) delimeters = ( Template.default_namespace['start_braces'], 8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) Template.default_namespace['end_braces'] ) 8305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens = lex(s, name=name, line_offset=line_offset, delimeters=delimeters) 8315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = [] 8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while tokens: 8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk, tokens = parse_expr(tokens, name) 8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result.append(next_chunk) 8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return result 8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_expr(tokens, name, context=()): 8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if isinstance(tokens[0], basestring_): 8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tokens[0], tokens[1:] 8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr, pos = tokens[0] 8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = expr.strip() 8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expr.startswith('py:'): 8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = expr[3:].lstrip(' \t') 8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if expr.startswith('\n') or expr.startswith('\r'): 8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = expr.lstrip('\r\n') 8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '\r' in expr: 8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = expr.replace('\r\n', '\n') 8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = expr.replace('\r', '') 8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr += '\n' 8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '\n' in expr: 8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Multi-line py blocks must start with a newline', 8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('py', pos, expr), tokens[1:] 8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr in ('continue', 'break'): 8585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if 'for' not in context: 8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'continue outside of for loop', 8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return (expr, pos), tokens[1:] 8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('if '): 8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return parse_cond(tokens, name, context) 8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif (expr.startswith('elif ') 8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or expr == 'else'): 8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '%s outside of an if block' % expr.split()[0], 8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr in ('if', 'elif', 'for'): 8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '%s with no expression' % expr, 8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr in ('endif', 'endfor', 'enddef'): 8755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Unexpected %s' % expr, 8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('for '): 8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return parse_for(tokens, name, context) 8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('default '): 8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return parse_default(tokens, name, context) 8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('inherit '): 8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return parse_inherit(tokens, name, context) 8845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('def '): 8855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return parse_def(tokens, name, context) 8865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif expr.startswith('#'): 8875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('comment', pos, tokens[0][0]), tokens[1:] 8885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('expr', pos, tokens[0][0]), tokens[1:] 8895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 8915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_cond(tokens, name, context): 8925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start = tokens[0][1] 8935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pieces = [] 8945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = context + ('if',) 8955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 8965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not tokens: 8975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 8985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Missing {{endif}}', 8995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=start, name=name) 9005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (isinstance(tokens[0], tuple) 9015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and tokens[0][0] == 'endif'): 9025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('cond', start) + tuple(pieces), tokens[1:] 9035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk, tokens = parse_one_cond(tokens, name, context) 9045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pieces.append(next_chunk) 9055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_one_cond(tokens, name, context): 9085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (first, pos), tokens = tokens[0], tokens[1:] 9095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content = [] 9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if first.endswith(':'): 9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first[:-1] 9125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if first.startswith('if '): 9135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) part = ('if', pos, first[3:].lstrip(), content) 9145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif first.startswith('elif '): 9155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) part = ('elif', pos, first[5:].lstrip(), content) 9165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif first == 'else': 9175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) part = ('else', pos, None, content) 9185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 9195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert 0, "Unexpected token %r at %s" % (first, pos) 9205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 9215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not tokens: 9225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'No {{endif}}', 9245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 9255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (isinstance(tokens[0], tuple) 9265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and (tokens[0][0] == 'endif' 9275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or tokens[0][0].startswith('elif ') 9285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) or tokens[0][0] == 'else')): 9295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return part, tokens 9305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk, tokens = parse_expr(tokens, name, context) 9315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content.append(next_chunk) 9325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_for(tokens, name, context): 9355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first, pos = tokens[0] 9365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens = tokens[1:] 9375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = ('for',) + context 9385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content = [] 9395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert first.startswith('for ') 9405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if first.endswith(':'): 9415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first[:-1] 9425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first[3:].strip() 9435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) match = in_re.search(first) 9445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not match: 9455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Bad for (no "in") in %r' % first, 9475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 9485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars = first[:match.start()] 9495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '(' in vars: 9505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'You cannot have () in the variable section of a for loop (%r)' 9525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) % vars, position=pos, name=name) 9535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars = tuple([ 9545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) v.strip() for v in first[:match.start()].split(',') 9555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if v.strip()]) 9565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = first[match.end():] 9575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 9585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not tokens: 9595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'No {{endfor}}', 9615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 9625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (isinstance(tokens[0], tuple) 9635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and tokens[0][0] == 'endfor'): 9645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('for', pos, vars, expr, content), tokens[1:] 9655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk, tokens = parse_expr(tokens, name, context) 9665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content.append(next_chunk) 9675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_default(tokens, name, context): 9705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first, pos = tokens[0] 9715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert first.startswith('default ') 9725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first.split(None, 1)[1] 9735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = first.split('=', 1) 9745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(parts) == 1: 9755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Expression must be {{default var=value}}; no = found in %r" % first, 9775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 9785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var = parts[0].strip() 9795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ',' in var: 9805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "{{default x, y = ...}} is not supported", 9825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 9835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not var_re.search(var): 9845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 9855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "Not a valid variable name for {{default}}: %r" 9865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) % var, position=pos, name=name) 9875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = parts[1].strip() 9885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('default', pos, var, expr), tokens[1:] 9895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_inherit(tokens, name, context): 9925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first, pos = tokens[0] 9935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert first.startswith('inherit ') 9945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) expr = first.split(None, 1)[1] 9955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('inherit', pos, expr), tokens[1:] 9965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 9985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_def(tokens, name, context): 9995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first, start = tokens[0] 10005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens = tokens[1:] 10015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) assert first.startswith('def ') 10025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first.split(None, 1)[1] 10035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if first.endswith(':'): 10045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first[:-1] 10055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '(' not in first: 10065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_name = first 10075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig = ((), None, None, {}) 10085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not first.endswith(')'): 10095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError("Function definition doesn't end with ): %s" % first, 10105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=start, name=name) 10115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 10125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) first = first[:-1] 10135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) func_name, sig_text = first.split('(', 1) 10145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig = parse_signature(sig_text, name, start) 10155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) context = context + ('def',) 10165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content = [] 10175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 10185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not tokens: 10195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError( 10205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 'Missing {{enddef}}', 10215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=start, name=name) 10225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (isinstance(tokens[0], tuple) 10235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) and tokens[0][0] == 'enddef'): 10245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ('def', start, func_name, sig, content), tokens[1:] 10255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) next_chunk, tokens = parse_expr(tokens, name, context) 10265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) content.append(next_chunk) 10275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def parse_signature(sig_text, name, pos): 10305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tokens = tokenize.generate_tokens(StringIO(sig_text).readline) 10315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args = [] 10325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_arg = None 10335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_kw = None 10345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) defaults = {} 10355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 10365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) def get_token(pos=False): 10375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) try: 10385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tok_type, tok_string, (srow, scol), (erow, ecol), line = next(tokens) 10395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) except StopIteration: 10405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tokenize.ENDMARKER, '' 10415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if pos: 10425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tok_type, tok_string, (srow, scol), (erow, ecol) 10435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 10445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return tok_type, tok_string 10455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 10465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_arg_type = None 10475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tok_type, tok_string = get_token() 10485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.ENDMARKER: 10495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 10505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.OP and (tok_string == '*' or tok_string == '**'): 10515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_arg_type = tok_string 10525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tok_type, tok_string = get_token() 10535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type != tokenize.NAME: 10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('Invalid signature: (%s)' % sig_text, 10555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 10565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_name = tok_string 10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tok_type, tok_string = get_token() 10585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.ENDMARKER or (tok_type == tokenize.OP and tok_string == ','): 10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if var_arg_type == '*': 10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_arg = var_name 10615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif var_arg_type == '**': 10625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) var_kw = var_name 10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 10645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args.append(var_name) 10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.ENDMARKER: 10665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 10675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) continue 10685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if var_arg_type is not None: 10695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('Invalid signature: (%s)' % sig_text, 10705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 10715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.OP and tok_string == '=': 10725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_type = None 10735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unnest_type = None 10745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_count = 0 10755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_pos = end_pos = None 10765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = [] 10775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) while 1: 10785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) tok_type, tok_string, s, e = get_token(True) 10795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if start_pos is None: 10805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) start_pos = s 10815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) end_pos = e 10825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if tok_type == tokenize.ENDMARKER and nest_count: 10835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) raise TemplateError('Invalid signature: (%s)' % sig_text, 10845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) position=pos, name=name) 10855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (not nest_count and 10865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (tok_type == tokenize.ENDMARKER or (tok_type == tokenize.OP and tok_string == ','))): 10875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) default_expr = isolate_expression(sig_text, start_pos, end_pos) 10885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) defaults[var_name] = default_expr 10895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sig_args.append(var_name) 10905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) break 10915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts.append((tok_type, tok_string)) 10925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if nest_count and tok_type == tokenize.OP and tok_string == nest_type: 10935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_count += 1 10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif nest_count and tok_type == tokenize.OP and tok_string == unnest_type: 10955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_count -= 1 10965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if not nest_count: 10975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_type = unnest_type = None 10985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) elif not nest_count and tok_type == tokenize.OP and tok_string in ('(', '[', '{'): 10995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_type = tok_string 11005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) nest_count = 1 11015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) unnest_type = {'(': ')', '[': ']', '{': '}'}[nest_type] 11025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return sig_args, var_arg, var_kw, defaults 11035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def isolate_expression(string, start_pos, end_pos): 11065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) srow, scol = start_pos 11075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) srow -= 1 11085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) erow, ecol = end_pos 11095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) erow -= 1 11105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) lines = string.splitlines(True) 11115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if srow == erow: 11125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return lines[srow][scol:ecol] 11135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts = [lines[srow][scol:]] 11145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts.extend(lines[srow+1:erow]) 11155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if erow < len(lines): 11165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) # It'll sometimes give (end_row_past_finish, 0) 11175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parts.append(lines[erow][:ecol]) 11185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ''.join(parts) 11195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)_fill_command_usage = """\ 11215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)%prog [OPTIONS] TEMPLATE arg=value 11225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)Use py:arg=value to set a Python value; otherwise all values are 11245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)strings. 11255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)""" 11265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)def fill_command(args=None): 11295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) import sys 11305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) import optparse 11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) import pkg_resources 11325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) import os 11335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if args is None: 11345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = sys.argv[1:] 11355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dist = pkg_resources.get_distribution('Paste') 11365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parser = optparse.OptionParser( 11375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) version=coerce_text(dist), 11385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) usage=_fill_command_usage) 11395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parser.add_option( 11405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '-o', '--output', 11415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dest='output', 11425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) metavar="FILENAME", 11435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) help="File to write output to (default stdout)") 11445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parser.add_option( 11455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '--html', 11465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dest='use_html', 11475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) action='store_true', 11485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) help="Use HTML style filling (including automatic HTML quoting)") 11495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) parser.add_option( 11505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) '--env', 11515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dest='use_env', 11525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) action='store_true', 11535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) help="Put the environment in as top-level variables") 11545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) options, args = parser.parse_args(args) 11555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if len(args) < 1: 11565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) print('You must give a template filename') 11575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sys.exit(2) 11585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template_name = args[0] 11595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) args = args[1:] 11605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars = {} 11615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if options.use_env: 11625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars.update(os.environ) 11635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for value in args: 11645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if '=' not in value: 11655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) print('Bad argument: %r' % value) 11665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sys.exit(2) 11675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name, value = value.split('=', 1) 11685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if name.startswith('py:'): 11695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) name = name[:3] 11705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) value = eval(value) 11715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) vars[name] = value 11725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if template_name == '-': 11735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template_content = sys.stdin.read() 11745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template_name = '<stdin>' 11755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 11765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f = open(template_name, 'rb') 11775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template_content = f.read() 11785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f.close() 11795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if options.use_html: 11805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateClass = HTMLTemplate 11815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 11825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) TemplateClass = Template 11835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) template = TemplateClass(template_content, name=template_name) 11845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) result = template.substitute(vars) 11855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if options.output: 11865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f = open(options.output, 'wb') 11875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f.write(result) 11885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) f.close() 11895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else: 11905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sys.stdout.write(result) 11915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 11925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)if __name__ == '__main__': 11935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) fill_command() 1194