mirror of
https://github.com/rembo10/headphones.git
synced 2026-05-20 18:45:32 +01:00
Upgrade mako to 1.0.1
This commit is contained in:
20
lib/mako/LICENSE
Normal file
20
lib/mako/LICENSE
Normal file
@@ -0,0 +1,20 @@
|
||||
This is the MIT license: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>.
|
||||
Mako is a trademark of Michael Bayer.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
||||
software and associated documentation files (the "Software"), to deal in the Software
|
||||
without restriction, including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
||||
to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or
|
||||
substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
52
lib/mako/README.rst
Normal file
52
lib/mako/README.rst
Normal file
@@ -0,0 +1,52 @@
|
||||
=========================
|
||||
Mako Templates for Python
|
||||
=========================
|
||||
|
||||
Mako is a template library written in Python. It provides a familiar, non-XML
|
||||
syntax which compiles into Python modules for maximum performance. Mako's
|
||||
syntax and API borrows from the best ideas of many others, including Django
|
||||
templates, Cheetah, Myghty, and Genshi. Conceptually, Mako is an embedded
|
||||
Python (i.e. Python Server Page) language, which refines the familiar ideas
|
||||
of componentized layout and inheritance to produce one of the most
|
||||
straightforward and flexible models available, while also maintaining close
|
||||
ties to Python calling and scoping semantics.
|
||||
|
||||
Nutshell
|
||||
========
|
||||
|
||||
::
|
||||
|
||||
<%inherit file="base.html"/>
|
||||
<%
|
||||
rows = [[v for v in range(0,10)] for row in range(0,10)]
|
||||
%>
|
||||
<table>
|
||||
% for row in rows:
|
||||
${makerow(row)}
|
||||
% endfor
|
||||
</table>
|
||||
|
||||
<%def name="makerow(row)">
|
||||
<tr>
|
||||
% for name in row:
|
||||
<td>${name}</td>\
|
||||
% endfor
|
||||
</tr>
|
||||
</%def>
|
||||
|
||||
Philosophy
|
||||
===========
|
||||
|
||||
Python is a great scripting language. Don't reinvent the wheel...your templates can handle it !
|
||||
|
||||
Documentation
|
||||
==============
|
||||
|
||||
See documentation for Mako at http://www.makotemplates.org/docs/
|
||||
|
||||
License
|
||||
========
|
||||
|
||||
Mako is licensed under an MIT-style license (see LICENSE).
|
||||
Other incorporated projects may be licensed under different licenses.
|
||||
All licenses allow for non-commercial and commercial use.
|
||||
@@ -1,9 +1,8 @@
|
||||
# mako/__init__.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
|
||||
__version__ = '0.9.1'
|
||||
|
||||
__version__ = '1.0.1'
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/_ast_util.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -34,42 +34,42 @@ from _ast import *
|
||||
from mako.compat import arg_stringname
|
||||
|
||||
BOOLOP_SYMBOLS = {
|
||||
And: 'and',
|
||||
Or: 'or'
|
||||
And: 'and',
|
||||
Or: 'or'
|
||||
}
|
||||
|
||||
BINOP_SYMBOLS = {
|
||||
Add: '+',
|
||||
Sub: '-',
|
||||
Mult: '*',
|
||||
Div: '/',
|
||||
FloorDiv: '//',
|
||||
Mod: '%',
|
||||
LShift: '<<',
|
||||
RShift: '>>',
|
||||
BitOr: '|',
|
||||
BitAnd: '&',
|
||||
BitXor: '^'
|
||||
Add: '+',
|
||||
Sub: '-',
|
||||
Mult: '*',
|
||||
Div: '/',
|
||||
FloorDiv: '//',
|
||||
Mod: '%',
|
||||
LShift: '<<',
|
||||
RShift: '>>',
|
||||
BitOr: '|',
|
||||
BitAnd: '&',
|
||||
BitXor: '^'
|
||||
}
|
||||
|
||||
CMPOP_SYMBOLS = {
|
||||
Eq: '==',
|
||||
Gt: '>',
|
||||
GtE: '>=',
|
||||
In: 'in',
|
||||
Is: 'is',
|
||||
IsNot: 'is not',
|
||||
Lt: '<',
|
||||
LtE: '<=',
|
||||
NotEq: '!=',
|
||||
NotIn: 'not in'
|
||||
Eq: '==',
|
||||
Gt: '>',
|
||||
GtE: '>=',
|
||||
In: 'in',
|
||||
Is: 'is',
|
||||
IsNot: 'is not',
|
||||
Lt: '<',
|
||||
LtE: '<=',
|
||||
NotEq: '!=',
|
||||
NotIn: 'not in'
|
||||
}
|
||||
|
||||
UNARYOP_SYMBOLS = {
|
||||
Invert: '~',
|
||||
Not: 'not',
|
||||
UAdd: '+',
|
||||
USub: '-'
|
||||
Invert: '~',
|
||||
Not: 'not',
|
||||
UAdd: '+',
|
||||
USub: '-'
|
||||
}
|
||||
|
||||
ALL_SYMBOLS = {}
|
||||
@@ -215,8 +215,8 @@ def get_compile_mode(node):
|
||||
if not isinstance(node, mod):
|
||||
raise TypeError('expected mod node, got %r' % node.__class__.__name__)
|
||||
return {
|
||||
Expression: 'eval',
|
||||
Interactive: 'single'
|
||||
Expression: 'eval',
|
||||
Interactive: 'single'
|
||||
}.get(node.__class__, 'expr')
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/ast.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -8,7 +8,6 @@
|
||||
code, as well as generating Python from AST nodes"""
|
||||
|
||||
from mako import exceptions, pyparser, compat
|
||||
from mako.compat import arg_stringname
|
||||
import re
|
||||
|
||||
class PythonCode(object):
|
||||
@@ -107,43 +106,70 @@ class FunctionDecl(object):
|
||||
f.visit(expr)
|
||||
if not hasattr(self, 'funcname'):
|
||||
raise exceptions.CompileException(
|
||||
"Code '%s' is not a function declaration" % code,
|
||||
**exception_kwargs)
|
||||
"Code '%s' is not a function declaration" % code,
|
||||
**exception_kwargs)
|
||||
if not allow_kwargs and self.kwargs:
|
||||
raise exceptions.CompileException(
|
||||
"'**%s' keyword argument not allowed here" %
|
||||
self.argnames[-1], **exception_kwargs)
|
||||
self.kwargnames[-1], **exception_kwargs)
|
||||
|
||||
def get_argument_expressions(self, include_defaults=True):
|
||||
"""return the argument declarations of this FunctionDecl as a printable
|
||||
list."""
|
||||
def get_argument_expressions(self, as_call=False):
|
||||
"""Return the argument declarations of this FunctionDecl as a printable
|
||||
list.
|
||||
|
||||
By default the return value is appropriate for writing in a ``def``;
|
||||
set `as_call` to true to build arguments to be passed to the function
|
||||
instead (assuming locals with the same names as the arguments exist).
|
||||
"""
|
||||
|
||||
namedecls = []
|
||||
defaults = [d for d in self.defaults]
|
||||
kwargs = self.kwargs
|
||||
varargs = self.varargs
|
||||
argnames = [f for f in self.argnames]
|
||||
argnames.reverse()
|
||||
for arg in argnames:
|
||||
default = None
|
||||
if kwargs:
|
||||
arg = "**" + arg_stringname(arg)
|
||||
kwargs = False
|
||||
elif varargs:
|
||||
arg = "*" + arg_stringname(arg)
|
||||
varargs = False
|
||||
|
||||
# Build in reverse order, since defaults and slurpy args come last
|
||||
argnames = self.argnames[::-1]
|
||||
kwargnames = self.kwargnames[::-1]
|
||||
defaults = self.defaults[::-1]
|
||||
kwdefaults = self.kwdefaults[::-1]
|
||||
|
||||
# Named arguments
|
||||
if self.kwargs:
|
||||
namedecls.append("**" + kwargnames.pop(0))
|
||||
|
||||
for name in kwargnames:
|
||||
# Keyword-only arguments must always be used by name, so even if
|
||||
# this is a call, print out `foo=foo`
|
||||
if as_call:
|
||||
namedecls.append("%s=%s" % (name, name))
|
||||
elif kwdefaults:
|
||||
default = kwdefaults.pop(0)
|
||||
if default is None:
|
||||
# The AST always gives kwargs a default, since you can do
|
||||
# `def foo(*, a=1, b, c=3)`
|
||||
namedecls.append(name)
|
||||
else:
|
||||
namedecls.append("%s=%s" % (
|
||||
name, pyparser.ExpressionGenerator(default).value()))
|
||||
else:
|
||||
default = len(defaults) and defaults.pop() or None
|
||||
if include_defaults and default:
|
||||
namedecls.insert(0, "%s=%s" %
|
||||
(arg,
|
||||
pyparser.ExpressionGenerator(default).value()
|
||||
)
|
||||
)
|
||||
namedecls.append(name)
|
||||
|
||||
# Positional arguments
|
||||
if self.varargs:
|
||||
namedecls.append("*" + argnames.pop(0))
|
||||
|
||||
for name in argnames:
|
||||
if as_call or not defaults:
|
||||
namedecls.append(name)
|
||||
else:
|
||||
namedecls.insert(0, arg)
|
||||
default = defaults.pop(0)
|
||||
namedecls.append("%s=%s" % (
|
||||
name, pyparser.ExpressionGenerator(default).value()))
|
||||
|
||||
namedecls.reverse()
|
||||
return namedecls
|
||||
|
||||
@property
|
||||
def allargnames(self):
|
||||
return tuple(self.argnames) + tuple(self.kwargnames)
|
||||
|
||||
class FunctionArgs(FunctionDecl):
|
||||
"""the argument portion of a function declaration"""
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/cache.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -88,9 +88,10 @@ class Cache(object):
|
||||
if not self.template.cache_enabled:
|
||||
return creation_function()
|
||||
|
||||
return self.impl.get_or_create(key,
|
||||
creation_function,
|
||||
**self._get_cache_kw(kw, context))
|
||||
return self.impl.get_or_create(
|
||||
key,
|
||||
creation_function,
|
||||
**self._get_cache_kw(kw, context))
|
||||
|
||||
def set(self, key, value, **kw):
|
||||
"""Place a value in the cache.
|
||||
@@ -178,6 +179,7 @@ class Cache(object):
|
||||
tmpl_kw.setdefault('context', context)
|
||||
return tmpl_kw
|
||||
|
||||
|
||||
class CacheImpl(object):
|
||||
"""Provide a cache implementation for use by :class:`.Cache`."""
|
||||
|
||||
|
||||
62
lib/mako/cmd.py
Executable file
62
lib/mako/cmd.py
Executable file
@@ -0,0 +1,62 @@
|
||||
# mako/cmd.py
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
from argparse import ArgumentParser
|
||||
from os.path import isfile, dirname
|
||||
import sys
|
||||
from mako.template import Template
|
||||
from mako.lookup import TemplateLookup
|
||||
from mako import exceptions
|
||||
|
||||
def varsplit(var):
|
||||
if "=" not in var:
|
||||
return (var, "")
|
||||
return var.split("=", 1)
|
||||
|
||||
def _exit():
|
||||
sys.stderr.write(exceptions.text_error_template().render())
|
||||
sys.exit(1)
|
||||
|
||||
def cmdline(argv=None):
|
||||
|
||||
parser = ArgumentParser("usage: %prog [FILENAME]")
|
||||
parser.add_argument("--var", default=[], action="append",
|
||||
help="variable (can be used multiple times, use name=value)")
|
||||
parser.add_argument("--template-dir", default=[], action="append",
|
||||
help="Directory to use for template lookup (multiple "
|
||||
"directories may be provided). If not given then if the "
|
||||
"template is read from stdin, the value defaults to be "
|
||||
"the current directory, otherwise it defaults to be the "
|
||||
"parent directory of the file provided.")
|
||||
parser.add_argument('input', nargs='?', default='-')
|
||||
|
||||
options = parser.parse_args(argv)
|
||||
if options.input == '-':
|
||||
lookup_dirs = options.template_dir or ["."]
|
||||
lookup = TemplateLookup(lookup_dirs)
|
||||
try:
|
||||
template = Template(sys.stdin.read(), lookup=lookup)
|
||||
except:
|
||||
_exit()
|
||||
else:
|
||||
filename = options.input
|
||||
if not isfile(filename):
|
||||
raise SystemExit("error: can't find %s" % filename)
|
||||
lookup_dirs = options.template_dir or [dirname(filename)]
|
||||
lookup = TemplateLookup(lookup_dirs)
|
||||
try:
|
||||
template = Template(filename=filename, lookup=lookup)
|
||||
except:
|
||||
_exit()
|
||||
|
||||
kw = dict([varsplit(var) for var in options.var])
|
||||
try:
|
||||
print(template.render(**kw))
|
||||
except:
|
||||
_exit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cmdline()
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/codegen.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -14,7 +14,7 @@ from mako import util, ast, parsetree, filters, exceptions
|
||||
from mako import compat
|
||||
|
||||
|
||||
MAGIC_NUMBER = 9
|
||||
MAGIC_NUMBER = 10
|
||||
|
||||
# names which are hardwired into the
|
||||
# template and are not accessed via the
|
||||
@@ -99,7 +99,6 @@ class _GenerateRenderMethod(object):
|
||||
"""
|
||||
def __init__(self, printer, compiler, node):
|
||||
self.printer = printer
|
||||
self.last_source_line = -1
|
||||
self.compiler = compiler
|
||||
self.node = node
|
||||
self.identifier_stack = [None]
|
||||
@@ -146,6 +145,26 @@ class _GenerateRenderMethod(object):
|
||||
for node in defs:
|
||||
_GenerateRenderMethod(printer, compiler, node)
|
||||
|
||||
if not self.in_def:
|
||||
self.write_metadata_struct()
|
||||
|
||||
def write_metadata_struct(self):
|
||||
self.printer.source_map[self.printer.lineno] = \
|
||||
max(self.printer.source_map)
|
||||
struct = {
|
||||
"filename": self.compiler.filename,
|
||||
"uri": self.compiler.uri,
|
||||
"source_encoding": self.compiler.source_encoding,
|
||||
"line_map": self.printer.source_map,
|
||||
}
|
||||
self.printer.writelines(
|
||||
'"""',
|
||||
'__M_BEGIN_METADATA',
|
||||
compat.json.dumps(struct),
|
||||
'__M_END_METADATA\n'
|
||||
'"""'
|
||||
)
|
||||
|
||||
@property
|
||||
def identifiers(self):
|
||||
return self.identifier_stack[-1]
|
||||
@@ -187,7 +206,7 @@ class _GenerateRenderMethod(object):
|
||||
|
||||
# module-level names, python code
|
||||
if self.compiler.generate_magic_comment and \
|
||||
self.compiler.source_encoding:
|
||||
self.compiler.source_encoding:
|
||||
self.printer.writeline("# -*- coding:%s -*-" %
|
||||
self.compiler.source_encoding)
|
||||
|
||||
@@ -232,7 +251,7 @@ class _GenerateRenderMethod(object):
|
||||
[n.name for n in
|
||||
main_identifiers.topleveldefs.values()]
|
||||
)
|
||||
self.printer.write("\n\n")
|
||||
self.printer.write_blanks(2)
|
||||
|
||||
if len(module_code):
|
||||
self.write_module_code(module_code)
|
||||
@@ -255,8 +274,9 @@ class _GenerateRenderMethod(object):
|
||||
decorator = node.decorator
|
||||
if decorator:
|
||||
self.printer.writeline(
|
||||
"@runtime._decorate_toplevel(%s)" % decorator)
|
||||
"@runtime._decorate_toplevel(%s)" % decorator)
|
||||
|
||||
self.printer.start_source(node.lineno)
|
||||
self.printer.writelines(
|
||||
"def %s(%s):" % (name, ','.join(args)),
|
||||
# push new frame, assign current frame to __M_caller
|
||||
@@ -267,7 +287,7 @@ class _GenerateRenderMethod(object):
|
||||
self.printer.writeline("context._push_buffer()")
|
||||
|
||||
self.identifier_stack.append(
|
||||
self.compiler.identifiers.branch(self.node))
|
||||
self.compiler.identifiers.branch(self.node))
|
||||
if (not self.in_def or self.node.is_block) and '**pageargs' in args:
|
||||
self.identifier_stack[-1].argument_declared.add('pageargs')
|
||||
|
||||
@@ -288,7 +308,7 @@ class _GenerateRenderMethod(object):
|
||||
|
||||
self.write_def_finish(self.node, buffered, filtered, cached)
|
||||
self.printer.writeline(None)
|
||||
self.printer.write("\n\n")
|
||||
self.printer.write_blanks(2)
|
||||
if cached:
|
||||
self.write_cache_decorator(
|
||||
node, name,
|
||||
@@ -299,7 +319,7 @@ class _GenerateRenderMethod(object):
|
||||
"""write module-level template code, i.e. that which
|
||||
is enclosed in <%! %> tags in the template."""
|
||||
for n in module_code:
|
||||
self.write_source_comment(n)
|
||||
self.printer.start_source(n.lineno)
|
||||
self.printer.write_indented_block(n.text)
|
||||
|
||||
def write_inherit(self, node):
|
||||
@@ -309,9 +329,9 @@ class _GenerateRenderMethod(object):
|
||||
"def _mako_inherit(template, context):",
|
||||
"_mako_generate_namespaces(context)",
|
||||
"return runtime._inherit_from(context, %s, _template_uri)" %
|
||||
(node.parsed_attributes['file']),
|
||||
(node.parsed_attributes['file']),
|
||||
None
|
||||
)
|
||||
)
|
||||
|
||||
def write_namespaces(self, namespaces):
|
||||
"""write the module-level namespace-generating callable."""
|
||||
@@ -323,14 +343,14 @@ class _GenerateRenderMethod(object):
|
||||
"_mako_generate_namespaces(context)",
|
||||
"return context.namespaces[(__name__, name)]",
|
||||
None, None
|
||||
)
|
||||
)
|
||||
self.printer.writeline("def _mako_generate_namespaces(context):")
|
||||
|
||||
|
||||
for node in namespaces.values():
|
||||
if 'import' in node.attributes:
|
||||
self.compiler.has_ns_imports = True
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
if len(node.nodes):
|
||||
self.printer.writeline("def make_namespace():")
|
||||
export = []
|
||||
@@ -369,9 +389,9 @@ class _GenerateRenderMethod(object):
|
||||
" templateuri=%s, callables=%s, "
|
||||
" calling_uri=_template_uri)" %
|
||||
(
|
||||
node.name,
|
||||
node.parsed_attributes.get('file', 'None'),
|
||||
callable_name,
|
||||
node.name,
|
||||
node.parsed_attributes.get('file', 'None'),
|
||||
callable_name,
|
||||
)
|
||||
)
|
||||
elif 'module' in node.parsed_attributes:
|
||||
@@ -381,9 +401,10 @@ class _GenerateRenderMethod(object):
|
||||
" callables=%s, calling_uri=_template_uri,"
|
||||
" module=%s)" %
|
||||
(
|
||||
node.name,
|
||||
callable_name,
|
||||
node.parsed_attributes.get('module', 'None')
|
||||
node.name,
|
||||
callable_name,
|
||||
node.parsed_attributes.get(
|
||||
'module', 'None')
|
||||
)
|
||||
)
|
||||
else:
|
||||
@@ -400,8 +421,8 @@ class _GenerateRenderMethod(object):
|
||||
self.printer.writeline("context['self'].%s = ns" % (node.name))
|
||||
|
||||
self.printer.writeline(
|
||||
"context.namespaces[(__name__, %s)] = ns" % repr(node.name))
|
||||
self.printer.write("\n")
|
||||
"context.namespaces[(__name__, %s)] = ns" % repr(node.name))
|
||||
self.printer.write_blanks(1)
|
||||
if not len(namespaces):
|
||||
self.printer.writeline("pass")
|
||||
self.printer.writeline(None)
|
||||
@@ -466,7 +487,7 @@ class _GenerateRenderMethod(object):
|
||||
for ident, ns in self.compiler.namespaces.items():
|
||||
if 'import' in ns.attributes:
|
||||
self.printer.writeline(
|
||||
"_mako_get_namespace(context, %r)."\
|
||||
"_mako_get_namespace(context, %r)."
|
||||
"_populate(_import_ns, %r)" %
|
||||
(
|
||||
ident,
|
||||
@@ -532,18 +553,11 @@ class _GenerateRenderMethod(object):
|
||||
|
||||
self.printer.writeline("__M_writer = context.writer()")
|
||||
|
||||
def write_source_comment(self, node):
|
||||
"""write a source comment containing the line number of the
|
||||
corresponding template line."""
|
||||
if self.last_source_line != node.lineno:
|
||||
self.printer.writeline("# SOURCE LINE %d" % node.lineno)
|
||||
self.last_source_line = node.lineno
|
||||
|
||||
def write_def_decl(self, node, identifiers):
|
||||
"""write a locally-available callable referencing a top-level def"""
|
||||
funcname = node.funcname
|
||||
namedecls = node.get_argument_expressions()
|
||||
nameargs = node.get_argument_expressions(include_defaults=False)
|
||||
nameargs = node.get_argument_expressions(as_call=True)
|
||||
|
||||
if not self.in_def and (
|
||||
len(self.identifiers.locally_assigned) > 0 or
|
||||
@@ -553,7 +567,7 @@ class _GenerateRenderMethod(object):
|
||||
nameargs.insert(0, 'context')
|
||||
self.printer.writeline("def %s(%s):" % (funcname, ",".join(namedecls)))
|
||||
self.printer.writeline(
|
||||
"return render_%s(%s)" % (funcname, ",".join(nameargs)))
|
||||
"return render_%s(%s)" % (funcname, ",".join(nameargs)))
|
||||
self.printer.writeline(None)
|
||||
|
||||
def write_inline_def(self, node, identifiers, nested):
|
||||
@@ -564,9 +578,9 @@ class _GenerateRenderMethod(object):
|
||||
decorator = node.decorator
|
||||
if decorator:
|
||||
self.printer.writeline(
|
||||
"@runtime._decorate_inline(context, %s)" % decorator)
|
||||
"@runtime._decorate_inline(context, %s)" % decorator)
|
||||
self.printer.writeline(
|
||||
"def %s(%s):" % (node.funcname, ",".join(namedecls)))
|
||||
"def %s(%s):" % (node.funcname, ",".join(namedecls)))
|
||||
filtered = len(node.filter_args.args) > 0
|
||||
buffered = eval(node.attributes.get('buffered', 'False'))
|
||||
cached = eval(node.attributes.get('cached', 'False'))
|
||||
@@ -574,11 +588,11 @@ class _GenerateRenderMethod(object):
|
||||
# push new frame, assign current frame to __M_caller
|
||||
"__M_caller = context.caller_stack._push_frame()",
|
||||
"try:"
|
||||
)
|
||||
)
|
||||
if buffered or filtered or cached:
|
||||
self.printer.writelines(
|
||||
"context._push_buffer()",
|
||||
)
|
||||
)
|
||||
|
||||
identifiers = identifiers.branch(node, nested=nested)
|
||||
|
||||
@@ -627,8 +641,8 @@ class _GenerateRenderMethod(object):
|
||||
)
|
||||
else:
|
||||
self.printer.writelines(
|
||||
"finally:",
|
||||
"__M_buf, __M_writer = context._pop_buffer_and_writer()"
|
||||
"finally:",
|
||||
"__M_buf, __M_writer = context._pop_buffer_and_writer()"
|
||||
)
|
||||
|
||||
if callstack:
|
||||
@@ -684,7 +698,7 @@ class _GenerateRenderMethod(object):
|
||||
|
||||
# form "arg1, arg2, arg3=arg3, arg4=arg4", etc.
|
||||
pass_args = [
|
||||
'=' in a and "%s=%s" % ((a.split('=')[0],)*2) or a
|
||||
"%s=%s" % ((a.split('=')[0],) * 2) if '=' in a else a
|
||||
for a in args
|
||||
]
|
||||
|
||||
@@ -696,11 +710,11 @@ class _GenerateRenderMethod(object):
|
||||
if buffered:
|
||||
s = "context.get('local')."\
|
||||
"cache._ctx_get_or_create("\
|
||||
"%s, lambda:__M_%s(%s), context, %s__M_defname=%r)" % \
|
||||
(cachekey, name, ','.join(pass_args),
|
||||
''.join(["%s=%s, " % (k, v)
|
||||
for k, v in cache_args.items()]),
|
||||
name
|
||||
"%s, lambda:__M_%s(%s), context, %s__M_defname=%r)" % (
|
||||
cachekey, name, ','.join(pass_args),
|
||||
''.join(["%s=%s, " % (k, v)
|
||||
for k, v in cache_args.items()]),
|
||||
name
|
||||
)
|
||||
# apply buffer_filters
|
||||
s = self.create_filter_callable(self.compiler.buffer_filters, s,
|
||||
@@ -709,12 +723,13 @@ class _GenerateRenderMethod(object):
|
||||
else:
|
||||
self.printer.writelines(
|
||||
"__M_writer(context.get('local')."
|
||||
"cache._ctx_get_or_create("\
|
||||
"cache._ctx_get_or_create("
|
||||
"%s, lambda:__M_%s(%s), context, %s__M_defname=%r))" %
|
||||
(cachekey, name, ','.join(pass_args),
|
||||
''.join(["%s=%s, " % (k, v)
|
||||
(
|
||||
cachekey, name, ','.join(pass_args),
|
||||
''.join(["%s=%s, " % (k, v)
|
||||
for k, v in cache_args.items()]),
|
||||
name,
|
||||
name,
|
||||
),
|
||||
"return ''",
|
||||
None
|
||||
@@ -745,18 +760,17 @@ class _GenerateRenderMethod(object):
|
||||
continue
|
||||
m = re.match(r'(.+?)(\(.*\))', e)
|
||||
if m:
|
||||
(ident, fargs) = m.group(1,2)
|
||||
ident, fargs = m.group(1, 2)
|
||||
f = locate_encode(ident)
|
||||
e = f + fargs
|
||||
else:
|
||||
x = e
|
||||
e = locate_encode(e)
|
||||
assert e is not None
|
||||
target = "%s(%s)" % (e, target)
|
||||
return target
|
||||
|
||||
def visitExpression(self, node):
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
if len(node.escapes) or \
|
||||
(
|
||||
self.compiler.pagetag is not None and
|
||||
@@ -778,7 +792,7 @@ class _GenerateRenderMethod(object):
|
||||
self.printer.writeline("loop = __M_loop._exit()")
|
||||
self.printer.writeline(None)
|
||||
else:
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
if self.compiler.enable_loop and node.keyword == 'for':
|
||||
text = mangle_mako_loop(node, self.printer)
|
||||
else:
|
||||
@@ -800,7 +814,7 @@ class _GenerateRenderMethod(object):
|
||||
self.printer.writeline("pass")
|
||||
|
||||
def visitText(self, node):
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
self.printer.writeline("__M_writer(%s)" % repr(node.content))
|
||||
|
||||
def visitTextTag(self, node):
|
||||
@@ -822,11 +836,11 @@ class _GenerateRenderMethod(object):
|
||||
"__M_buf.getvalue()",
|
||||
False),
|
||||
None
|
||||
)
|
||||
)
|
||||
|
||||
def visitCode(self, node):
|
||||
if not node.ismodule:
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
self.printer.write_indented_block(node.text)
|
||||
|
||||
if not self.in_def and len(self.identifiers.locally_assigned) > 0:
|
||||
@@ -835,20 +849,20 @@ class _GenerateRenderMethod(object):
|
||||
# which is used for def calls within the same template,
|
||||
# to simulate "enclosing scope"
|
||||
self.printer.writeline(
|
||||
'__M_locals_builtin_stored = __M_locals_builtin()')
|
||||
'__M_locals_builtin_stored = __M_locals_builtin()')
|
||||
self.printer.writeline(
|
||||
'__M_locals.update(__M_dict_builtin([(__M_key,'
|
||||
' __M_locals_builtin_stored[__M_key]) for __M_key in'
|
||||
' [%s] if __M_key in __M_locals_builtin_stored]))' %
|
||||
','.join([repr(x) for x in node.declared_identifiers()]))
|
||||
'__M_locals.update(__M_dict_builtin([(__M_key,'
|
||||
' __M_locals_builtin_stored[__M_key]) for __M_key in'
|
||||
' [%s] if __M_key in __M_locals_builtin_stored]))' %
|
||||
','.join([repr(x) for x in node.declared_identifiers()]))
|
||||
|
||||
def visitIncludeTag(self, node):
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
args = node.attributes.get('args')
|
||||
if args:
|
||||
self.printer.writeline(
|
||||
"runtime._include_file(context, %s, _template_uri, %s)" %
|
||||
(node.parsed_attributes['file'], args))
|
||||
"runtime._include_file(context, %s, _template_uri, %s)" %
|
||||
(node.parsed_attributes['file'], args))
|
||||
else:
|
||||
self.printer.writeline(
|
||||
"runtime._include_file(context, %s, _template_uri)" %
|
||||
@@ -864,7 +878,7 @@ class _GenerateRenderMethod(object):
|
||||
if node.is_anonymous:
|
||||
self.printer.writeline("%s()" % node.funcname)
|
||||
else:
|
||||
nameargs = node.get_argument_expressions(include_defaults=False)
|
||||
nameargs = node.get_argument_expressions(as_call=True)
|
||||
nameargs += ['**pageargs']
|
||||
self.printer.writeline("if 'parent' not in context._data or "
|
||||
"not hasattr(context._data['parent'], '%s'):"
|
||||
@@ -941,9 +955,9 @@ class _GenerateRenderMethod(object):
|
||||
# push on caller for nested call
|
||||
"context.caller_stack.nextcaller = "
|
||||
"runtime.Namespace('caller', context, "
|
||||
"callables=ccall(__M_caller))",
|
||||
"callables=ccall(__M_caller))",
|
||||
"try:")
|
||||
self.write_source_comment(node)
|
||||
self.printer.start_source(node.lineno)
|
||||
self.printer.writelines(
|
||||
"__M_writer(%s)" % self.create_filter_callable(
|
||||
[], node.expression, True),
|
||||
@@ -966,9 +980,9 @@ class _Identifiers(object):
|
||||
# things that have already been declared
|
||||
# in an enclosing namespace (i.e. names we can just use)
|
||||
self.declared = set(parent.declared).\
|
||||
union([c.name for c in parent.closuredefs.values()]).\
|
||||
union(parent.locally_declared).\
|
||||
union(parent.argument_declared)
|
||||
union([c.name for c in parent.closuredefs.values()]).\
|
||||
union(parent.locally_declared).\
|
||||
union(parent.argument_declared)
|
||||
|
||||
# if these identifiers correspond to a "nested"
|
||||
# scope, it means whatever the parent identifiers
|
||||
@@ -1012,7 +1026,7 @@ class _Identifiers(object):
|
||||
node.accept_visitor(self)
|
||||
|
||||
illegal_names = self.compiler.reserved_names.intersection(
|
||||
self.locally_declared)
|
||||
self.locally_declared)
|
||||
if illegal_names:
|
||||
raise exceptions.NameConflictError(
|
||||
"Reserved words declared in template: %s" %
|
||||
@@ -1047,7 +1061,7 @@ class _Identifiers(object):
|
||||
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and\
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
for ident in node.declared_identifiers():
|
||||
self.locally_declared.add(ident)
|
||||
@@ -1067,7 +1081,7 @@ class _Identifiers(object):
|
||||
if not node.ismodule:
|
||||
self.check_declared(node)
|
||||
self.locally_assigned = self.locally_assigned.union(
|
||||
node.declared_identifiers())
|
||||
node.declared_identifiers())
|
||||
|
||||
def visitNamespaceTag(self, node):
|
||||
# only traverse into the sub-elements of a
|
||||
@@ -1095,8 +1109,8 @@ class _Identifiers(object):
|
||||
self._check_name_exists(self.closuredefs, node)
|
||||
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and\
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
if ident != 'context' and \
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
|
||||
# visit defs only one level deep
|
||||
@@ -1108,8 +1122,7 @@ class _Identifiers(object):
|
||||
n.accept_visitor(self)
|
||||
|
||||
def visitBlockTag(self, node):
|
||||
if node is not self.node and \
|
||||
not node.is_anonymous:
|
||||
if node is not self.node and not node.is_anonymous:
|
||||
|
||||
if isinstance(self.node, parsetree.DefTag):
|
||||
raise exceptions.CompileException(
|
||||
@@ -1123,7 +1136,7 @@ class _Identifiers(object):
|
||||
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and \
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
|
||||
if not node.is_anonymous:
|
||||
@@ -1139,7 +1152,7 @@ class _Identifiers(object):
|
||||
def visitTextTag(self, node):
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and \
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
|
||||
def visitIncludeTag(self, node):
|
||||
@@ -1156,8 +1169,9 @@ class _Identifiers(object):
|
||||
def visitCallTag(self, node):
|
||||
if node is self.node:
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and\
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
if ident != 'context' and \
|
||||
ident not in self.declared.union(
|
||||
self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
for ident in node.declared_identifiers():
|
||||
self.argument_declared.add(ident)
|
||||
@@ -1165,15 +1179,16 @@ class _Identifiers(object):
|
||||
n.accept_visitor(self)
|
||||
else:
|
||||
for ident in node.undeclared_identifiers():
|
||||
if ident != 'context' and\
|
||||
ident not in self.declared.union(self.locally_declared):
|
||||
if ident != 'context' and \
|
||||
ident not in self.declared.union(
|
||||
self.locally_declared):
|
||||
self.undeclared.add(ident)
|
||||
|
||||
|
||||
_FOR_LOOP = re.compile(
|
||||
r'^for\s+((?:\(?)\s*[A-Za-z_][A-Za-z_0-9]*'
|
||||
r'(?:\s*,\s*(?:[A-Za-z_][A-Za-z0-9_]*),??)*\s*(?:\)?))\s+in\s+(.*):'
|
||||
)
|
||||
)
|
||||
|
||||
def mangle_mako_loop(node, printer):
|
||||
"""converts a for loop into a context manager wrapped around a for loop
|
||||
@@ -1189,7 +1204,7 @@ def mangle_mako_loop(node, printer):
|
||||
'loop = __M_loop._enter(%s)' % match.group(2),
|
||||
'try:'
|
||||
#'with __M_loop(%s) as loop:' % match.group(2)
|
||||
)
|
||||
)
|
||||
text = 'for %s in loop:' % match.group(1)
|
||||
else:
|
||||
raise SyntaxError("Couldn't apply loop context: %s" % node.text)
|
||||
|
||||
@@ -3,8 +3,8 @@ import time
|
||||
|
||||
py3k = sys.version_info >= (3, 0)
|
||||
py33 = sys.version_info >= (3, 3)
|
||||
py2k = sys.version_info < (3,)
|
||||
py26 = sys.version_info >= (2, 6)
|
||||
py25 = sys.version_info >= (2, 5)
|
||||
jython = sys.platform.startswith('java')
|
||||
win32 = sys.platform.startswith('win')
|
||||
pypy = hasattr(sys, 'pypy_version_info')
|
||||
@@ -23,6 +23,9 @@ if py3k:
|
||||
def u(s):
|
||||
return s
|
||||
|
||||
def b(s):
|
||||
return s.encode("latin-1")
|
||||
|
||||
def octal(lit):
|
||||
return eval("0o" + lit)
|
||||
|
||||
@@ -44,6 +47,9 @@ else:
|
||||
def u(s):
|
||||
return unicode(s, "utf-8")
|
||||
|
||||
def b(s):
|
||||
return s
|
||||
|
||||
def octal(lit):
|
||||
return eval("0" + lit)
|
||||
|
||||
@@ -62,6 +68,18 @@ else:
|
||||
fp.close()
|
||||
|
||||
|
||||
if py3k:
|
||||
def reraise(tp, value, tb=None, cause=None):
|
||||
if cause is not None:
|
||||
value.__cause__ = cause
|
||||
if value.__traceback__ is not tb:
|
||||
raise value.with_traceback(tb)
|
||||
raise value
|
||||
else:
|
||||
exec("def reraise(tp, value, tb=None, cause=None):\n"
|
||||
" raise tp, value, tb\n")
|
||||
|
||||
|
||||
def exception_as():
|
||||
return sys.exc_info()[1]
|
||||
|
||||
@@ -93,23 +111,12 @@ except:
|
||||
return func(*(args + fargs), **newkeywords)
|
||||
return newfunc
|
||||
|
||||
if not py25:
|
||||
def all(iterable):
|
||||
for i in iterable:
|
||||
if not i:
|
||||
return False
|
||||
return True
|
||||
|
||||
def exception_name(exc):
|
||||
try:
|
||||
return exc.__class__.__name__
|
||||
except AttributeError:
|
||||
return exc.__name__
|
||||
else:
|
||||
all = all
|
||||
all = all
|
||||
import json
|
||||
|
||||
def exception_name(exc):
|
||||
return exc.__class__.__name__
|
||||
def exception_name(exc):
|
||||
return exc.__class__.__name__
|
||||
|
||||
try:
|
||||
from inspect import CO_VARKEYWORDS, CO_VARARGS
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/exceptions.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -8,7 +8,6 @@
|
||||
|
||||
import traceback
|
||||
import sys
|
||||
import re
|
||||
from mako import util, compat
|
||||
|
||||
class MakoException(Exception):
|
||||
@@ -28,7 +27,7 @@ class CompileException(MakoException):
|
||||
def __init__(self, message, source, lineno, pos, filename):
|
||||
MakoException.__init__(self,
|
||||
message + _format_filepos(lineno, pos, filename))
|
||||
self.lineno =lineno
|
||||
self.lineno = lineno
|
||||
self.pos = pos
|
||||
self.filename = filename
|
||||
self.source = source
|
||||
@@ -37,7 +36,7 @@ class SyntaxException(MakoException):
|
||||
def __init__(self, message, source, lineno, pos, filename):
|
||||
MakoException.__init__(self,
|
||||
message + _format_filepos(lineno, pos, filename))
|
||||
self.lineno =lineno
|
||||
self.lineno = lineno
|
||||
self.pos = pos
|
||||
self.filename = filename
|
||||
self.source = source
|
||||
@@ -77,7 +76,6 @@ class RichTraceback(object):
|
||||
self.records = self._init(traceback)
|
||||
|
||||
if isinstance(self.error, (CompileException, SyntaxException)):
|
||||
import mako.template
|
||||
self.source = self.error.source
|
||||
self.lineno = self.error.lineno
|
||||
self._has_source = True
|
||||
@@ -167,19 +165,19 @@ class RichTraceback(object):
|
||||
None, None, None, None))
|
||||
continue
|
||||
|
||||
template_ln = module_ln = 1
|
||||
line_map = {}
|
||||
for line in module_source.split("\n"):
|
||||
match = re.match(r'\s*# SOURCE LINE (\d+)', line)
|
||||
if match:
|
||||
template_ln = int(match.group(1))
|
||||
module_ln += 1
|
||||
line_map[module_ln] = template_ln
|
||||
template_ln = 1
|
||||
|
||||
source_map = mako.template.ModuleInfo.\
|
||||
get_module_source_metadata(
|
||||
module_source, full_line_map=True)
|
||||
line_map = source_map['full_line_map']
|
||||
|
||||
template_lines = [line for line in
|
||||
template_source.split("\n")]
|
||||
mods[filename] = (line_map, template_lines)
|
||||
|
||||
template_ln = line_map[lineno]
|
||||
template_ln = line_map[lineno - 1]
|
||||
|
||||
if template_ln <= len(template_lines):
|
||||
template_line = template_lines[template_ln - 1]
|
||||
else:
|
||||
@@ -188,7 +186,7 @@ class RichTraceback(object):
|
||||
line, template_filename, template_ln,
|
||||
template_line, template_source))
|
||||
if not self.source:
|
||||
for l in range(len(new_trcback)-1, 0, -1):
|
||||
for l in range(len(new_trcback) - 1, 0, -1):
|
||||
if new_trcback[l][5]:
|
||||
self.source = new_trcback[l][7]
|
||||
self.lineno = new_trcback[l][5]
|
||||
@@ -260,10 +258,11 @@ def html_error_template():
|
||||
filenames, line numbers and code for that of the originating source
|
||||
template, as applicable.
|
||||
|
||||
The template's default ``encoding_errors`` value is ``'htmlentityreplace'``. The
|
||||
template has two options. With the ``full`` option disabled, only a section of
|
||||
an HTML document is returned. With the ``css`` option disabled, the default
|
||||
stylesheet won't be included.
|
||||
The template's default ``encoding_errors`` value is
|
||||
``'htmlentityreplace'``. The template has two options. With the
|
||||
``full`` option disabled, only a section of an HTML document is
|
||||
returned. With the ``css`` option disabled, the default stylesheet
|
||||
won't be included.
|
||||
|
||||
"""
|
||||
import mako.template
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ext/autohandler.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -48,7 +48,7 @@ def autohandler(template, context, name='autohandler'):
|
||||
if len(tokens) == 1:
|
||||
break
|
||||
tokens[-2:] = [name]
|
||||
|
||||
|
||||
if not lookup.filesystem_checks:
|
||||
return lookup._uri_cache.setdefault(
|
||||
(autohandler, _template_uri, name), None)
|
||||
@@ -62,4 +62,4 @@ def _file_exists(lookup, path):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
|
||||
@@ -1,14 +1,36 @@
|
||||
# ext/babelplugin.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""gettext message extraction via Babel: http://babel.edgewall.org/"""
|
||||
from babel.messages.extract import extract_python
|
||||
from mako.compat import StringIO
|
||||
from mako import compat
|
||||
from mako import lexer, parsetree
|
||||
from mako.ext.extract import MessageExtractor
|
||||
|
||||
|
||||
class BabelMakoExtractor(MessageExtractor):
|
||||
def __init__(self, keywords, comment_tags, options):
|
||||
self.keywords = keywords
|
||||
self.options = options
|
||||
self.config = {
|
||||
'comment-tags': u' '.join(comment_tags),
|
||||
'encoding': options.get('input_encoding',
|
||||
options.get('encoding', None)),
|
||||
}
|
||||
super(BabelMakoExtractor, self).__init__()
|
||||
|
||||
def __call__(self, fileobj):
|
||||
return self.process_file(fileobj)
|
||||
|
||||
def process_python(self, code, code_lineno, translator_strings):
|
||||
comment_tags = self.config['comment-tags']
|
||||
for lineno, funcname, messages, python_translator_comments \
|
||||
in extract_python(code,
|
||||
self.keywords, comment_tags, self.options):
|
||||
yield (code_lineno + (lineno - 1), funcname, messages,
|
||||
translator_strings + python_translator_comments)
|
||||
|
||||
|
||||
def extract(fileobj, keywords, comment_tags, options):
|
||||
"""Extract messages from Mako templates.
|
||||
@@ -22,105 +44,6 @@ def extract(fileobj, keywords, comment_tags, options):
|
||||
:return: an iterator over ``(lineno, funcname, message, comments)`` tuples
|
||||
:rtype: ``iterator``
|
||||
"""
|
||||
encoding = options.get('input_encoding', options.get('encoding', None))
|
||||
|
||||
template_node = lexer.Lexer(fileobj.read(),
|
||||
input_encoding=encoding).parse()
|
||||
for extracted in extract_nodes(template_node.get_children(),
|
||||
keywords, comment_tags, options):
|
||||
yield extracted
|
||||
|
||||
def extract_nodes(nodes, keywords, comment_tags, options):
|
||||
"""Extract messages from Mako's lexer node objects
|
||||
|
||||
:param nodes: an iterable of Mako parsetree.Node objects to extract from
|
||||
:param keywords: a list of keywords (i.e. function names) that should be
|
||||
recognized as translation functions
|
||||
:param comment_tags: a list of translator tags to search for and include
|
||||
in the results
|
||||
:param options: a dictionary of additional options (optional)
|
||||
:return: an iterator over ``(lineno, funcname, message, comments)`` tuples
|
||||
:rtype: ``iterator``
|
||||
"""
|
||||
translator_comments = []
|
||||
in_translator_comments = False
|
||||
|
||||
for node in nodes:
|
||||
child_nodes = None
|
||||
if in_translator_comments and isinstance(node, parsetree.Text) and \
|
||||
not node.content.strip():
|
||||
# Ignore whitespace within translator comments
|
||||
continue
|
||||
|
||||
if isinstance(node, parsetree.Comment):
|
||||
value = node.text.strip()
|
||||
if in_translator_comments:
|
||||
translator_comments.extend(_split_comment(node.lineno, value))
|
||||
continue
|
||||
for comment_tag in comment_tags:
|
||||
if value.startswith(comment_tag):
|
||||
in_translator_comments = True
|
||||
translator_comments.extend(_split_comment(node.lineno,
|
||||
value))
|
||||
continue
|
||||
|
||||
if isinstance(node, parsetree.DefTag):
|
||||
code = node.function_decl.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.BlockTag):
|
||||
code = node.body_decl.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.CallTag):
|
||||
code = node.code.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.PageTag):
|
||||
code = node.body_decl.code
|
||||
elif isinstance(node, parsetree.CallNamespaceTag):
|
||||
code = node.expression
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.ControlLine):
|
||||
if node.isend:
|
||||
in_translator_comments = False
|
||||
continue
|
||||
code = node.text
|
||||
elif isinstance(node, parsetree.Code):
|
||||
in_translator_comments = False
|
||||
code = node.code.code
|
||||
elif isinstance(node, parsetree.Expression):
|
||||
code = node.code.code
|
||||
else:
|
||||
continue
|
||||
|
||||
# Comments don't apply unless they immediately preceed the message
|
||||
if translator_comments and \
|
||||
translator_comments[-1][0] < node.lineno - 1:
|
||||
translator_comments = []
|
||||
|
||||
translator_strings = [comment[1] for comment in translator_comments]
|
||||
|
||||
if isinstance(code, compat.text_type):
|
||||
code = code.encode('ascii', 'backslashreplace')
|
||||
|
||||
used_translator_comments = False
|
||||
code = compat.byte_buffer(code)
|
||||
for lineno, funcname, messages, python_translator_comments \
|
||||
in extract_python(code, keywords, comment_tags, options):
|
||||
yield (node.lineno + (lineno - 1), funcname, messages,
|
||||
translator_strings + python_translator_comments)
|
||||
used_translator_comments = True
|
||||
|
||||
if used_translator_comments:
|
||||
translator_comments = []
|
||||
in_translator_comments = False
|
||||
|
||||
if child_nodes:
|
||||
for extracted in extract_nodes(child_nodes, keywords, comment_tags,
|
||||
options):
|
||||
yield extracted
|
||||
|
||||
|
||||
def _split_comment(lineno, comment):
|
||||
"""Return the multiline comment at lineno split into a list of comment line
|
||||
numbers and the accompanying comment line"""
|
||||
return [(lineno + index, line) for index, line in
|
||||
enumerate(comment.splitlines())]
|
||||
extractor = BabelMakoExtractor(keywords, comment_tags, options)
|
||||
for message in extractor(fileobj):
|
||||
yield message
|
||||
|
||||
@@ -4,7 +4,16 @@ from mako import exceptions
|
||||
|
||||
from mako.cache import CacheImpl
|
||||
|
||||
try:
|
||||
from beaker import cache as beaker_cache
|
||||
except:
|
||||
has_beaker = False
|
||||
else:
|
||||
has_beaker = True
|
||||
|
||||
_beaker_cache = None
|
||||
|
||||
|
||||
class BeakerCacheImpl(CacheImpl):
|
||||
"""A :class:`.CacheImpl` provided for the Beaker caching system.
|
||||
|
||||
@@ -15,15 +24,11 @@ class BeakerCacheImpl(CacheImpl):
|
||||
"""
|
||||
|
||||
def __init__(self, cache):
|
||||
if not has_beaker:
|
||||
raise exceptions.RuntimeException(
|
||||
"Can't initialize Beaker plugin; Beaker is not installed.")
|
||||
global _beaker_cache
|
||||
if _beaker_cache is None:
|
||||
try:
|
||||
from beaker import cache as beaker_cache
|
||||
except ImportError:
|
||||
raise exceptions.RuntimeException(
|
||||
"the Beaker package is required to use cache "
|
||||
"functionality.")
|
||||
|
||||
if 'manager' in cache.template.cache_args:
|
||||
_beaker_cache = cache.template.cache_args['manager']
|
||||
else:
|
||||
@@ -48,7 +53,7 @@ class BeakerCacheImpl(CacheImpl):
|
||||
cache = _beaker_cache.get_cache_region(self.cache.id, region, **kw)
|
||||
else:
|
||||
cache = _beaker_cache.get_cache(self.cache.id, **kw)
|
||||
cache_args = {'starttime':self.cache.starttime}
|
||||
cache_args = {'starttime': self.cache.starttime}
|
||||
if expiretime:
|
||||
cache_args['expiretime'] = expiretime
|
||||
return cache, cache_args
|
||||
|
||||
101
lib/mako/ext/extract.py
Normal file
101
lib/mako/ext/extract.py
Normal file
@@ -0,0 +1,101 @@
|
||||
import re
|
||||
from mako import compat
|
||||
from mako import lexer
|
||||
from mako import parsetree
|
||||
|
||||
|
||||
class MessageExtractor(object):
|
||||
def process_file(self, fileobj):
|
||||
template_node = lexer.Lexer(
|
||||
fileobj.read(),
|
||||
input_encoding=self.config['encoding']).parse()
|
||||
for extracted in self.extract_nodes(template_node.get_children()):
|
||||
yield extracted
|
||||
|
||||
def extract_nodes(self, nodes):
|
||||
translator_comments = []
|
||||
in_translator_comments = False
|
||||
comment_tags = list(
|
||||
filter(None, re.split(r'\s+', self.config['comment-tags'])))
|
||||
|
||||
for node in nodes:
|
||||
child_nodes = None
|
||||
if in_translator_comments and \
|
||||
isinstance(node, parsetree.Text) and \
|
||||
not node.content.strip():
|
||||
# Ignore whitespace within translator comments
|
||||
continue
|
||||
|
||||
if isinstance(node, parsetree.Comment):
|
||||
value = node.text.strip()
|
||||
if in_translator_comments:
|
||||
translator_comments.extend(
|
||||
self._split_comment(node.lineno, value))
|
||||
continue
|
||||
for comment_tag in comment_tags:
|
||||
if value.startswith(comment_tag):
|
||||
in_translator_comments = True
|
||||
translator_comments.extend(
|
||||
self._split_comment(node.lineno, value))
|
||||
continue
|
||||
|
||||
if isinstance(node, parsetree.DefTag):
|
||||
code = node.function_decl.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.BlockTag):
|
||||
code = node.body_decl.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.CallTag):
|
||||
code = node.code.code
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.PageTag):
|
||||
code = node.body_decl.code
|
||||
elif isinstance(node, parsetree.CallNamespaceTag):
|
||||
code = node.expression
|
||||
child_nodes = node.nodes
|
||||
elif isinstance(node, parsetree.ControlLine):
|
||||
if node.isend:
|
||||
in_translator_comments = False
|
||||
continue
|
||||
code = node.text
|
||||
elif isinstance(node, parsetree.Code):
|
||||
in_translator_comments = False
|
||||
code = node.code.code
|
||||
elif isinstance(node, parsetree.Expression):
|
||||
code = node.code.code
|
||||
else:
|
||||
continue
|
||||
|
||||
# Comments don't apply unless they immediately preceed the message
|
||||
if translator_comments and \
|
||||
translator_comments[-1][0] < node.lineno - 1:
|
||||
translator_comments = []
|
||||
|
||||
translator_strings = [
|
||||
comment[1] for comment in translator_comments]
|
||||
|
||||
if isinstance(code, compat.text_type):
|
||||
code = code.encode('ascii', 'backslashreplace')
|
||||
|
||||
used_translator_comments = False
|
||||
code = compat.byte_buffer(code)
|
||||
|
||||
for message in self.process_python(
|
||||
code, node.lineno, translator_strings):
|
||||
yield message
|
||||
used_translator_comments = True
|
||||
|
||||
if used_translator_comments:
|
||||
translator_comments = []
|
||||
in_translator_comments = False
|
||||
|
||||
if child_nodes:
|
||||
for extracted in self.extract_nodes(child_nodes):
|
||||
yield extracted
|
||||
|
||||
@staticmethod
|
||||
def _split_comment(lineno, comment):
|
||||
"""Return the multiline comment at lineno split into a list of
|
||||
comment line numbers and the accompanying comment line"""
|
||||
return [(lineno + index, line) for index, line in
|
||||
enumerate(comment.splitlines())]
|
||||
38
lib/mako/ext/linguaplugin.py
Normal file
38
lib/mako/ext/linguaplugin.py
Normal file
@@ -0,0 +1,38 @@
|
||||
import io
|
||||
from lingua.extractors import Extractor
|
||||
from lingua.extractors import Message
|
||||
from lingua.extractors import get_extractor
|
||||
from mako.ext.extract import MessageExtractor
|
||||
from mako import compat
|
||||
|
||||
|
||||
class LinguaMakoExtractor(Extractor, MessageExtractor):
|
||||
'''Mako templates'''
|
||||
extensions = ['.mako']
|
||||
default_config = {
|
||||
'encoding': 'utf-8',
|
||||
'comment-tags': '',
|
||||
}
|
||||
|
||||
def __call__(self, filename, options, fileobj=None):
|
||||
self.options = options
|
||||
self.filename = filename
|
||||
self.python_extractor = get_extractor('x.py')
|
||||
if fileobj is None:
|
||||
fileobj = open(filename, 'rb')
|
||||
return self.process_file(fileobj)
|
||||
|
||||
def process_python(self, code, code_lineno, translator_strings):
|
||||
source = code.getvalue().strip()
|
||||
if source.endswith(compat.b(':')):
|
||||
source += compat.b(' pass')
|
||||
code = io.BytesIO(source)
|
||||
for msg in self.python_extractor(
|
||||
self.filename, self.options, code, code_lineno):
|
||||
if translator_strings:
|
||||
msg = Message(msg.msgctxt, msg.msgid, msg.msgid_plural,
|
||||
msg.flags,
|
||||
compat.u(' ').join(
|
||||
translator_strings + [msg.comment]),
|
||||
msg.tcomment, msg.location)
|
||||
yield msg
|
||||
@@ -1,20 +1,20 @@
|
||||
# ext/preprocessors.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
"""preprocessing functions, used with the 'preprocessor'
|
||||
"""preprocessing functions, used with the 'preprocessor'
|
||||
argument on Template, TemplateLookup"""
|
||||
|
||||
import re
|
||||
|
||||
def convert_comments(text):
|
||||
"""preprocess old style comments.
|
||||
|
||||
|
||||
example:
|
||||
|
||||
|
||||
from mako.ext.preprocessors import convert_comments
|
||||
t = Template(..., preprocessor=preprocess_comments)"""
|
||||
t = Template(..., preprocessor=convert_comments)"""
|
||||
return re.sub(r'(?<=\n)\s*#[^#]', "##", text)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ext/pygmentplugin.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# ext/turbogears.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/filters.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -48,6 +48,10 @@ def url_escape(string):
|
||||
string = string.encode("utf8")
|
||||
return quote_plus(string)
|
||||
|
||||
def legacy_url_escape(string):
|
||||
# convert into a list of octets
|
||||
return quote_plus(string)
|
||||
|
||||
def url_unescape(string):
|
||||
text = unquote_plus(string)
|
||||
if not is_ascii_str(text):
|
||||
@@ -64,7 +68,7 @@ class Decode(object):
|
||||
if isinstance(x, compat.text_type):
|
||||
return x
|
||||
elif not isinstance(x, compat.binary_type):
|
||||
return compat.text_type(str(x), encoding=key)
|
||||
return decode(str(x))
|
||||
else:
|
||||
return compat.text_type(x, encoding=key)
|
||||
return decode
|
||||
@@ -193,4 +197,5 @@ if compat.py3k:
|
||||
|
||||
NON_UNICODE_ESCAPES = DEFAULT_ESCAPES.copy()
|
||||
NON_UNICODE_ESCAPES['h'] = 'filters.legacy_html_escape'
|
||||
NON_UNICODE_ESCAPES['u'] = 'filters.legacy_url_escape'
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/lexer.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -44,10 +44,10 @@ class Lexer(object):
|
||||
|
||||
@property
|
||||
def exception_kwargs(self):
|
||||
return {'source':self.text,
|
||||
'lineno':self.matched_lineno,
|
||||
'pos':self.matched_charpos,
|
||||
'filename':self.filename}
|
||||
return {'source': self.text,
|
||||
'lineno': self.matched_lineno,
|
||||
'pos': self.matched_charpos,
|
||||
'filename': self.filename}
|
||||
|
||||
def match(self, regexp, flags=None):
|
||||
"""compile the given regexp, cache the reg, and call match_reg()."""
|
||||
@@ -83,8 +83,8 @@ class Lexer(object):
|
||||
self.matched_lineno = self.lineno
|
||||
lines = re.findall(r"\n", self.text[mp:self.match_position])
|
||||
cp = mp - 1
|
||||
while (cp >= 0 and cp<self.textlength and self.text[cp] != '\n'):
|
||||
cp -=1
|
||||
while (cp >= 0 and cp < self.textlength and self.text[cp] != '\n'):
|
||||
cp -= 1
|
||||
self.matched_charpos = mp - cp
|
||||
self.lineno += len(lines)
|
||||
#print "MATCHED:", match.group(0), "LINE START:",
|
||||
@@ -111,8 +111,8 @@ class Lexer(object):
|
||||
brace_level -= 1
|
||||
continue
|
||||
return \
|
||||
self.text[startpos:\
|
||||
self.match_position-len(match.group(1))],\
|
||||
self.text[startpos:
|
||||
self.match_position - len(match.group(1))],\
|
||||
match.group(1)
|
||||
match = self.match(r"(.*?)(?=\"|\'|#|%s)" % text_re, re.S)
|
||||
if match:
|
||||
@@ -162,9 +162,9 @@ class Lexer(object):
|
||||
elif self.control_line and \
|
||||
not self.control_line[-1].is_ternary(node.keyword):
|
||||
raise exceptions.SyntaxException(
|
||||
"Keyword '%s' not a legal ternary for keyword '%s'" %
|
||||
(node.keyword, self.control_line[-1].keyword),
|
||||
**self.exception_kwargs)
|
||||
"Keyword '%s' not a legal ternary for keyword '%s'" %
|
||||
(node.keyword, self.control_line[-1].keyword),
|
||||
**self.exception_kwargs)
|
||||
|
||||
_coding_re = re.compile(r'#.*coding[:=]\s*([-\w.]+).*\r?\n')
|
||||
|
||||
@@ -201,10 +201,10 @@ class Lexer(object):
|
||||
text = text.decode(parsed_encoding)
|
||||
except UnicodeDecodeError:
|
||||
raise exceptions.CompileException(
|
||||
"Unicode decode operation of encoding '%s' failed" %
|
||||
parsed_encoding,
|
||||
text.decode('utf-8', 'ignore'),
|
||||
0, 0, filename)
|
||||
"Unicode decode operation of encoding '%s' failed" %
|
||||
parsed_encoding,
|
||||
text.decode('utf-8', 'ignore'),
|
||||
0, 0, filename)
|
||||
|
||||
return parsed_encoding, text
|
||||
|
||||
@@ -254,11 +254,11 @@ class Lexer(object):
|
||||
**self.exception_kwargs)
|
||||
if len(self.control_line):
|
||||
raise exceptions.SyntaxException(
|
||||
"Unterminated control keyword: '%s'" %
|
||||
self.control_line[-1].keyword,
|
||||
self.text,
|
||||
self.control_line[-1].lineno,
|
||||
self.control_line[-1].pos, self.filename)
|
||||
"Unterminated control keyword: '%s'" %
|
||||
self.control_line[-1].keyword,
|
||||
self.text,
|
||||
self.control_line[-1].lineno,
|
||||
self.control_line[-1].pos, self.filename)
|
||||
return self.template
|
||||
|
||||
def match_tag_start(self):
|
||||
@@ -311,14 +311,14 @@ class Lexer(object):
|
||||
if match:
|
||||
if not len(self.tag):
|
||||
raise exceptions.SyntaxException(
|
||||
"Closing tag without opening tag: </%%%s>" %
|
||||
match.group(1),
|
||||
**self.exception_kwargs)
|
||||
"Closing tag without opening tag: </%%%s>" %
|
||||
match.group(1),
|
||||
**self.exception_kwargs)
|
||||
elif self.tag[-1].keyword != match.group(1):
|
||||
raise exceptions.SyntaxException(
|
||||
"Closing tag </%%%s> does not match tag: <%%%s>" %
|
||||
(match.group(1), self.tag[-1].keyword),
|
||||
**self.exception_kwargs)
|
||||
"Closing tag </%%%s> does not match tag: <%%%s>" %
|
||||
(match.group(1), self.tag[-1].keyword),
|
||||
**self.exception_kwargs)
|
||||
self.tag.pop()
|
||||
return True
|
||||
else:
|
||||
@@ -370,9 +370,9 @@ class Lexer(object):
|
||||
# compiler.parse() not complain about indentation
|
||||
text = adjust_whitespace(text) + "\n"
|
||||
self.append_node(
|
||||
parsetree.Code,
|
||||
text,
|
||||
match.group(1)=='!', lineno=line, pos=pos)
|
||||
parsetree.Code,
|
||||
text,
|
||||
match.group(1) == '!', lineno=line, pos=pos)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
@@ -397,8 +397,8 @@ class Lexer(object):
|
||||
|
||||
def match_control_line(self):
|
||||
match = self.match(
|
||||
r"(?<=^)[\t ]*(%(?!%)|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)"
|
||||
r"(?:\r?\n|\Z)", re.M)
|
||||
r"(?<=^)[\t ]*(%(?!%)|##)[\t ]*((?:(?:\\r?\n)|[^\r\n])*)"
|
||||
r"(?:\r?\n|\Z)", re.M)
|
||||
if match:
|
||||
operator = match.group(1)
|
||||
text = match.group(2)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/lookup.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/parsetree.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -437,7 +437,7 @@ class DefTag(Tag):
|
||||
return self.function_decl.get_argument_expressions(**kw)
|
||||
|
||||
def declared_identifiers(self):
|
||||
return self.function_decl.argnames
|
||||
return self.function_decl.allargnames
|
||||
|
||||
def undeclared_identifiers(self):
|
||||
res = []
|
||||
@@ -451,7 +451,7 @@ class DefTag(Tag):
|
||||
).union(
|
||||
self.expression_undeclared_identifiers
|
||||
).difference(
|
||||
self.function_decl.argnames
|
||||
self.function_decl.allargnames
|
||||
)
|
||||
|
||||
class BlockTag(Tag):
|
||||
@@ -502,7 +502,7 @@ class BlockTag(Tag):
|
||||
return self.body_decl.get_argument_expressions(**kw)
|
||||
|
||||
def declared_identifiers(self):
|
||||
return self.body_decl.argnames
|
||||
return self.body_decl.allargnames
|
||||
|
||||
def undeclared_identifiers(self):
|
||||
return (self.filter_args.\
|
||||
@@ -524,7 +524,7 @@ class CallTag(Tag):
|
||||
**self.exception_kwargs)
|
||||
|
||||
def declared_identifiers(self):
|
||||
return self.code.declared_identifiers.union(self.body_decl.argnames)
|
||||
return self.code.declared_identifiers.union(self.body_decl.allargnames)
|
||||
|
||||
def undeclared_identifiers(self):
|
||||
return self.code.undeclared_identifiers.\
|
||||
@@ -554,7 +554,7 @@ class CallNamespaceTag(Tag):
|
||||
**self.exception_kwargs)
|
||||
|
||||
def declared_identifiers(self):
|
||||
return self.code.declared_identifiers.union(self.body_decl.argnames)
|
||||
return self.code.declared_identifiers.union(self.body_decl.allargnames)
|
||||
|
||||
def undeclared_identifiers(self):
|
||||
return self.code.undeclared_identifiers.\
|
||||
@@ -589,6 +589,6 @@ class PageTag(Tag):
|
||||
**self.exception_kwargs)
|
||||
|
||||
def declared_identifiers(self):
|
||||
return self.body_decl.argnames
|
||||
return self.body_decl.allargnames
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/pygen.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -26,6 +26,9 @@ class PythonPrinter(object):
|
||||
# the stream we are writing to
|
||||
self.stream = stream
|
||||
|
||||
# current line number
|
||||
self.lineno = 1
|
||||
|
||||
# a list of lines that represents a buffered "block" of code,
|
||||
# which can be later printed relative to an indent level
|
||||
self.line_buffer = []
|
||||
@@ -34,8 +37,20 @@ class PythonPrinter(object):
|
||||
|
||||
self._reset_multi_line_flags()
|
||||
|
||||
def write(self, text):
|
||||
self.stream.write(text)
|
||||
# mapping of generated python lines to template
|
||||
# source lines
|
||||
self.source_map = {}
|
||||
|
||||
def _update_lineno(self, num):
|
||||
self.lineno += num
|
||||
|
||||
def start_source(self, lineno):
|
||||
if self.lineno not in self.source_map:
|
||||
self.source_map[self.lineno] = lineno
|
||||
|
||||
def write_blanks(self, num):
|
||||
self.stream.write("\n" * num)
|
||||
self._update_lineno(num)
|
||||
|
||||
def write_indented_block(self, block):
|
||||
"""print a line or lines of python which already contain indentation.
|
||||
@@ -45,6 +60,7 @@ class PythonPrinter(object):
|
||||
self.in_indent_lines = False
|
||||
for l in re.split(r'\r?\n', block):
|
||||
self.line_buffer.append(l)
|
||||
self._update_lineno(1)
|
||||
|
||||
def writelines(self, *lines):
|
||||
"""print a series of lines of python."""
|
||||
@@ -80,7 +96,7 @@ class PythonPrinter(object):
|
||||
):
|
||||
|
||||
if self.indent > 0:
|
||||
self.indent -=1
|
||||
self.indent -= 1
|
||||
# if the indent_detail stack is empty, the user
|
||||
# probably put extra closures - the resulting
|
||||
# module wont compile.
|
||||
@@ -94,6 +110,7 @@ class PythonPrinter(object):
|
||||
|
||||
# write the line
|
||||
self.stream.write(self._indent_line(line) + "\n")
|
||||
self._update_lineno(len(line.split("\n")))
|
||||
|
||||
# see if this line should increase the indentation level.
|
||||
# note that a line can both decrase (before printing) and
|
||||
@@ -108,7 +125,7 @@ class PythonPrinter(object):
|
||||
if match:
|
||||
# its a "compound" keyword, so we will check for "unindentors"
|
||||
indentor = match.group(1)
|
||||
self.indent +=1
|
||||
self.indent += 1
|
||||
self.indent_detail.append(indentor)
|
||||
else:
|
||||
indentor = None
|
||||
@@ -265,7 +282,7 @@ def adjust_whitespace(text):
|
||||
|
||||
return start_state
|
||||
|
||||
def _indent_line(line, stripspace = ''):
|
||||
def _indent_line(line, stripspace=''):
|
||||
return re.sub(r"^%s" % stripspace, '', line)
|
||||
|
||||
lines = []
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/pyparser.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -11,7 +11,7 @@ module is used.
|
||||
"""
|
||||
|
||||
from mako import exceptions, util, compat
|
||||
from mako.compat import StringIO, arg_stringname
|
||||
from mako.compat import arg_stringname
|
||||
import operator
|
||||
|
||||
if compat.py3k:
|
||||
@@ -29,29 +29,16 @@ else:
|
||||
# the "id" attribute on a function node
|
||||
arg_id = operator.attrgetter('id')
|
||||
|
||||
|
||||
try:
|
||||
import _ast
|
||||
util.restore__ast(_ast)
|
||||
from mako import _ast_util
|
||||
except ImportError:
|
||||
_ast = None
|
||||
from compiler import parse as compiler_parse
|
||||
from compiler import visitor
|
||||
|
||||
import _ast
|
||||
util.restore__ast(_ast)
|
||||
from mako import _ast_util
|
||||
|
||||
|
||||
def parse(code, mode='exec', **exception_kwargs):
|
||||
"""Parse an expression into AST"""
|
||||
|
||||
|
||||
try:
|
||||
if _ast:
|
||||
return _ast_util.parse(code, '<unknown>', mode)
|
||||
else:
|
||||
if isinstance(code, compat.text_type):
|
||||
code = code.encode('ascii', 'backslashreplace')
|
||||
return compiler_parse(code, mode)
|
||||
return _ast_util.parse(code, '<unknown>', mode)
|
||||
except Exception:
|
||||
raise exceptions.SyntaxException(
|
||||
"(%s) %s (%r)" % (
|
||||
@@ -61,512 +48,185 @@ def parse(code, mode='exec', **exception_kwargs):
|
||||
), **exception_kwargs)
|
||||
|
||||
|
||||
if _ast:
|
||||
class FindIdentifiers(_ast_util.NodeVisitor):
|
||||
class FindIdentifiers(_ast_util.NodeVisitor):
|
||||
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.in_function = False
|
||||
self.in_assign_targets = False
|
||||
self.local_ident_stack = set()
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.in_function = False
|
||||
self.in_assign_targets = False
|
||||
self.local_ident_stack = set()
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
|
||||
def _add_declared(self, name):
|
||||
if not self.in_function:
|
||||
self.listener.declared_identifiers.add(name)
|
||||
else:
|
||||
self.local_ident_stack.add(name)
|
||||
def _add_declared(self, name):
|
||||
if not self.in_function:
|
||||
self.listener.declared_identifiers.add(name)
|
||||
else:
|
||||
self.local_ident_stack.add(name)
|
||||
|
||||
def visit_ClassDef(self, node):
|
||||
self._add_declared(node.name)
|
||||
def visit_ClassDef(self, node):
|
||||
self._add_declared(node.name)
|
||||
|
||||
def visit_Assign(self, node):
|
||||
def visit_Assign(self, node):
|
||||
|
||||
# flip around the visiting of Assign so the expression gets
|
||||
# evaluated first, in the case of a clause like "x=x+5" (x
|
||||
# is undeclared)
|
||||
# flip around the visiting of Assign so the expression gets
|
||||
# evaluated first, in the case of a clause like "x=x+5" (x
|
||||
# is undeclared)
|
||||
|
||||
self.visit(node.value)
|
||||
in_a = self.in_assign_targets
|
||||
self.in_assign_targets = True
|
||||
for n in node.targets:
|
||||
self.visit(n)
|
||||
self.in_assign_targets = in_a
|
||||
self.visit(node.value)
|
||||
in_a = self.in_assign_targets
|
||||
self.in_assign_targets = True
|
||||
for n in node.targets:
|
||||
self.visit(n)
|
||||
self.in_assign_targets = in_a
|
||||
|
||||
if compat.py3k:
|
||||
if compat.py3k:
|
||||
|
||||
# ExceptHandler is in Python 2, but this block only works in
|
||||
# Python 3 (and is required there)
|
||||
# ExceptHandler is in Python 2, but this block only works in
|
||||
# Python 3 (and is required there)
|
||||
|
||||
def visit_ExceptHandler(self, node):
|
||||
if node.name is not None:
|
||||
self._add_declared(node.name)
|
||||
if node.type is not None:
|
||||
self.listener.undeclared_identifiers.add(node.type.id)
|
||||
for statement in node.body:
|
||||
self.visit(statement)
|
||||
|
||||
def visit_Lambda(self, node, *args):
|
||||
self._visit_function(node, True)
|
||||
|
||||
def visit_FunctionDef(self, node):
|
||||
self._add_declared(node.name)
|
||||
self._visit_function(node, False)
|
||||
|
||||
def _expand_tuples(self, args):
|
||||
for arg in args:
|
||||
if isinstance(arg, _ast.Tuple):
|
||||
for n in arg.elts:
|
||||
yield n
|
||||
else:
|
||||
yield arg
|
||||
|
||||
def _visit_function(self, node, islambda):
|
||||
|
||||
# push function state onto stack. dont log any more
|
||||
# identifiers as "declared" until outside of the function,
|
||||
# but keep logging identifiers as "undeclared". track
|
||||
# argument names in each function header so they arent
|
||||
# counted as "undeclared"
|
||||
|
||||
inf = self.in_function
|
||||
self.in_function = True
|
||||
|
||||
local_ident_stack = self.local_ident_stack
|
||||
self.local_ident_stack = local_ident_stack.union([
|
||||
arg_id(arg) for arg in self._expand_tuples(node.args.args)
|
||||
])
|
||||
if islambda:
|
||||
self.visit(node.body)
|
||||
else:
|
||||
for n in node.body:
|
||||
self.visit(n)
|
||||
self.in_function = inf
|
||||
self.local_ident_stack = local_ident_stack
|
||||
|
||||
def visit_For(self, node):
|
||||
|
||||
# flip around visit
|
||||
|
||||
self.visit(node.iter)
|
||||
self.visit(node.target)
|
||||
def visit_ExceptHandler(self, node):
|
||||
if node.name is not None:
|
||||
self._add_declared(node.name)
|
||||
if node.type is not None:
|
||||
self.visit(node.type)
|
||||
for statement in node.body:
|
||||
self.visit(statement)
|
||||
for statement in node.orelse:
|
||||
self.visit(statement)
|
||||
|
||||
def visit_Name(self, node):
|
||||
if isinstance(node.ctx, _ast.Store):
|
||||
# this is eqiuvalent to visit_AssName in
|
||||
# compiler
|
||||
self._add_declared(node.id)
|
||||
elif node.id not in reserved and node.id \
|
||||
not in self.listener.declared_identifiers and node.id \
|
||||
not in self.local_ident_stack:
|
||||
self.listener.undeclared_identifiers.add(node.id)
|
||||
def visit_Lambda(self, node, *args):
|
||||
self._visit_function(node, True)
|
||||
|
||||
def visit_Import(self, node):
|
||||
for name in node.names:
|
||||
if name.asname is not None:
|
||||
self._add_declared(name.asname)
|
||||
else:
|
||||
self._add_declared(name.name.split('.')[0])
|
||||
def visit_FunctionDef(self, node):
|
||||
self._add_declared(node.name)
|
||||
self._visit_function(node, False)
|
||||
|
||||
def visit_ImportFrom(self, node):
|
||||
for name in node.names:
|
||||
if name.asname is not None:
|
||||
self._add_declared(name.asname)
|
||||
else:
|
||||
if name.name == '*':
|
||||
raise exceptions.CompileException(
|
||||
"'import *' is not supported, since all identifier "
|
||||
"names must be explicitly declared. Please use the "
|
||||
"form 'from <modulename> import <name1>, <name2>, "
|
||||
"...' instead.", **self.exception_kwargs)
|
||||
self._add_declared(name.name)
|
||||
|
||||
|
||||
class FindTuple(_ast_util.NodeVisitor):
|
||||
|
||||
def __init__(self, listener, code_factory, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
self.code_factory = code_factory
|
||||
|
||||
def visit_Tuple(self, node):
|
||||
for n in node.elts:
|
||||
p = self.code_factory(n, **self.exception_kwargs)
|
||||
self.listener.codeargs.append(p)
|
||||
self.listener.args.append(ExpressionGenerator(n).value())
|
||||
self.listener.declared_identifiers = \
|
||||
self.listener.declared_identifiers.union(
|
||||
p.declared_identifiers)
|
||||
self.listener.undeclared_identifiers = \
|
||||
self.listener.undeclared_identifiers.union(
|
||||
p.undeclared_identifiers)
|
||||
|
||||
|
||||
class ParseFunc(_ast_util.NodeVisitor):
|
||||
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
|
||||
def visit_FunctionDef(self, node):
|
||||
self.listener.funcname = node.name
|
||||
argnames = [arg_id(arg) for arg in node.args.args]
|
||||
if node.args.vararg:
|
||||
argnames.append(arg_stringname(node.args.vararg))
|
||||
if node.args.kwarg:
|
||||
argnames.append(arg_stringname(node.args.kwarg))
|
||||
self.listener.argnames = argnames
|
||||
self.listener.defaults = node.args.defaults # ast
|
||||
self.listener.varargs = node.args.vararg
|
||||
self.listener.kwargs = node.args.kwarg
|
||||
|
||||
class ExpressionGenerator(object):
|
||||
|
||||
def __init__(self, astnode):
|
||||
self.generator = _ast_util.SourceGenerator(' ' * 4)
|
||||
self.generator.visit(astnode)
|
||||
|
||||
def value(self):
|
||||
return ''.join(self.generator.result)
|
||||
else:
|
||||
class FindIdentifiers(object):
|
||||
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.in_function = False
|
||||
self.local_ident_stack = set()
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
|
||||
def _add_declared(self, name):
|
||||
if not self.in_function:
|
||||
self.listener.declared_identifiers.add(name)
|
||||
def _expand_tuples(self, args):
|
||||
for arg in args:
|
||||
if isinstance(arg, _ast.Tuple):
|
||||
for n in arg.elts:
|
||||
yield n
|
||||
else:
|
||||
self.local_ident_stack.add(name)
|
||||
yield arg
|
||||
|
||||
def visitClass(self, node, *args):
|
||||
self._add_declared(node.name)
|
||||
def _visit_function(self, node, islambda):
|
||||
|
||||
def visitAssName(self, node, *args):
|
||||
self._add_declared(node.name)
|
||||
# push function state onto stack. dont log any more
|
||||
# identifiers as "declared" until outside of the function,
|
||||
# but keep logging identifiers as "undeclared". track
|
||||
# argument names in each function header so they arent
|
||||
# counted as "undeclared"
|
||||
|
||||
def visitAssign(self, node, *args):
|
||||
inf = self.in_function
|
||||
self.in_function = True
|
||||
|
||||
# flip around the visiting of Assign so the expression gets
|
||||
# evaluated first, in the case of a clause like "x=x+5" (x
|
||||
# is undeclared)
|
||||
self.visit(node.expr, *args)
|
||||
for n in node.nodes:
|
||||
self.visit(n, *args)
|
||||
local_ident_stack = self.local_ident_stack
|
||||
self.local_ident_stack = local_ident_stack.union([
|
||||
arg_id(arg) for arg in self._expand_tuples(node.args.args)
|
||||
])
|
||||
if islambda:
|
||||
self.visit(node.body)
|
||||
else:
|
||||
for n in node.body:
|
||||
self.visit(n)
|
||||
self.in_function = inf
|
||||
self.local_ident_stack = local_ident_stack
|
||||
|
||||
def visitLambda(self, node, *args):
|
||||
self._visit_function(node, args)
|
||||
def visit_For(self, node):
|
||||
|
||||
def visitFunction(self, node, *args):
|
||||
self._add_declared(node.name)
|
||||
self._visit_function(node, args)
|
||||
# flip around visit
|
||||
|
||||
def _expand_tuples(self, args):
|
||||
for arg in args:
|
||||
if isinstance(arg, tuple):
|
||||
for n in arg:
|
||||
yield n
|
||||
else:
|
||||
yield arg
|
||||
self.visit(node.iter)
|
||||
self.visit(node.target)
|
||||
for statement in node.body:
|
||||
self.visit(statement)
|
||||
for statement in node.orelse:
|
||||
self.visit(statement)
|
||||
|
||||
def _visit_function(self, node, args):
|
||||
|
||||
# push function state onto stack. dont log any more
|
||||
# identifiers as "declared" until outside of the function,
|
||||
# but keep logging identifiers as "undeclared". track
|
||||
# argument names in each function header so they arent
|
||||
# counted as "undeclared"
|
||||
|
||||
inf = self.in_function
|
||||
self.in_function = True
|
||||
|
||||
local_ident_stack = self.local_ident_stack
|
||||
self.local_ident_stack = local_ident_stack.union([
|
||||
arg for arg in self._expand_tuples(node.argnames)
|
||||
])
|
||||
|
||||
for n in node.getChildNodes():
|
||||
self.visit(n, *args)
|
||||
self.in_function = inf
|
||||
self.local_ident_stack = local_ident_stack
|
||||
|
||||
def visitFor(self, node, *args):
|
||||
|
||||
# flip around visit
|
||||
|
||||
self.visit(node.list, *args)
|
||||
self.visit(node.assign, *args)
|
||||
self.visit(node.body, *args)
|
||||
|
||||
def visitName(self, node, *args):
|
||||
if node.name not in reserved and node.name \
|
||||
not in self.listener.declared_identifiers and node.name \
|
||||
def visit_Name(self, node):
|
||||
if isinstance(node.ctx, _ast.Store):
|
||||
# this is eqiuvalent to visit_AssName in
|
||||
# compiler
|
||||
self._add_declared(node.id)
|
||||
elif node.id not in reserved and node.id \
|
||||
not in self.listener.declared_identifiers and node.id \
|
||||
not in self.local_ident_stack:
|
||||
self.listener.undeclared_identifiers.add(node.name)
|
||||
self.listener.undeclared_identifiers.add(node.id)
|
||||
|
||||
def visitImport(self, node, *args):
|
||||
for mod, alias in node.names:
|
||||
if alias is not None:
|
||||
self._add_declared(alias)
|
||||
else:
|
||||
self._add_declared(mod.split('.')[0])
|
||||
def visit_Import(self, node):
|
||||
for name in node.names:
|
||||
if name.asname is not None:
|
||||
self._add_declared(name.asname)
|
||||
else:
|
||||
self._add_declared(name.name.split('.')[0])
|
||||
|
||||
def visitFrom(self, node, *args):
|
||||
for mod, alias in node.names:
|
||||
if alias is not None:
|
||||
self._add_declared(alias)
|
||||
else:
|
||||
if mod == '*':
|
||||
raise exceptions.CompileException(
|
||||
def visit_ImportFrom(self, node):
|
||||
for name in node.names:
|
||||
if name.asname is not None:
|
||||
self._add_declared(name.asname)
|
||||
else:
|
||||
if name.name == '*':
|
||||
raise exceptions.CompileException(
|
||||
"'import *' is not supported, since all identifier "
|
||||
"names must be explicitly declared. Please use the "
|
||||
"form 'from <modulename> import <name1>, <name2>, "
|
||||
"...' instead.", **self.exception_kwargs)
|
||||
self._add_declared(mod)
|
||||
|
||||
def visit(self, expr):
|
||||
visitor.walk(expr, self) # , walker=walker())
|
||||
self._add_declared(name.name)
|
||||
|
||||
|
||||
class FindTuple(object):
|
||||
class FindTuple(_ast_util.NodeVisitor):
|
||||
|
||||
def __init__(self, listener, code_factory, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
self.code_factory = code_factory
|
||||
def __init__(self, listener, code_factory, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
self.code_factory = code_factory
|
||||
|
||||
def visitTuple(self, node, *args):
|
||||
for n in node.nodes:
|
||||
p = self.code_factory(n, **self.exception_kwargs)
|
||||
self.listener.codeargs.append(p)
|
||||
self.listener.args.append(ExpressionGenerator(n).value())
|
||||
self.listener.declared_identifiers = \
|
||||
self.listener.declared_identifiers.union(
|
||||
p.declared_identifiers)
|
||||
self.listener.undeclared_identifiers = \
|
||||
self.listener.undeclared_identifiers.union(
|
||||
p.undeclared_identifiers)
|
||||
|
||||
def visit(self, expr):
|
||||
visitor.walk(expr, self) # , walker=walker())
|
||||
def visit_Tuple(self, node):
|
||||
for n in node.elts:
|
||||
p = self.code_factory(n, **self.exception_kwargs)
|
||||
self.listener.codeargs.append(p)
|
||||
self.listener.args.append(ExpressionGenerator(n).value())
|
||||
self.listener.declared_identifiers = \
|
||||
self.listener.declared_identifiers.union(
|
||||
p.declared_identifiers)
|
||||
self.listener.undeclared_identifiers = \
|
||||
self.listener.undeclared_identifiers.union(
|
||||
p.undeclared_identifiers)
|
||||
|
||||
|
||||
class ParseFunc(object):
|
||||
class ParseFunc(_ast_util.NodeVisitor):
|
||||
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
def __init__(self, listener, **exception_kwargs):
|
||||
self.listener = listener
|
||||
self.exception_kwargs = exception_kwargs
|
||||
|
||||
def visitFunction(self, node, *args):
|
||||
self.listener.funcname = node.name
|
||||
self.listener.argnames = node.argnames
|
||||
self.listener.defaults = node.defaults
|
||||
self.listener.varargs = node.varargs
|
||||
self.listener.kwargs = node.kwargs
|
||||
def visit_FunctionDef(self, node):
|
||||
self.listener.funcname = node.name
|
||||
|
||||
def visit(self, expr):
|
||||
visitor.walk(expr, self)
|
||||
argnames = [arg_id(arg) for arg in node.args.args]
|
||||
if node.args.vararg:
|
||||
argnames.append(arg_stringname(node.args.vararg))
|
||||
|
||||
if compat.py2k:
|
||||
# kw-only args don't exist in Python 2
|
||||
kwargnames = []
|
||||
else:
|
||||
kwargnames = [arg_id(arg) for arg in node.args.kwonlyargs]
|
||||
if node.args.kwarg:
|
||||
kwargnames.append(arg_stringname(node.args.kwarg))
|
||||
self.listener.argnames = argnames
|
||||
self.listener.defaults = node.args.defaults # ast
|
||||
self.listener.kwargnames = kwargnames
|
||||
if compat.py2k:
|
||||
self.listener.kwdefaults = []
|
||||
else:
|
||||
self.listener.kwdefaults = node.args.kw_defaults
|
||||
self.listener.varargs = node.args.vararg
|
||||
self.listener.kwargs = node.args.kwarg
|
||||
|
||||
class ExpressionGenerator(object):
|
||||
class ExpressionGenerator(object):
|
||||
|
||||
"""given an AST node, generates an equivalent literal Python
|
||||
expression."""
|
||||
def __init__(self, astnode):
|
||||
self.generator = _ast_util.SourceGenerator(' ' * 4)
|
||||
self.generator.visit(astnode)
|
||||
|
||||
def __init__(self, astnode):
|
||||
self.buf = StringIO()
|
||||
visitor.walk(astnode, self) # , walker=walker())
|
||||
|
||||
def value(self):
|
||||
return self.buf.getvalue()
|
||||
|
||||
def operator(self, op, node, *args):
|
||||
self.buf.write('(')
|
||||
self.visit(node.left, *args)
|
||||
self.buf.write(' %s ' % op)
|
||||
self.visit(node.right, *args)
|
||||
self.buf.write(')')
|
||||
|
||||
def booleanop(self, op, node, *args):
|
||||
self.visit(node.nodes[0])
|
||||
for n in node.nodes[1:]:
|
||||
self.buf.write(' ' + op + ' ')
|
||||
self.visit(n, *args)
|
||||
|
||||
def visitConst(self, node, *args):
|
||||
self.buf.write(repr(node.value))
|
||||
|
||||
def visitAssName(self, node, *args):
|
||||
|
||||
# TODO: figure out OP_ASSIGN, other OP_s
|
||||
|
||||
self.buf.write(node.name)
|
||||
|
||||
def visitName(self, node, *args):
|
||||
self.buf.write(node.name)
|
||||
|
||||
def visitMul(self, node, *args):
|
||||
self.operator('*', node, *args)
|
||||
|
||||
def visitAnd(self, node, *args):
|
||||
self.booleanop('and', node, *args)
|
||||
|
||||
def visitOr(self, node, *args):
|
||||
self.booleanop('or', node, *args)
|
||||
|
||||
def visitBitand(self, node, *args):
|
||||
self.booleanop('&', node, *args)
|
||||
|
||||
def visitBitor(self, node, *args):
|
||||
self.booleanop('|', node, *args)
|
||||
|
||||
def visitBitxor(self, node, *args):
|
||||
self.booleanop('^', node, *args)
|
||||
|
||||
def visitAdd(self, node, *args):
|
||||
self.operator('+', node, *args)
|
||||
|
||||
def visitGetattr(self, node, *args):
|
||||
self.visit(node.expr, *args)
|
||||
self.buf.write('.%s' % node.attrname)
|
||||
|
||||
def visitSub(self, node, *args):
|
||||
self.operator('-', node, *args)
|
||||
|
||||
def visitNot(self, node, *args):
|
||||
self.buf.write('not ')
|
||||
self.visit(node.expr)
|
||||
|
||||
def visitDiv(self, node, *args):
|
||||
self.operator('/', node, *args)
|
||||
|
||||
def visitFloorDiv(self, node, *args):
|
||||
self.operator('//', node, *args)
|
||||
|
||||
def visitSubscript(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
self.buf.write('[')
|
||||
[self.visit(x) for x in node.subs]
|
||||
self.buf.write(']')
|
||||
|
||||
def visitUnarySub(self, node, *args):
|
||||
self.buf.write('-')
|
||||
self.visit(node.expr)
|
||||
|
||||
def visitUnaryAdd(self, node, *args):
|
||||
self.buf.write('-')
|
||||
self.visit(node.expr)
|
||||
|
||||
def visitSlice(self, node, *args):
|
||||
self.visit(node.expr)
|
||||
self.buf.write('[')
|
||||
if node.lower is not None:
|
||||
self.visit(node.lower)
|
||||
self.buf.write(':')
|
||||
if node.upper is not None:
|
||||
self.visit(node.upper)
|
||||
self.buf.write(']')
|
||||
|
||||
def visitDict(self, node):
|
||||
self.buf.write('{')
|
||||
c = node.getChildren()
|
||||
for i in range(0, len(c), 2):
|
||||
self.visit(c[i])
|
||||
self.buf.write(': ')
|
||||
self.visit(c[i + 1])
|
||||
if i < len(c) - 2:
|
||||
self.buf.write(', ')
|
||||
self.buf.write('}')
|
||||
|
||||
def visitTuple(self, node):
|
||||
self.buf.write('(')
|
||||
c = node.getChildren()
|
||||
for i in range(0, len(c)):
|
||||
self.visit(c[i])
|
||||
if i < len(c) - 1:
|
||||
self.buf.write(', ')
|
||||
self.buf.write(')')
|
||||
|
||||
def visitList(self, node):
|
||||
self.buf.write('[')
|
||||
c = node.getChildren()
|
||||
for i in range(0, len(c)):
|
||||
self.visit(c[i])
|
||||
if i < len(c) - 1:
|
||||
self.buf.write(', ')
|
||||
self.buf.write(']')
|
||||
|
||||
def visitListComp(self, node):
|
||||
self.buf.write('[')
|
||||
self.visit(node.expr)
|
||||
self.buf.write(' ')
|
||||
for n in node.quals:
|
||||
self.visit(n)
|
||||
self.buf.write(']')
|
||||
|
||||
def visitListCompFor(self, node):
|
||||
self.buf.write(' for ')
|
||||
self.visit(node.assign)
|
||||
self.buf.write(' in ')
|
||||
self.visit(node.list)
|
||||
for n in node.ifs:
|
||||
self.visit(n)
|
||||
|
||||
def visitListCompIf(self, node):
|
||||
self.buf.write(' if ')
|
||||
self.visit(node.test)
|
||||
|
||||
def visitCompare(self, node):
|
||||
self.visit(node.expr)
|
||||
for tup in node.ops:
|
||||
self.buf.write(tup[0])
|
||||
self.visit(tup[1])
|
||||
|
||||
def visitCallFunc(self, node, *args):
|
||||
self.visit(node.node)
|
||||
self.buf.write('(')
|
||||
if len(node.args):
|
||||
self.visit(node.args[0])
|
||||
for a in node.args[1:]:
|
||||
self.buf.write(', ')
|
||||
self.visit(a)
|
||||
self.buf.write(')')
|
||||
|
||||
def visitLambda(self, node, *args):
|
||||
self.buf.write('lambda ')
|
||||
|
||||
argnames = list(node.argnames)
|
||||
|
||||
kw = arg = None
|
||||
if node.kwargs > 0:
|
||||
kw = argnames.pop(-1)
|
||||
if node.varargs > 0:
|
||||
arg = argnames.pop(-1)
|
||||
|
||||
if arg:
|
||||
argnames.append("*%s" % arg)
|
||||
if kw:
|
||||
argnames.append("**%s" % kw)
|
||||
|
||||
self.buf.write(", ".join(argnames))
|
||||
|
||||
self.buf.write(': ')
|
||||
self.visit(node.code)
|
||||
|
||||
|
||||
class walker(visitor.ASTVisitor):
|
||||
|
||||
def dispatch(self, node, *args):
|
||||
print('Node:', str(node))
|
||||
|
||||
# print "dir:", dir(node)
|
||||
|
||||
return visitor.ASTVisitor.dispatch(self, node, *args)
|
||||
def value(self):
|
||||
return ''.join(self.generator.result)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/runtime.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -9,9 +9,7 @@ Namespace, and various helper functions."""
|
||||
|
||||
from mako import exceptions, util, compat
|
||||
from mako.compat import compat_builtins
|
||||
import inspect
|
||||
import sys
|
||||
import collections
|
||||
|
||||
|
||||
class Context(object):
|
||||
@@ -132,9 +130,7 @@ class Context(object):
|
||||
def get(self, key, default=None):
|
||||
"""Return a value from this :class:`.Context`."""
|
||||
|
||||
return self._data.get(key,
|
||||
compat_builtins.__dict__.get(key, default)
|
||||
)
|
||||
return self._data.get(key, compat_builtins.__dict__.get(key, default))
|
||||
|
||||
def write(self, string):
|
||||
"""Write a string to this :class:`.Context` object's
|
||||
@@ -474,8 +470,8 @@ class Namespace(object):
|
||||
def get_template(self, uri):
|
||||
"""Return a :class:`.Template` from the given ``uri``.
|
||||
|
||||
The ``uri`` resolution is relative to the ``uri`` of this :class:`.Namespace`
|
||||
object's :class:`.Template`.
|
||||
The ``uri`` resolution is relative to the ``uri`` of this
|
||||
:class:`.Namespace` object's :class:`.Template`.
|
||||
|
||||
"""
|
||||
return _lookup_template(self.context, uri, self._templateuri)
|
||||
@@ -673,7 +669,7 @@ def supports_caller(func):
|
||||
|
||||
"""
|
||||
|
||||
def wrap_stackframe(context, *args, **kwargs):
|
||||
def wrap_stackframe(context, *args, **kwargs):
|
||||
context.caller_stack._push_frame()
|
||||
try:
|
||||
return func(context, *args, **kwargs)
|
||||
@@ -691,8 +687,8 @@ def capture(context, callable_, *args, **kwargs):
|
||||
|
||||
if not compat.callable(callable_):
|
||||
raise exceptions.RuntimeException(
|
||||
"capture() function expects a callable as "
|
||||
"its argument (i.e. capture(func, *args, **kwargs))"
|
||||
"capture() function expects a callable as "
|
||||
"its argument (i.e. capture(func, *args, **kwargs))"
|
||||
)
|
||||
context._push_buffer()
|
||||
try:
|
||||
@@ -853,7 +849,6 @@ def _exec_template(callable_, context, args=None, kwargs=None):
|
||||
template = context._with_template
|
||||
if template is not None and \
|
||||
(template.format_exceptions or template.error_handler):
|
||||
error = None
|
||||
try:
|
||||
callable_(context, *args, **kwargs)
|
||||
except Exception:
|
||||
@@ -868,11 +863,12 @@ def _render_error(template, context, error):
|
||||
if template.error_handler:
|
||||
result = template.error_handler(context, error)
|
||||
if not result:
|
||||
raise error
|
||||
compat.reraise(*sys.exc_info())
|
||||
else:
|
||||
error_template = exceptions.html_error_template()
|
||||
if context._outputting_as_unicode:
|
||||
context._buffer_stack[:] = [util.FastEncodingBuffer(as_unicode=True)]
|
||||
context._buffer_stack[:] = [
|
||||
util.FastEncodingBuffer(as_unicode=True)]
|
||||
else:
|
||||
context._buffer_stack[:] = [util.FastEncodingBuffer(
|
||||
error_template.output_encoding,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/template.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -596,6 +596,25 @@ class ModuleInfo(object):
|
||||
if module_filename:
|
||||
self._modules[module_filename] = self
|
||||
|
||||
@classmethod
|
||||
def get_module_source_metadata(cls, module_source, full_line_map=False):
|
||||
source_map = re.search(
|
||||
r"__M_BEGIN_METADATA(.+?)__M_END_METADATA",
|
||||
module_source, re.S).group(1)
|
||||
source_map = compat.json.loads(source_map)
|
||||
source_map['line_map'] = dict((int(k), int(v))
|
||||
for k, v in source_map['line_map'].items())
|
||||
if full_line_map:
|
||||
f_line_map = source_map['full_line_map'] = []
|
||||
line_map = source_map['line_map']
|
||||
|
||||
curr_templ_line = 1
|
||||
for mod_line in range(1, max(line_map)):
|
||||
if mod_line in line_map:
|
||||
curr_templ_line = line_map[mod_line]
|
||||
f_line_map.append(curr_templ_line)
|
||||
return source_map
|
||||
|
||||
@property
|
||||
def code(self):
|
||||
if self.module_source is not None:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# mako/util.py
|
||||
# Copyright (C) 2006-2013 the Mako authors and contributors <see AUTHORS file>
|
||||
# Copyright (C) 2006-2015 the Mako authors and contributors <see AUTHORS file>
|
||||
#
|
||||
# This module is part of Mako and is released under
|
||||
# the MIT License: http://www.opensource.org/licenses/mit-license.php
|
||||
@@ -11,15 +11,10 @@ import os
|
||||
from mako import compat
|
||||
import operator
|
||||
|
||||
def function_named(fn, name):
|
||||
"""Return a function with a given __name__.
|
||||
|
||||
Will assign to __name__ and return the original function if possible on
|
||||
the Python implementation, otherwise a new function will be constructed.
|
||||
|
||||
"""
|
||||
fn.__name__ = name
|
||||
return fn
|
||||
def update_wrapper(decorated, fn):
|
||||
decorated.__wrapped__ = fn
|
||||
decorated.__name__ = fn.__name__
|
||||
return decorated
|
||||
|
||||
|
||||
class PluginLoader(object):
|
||||
|
||||
85
lib/requests/README.rst
Normal file
85
lib/requests/README.rst
Normal file
@@ -0,0 +1,85 @@
|
||||
Requests: HTTP for Humans
|
||||
=========================
|
||||
|
||||
.. image:: https://badge.fury.io/py/requests.png
|
||||
:target: http://badge.fury.io/py/requests
|
||||
|
||||
.. image:: https://pypip.in/d/requests/badge.png
|
||||
:target: https://crate.io/packages/requests/
|
||||
|
||||
|
||||
Requests is an Apache2 Licensed HTTP library, written in Python, for human
|
||||
beings.
|
||||
|
||||
Most existing Python modules for sending HTTP requests are extremely
|
||||
verbose and cumbersome. Python's builtin urllib2 module provides most of
|
||||
the HTTP capabilities you should need, but the api is thoroughly broken.
|
||||
It requires an enormous amount of work (even method overrides) to
|
||||
perform the simplest of tasks.
|
||||
|
||||
Things shouldn't be this way. Not in Python.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
>>> r = requests.get('https://api.github.com', auth=('user', 'pass'))
|
||||
>>> r.status_code
|
||||
204
|
||||
>>> r.headers['content-type']
|
||||
'application/json'
|
||||
>>> r.text
|
||||
...
|
||||
|
||||
See `the same code, without Requests <https://gist.github.com/973705>`_.
|
||||
|
||||
Requests allow you to send HTTP/1.1 requests. You can add headers, form data,
|
||||
multipart files, and parameters with simple Python dictionaries, and access the
|
||||
response data in the same way. It's powered by httplib and `urllib3
|
||||
<https://github.com/shazow/urllib3>`_, but it does all the hard work and crazy
|
||||
hacks for you.
|
||||
|
||||
|
||||
Features
|
||||
--------
|
||||
|
||||
- International Domains and URLs
|
||||
- Keep-Alive & Connection Pooling
|
||||
- Sessions with Cookie Persistence
|
||||
- Browser-style SSL Verification
|
||||
- Basic/Digest Authentication
|
||||
- Elegant Key/Value Cookies
|
||||
- Automatic Decompression
|
||||
- Unicode Response Bodies
|
||||
- Multipart File Uploads
|
||||
- Connection Timeouts
|
||||
- Thread-safety
|
||||
- HTTP(S) proxy support
|
||||
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
To install Requests, simply:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
$ pip install requests
|
||||
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
|
||||
Documentation is available at http://docs.python-requests.org/.
|
||||
|
||||
|
||||
Contribute
|
||||
----------
|
||||
|
||||
#. Check for open issues or open a fresh issue to start a discussion around a feature idea or a bug. There is a `Contributor Friendly`_ tag for issues that should be ideal for people who are not very familiar with the codebase yet.
|
||||
#. If you feel uncomfortable or uncertain about an issue or your changes, feel free to email @sigmavirus24 and he will happily help you via email, Skype, remote pairing or whatever you are comfortable with.
|
||||
#. Fork `the repository`_ on GitHub to start making your changes to the **master** branch (or branch off of it).
|
||||
#. Write a test which shows that the bug was fixed or that the feature works as expected.
|
||||
#. Send a pull request and bug the maintainer until it gets merged and published. :) Make sure to add yourself to AUTHORS_.
|
||||
|
||||
.. _`the repository`: http://github.com/kennethreitz/requests
|
||||
.. _AUTHORS: https://github.com/kennethreitz/requests/blob/master/AUTHORS.rst
|
||||
.. _Contributor Friendly: https://github.com/kennethreitz/requests/issues?direction=desc&labels=Contributor+Friendly&page=1&sort=updated&state=open
|
||||
Reference in New Issue
Block a user