diff options
author | mike bayer <mike_mp@zzzcomputing.com> | 2021-10-25 17:45:20 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@ci3.zzzcomputing.com> | 2021-10-25 17:45:20 +0000 |
commit | 781e5e9948dfb701823fb9cd7a07be28d2460290 (patch) | |
tree | f00f9a27fbdbb696d8737b381000a5d23d75dcaf | |
parent | 4371b7e6e59b8438af56bac9a8a9e19d3167d854 (diff) | |
parent | 3fae86f10914c11c89d4c272fda792da6c61eb51 (diff) | |
download | mako-781e5e9948dfb701823fb9cd7a07be28d2460290.tar.gz |
Merge "more code updates" into main
-rw-r--r-- | doc/build/unreleased/bytestring_passthrough.rst | 5 | ||||
-rw-r--r-- | mako/__init__.py | 2 | ||||
-rw-r--r-- | mako/_ast_util.py | 11 | ||||
-rw-r--r-- | mako/ast.py | 10 | ||||
-rw-r--r-- | mako/cache.py | 2 | ||||
-rwxr-xr-x | mako/cmd.py | 4 | ||||
-rw-r--r-- | mako/codegen.py | 21 | ||||
-rw-r--r-- | mako/compat.py | 39 | ||||
-rw-r--r-- | mako/exceptions.py | 2 | ||||
-rw-r--r-- | mako/ext/autohandler.py | 2 | ||||
-rw-r--r-- | mako/ext/babelplugin.py | 4 | ||||
-rw-r--r-- | mako/ext/beaker_cache.py | 2 | ||||
-rw-r--r-- | mako/ext/extract.py | 2 | ||||
-rw-r--r-- | mako/ext/linguaplugin.py | 9 | ||||
-rw-r--r-- | mako/ext/preprocessors.py | 2 | ||||
-rw-r--r-- | mako/ext/pygmentplugin.py | 2 | ||||
-rw-r--r-- | mako/ext/turbogears.py | 2 | ||||
-rw-r--r-- | mako/filters.py | 71 | ||||
-rw-r--r-- | mako/lexer.py | 27 | ||||
-rw-r--r-- | mako/lookup.py | 12 | ||||
-rw-r--r-- | mako/parsetree.py | 44 | ||||
-rw-r--r-- | mako/pygen.py | 5 | ||||
-rw-r--r-- | mako/pyparser.py | 16 | ||||
-rw-r--r-- | mako/runtime.py | 26 | ||||
-rw-r--r-- | mako/template.py | 28 | ||||
-rw-r--r-- | mako/util.py | 6 | ||||
-rw-r--r-- | test/test_template.py | 27 |
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 = { "&": "&", @@ -20,27 +23,6 @@ xml_escapes = { "'": "'", # also ' in html-only } -# XXX: " is valid in HTML and XML -# ' is not valid HTML, but is valid XML - - -def legacy_html_escape(s): - """legacy HTML escape for non-unicode mode.""" - s = s.replace("&", "&") - s = s.replace(">", ">") - s = s.replace("<", "<") - s = s.replace('"', """) - s = s.replace("'", "'") - 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 €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( ( |