summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormike bayer <mike_mp@zzzcomputing.com>2021-10-25 17:45:20 +0000
committerGerrit Code Review <gerrit@ci3.zzzcomputing.com>2021-10-25 17:45:20 +0000
commit781e5e9948dfb701823fb9cd7a07be28d2460290 (patch)
treef00f9a27fbdbb696d8737b381000a5d23d75dcaf
parent4371b7e6e59b8438af56bac9a8a9e19d3167d854 (diff)
parent3fae86f10914c11c89d4c272fda792da6c61eb51 (diff)
downloadmako-781e5e9948dfb701823fb9cd7a07be28d2460290.tar.gz
Merge "more code updates" into main
-rw-r--r--doc/build/unreleased/bytestring_passthrough.rst5
-rw-r--r--mako/__init__.py2
-rw-r--r--mako/_ast_util.py11
-rw-r--r--mako/ast.py10
-rw-r--r--mako/cache.py2
-rwxr-xr-xmako/cmd.py4
-rw-r--r--mako/codegen.py21
-rw-r--r--mako/compat.py39
-rw-r--r--mako/exceptions.py2
-rw-r--r--mako/ext/autohandler.py2
-rw-r--r--mako/ext/babelplugin.py4
-rw-r--r--mako/ext/beaker_cache.py2
-rw-r--r--mako/ext/extract.py2
-rw-r--r--mako/ext/linguaplugin.py9
-rw-r--r--mako/ext/preprocessors.py2
-rw-r--r--mako/ext/pygmentplugin.py2
-rw-r--r--mako/ext/turbogears.py2
-rw-r--r--mako/filters.py71
-rw-r--r--mako/lexer.py27
-rw-r--r--mako/lookup.py12
-rw-r--r--mako/parsetree.py44
-rw-r--r--mako/pygen.py5
-rw-r--r--mako/pyparser.py16
-rw-r--r--mako/runtime.py26
-rw-r--r--mako/template.py28
-rw-r--r--mako/util.py6
-rw-r--r--test/test_template.py27
27 files changed, 114 insertions, 269 deletions
diff --git a/doc/build/unreleased/bytestring_passthrough.rst b/doc/build/unreleased/bytestring_passthrough.rst
new file mode 100644
index 0000000..e2c8849
--- /dev/null
+++ b/doc/build/unreleased/bytestring_passthrough.rst
@@ -0,0 +1,5 @@
+.. change::
+ :tags: py3k
+
+ The ``bytestring_passthrough`` template argument is removed, as this
+ flag only applied to Python 2.
diff --git a/mako/__init__.py b/mako/__init__.py
index d595275..5ae5501 100644
--- a/mako/__init__.py
+++ b/mako/__init__.py
@@ -1,5 +1,5 @@
# mako/__init__.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/_ast_util.py b/mako/_ast_util.py
index 21a60fc..b861533 100644
--- a/mako/_ast_util.py
+++ b/mako/_ast_util.py
@@ -1,5 +1,5 @@
# mako/_ast_util.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -47,7 +47,6 @@ from _ast import Sub
from _ast import UAdd
from _ast import USub
-from mako.compat import arg_stringname
BOOLOP_SYMBOLS = {And: "and", Or: "or"}
@@ -94,9 +93,7 @@ def parse(expr, filename="<unknown>", mode="exec"):
def iter_fields(node):
"""Iterate over all fields of a node, only yielding existing fields."""
- # CPython 2.5 compat
- if not hasattr(node, "_fields") or not node._fields:
- return
+
for field in node._fields:
try:
yield field, getattr(node, field)
@@ -266,10 +263,10 @@ class SourceGenerator(NodeVisitor):
self.visit(default)
if node.vararg is not None:
write_comma()
- self.write("*" + arg_stringname(node.vararg))
+ self.write("*" + node.vararg.arg)
if node.kwarg is not None:
write_comma()
- self.write("**" + arg_stringname(node.kwarg))
+ self.write("**" + node.kwarg.arg)
def decorators(self, node):
for decorator in node.decorator_list:
diff --git a/mako/ast.py b/mako/ast.py
index 5e52e02..1b017e1 100644
--- a/mako/ast.py
+++ b/mako/ast.py
@@ -1,5 +1,5 @@
# mako/ast.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -87,7 +87,7 @@ class PythonFragment(PythonCode):
if not m:
raise exceptions.CompileException(
"Fragment '%s' is not a partial control statement" % code,
- **exception_kwargs
+ **exception_kwargs,
)
if m.group(3):
code = code[: m.start(3)]
@@ -105,7 +105,7 @@ class PythonFragment(PythonCode):
else:
raise exceptions.CompileException(
"Unsupported control keyword: '%s'" % keyword,
- **exception_kwargs
+ **exception_kwargs,
)
super(PythonFragment, self).__init__(code, **exception_kwargs)
@@ -123,13 +123,13 @@ class FunctionDecl:
if not hasattr(self, "funcname"):
raise exceptions.CompileException(
"Code '%s' is not a function declaration" % code,
- **exception_kwargs
+ **exception_kwargs,
)
if not allow_kwargs and self.kwargs:
raise exceptions.CompileException(
"'**%s' keyword argument not allowed here"
% self.kwargnames[-1],
- **exception_kwargs
+ **exception_kwargs,
)
def get_argument_expressions(self, as_call=False):
diff --git a/mako/cache.py b/mako/cache.py
index c382aea..d77be27 100644
--- a/mako/cache.py
+++ b/mako/cache.py
@@ -1,5 +1,5 @@
# mako/cache.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/cmd.py b/mako/cmd.py
index c0f2c75..986a1d2 100755
--- a/mako/cmd.py
+++ b/mako/cmd.py
@@ -1,5 +1,5 @@
# mako/cmd.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -85,7 +85,7 @@ def cmdline(argv=None):
except:
_exit()
- kw = dict([varsplit(var) for var in options.var])
+ kw = dict(varsplit(var) for var in options.var)
try:
rendered = template.render(**kw)
except:
diff --git a/mako/codegen.py b/mako/codegen.py
index 415d274..7f1c8c3 100644
--- a/mako/codegen.py
+++ b/mako/codegen.py
@@ -1,5 +1,5 @@
# mako/codegen.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -12,7 +12,6 @@ import re
import time
from mako import ast
-from mako import compat
from mako import exceptions
from mako import filters
from mako import parsetree
@@ -25,8 +24,8 @@ MAGIC_NUMBER = 10
# names which are hardwired into the
# template and are not accessed via the
# context itself
-TOPLEVEL_DECLARED = set(["UNDEFINED", "STOP_RENDERING"])
-RESERVED_NAMES = set(["context", "loop"]).union(TOPLEVEL_DECLARED)
+TOPLEVEL_DECLARED = {"UNDEFINED", "STOP_RENDERING"}
+RESERVED_NAMES = {"context", "loop"}.union(TOPLEVEL_DECLARED)
def compile( # noqa
@@ -393,7 +392,7 @@ class _GenerateRenderMethod:
raise exceptions.CompileException(
"Can't put anonymous blocks inside "
"<%namespace>",
- **node.exception_kwargs
+ **node.exception_kwargs,
)
self.write_inline_def(node, identifiers, nested=False)
export.append(node.funcname)
@@ -470,7 +469,7 @@ class _GenerateRenderMethod:
"""
# collection of all defs available to us in this scope
- comp_idents = dict([(c.funcname, c) for c in identifiers.defs])
+ comp_idents = {c.funcname: c for c in identifiers.defs}
to_write = set()
# write "context.get()" for all variables we are going to
@@ -846,11 +845,11 @@ class _GenerateRenderMethod:
# and end control lines, and
# 3) any control line with no content other than comments
if not children or (
- compat.all(
+ all(
isinstance(c, (parsetree.Comment, parsetree.ControlLine))
for c in children
)
- and compat.all(
+ and all(
(node.is_ternary(c.keyword) or c.isend)
for c in children
if isinstance(c, parsetree.ControlLine)
@@ -1157,7 +1156,7 @@ class _Identifiers:
raise exceptions.CompileException(
"%%def or %%block named '%s' already "
"exists in this template." % node.funcname,
- **node.exception_kwargs
+ **node.exception_kwargs,
)
def visitDefTag(self, node):
@@ -1187,7 +1186,7 @@ class _Identifiers:
raise exceptions.CompileException(
"Named block '%s' not allowed inside of def '%s'"
% (node.name, self.node.name),
- **node.exception_kwargs
+ **node.exception_kwargs,
)
elif isinstance(
self.node, (parsetree.CallTag, parsetree.CallNamespaceTag)
@@ -1195,7 +1194,7 @@ class _Identifiers:
raise exceptions.CompileException(
"Named block '%s' not allowed inside of <%%call> tag"
% (node.name,),
- **node.exception_kwargs
+ **node.exception_kwargs,
)
for ident in node.undeclared_identifiers():
diff --git a/mako/compat.py b/mako/compat.py
index 4baa479..852d759 100644
--- a/mako/compat.py
+++ b/mako/compat.py
@@ -1,5 +1,5 @@
# mako/compat.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -46,10 +46,6 @@ def inspect_getargspec(func):
return ArgSpec(args, varargs, varkw, func.__defaults__)
-def octal(lit):
- return eval("0o" + lit)
-
-
def load_module(module_id, path):
spec = util.spec_from_file_location(module_id, path)
module = util.module_from_spec(spec)
@@ -57,42 +53,9 @@ def load_module(module_id, path):
return module
-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
-
-
def exception_as():
return sys.exc_info()[1]
-all = all # noqa
-
-
def exception_name(exc):
return exc.__class__.__name__
-
-
-################################################
-# cross-compatible metaclass implementation
-# Copyright (c) 2010-2012 Benjamin Peterson
-def with_metaclass(meta, base=object):
- """Create a base class with a metaclass."""
- return meta("%sBase" % meta.__name__, (base,), {})
-
-
-################################################
-
-
-def arg_stringname(func_arg):
- """Gets the string name of a kwarg or vararg
- In Python3.4 a function's args are
- of _ast.arg type not _ast.name
- """
- if hasattr(func_arg, "arg"):
- return func_arg.arg
- else:
- return str(func_arg)
diff --git a/mako/exceptions.py b/mako/exceptions.py
index a5f9370..c8c77a5 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -1,5 +1,5 @@
# mako/exceptions.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/autohandler.py b/mako/ext/autohandler.py
index 8b1324e..e8fdac8 100644
--- a/mako/ext/autohandler.py
+++ b/mako/ext/autohandler.py
@@ -1,5 +1,5 @@
# ext/autohandler.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/babelplugin.py b/mako/ext/babelplugin.py
index d5c6b4b..8f8e7d9 100644
--- a/mako/ext/babelplugin.py
+++ b/mako/ext/babelplugin.py
@@ -1,10 +1,10 @@
# ext/babelplugin.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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/"""
+"""gettext message extraction via Babel: https://pypi.org/project/Babel/"""
from babel.messages.extract import extract_python
from mako.ext.extract import MessageExtractor
diff --git a/mako/ext/beaker_cache.py b/mako/ext/beaker_cache.py
index f65ce43..6a7e898 100644
--- a/mako/ext/beaker_cache.py
+++ b/mako/ext/beaker_cache.py
@@ -1,5 +1,5 @@
# ext/beaker_cache.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/extract.py b/mako/ext/extract.py
index 66e3c19..9e14a0a 100644
--- a/mako/ext/extract.py
+++ b/mako/ext/extract.py
@@ -1,5 +1,5 @@
# ext/extract.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/linguaplugin.py b/mako/ext/linguaplugin.py
index 438258e..e50151e 100644
--- a/mako/ext/linguaplugin.py
+++ b/mako/ext/linguaplugin.py
@@ -1,5 +1,5 @@
# ext/linguaplugin.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -39,11 +39,8 @@ class LinguaMakoExtractor(Extractor, MessageExtractor):
def process_python(self, code, code_lineno, translator_strings):
source = code.getvalue().strip()
if source.endswith(":"):
- if source in (
- "try:",
- "else:",
- ) or source.startswith("except"):
- source = "" # Ignore try/except and else
+ if source in ("try:", "else:") or source.startswith("except"):
+ source = "" # Ignore try/except and else
elif source.startswith("elif"):
source = source[2:] # Replace "elif" with "if"
source += "pass"
diff --git a/mako/ext/preprocessors.py b/mako/ext/preprocessors.py
index 9cc0621..6855eeb 100644
--- a/mako/ext/preprocessors.py
+++ b/mako/ext/preprocessors.py
@@ -1,5 +1,5 @@
# ext/preprocessors.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/pygmentplugin.py b/mako/ext/pygmentplugin.py
index dcfe5c4..9096f33 100644
--- a/mako/ext/pygmentplugin.py
+++ b/mako/ext/pygmentplugin.py
@@ -1,5 +1,5 @@
# ext/pygmentplugin.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/ext/turbogears.py b/mako/ext/turbogears.py
index e37349e..413d9f7 100644
--- a/mako/ext/turbogears.py
+++ b/mako/ext/turbogears.py
@@ -1,5 +1,5 @@
# ext/turbogears.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
diff --git a/mako/filters.py b/mako/filters.py
index d6323b9..26edd8e 100644
--- a/mako/filters.py
+++ b/mako/filters.py
@@ -1,5 +1,5 @@
# mako/filters.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -10,7 +10,10 @@ from html.entities import codepoint2name
from html.entities import name2codepoint
import re
from urllib.parse import quote_plus
-from urllib.parse import unquote_plus
+
+import markupsafe
+
+html_escape = markupsafe.escape
xml_escapes = {
"&": "&amp;",
@@ -20,27 +23,6 @@ xml_escapes = {
"'": "&#39;", # also &apos; in html-only
}
-# XXX: &quot; is valid in HTML and XML
-# &apos; is not valid HTML, but is valid XML
-
-
-def legacy_html_escape(s):
- """legacy HTML escape for non-unicode mode."""
- s = s.replace("&", "&amp;")
- s = s.replace(">", "&gt;")
- s = s.replace("<", "&lt;")
- s = s.replace('"', "&#34;")
- s = s.replace("'", "&#39;")
- return s
-
-
-try:
- import markupsafe
-
- html_escape = markupsafe.escape
-except ImportError:
- html_escape = legacy_html_escape
-
def xml_escape(string):
return re.sub(r'([&<"\'>])', lambda m: xml_escapes[m.group()], string)
@@ -52,18 +34,6 @@ def url_escape(string):
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):
- text = text.decode("utf8")
- return text
-
-
def trim(string):
return string.strip()
@@ -84,24 +54,11 @@ class Decode:
decode = Decode()
-_ASCII_re = re.compile(r"\A[\x00-\x7f]*\Z")
-
-
-def is_ascii_str(text):
- return isinstance(text, str) and _ASCII_re.match(text)
-
-
-################################################################
-
-
class XMLEntityEscaper:
def __init__(self, codepoint2name, name2codepoint):
- self.codepoint2entity = dict(
- [
- (c, str("&%s;" % n))
- for c, n in codepoint2name.items()
- ]
- )
+ self.codepoint2entity = {
+ c: str("&%s;" % n) for c, n in codepoint2name.items()
+ }
self.name2codepoint = name2codepoint
def escape_entities(self, text):
@@ -129,9 +86,7 @@ class XMLEntityEscaper:
The return value is guaranteed to be ASCII.
"""
- return self.__escapable.sub(
- self.__escape, str(text)
- ).encode("ascii")
+ return self.__escapable.sub(self.__escape, str(text)).encode("ascii")
# XXX: This regexp will not match all valid XML entity names__.
# (It punts on details involving involving CombiningChars and Extenders.)
@@ -181,7 +136,7 @@ def htmlentityreplace_errors(ex):
characters with HTML entities, or, if no HTML entity exists for
the character, XML character references::
- >>> u'The cost was \u20ac12.'.encode('latin1', 'htmlentityreplace')
+ >>> 'The cost was \u20ac12.'.encode('latin1', 'htmlentityreplace')
'The cost was &euro;12.'
"""
if isinstance(ex, UnicodeEncodeError):
@@ -195,8 +150,6 @@ def htmlentityreplace_errors(ex):
codecs.register_error("htmlentityreplace", htmlentityreplace_errors)
-# TODO: options to make this dynamic per-compilation will be added in a later
-# release
DEFAULT_ESCAPES = {
"x": "filters.xml_escape",
"h": "filters.html_escape",
@@ -208,7 +161,3 @@ DEFAULT_ESCAPES = {
"str": "str",
"n": "n",
}
-
-NON_UNICODE_ESCAPES = DEFAULT_ESCAPES.copy()
-NON_UNICODE_ESCAPES["h"] = "filters.legacy_html_escape"
-NON_UNICODE_ESCAPES["u"] = "filters.legacy_url_escape"
diff --git a/mako/lexer.py b/mako/lexer.py
index 05aa2d9..74fafa1 100644
--- a/mako/lexer.py
+++ b/mako/lexer.py
@@ -1,5 +1,5 @@
# mako/lexer.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -18,11 +18,7 @@ _regexp_cache = {}
class Lexer:
def __init__(
- self,
- text,
- filename=None,
- input_encoding=None,
- preprocessor=None,
+ self, text, filename=None, input_encoding=None, preprocessor=None
):
self.text = text
self.filename = filename
@@ -180,7 +176,7 @@ class Lexer:
raise exceptions.SyntaxException(
"Keyword '%s' not a legal ternary for keyword '%s'"
% (node.keyword, self.control_line[-1].keyword),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
_coding_re = re.compile(r"#.*coding[:=]\s*([-\w.]+).*\r?\n")
@@ -268,12 +264,13 @@ class Lexer:
if self.match_position > self.textlength:
break
- raise exceptions.CompileException("assertion failed")
+ # TODO: no coverage here
+ raise exceptions.MakoException("assertion failed")
if len(self.tag):
raise exceptions.SyntaxException(
"Unclosed tag: <%%%s>" % self.tag[-1].keyword,
- **self.exception_kwargs
+ **self.exception_kwargs,
)
if len(self.control_line):
raise exceptions.SyntaxException(
@@ -325,7 +322,7 @@ class Lexer:
if not match:
raise exceptions.SyntaxException(
"Unclosed tag: <%%%s>" % self.tag[-1].keyword,
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self.append_node(parsetree.Text, match.group(1))
return self.match_tag_end()
@@ -340,13 +337,13 @@ class Lexer:
raise exceptions.SyntaxException(
"Closing tag without opening tag: </%%%s>"
% match.group(1),
- **self.exception_kwargs
+ **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
+ **self.exception_kwargs,
)
self.tag.pop()
return True
@@ -447,7 +444,7 @@ class Lexer:
if not m2:
raise exceptions.SyntaxException(
"Invalid control line: '%s'" % text,
- **self.exception_kwargs
+ **self.exception_kwargs,
)
isend, keyword = m2.group(1, 2)
isend = isend is not None
@@ -457,13 +454,13 @@ class Lexer:
raise exceptions.SyntaxException(
"No starting keyword '%s' for '%s'"
% (keyword, text),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
elif self.control_line[-1].keyword != keyword:
raise exceptions.SyntaxException(
"Keyword '%s' doesn't match keyword '%s'"
% (text, self.control_line[-1].keyword),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self.append_node(parsetree.ControlLine, keyword, isend, text)
else:
diff --git a/mako/lookup.py b/mako/lookup.py
index 57d0de4..b048f2a 100644
--- a/mako/lookup.py
+++ b/mako/lookup.py
@@ -1,5 +1,5 @@
# mako/lookup.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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,16 +8,12 @@ import os
import posixpath
import re
import stat
+import threading
from mako import exceptions
from mako import util
from mako.template import Template
-try:
- import threading
-except:
- import dummy_threading as threading
-
class TemplateCollection:
@@ -161,7 +157,6 @@ class TemplateLookup(TemplateCollection):
collection_size=-1,
format_exceptions=False,
error_handler=None,
- bytestring_passthrough=False,
output_encoding=None,
encoding_errors="strict",
cache_args=None,
@@ -206,7 +201,6 @@ class TemplateLookup(TemplateCollection):
"format_exceptions": format_exceptions,
"error_handler": error_handler,
"include_error_handler": include_error_handler,
- "bytestring_passthrough": bytestring_passthrough,
"output_encoding": output_encoding,
"cache_impl": cache_impl,
"encoding_errors": encoding_errors,
@@ -322,7 +316,7 @@ class TemplateLookup(TemplateCollection):
filename=posixpath.normpath(filename),
lookup=self,
module_filename=module_filename,
- **self.template_args
+ **self.template_args,
)
return template
except:
diff --git a/mako/parsetree.py b/mako/parsetree.py
index 54aaa56..4501b49 100644
--- a/mako/parsetree.py
+++ b/mako/parsetree.py
@@ -1,5 +1,5 @@
# mako/parsetree.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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,7 +9,6 @@
import re
from mako import ast
-from mako import compat
from mako import exceptions
from mako import filters
from mako import util
@@ -108,9 +107,9 @@ class ControlLine(Node):
for this ControlLine"""
return keyword in {
- "if": set(["else", "elif"]),
- "try": set(["except", "finally"]),
- "for": set(["else"]),
+ "if": {"else", "elif"},
+ "try": {"except", "finally"},
+ "for": {"else"},
}.get(self.keyword, [])
def __repr__(self):
@@ -123,7 +122,6 @@ class ControlLine(Node):
class Text(Node):
-
"""defines plain text in the template."""
def __init__(self, content, **kwargs):
@@ -135,7 +133,6 @@ class Text(Node):
class Code(Node):
-
"""defines a Python code block, either inline or module level.
e.g.::
@@ -173,7 +170,6 @@ class Code(Node):
class Comment(Node):
-
"""defines a comment line.
# this is a comment
@@ -189,7 +185,6 @@ class Comment(Node):
class Expression(Node):
-
"""defines an inline expression.
${x+y}
@@ -210,7 +205,7 @@ class Expression(Node):
# TODO: make the "filter" shortcut list configurable at parse/gen time
return self.code.undeclared_identifiers.union(
self.escapes_code.undeclared_identifiers.difference(
- set(filters.DEFAULT_ESCAPES.keys())
+ filters.DEFAULT_ESCAPES
)
).difference(self.code.declared_identifiers)
@@ -223,7 +218,6 @@ class Expression(Node):
class _TagMeta(type):
-
"""metaclass to allow Tag to produce a subclass according to
its keyword"""
@@ -254,7 +248,7 @@ class _TagMeta(type):
return type.__call__(cls, keyword, attributes, **kwargs)
-class Tag(compat.with_metaclass(_TagMeta, Node)):
+class Tag(Node, metaclass=_TagMeta):
"""abstract base class for tags.
e.g.::
@@ -276,7 +270,7 @@ class Tag(compat.with_metaclass(_TagMeta, Node)):
expressions,
nonexpressions,
required,
- **kwargs
+ **kwargs,
):
r"""construct a new Tag instance.
@@ -306,7 +300,7 @@ class Tag(compat.with_metaclass(_TagMeta, Node)):
raise exceptions.CompileException(
"Missing attribute(s): %s"
% ",".join([repr(m) for m in missing]),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self.parent = None
self.nodes = []
@@ -348,14 +342,14 @@ class Tag(compat.with_metaclass(_TagMeta, Node)):
raise exceptions.CompileException(
"Attibute '%s' in tag '%s' does not allow embedded "
"expressions" % (key, self.keyword),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self.parsed_attributes[key] = repr(self.attributes[key])
else:
raise exceptions.CompileException(
"Invalid attribute for tag '%s': '%s'"
% (self.keyword, key),
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self.expression_undeclared_identifiers = undeclared_identifiers
@@ -385,7 +379,7 @@ class IncludeTag(Tag):
("file", "import", "args"),
(),
("file",),
- **kwargs
+ **kwargs,
)
self.page_args = ast.PythonCode(
"__DUMMY(%s)" % attributes.get("args", ""), **self.exception_kwargs
@@ -396,7 +390,7 @@ class IncludeTag(Tag):
def undeclared_identifiers(self):
identifiers = self.page_args.undeclared_identifiers.difference(
- set(["__DUMMY"])
+ {"__DUMMY"}
).difference(self.page_args.declared_identifiers)
return identifiers.union(
super(IncludeTag, self).undeclared_identifiers()
@@ -413,7 +407,7 @@ class NamespaceTag(Tag):
("file",),
("name", "inheritable", "import", "module"),
(),
- **kwargs
+ **kwargs,
)
self.name = attributes.get("name", "__anon_%s" % hex(abs(id(self))))
@@ -421,12 +415,12 @@ class NamespaceTag(Tag):
raise exceptions.CompileException(
"'name' and/or 'import' attributes are required "
"for <%namespace>",
- **self.exception_kwargs
+ **self.exception_kwargs,
)
if "file" in attributes and "module" in attributes:
raise exceptions.CompileException(
"<%namespace> may only have one of 'file' or 'module'",
- **self.exception_kwargs
+ **self.exception_kwargs,
)
def declared_identifiers(self):
@@ -464,7 +458,7 @@ class DefTag(Tag):
expressions,
("name", "filter", "decorator"),
("name",),
- **kwargs
+ **kwargs,
)
name = attributes["name"]
if re.match(r"^[\w_]+$", name):
@@ -527,13 +521,13 @@ class BlockTag(Tag):
expressions,
("name", "filter", "decorator"),
(),
- **kwargs
+ **kwargs,
)
name = attributes.get("name")
if name and not re.match(r"^[\w_]+$", name):
raise exceptions.CompileException(
"%block may not specify an argument signature",
- **self.exception_kwargs
+ **self.exception_kwargs,
)
if not name and attributes.get("args", None):
raise exceptions.CompileException(
@@ -603,7 +597,7 @@ class CallNamespaceTag(Tag):
tuple(attributes.keys()) + ("args",),
(),
(),
- **kwargs
+ **kwargs,
)
self.expression = "%s.%s(%s)" % (
diff --git a/mako/pygen.py b/mako/pygen.py
index bae285a..b9d4c2e 100644
--- a/mako/pygen.py
+++ b/mako/pygen.py
@@ -1,5 +1,5 @@
# mako/pygen.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -104,7 +104,8 @@ class PythonPrinter:
# probably put extra closures - the resulting
# module wont compile.
if len(self.indent_detail) == 0:
- raise exceptions.SyntaxException(
+ # TODO: no coverage here
+ raise exceptions.MakoException(
"Too many whitespace closures"
)
self.indent_detail.pop()
diff --git a/mako/pyparser.py b/mako/pyparser.py
index b441132..411b1b5 100644
--- a/mako/pyparser.py
+++ b/mako/pyparser.py
@@ -1,5 +1,5 @@
# mako/pyparser.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -18,11 +18,10 @@ from mako import _ast_util
from mako import compat
from mako import exceptions
from mako import util
-from mako.compat import arg_stringname
# words that cannot be assigned to (notably
# smaller than the total keys in __builtins__)
-reserved = set(["True", "False", "None", "print"])
+reserved = {"True", "False", "None", "print"}
# the "id" attribute on a function node
arg_id = operator.attrgetter("arg")
@@ -43,7 +42,7 @@ def parse(code, mode="exec", **exception_kwargs):
compat.exception_as(),
code[0:50],
),
- **exception_kwargs
+ **exception_kwargs,
)
@@ -77,9 +76,6 @@ class FindIdentifiers(_ast_util.NodeVisitor):
self.visit(n)
self.in_assign_targets = in_a
- # 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)
@@ -167,7 +163,7 @@ class FindIdentifiers(_ast_util.NodeVisitor):
"names must be explicitly declared. Please use the "
"form 'from <modulename> import <name1>, <name2>, "
"...' instead.",
- **self.exception_kwargs
+ **self.exception_kwargs,
)
self._add_declared(name.name)
@@ -203,11 +199,11 @@ class ParseFunc(_ast_util.NodeVisitor):
argnames = [arg_id(arg) for arg in node.args.args]
if node.args.vararg:
- argnames.append(arg_stringname(node.args.vararg))
+ argnames.append(node.args.vararg.arg)
kwargnames = [arg_id(arg) for arg in node.args.kwonlyargs]
if node.args.kwarg:
- kwargnames.append(arg_stringname(node.args.kwarg))
+ kwargnames.append(node.args.kwarg.arg)
self.listener.argnames = argnames
self.listener.defaults = node.args.defaults # ast
self.listener.kwargnames = kwargnames
diff --git a/mako/runtime.py b/mako/runtime.py
index bf31d28..f9ce630 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -9,7 +9,6 @@ Namespace, and various helper functions."""
import builtins
import functools
-from io import StringIO
import sys
from mako import compat
@@ -391,7 +390,7 @@ class Namespace:
self.context = context
self.inherits = inherits
if callables is not None:
- self.callables = dict([(c.__name__, c) for c in callables])
+ self.callables = {c.__name__: c for c in callables}
callables = ()
@@ -575,7 +574,7 @@ class TemplateNamespace(Namespace):
self.context = context
self.inherits = inherits
if callables is not None:
- self.callables = dict([(c.__name__, c) for c in callables])
+ self.callables = {c.__name__: c for c in callables}
if templateuri is not None:
self.template = _lookup_template(context, templateuri, calling_uri)
@@ -667,7 +666,7 @@ class ModuleNamespace(Namespace):
self.context = context
self.inherits = inherits
if callables is not None:
- self.callables = dict([(c.__name__, c) for c in callables])
+ self.callables = {c.__name__: c for c in callables}
mod = __import__(module)
for token in module.split(".")[1:]:
@@ -791,7 +790,7 @@ def _include_file(context, uri, calling_uri, **kwargs):
except Exception:
result = template.include_error_handler(ctx, compat.exception_as())
if not result:
- compat.reraise(*sys.exc_info())
+ raise
else:
callable_(ctx, **kwargs)
@@ -864,12 +863,9 @@ def _render(template, callable_, args, data, as_unicode=False):
if as_unicode:
buf = util.FastEncodingBuffer()
- elif template.bytestring_passthrough:
- buf = StringIO()
else:
buf = util.FastEncodingBuffer(
- encoding=template.output_encoding,
- errors=template.encoding_errors,
+ encoding=template.output_encoding, errors=template.encoding_errors
)
context = Context(buf, **data)
context._outputting_as_unicode = as_unicode
@@ -880,7 +876,7 @@ def _render(template, callable_, args, data, as_unicode=False):
callable_,
context,
*args,
- **_kwargs_for_callable(callable_, data)
+ **_kwargs_for_callable(callable_, data),
)
return context._pop_buffer().getvalue()
@@ -951,13 +947,15 @@ def _render_error(template, context, error):
if template.error_handler:
result = template.error_handler(context, error)
if not result:
- compat.reraise(*sys.exc_info())
+ tp, value, tb = sys.exc_info()
+ if value and tb:
+ raise value.with_traceback(tb)
+ else:
+ raise error
else:
error_template = exceptions.html_error_template()
if context._outputting_as_unicode:
- context._buffer_stack[:] = [
- util.FastEncodingBuffer()
- ]
+ context._buffer_stack[:] = [util.FastEncodingBuffer()]
else:
context._buffer_stack[:] = [
util.FastEncodingBuffer(
diff --git a/mako/template.py b/mako/template.py
index 1f11e73..58b5e0f 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -1,5 +1,5 @@
# mako/template.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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
@@ -53,16 +53,6 @@ class Template:
of return-valued ``%def``\ s "opt out" of that filtering via
passing special attributes or objects.
- :param bytestring_passthrough: When ``True``, and ``output_encoding`` is
- set to ``None``, and :meth:`.Template.render` is used to render,
- the `StringIO` buffer will be used instead of the
- default "fast" buffer. This allows raw bytestrings in the
- output stream, such as in expressions, to pass straight
- through to the buffer.
-
- .. versionadded:: 0.4
- Added to provide the same behavior as that of the previous series.
-
:param cache_args: Dictionary of cache configuration arguments that
will be passed to the :class:`.CacheImpl`. See :ref:`caching_toplevel`.
@@ -252,7 +242,6 @@ class Template:
module_filename=None,
input_encoding=None,
module_writer=None,
- bytestring_passthrough=False,
default_filters=None,
buffer_filters=(),
strict_undefined=False,
@@ -289,7 +278,6 @@ class Template:
self.input_encoding = input_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
- self.bytestring_passthrough = bytestring_passthrough
self.enable_loop = enable_loop
self.strict_undefined = strict_undefined
self.module_writer = module_writer
@@ -523,7 +511,6 @@ class ModuleTemplate(Template):
template_source=None,
output_encoding=None,
encoding_errors="strict",
- bytestring_passthrough=False,
format_exceptions=False,
error_handler=None,
lookup=None,
@@ -540,7 +527,6 @@ class ModuleTemplate(Template):
self.input_encoding = module._source_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
- self.bytestring_passthrough = bytestring_passthrough
self.enable_loop = module._enable_loop
self.module = module
@@ -586,7 +572,6 @@ class DefTemplate(Template):
self.include_error_handler = parent.include_error_handler
self.enable_loop = parent.enable_loop
self.lookup = parent.lookup
- self.bytestring_passthrough = parent.bytestring_passthrough
def get_def(self, name):
return self.parent.get_def(name)
@@ -628,9 +613,9 @@ class ModuleInfo:
r"__M_BEGIN_METADATA(.+?)__M_END_METADATA", module_source, re.S
).group(1)
source_map = json.loads(source_map)
- source_map["line_map"] = dict(
- (int(k), int(v)) for k, v in source_map["line_map"].items()
- )
+ source_map["line_map"] = {
+ 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"]
@@ -696,10 +681,7 @@ def _compile(template, text, filename, generate_magic_comment):
def _compile_text(template, text, filename):
identifier = template.module_id
source, lexer = _compile(
- template,
- text,
- filename,
- generate_magic_comment=False,
+ template, text, filename, generate_magic_comment=False
)
cid = identifier
diff --git a/mako/util.py b/mako/util.py
index a34a8c1..2c927bf 100644
--- a/mako/util.py
+++ b/mako/util.py
@@ -1,5 +1,5 @@
# mako/util.py
-# Copyright 2006-2020 the Mako authors and contributors <see AUTHORS file>
+# Copyright 2006-2021 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,8 +11,6 @@ import os
import re
import timeit
-from mako import compat
-
def update_wrapper(decorated, fn):
decorated.__wrapped__ = fn
@@ -59,7 +57,7 @@ def verify_directory(dir_):
while not os.path.exists(dir_):
try:
tries += 1
- os.makedirs(dir_, compat.octal("0775"))
+ os.makedirs(dir_, 0o755)
except:
if tries > 5:
raise
diff --git a/test/test_template.py b/test/test_template.py
index 4b0d271..715bc4c 100644
--- a/test/test_template.py
+++ b/test/test_template.py
@@ -188,8 +188,7 @@ class EncodingTest(TemplateTest):
)
def test_unicode_text_ccall(self):
- val = (
- """
+ val = """
<%def name="foo()">
${capture(caller.body)}
</%def>
@@ -198,7 +197,6 @@ class EncodingTest(TemplateTest):
quand une drôle de petite voix m’a réveillé. Elle disait:
« S’il vous plaît… dessine-moi un mouton! »</%text>
</%call>"""
- )
self._do_memory_test(
("## -*- coding: utf-8 -*-\n" + val).encode("utf-8"),
(
@@ -349,29 +347,6 @@ quand une drôle de petite voix m’a réveillé. Elle disait:
template_args={"f": lambda x: x},
)
- def test_raw_strings(self):
- """test that raw strings go straight thru with default_filters
- turned off, bytestring_passthrough enabled.
-
- """
-
- self._do_memory_test(
- ("## -*- coding: utf-8 -*-\nhello ${x}"),
- "hello śląsk",
- default_filters=[],
- template_args={"x": "śląsk"},
- unicode_=False,
- bytestring_passthrough=True,
- output_encoding=None, # 'ascii'
- )
-
- # now, the way you *should* be doing it....
- self._do_memory_test(
- ("## -*- coding: utf-8 -*-\nhello ${x}"),
- ("hello śląsk"),
- template_args={"x": ("śląsk")},
- )
-
def test_encoding(self):
self._do_memory_test(
(