| Index: third_party/Paste/paste/util/template.py.orig
|
| diff --git a/third_party/Paste/paste/util/template.py.orig b/third_party/Paste/paste/util/template.py.orig
|
| deleted file mode 100644
|
| index 89466c3dae2ffa5bef9c51fdfacf549189dfc007..0000000000000000000000000000000000000000
|
| --- a/third_party/Paste/paste/util/template.py.orig
|
| +++ /dev/null
|
| @@ -1,762 +0,0 @@
|
| -"""
|
| -A small templating language
|
| -
|
| -This implements a small templating language for use internally in
|
| -Paste and Paste Script. This language implements if/elif/else,
|
| -for/continue/break, expressions, and blocks of Python code. The
|
| -syntax is::
|
| -
|
| - {{any expression (function calls etc)}}
|
| - {{any expression | filter}}
|
| - {{for x in y}}...{{endfor}}
|
| - {{if x}}x{{elif y}}y{{else}}z{{endif}}
|
| - {{py:x=1}}
|
| - {{py:
|
| - def foo(bar):
|
| - return 'baz'
|
| - }}
|
| - {{default var = default_value}}
|
| - {{# comment}}
|
| -
|
| -You use this with the ``Template`` class or the ``sub`` shortcut.
|
| -The ``Template`` class takes the template string and the name of
|
| -the template (for errors) and a default namespace. Then (like
|
| -``string.Template``) you can call the ``tmpl.substitute(**kw)``
|
| -method to make a substitution (or ``tmpl.substitute(a_dict)``).
|
| -
|
| -``sub(content, **kw)`` substitutes the template immediately. You
|
| -can use ``__name='tmpl.html'`` to set the name of the template.
|
| -
|
| -If there are syntax errors ``TemplateError`` will be raised.
|
| -"""
|
| -
|
| -import re
|
| -import six
|
| -import sys
|
| -import cgi
|
| -from six.moves.urllib.parse import quote
|
| -from paste.util.looper import looper
|
| -
|
| -__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
|
| - 'sub_html', 'html', 'bunch']
|
| -
|
| -token_re = re.compile(r'\{\{|\}\}')
|
| -in_re = re.compile(r'\s+in\s+')
|
| -var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
|
| -
|
| -class TemplateError(Exception):
|
| - """Exception raised while parsing a template
|
| - """
|
| -
|
| - def __init__(self, message, position, name=None):
|
| - self.message = message
|
| - self.position = position
|
| - self.name = name
|
| -
|
| - def __str__(self):
|
| - msg = '%s at line %s column %s' % (
|
| - self.message, self.position[0], self.position[1])
|
| - if self.name:
|
| - msg += ' in %s' % self.name
|
| - return msg
|
| -
|
| -class _TemplateContinue(Exception):
|
| - pass
|
| -
|
| -class _TemplateBreak(Exception):
|
| - pass
|
| -
|
| -class Template(object):
|
| -
|
| - default_namespace = {
|
| - 'start_braces': '{{',
|
| - 'end_braces': '}}',
|
| - 'looper': looper,
|
| - }
|
| -
|
| - default_encoding = 'utf8'
|
| -
|
| - def __init__(self, content, name=None, namespace=None):
|
| - self.content = content
|
| - self._unicode = isinstance(content, six.text_type)
|
| - self.name = name
|
| -
|
| - if not self._unicode:
|
| - content = content.decode(self.default_encoding)
|
| - self._unicode = True
|
| -
|
| - self._parsed = parse(content, name=name)
|
| - if namespace is None:
|
| - namespace = {}
|
| - self.namespace = namespace
|
| -
|
| - def from_filename(cls, filename, namespace=None, encoding=None):
|
| - f = open(filename, 'rb')
|
| - c = f.read()
|
| - f.close()
|
| - if encoding:
|
| - c = c.decode(encoding)
|
| - return cls(content=c, name=filename, namespace=namespace)
|
| -
|
| - from_filename = classmethod(from_filename)
|
| -
|
| - def __repr__(self):
|
| - return '<%s %s name=%r>' % (
|
| - self.__class__.__name__,
|
| - hex(id(self))[2:], self.name)
|
| -
|
| - def substitute(self, *args, **kw):
|
| - if args:
|
| - if kw:
|
| - raise TypeError(
|
| - "You can only give positional *or* keyword arguments")
|
| - if len(args) > 1:
|
| - raise TypeError(
|
| - "You can only give on positional argument")
|
| - kw = args[0]
|
| - ns = self.default_namespace.copy()
|
| - ns.update(self.namespace)
|
| - ns.update(kw)
|
| - result = self._interpret(ns)
|
| - return result
|
| -
|
| - def _interpret(self, ns):
|
| - __traceback_hide__ = True
|
| - parts = []
|
| - self._interpret_codes(self._parsed, ns, out=parts)
|
| - return ''.join(parts)
|
| -
|
| - def _interpret_codes(self, codes, ns, out):
|
| - __traceback_hide__ = True
|
| - for item in codes:
|
| - if isinstance(item, six.string_types):
|
| - out.append(item)
|
| - else:
|
| - self._interpret_code(item, ns, out)
|
| -
|
| - def _interpret_code(self, code, ns, out):
|
| - __traceback_hide__ = True
|
| - name, pos = code[0], code[1]
|
| - if name == 'py':
|
| - self._exec(code[2], ns, pos)
|
| - elif name == 'continue':
|
| - raise _TemplateContinue()
|
| - elif name == 'break':
|
| - raise _TemplateBreak()
|
| - elif name == 'for':
|
| - vars, expr, content = code[2], code[3], code[4]
|
| - expr = self._eval(expr, ns, pos)
|
| - self._interpret_for(vars, expr, content, ns, out)
|
| - elif name == 'cond':
|
| - parts = code[2:]
|
| - self._interpret_if(parts, ns, out)
|
| - elif name == 'expr':
|
| - parts = code[2].split('|')
|
| - base = self._eval(parts[0], ns, pos)
|
| - for part in parts[1:]:
|
| - func = self._eval(part, ns, pos)
|
| - base = func(base)
|
| - out.append(self._repr(base, pos))
|
| - elif name == 'default':
|
| - var, expr = code[2], code[3]
|
| - if var not in ns:
|
| - result = self._eval(expr, ns, pos)
|
| - ns[var] = result
|
| - elif name == 'comment':
|
| - return
|
| - else:
|
| - assert 0, "Unknown code: %r" % name
|
| -
|
| - def _interpret_for(self, vars, expr, content, ns, out):
|
| - __traceback_hide__ = True
|
| - for item in expr:
|
| - if len(vars) == 1:
|
| - ns[vars[0]] = item
|
| - else:
|
| - if len(vars) != len(item):
|
| - raise ValueError(
|
| - 'Need %i items to unpack (got %i items)'
|
| - % (len(vars), len(item)))
|
| - for name, value in zip(vars, item):
|
| - ns[name] = value
|
| - try:
|
| - self._interpret_codes(content, ns, out)
|
| - except _TemplateContinue:
|
| - continue
|
| - except _TemplateBreak:
|
| - break
|
| -
|
| - def _interpret_if(self, parts, ns, out):
|
| - __traceback_hide__ = True
|
| - # @@: if/else/else gets through
|
| - for part in parts:
|
| - assert not isinstance(part, six.string_types)
|
| - name, pos = part[0], part[1]
|
| - if name == 'else':
|
| - result = True
|
| - else:
|
| - result = self._eval(part[2], ns, pos)
|
| - if result:
|
| - self._interpret_codes(part[3], ns, out)
|
| - break
|
| -
|
| - def _eval(self, code, ns, pos):
|
| - __traceback_hide__ = True
|
| - try:
|
| - value = eval(code, ns)
|
| - return value
|
| - except:
|
| - exc_info = sys.exc_info()
|
| - e = exc_info[1]
|
| - if getattr(e, 'args'):
|
| - arg0 = e.args[0]
|
| - else:
|
| - arg0 = str(e)
|
| - e.args = (self._add_line_info(arg0, pos),)
|
| - six.reraise(exc_info[0], e, exc_info[2])
|
| -
|
| - def _exec(self, code, ns, pos):
|
| - __traceback_hide__ = True
|
| - try:
|
| - six.exec_(code, ns)
|
| - except:
|
| - exc_info = sys.exc_info()
|
| - e = exc_info[1]
|
| - e.args = (self._add_line_info(e.args[0], pos),)
|
| - six.reraise(exc_info[0], e, exc_info[2])
|
| -
|
| - def _repr(self, value, pos):
|
| - __traceback_hide__ = True
|
| - try:
|
| - if value is None:
|
| - return ''
|
| - if self._unicode:
|
| - try:
|
| - value = six.text_type(value)
|
| - except UnicodeDecodeError:
|
| - value = str(value)
|
| - else:
|
| - value = str(value)
|
| - except:
|
| - exc_info = sys.exc_info()
|
| - e = exc_info[1]
|
| - e.args = (self._add_line_info(e.args[0], pos),)
|
| - six.reraise(exc_info[0], e, exc_info[2])
|
| - else:
|
| - if self._unicode and isinstance(value, six.binary_type):
|
| - if not self.default_encoding:
|
| - raise UnicodeDecodeError(
|
| - 'Cannot decode str value %r into unicode '
|
| - '(no default_encoding provided)' % value)
|
| - value = value.decode(self.default_encoding)
|
| - elif not self._unicode and isinstance(value, six.text_type):
|
| - if not self.default_encoding:
|
| - raise UnicodeEncodeError(
|
| - 'Cannot encode unicode value %r into str '
|
| - '(no default_encoding provided)' % value)
|
| - value = value.encode(self.default_encoding)
|
| - return value
|
| -
|
| -
|
| - def _add_line_info(self, msg, pos):
|
| - msg = "%s at line %s column %s" % (
|
| - msg, pos[0], pos[1])
|
| - if self.name:
|
| - msg += " in file %s" % self.name
|
| - return msg
|
| -
|
| -def sub(content, **kw):
|
| - name = kw.get('__name')
|
| - tmpl = Template(content, name=name)
|
| - return tmpl.substitute(kw)
|
| -
|
| -def paste_script_template_renderer(content, vars, filename=None):
|
| - tmpl = Template(content, name=filename)
|
| - return tmpl.substitute(vars)
|
| -
|
| -class bunch(dict):
|
| -
|
| - def __init__(self, **kw):
|
| - for name, value in kw.items():
|
| - setattr(self, name, value)
|
| -
|
| - def __setattr__(self, name, value):
|
| - self[name] = value
|
| -
|
| - def __getattr__(self, name):
|
| - try:
|
| - return self[name]
|
| - except KeyError:
|
| - raise AttributeError(name)
|
| -
|
| - def __getitem__(self, key):
|
| - if 'default' in self:
|
| - try:
|
| - return dict.__getitem__(self, key)
|
| - except KeyError:
|
| - return dict.__getitem__(self, 'default')
|
| - else:
|
| - return dict.__getitem__(self, key)
|
| -
|
| - def __repr__(self):
|
| - items = [
|
| - (k, v) for k, v in self.items()]
|
| - items.sort()
|
| - return '<%s %s>' % (
|
| - self.__class__.__name__,
|
| - ' '.join(['%s=%r' % (k, v) for k, v in items]))
|
| -
|
| -############################################################
|
| -## HTML Templating
|
| -############################################################
|
| -
|
| -class html(object):
|
| - def __init__(self, value):
|
| - self.value = value
|
| - def __str__(self):
|
| - return self.value
|
| - def __repr__(self):
|
| - return '<%s %r>' % (
|
| - self.__class__.__name__, self.value)
|
| -
|
| -def html_quote(value):
|
| - if value is None:
|
| - return ''
|
| - if not isinstance(value, six.string_types):
|
| - if hasattr(value, '__unicode__'):
|
| - value = unicode(value)
|
| - else:
|
| - value = str(value)
|
| - value = cgi.escape(value, 1)
|
| - if isinstance(value, unicode):
|
| - value = value.encode('ascii', 'xmlcharrefreplace')
|
| - return value
|
| -
|
| -def url(v):
|
| - if not isinstance(v, six.string_types):
|
| - if hasattr(v, '__unicode__'):
|
| - v = unicode(v)
|
| - else:
|
| - v = str(v)
|
| - if isinstance(v, unicode):
|
| - v = v.encode('utf8')
|
| - return quote(v)
|
| -
|
| -def attr(**kw):
|
| - kw = kw.items()
|
| - kw.sort()
|
| - parts = []
|
| - for name, value in kw:
|
| - if value is None:
|
| - continue
|
| - if name.endswith('_'):
|
| - name = name[:-1]
|
| - parts.append('%s="%s"' % (html_quote(name), html_quote(value)))
|
| - return html(' '.join(parts))
|
| -
|
| -class HTMLTemplate(Template):
|
| -
|
| - default_namespace = Template.default_namespace.copy()
|
| - default_namespace.update(dict(
|
| - html=html,
|
| - attr=attr,
|
| - url=url,
|
| - ))
|
| -
|
| - def _repr(self, value, pos):
|
| - plain = Template._repr(self, value, pos)
|
| - if isinstance(value, html):
|
| - return plain
|
| - else:
|
| - return html_quote(plain)
|
| -
|
| -def sub_html(content, **kw):
|
| - name = kw.get('__name')
|
| - tmpl = HTMLTemplate(content, name=name)
|
| - return tmpl.substitute(kw)
|
| -
|
| -
|
| -############################################################
|
| -## Lexing and Parsing
|
| -############################################################
|
| -
|
| -def lex(s, name=None, trim_whitespace=True):
|
| - """
|
| - Lex a string into chunks:
|
| -
|
| - >>> lex('hey')
|
| - ['hey']
|
| - >>> lex('hey {{you}}')
|
| - ['hey ', ('you', (1, 7))]
|
| - >>> lex('hey {{')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: No }} to finish last expression at line 1 column 7
|
| - >>> lex('hey }}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: }} outside expression at line 1 column 7
|
| - >>> lex('hey {{ {{')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: {{ inside expression at line 1 column 10
|
| -
|
| - """
|
| - in_expr = False
|
| - chunks = []
|
| - last = 0
|
| - last_pos = (1, 1)
|
| - for match in token_re.finditer(s):
|
| - expr = match.group(0)
|
| - pos = find_position(s, match.end())
|
| - if expr == '{{' and in_expr:
|
| - raise TemplateError('{{ inside expression', position=pos,
|
| - name=name)
|
| - elif expr == '}}' and not in_expr:
|
| - raise TemplateError('}} outside expression', position=pos,
|
| - name=name)
|
| - if expr == '{{':
|
| - part = s[last:match.start()]
|
| - if part:
|
| - chunks.append(part)
|
| - in_expr = True
|
| - else:
|
| - chunks.append((s[last:match.start()], last_pos))
|
| - in_expr = False
|
| - last = match.end()
|
| - last_pos = pos
|
| - if in_expr:
|
| - raise TemplateError('No }} to finish last expression',
|
| - name=name, position=last_pos)
|
| - part = s[last:]
|
| - if part:
|
| - chunks.append(part)
|
| - if trim_whitespace:
|
| - chunks = trim_lex(chunks)
|
| - return chunks
|
| -
|
| -statement_re = re.compile(r'^(?:if |elif |else |for |py:)')
|
| -single_statements = ['endif', 'endfor', 'continue', 'break']
|
| -trail_whitespace_re = re.compile(r'\n[\t ]*$')
|
| -lead_whitespace_re = re.compile(r'^[\t ]*\n')
|
| -
|
| -def trim_lex(tokens):
|
| - r"""
|
| - Takes a lexed set of tokens, and removes whitespace when there is
|
| - a directive on a line by itself:
|
| -
|
| - >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
|
| - >>> tokens
|
| - [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
|
| - >>> trim_lex(tokens)
|
| - [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
|
| - """
|
| - for i in range(len(tokens)):
|
| - current = tokens[i]
|
| - if isinstance(tokens[i], six.string_types):
|
| - # we don't trim this
|
| - continue
|
| - item = current[0]
|
| - if not statement_re.search(item) and item not in single_statements:
|
| - continue
|
| - if not i:
|
| - prev = ''
|
| - else:
|
| - prev = tokens[i-1]
|
| - if i+1 >= len(tokens):
|
| - next = ''
|
| - else:
|
| - next = tokens[i+1]
|
| - if (not isinstance(next, six.string_types)
|
| - or not isinstance(prev, six.string_types)):
|
| - continue
|
| - if ((not prev or trail_whitespace_re.search(prev))
|
| - and (not next or lead_whitespace_re.search(next))):
|
| - if prev:
|
| - m = trail_whitespace_re.search(prev)
|
| - # +1 to leave the leading \n on:
|
| - prev = prev[:m.start()+1]
|
| - tokens[i-1] = prev
|
| - if next:
|
| - m = lead_whitespace_re.search(next)
|
| - next = next[m.end():]
|
| - tokens[i+1] = next
|
| - return tokens
|
| -
|
| -
|
| -def find_position(string, index):
|
| - """Given a string and index, return (line, column)"""
|
| - leading = string[:index].splitlines()
|
| - return (len(leading), len(leading[-1])+1)
|
| -
|
| -def parse(s, name=None):
|
| - r"""
|
| - Parses a string into a kind of AST
|
| -
|
| - >>> parse('{{x}}')
|
| - [('expr', (1, 3), 'x')]
|
| - >>> parse('foo')
|
| - ['foo']
|
| - >>> parse('{{if x}}test{{endif}}')
|
| - [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
|
| - >>> parse('series->{{for x in y}}x={{x}}{{endfor}}')
|
| - ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
|
| - >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
|
| - [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
|
| - >>> parse('{{py:x=1}}')
|
| - [('py', (1, 3), 'x=1')]
|
| - >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}')
|
| - [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
|
| -
|
| - Some exceptions::
|
| -
|
| - >>> parse('{{continue}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: continue outside of for loop at line 1 column 3
|
| - >>> parse('{{if x}}foo')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: No {{endif}} at line 1 column 3
|
| - >>> parse('{{else}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: else outside of an if block at line 1 column 3
|
| - >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: Unexpected endif at line 1 column 25
|
| - >>> parse('{{if}}{{endif}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: if with no expression at line 1 column 3
|
| - >>> parse('{{for x y}}{{endfor}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
|
| - >>> parse('{{py:x=1\ny=2}}')
|
| - Traceback (most recent call last):
|
| - ...
|
| - TemplateError: Multi-line py blocks must start with a newline at line 1 column 3
|
| - """
|
| - tokens = lex(s, name=name)
|
| - result = []
|
| - while tokens:
|
| - next, tokens = parse_expr(tokens, name)
|
| - result.append(next)
|
| - return result
|
| -
|
| -def parse_expr(tokens, name, context=()):
|
| - if isinstance(tokens[0], six.string_types):
|
| - return tokens[0], tokens[1:]
|
| - expr, pos = tokens[0]
|
| - expr = expr.strip()
|
| - if expr.startswith('py:'):
|
| - expr = expr[3:].lstrip(' \t')
|
| - if expr.startswith('\n'):
|
| - expr = expr[1:]
|
| - else:
|
| - if '\n' in expr:
|
| - raise TemplateError(
|
| - 'Multi-line py blocks must start with a newline',
|
| - position=pos, name=name)
|
| - return ('py', pos, expr), tokens[1:]
|
| - elif expr in ('continue', 'break'):
|
| - if 'for' not in context:
|
| - raise TemplateError(
|
| - 'continue outside of for loop',
|
| - position=pos, name=name)
|
| - return (expr, pos), tokens[1:]
|
| - elif expr.startswith('if '):
|
| - return parse_cond(tokens, name, context)
|
| - elif (expr.startswith('elif ')
|
| - or expr == 'else'):
|
| - raise TemplateError(
|
| - '%s outside of an if block' % expr.split()[0],
|
| - position=pos, name=name)
|
| - elif expr in ('if', 'elif', 'for'):
|
| - raise TemplateError(
|
| - '%s with no expression' % expr,
|
| - position=pos, name=name)
|
| - elif expr in ('endif', 'endfor'):
|
| - raise TemplateError(
|
| - 'Unexpected %s' % expr,
|
| - position=pos, name=name)
|
| - elif expr.startswith('for '):
|
| - return parse_for(tokens, name, context)
|
| - elif expr.startswith('default '):
|
| - return parse_default(tokens, name, context)
|
| - elif expr.startswith('#'):
|
| - return ('comment', pos, tokens[0][0]), tokens[1:]
|
| - return ('expr', pos, tokens[0][0]), tokens[1:]
|
| -
|
| -def parse_cond(tokens, name, context):
|
| - start = tokens[0][1]
|
| - pieces = []
|
| - context = context + ('if',)
|
| - while 1:
|
| - if not tokens:
|
| - raise TemplateError(
|
| - 'Missing {{endif}}',
|
| - position=start, name=name)
|
| - if (isinstance(tokens[0], tuple)
|
| - and tokens[0][0] == 'endif'):
|
| - return ('cond', start) + tuple(pieces), tokens[1:]
|
| - next, tokens = parse_one_cond(tokens, name, context)
|
| - pieces.append(next)
|
| -
|
| -def parse_one_cond(tokens, name, context):
|
| - (first, pos), tokens = tokens[0], tokens[1:]
|
| - content = []
|
| - if first.endswith(':'):
|
| - first = first[:-1]
|
| - if first.startswith('if '):
|
| - part = ('if', pos, first[3:].lstrip(), content)
|
| - elif first.startswith('elif '):
|
| - part = ('elif', pos, first[5:].lstrip(), content)
|
| - elif first == 'else':
|
| - part = ('else', pos, None, content)
|
| - else:
|
| - assert 0, "Unexpected token %r at %s" % (first, pos)
|
| - while 1:
|
| - if not tokens:
|
| - raise TemplateError(
|
| - 'No {{endif}}',
|
| - position=pos, name=name)
|
| - if (isinstance(tokens[0], tuple)
|
| - and (tokens[0][0] == 'endif'
|
| - or tokens[0][0].startswith('elif ')
|
| - or tokens[0][0] == 'else')):
|
| - return part, tokens
|
| - next, tokens = parse_expr(tokens, name, context)
|
| - content.append(next)
|
| -
|
| -def parse_for(tokens, name, context):
|
| - first, pos = tokens[0]
|
| - tokens = tokens[1:]
|
| - context = ('for',) + context
|
| - content = []
|
| - assert first.startswith('for ')
|
| - if first.endswith(':'):
|
| - first = first[:-1]
|
| - first = first[3:].strip()
|
| - match = in_re.search(first)
|
| - if not match:
|
| - raise TemplateError(
|
| - 'Bad for (no "in") in %r' % first,
|
| - position=pos, name=name)
|
| - vars = first[:match.start()]
|
| - if '(' in vars:
|
| - raise TemplateError(
|
| - 'You cannot have () in the variable section of a for loop (%r)'
|
| - % vars, position=pos, name=name)
|
| - vars = tuple([
|
| - v.strip() for v in first[:match.start()].split(',')
|
| - if v.strip()])
|
| - expr = first[match.end():]
|
| - while 1:
|
| - if not tokens:
|
| - raise TemplateError(
|
| - 'No {{endfor}}',
|
| - position=pos, name=name)
|
| - if (isinstance(tokens[0], tuple)
|
| - and tokens[0][0] == 'endfor'):
|
| - return ('for', pos, vars, expr, content), tokens[1:]
|
| - next, tokens = parse_expr(tokens, name, context)
|
| - content.append(next)
|
| -
|
| -def parse_default(tokens, name, context):
|
| - first, pos = tokens[0]
|
| - assert first.startswith('default ')
|
| - first = first.split(None, 1)[1]
|
| - parts = first.split('=', 1)
|
| - if len(parts) == 1:
|
| - raise TemplateError(
|
| - "Expression must be {{default var=value}}; no = found in %r" % first,
|
| - position=pos, name=name)
|
| - var = parts[0].strip()
|
| - if ',' in var:
|
| - raise TemplateError(
|
| - "{{default x, y = ...}} is not supported",
|
| - position=pos, name=name)
|
| - if not var_re.search(var):
|
| - raise TemplateError(
|
| - "Not a valid variable name for {{default}}: %r"
|
| - % var, position=pos, name=name)
|
| - expr = parts[1].strip()
|
| - return ('default', pos, var, expr), tokens[1:]
|
| -
|
| -_fill_command_usage = """\
|
| -%prog [OPTIONS] TEMPLATE arg=value
|
| -
|
| -Use py:arg=value to set a Python value; otherwise all values are
|
| -strings.
|
| -"""
|
| -
|
| -def fill_command(args=None):
|
| - import sys, optparse, pkg_resources, os
|
| - if args is None:
|
| - args = sys.argv[1:]
|
| - dist = pkg_resources.get_distribution('Paste')
|
| - parser = optparse.OptionParser(
|
| - version=str(dist),
|
| - usage=_fill_command_usage)
|
| - parser.add_option(
|
| - '-o', '--output',
|
| - dest='output',
|
| - metavar="FILENAME",
|
| - help="File to write output to (default stdout)")
|
| - parser.add_option(
|
| - '--html',
|
| - dest='use_html',
|
| - action='store_true',
|
| - help="Use HTML style filling (including automatic HTML quoting)")
|
| - parser.add_option(
|
| - '--env',
|
| - dest='use_env',
|
| - action='store_true',
|
| - help="Put the environment in as top-level variables")
|
| - options, args = parser.parse_args(args)
|
| - if len(args) < 1:
|
| - print('You must give a template filename')
|
| - print(dir(parser))
|
| - assert 0
|
| - template_name = args[0]
|
| - args = args[1:]
|
| - vars = {}
|
| - if options.use_env:
|
| - vars.update(os.environ)
|
| - for value in args:
|
| - if '=' not in value:
|
| - print('Bad argument: %r' % value)
|
| - sys.exit(2)
|
| - name, value = value.split('=', 1)
|
| - if name.startswith('py:'):
|
| - name = name[:3]
|
| - value = eval(value)
|
| - vars[name] = value
|
| - if template_name == '-':
|
| - template_content = sys.stdin.read()
|
| - template_name = '<stdin>'
|
| - else:
|
| - f = open(template_name, 'rb')
|
| - template_content = f.read()
|
| - f.close()
|
| - if options.use_html:
|
| - TemplateClass = HTMLTemplate
|
| - else:
|
| - TemplateClass = Template
|
| - template = TemplateClass(template_content, name=template_name)
|
| - result = template.substitute(vars)
|
| - if options.output:
|
| - f = open(options.output, 'wb')
|
| - f.write(result)
|
| - f.close()
|
| - else:
|
| - sys.stdout.write(result)
|
| -
|
| -if __name__ == '__main__':
|
| - from paste.util.template import fill_command
|
| - fill_command()
|
| -
|
| -
|
|
|