summaryrefslogtreecommitdiff
path: root/mako
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2021-09-13 23:09:06 +0200
committerFederico Caselli <cfederico87@gmail.com>2021-10-23 11:11:48 +0200
commita1d70afb5974125a1a65f590418c7c371bbdb3e6 (patch)
tree0f4d4ef4170e963aa6784a222e192d16ba753e21 /mako
parent09cf4f68a7f7f63c2f249d61d7cc6600afe12c1a (diff)
downloadmako-a1d70afb5974125a1a65f590418c7c371bbdb3e6.tar.gz
- remove python 2 support - add github workflows - remove disable unicode - cleanup compat file - modernize setup - use pep517 Change-Id: Ic38dbf478046cec5d0815b468f0c235b4ea5e20c
Diffstat (limited to 'mako')
-rw-r--r--mako/__init__.py2
-rw-r--r--mako/_ast_util.py2
-rw-r--r--mako/ast.py11
-rw-r--r--mako/cache.py7
-rw-r--r--mako/codegen.py27
-rw-r--r--mako/compat.py109
-rw-r--r--mako/exceptions.py21
-rw-r--r--mako/ext/babelplugin.py2
-rw-r--r--mako/ext/extract.py14
-rw-r--r--mako/ext/linguaplugin.py23
-rw-r--r--mako/ext/pygmentplugin.py7
-rw-r--r--mako/ext/turbogears.py4
-rw-r--r--mako/filters.py33
-rw-r--r--mako/lexer.py14
-rw-r--r--mako/lookup.py4
-rw-r--r--mako/parsetree.py2
-rw-r--r--mako/pygen.py2
-rw-r--r--mako/pyparser.py51
-rw-r--r--mako/runtime.py26
-rw-r--r--mako/template.py61
-rw-r--r--mako/util.py24
21 files changed, 133 insertions, 313 deletions
diff --git a/mako/__init__.py b/mako/__init__.py
index df2ae48..d595275 100644
--- a/mako/__init__.py
+++ b/mako/__init__.py
@@ -5,4 +5,4 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-__version__ = "1.1.6"
+__version__ = "1.2.0"
diff --git a/mako/_ast_util.py b/mako/_ast_util.py
index bdcdbf6..21a60fc 100644
--- a/mako/_ast_util.py
+++ b/mako/_ast_util.py
@@ -104,7 +104,7 @@ def iter_fields(node):
pass
-class NodeVisitor(object):
+class NodeVisitor:
"""
Walks the abstract syntax tree and call visitor functions for every node
diff --git a/mako/ast.py b/mako/ast.py
index cfae280..5e52e02 100644
--- a/mako/ast.py
+++ b/mako/ast.py
@@ -9,12 +9,11 @@ code, as well as generating Python from AST nodes"""
import re
-from mako import compat
from mako import exceptions
from mako import pyparser
-class PythonCode(object):
+class PythonCode:
"""represents information about a string containing Python code"""
@@ -39,7 +38,7 @@ class PythonCode(object):
# - AST is less likely to break with version changes
# (for example, the behavior of co_names changed a little bit
# in python version 2.5)
- if isinstance(code, compat.string_types):
+ if isinstance(code, str):
expr = pyparser.parse(code.lstrip(), "exec", **exception_kwargs)
else:
expr = code
@@ -48,7 +47,7 @@ class PythonCode(object):
f.visit(expr)
-class ArgumentList(object):
+class ArgumentList:
"""parses a fragment of code as a comma-separated list of expressions"""
@@ -57,7 +56,7 @@ class ArgumentList(object):
self.args = []
self.declared_identifiers = set()
self.undeclared_identifiers = set()
- if isinstance(code, compat.string_types):
+ if isinstance(code, str):
if re.match(r"\S", code) and not re.match(r",\s*$", code):
# if theres text and no trailing comma, insure its parsed
# as a tuple by adding a trailing comma
@@ -111,7 +110,7 @@ class PythonFragment(PythonCode):
super(PythonFragment, self).__init__(code, **exception_kwargs)
-class FunctionDecl(object):
+class FunctionDecl:
"""function declaration"""
diff --git a/mako/cache.py b/mako/cache.py
index 26aa93e..c382aea 100644
--- a/mako/cache.py
+++ b/mako/cache.py
@@ -4,7 +4,6 @@
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-from mako import compat
from mako import util
_cache_plugins = util.PluginLoader("mako.cache")
@@ -13,7 +12,7 @@ register_plugin = _cache_plugins.register
register_plugin("beaker", "mako.ext.beaker_cache", "BeakerCacheImpl")
-class Cache(object):
+class Cache:
"""Represents a data content cache made available to the module
space of a specific :class:`.Template` object.
@@ -66,7 +65,7 @@ class Cache(object):
def __init__(self, template, *args):
# check for a stale template calling the
# constructor
- if isinstance(template, compat.string_types) and args:
+ if isinstance(template, str) and args:
return
self.template = template
self.id = template.module.__name__
@@ -181,7 +180,7 @@ class Cache(object):
return tmpl_kw
-class CacheImpl(object):
+class CacheImpl:
"""Provide a cache implementation for use by :class:`.Cache`."""
diff --git a/mako/codegen.py b/mako/codegen.py
index a9ae55b..415d274 100644
--- a/mako/codegen.py
+++ b/mako/codegen.py
@@ -39,7 +39,6 @@ def compile( # noqa
future_imports=None,
source_encoding=None,
generate_magic_comment=True,
- disable_unicode=False,
strict_undefined=False,
enable_loop=True,
reserved_names=frozenset(),
@@ -47,13 +46,6 @@ def compile( # noqa
"""Generate module source code given a parsetree node,
uri, and optional source filename"""
- # if on Py2K, push the "source_encoding" string to be
- # a bytestring itself, as we will be embedding it into
- # the generated source and we don't want to coerce the
- # result into a unicode object, in "disable_unicode" mode
- if not compat.py3k and isinstance(source_encoding, compat.text_type):
- source_encoding = source_encoding.encode(source_encoding)
-
buf = util.FastEncodingBuffer()
printer = PythonPrinter(buf)
@@ -68,7 +60,6 @@ def compile( # noqa
future_imports,
source_encoding,
generate_magic_comment,
- disable_unicode,
strict_undefined,
enable_loop,
reserved_names,
@@ -78,7 +69,7 @@ def compile( # noqa
return buf.getvalue()
-class _CompileContext(object):
+class _CompileContext:
def __init__(
self,
uri,
@@ -89,7 +80,6 @@ class _CompileContext(object):
future_imports,
source_encoding,
generate_magic_comment,
- disable_unicode,
strict_undefined,
enable_loop,
reserved_names,
@@ -102,13 +92,12 @@ class _CompileContext(object):
self.future_imports = future_imports
self.source_encoding = source_encoding
self.generate_magic_comment = generate_magic_comment
- self.disable_unicode = disable_unicode
self.strict_undefined = strict_undefined
self.enable_loop = enable_loop
self.reserved_names = reserved_names
-class _GenerateRenderMethod(object):
+class _GenerateRenderMethod:
"""A template visitor object which generates the
full module source for a template.
@@ -196,7 +185,7 @@ class _GenerateRenderMethod(object):
self.compiler.pagetag = None
- class FindTopLevel(object):
+ class FindTopLevel:
def visitInheritTag(s, node):
inherit.append(node)
@@ -392,7 +381,7 @@ class _GenerateRenderMethod(object):
identifiers = self.compiler.identifiers.branch(node)
self.in_def = True
- class NSDefVisitor(object):
+ class NSDefVisitor:
def visitDefTag(s, node):
s.visitDefOrBase(node)
@@ -794,8 +783,6 @@ class _GenerateRenderMethod(object):
def locate_encode(name):
if re.match(r"decode\..+", name):
return "filters." + name
- elif self.compiler.disable_unicode:
- return filters.NON_UNICODE_ESCAPES.get(name, name)
else:
return filters.DEFAULT_ESCAPES.get(name, name)
@@ -969,7 +956,7 @@ class _GenerateRenderMethod(object):
self.identifier_stack.append(body_identifiers)
- class DefVisitor(object):
+ class DefVisitor:
def visitDefTag(s, node):
s.visitDefOrBase(node)
@@ -1025,7 +1012,7 @@ class _GenerateRenderMethod(object):
)
-class _Identifiers(object):
+class _Identifiers:
"""tracks the status of identifier names as template code is rendered."""
@@ -1293,7 +1280,7 @@ def mangle_mako_loop(node, printer):
return text
-class LoopVariable(object):
+class LoopVariable:
"""A node visitor which looks for the name 'loop' within undeclared
identifiers."""
diff --git a/mako/compat.py b/mako/compat.py
index 06bb8d9..4baa479 100644
--- a/mako/compat.py
+++ b/mako/compat.py
@@ -5,13 +5,10 @@
# the MIT License: http://www.opensource.org/licenses/mit-license.php
import collections
+from importlib import util
import inspect
import sys
-py3k = sys.version_info >= (3, 0)
-py2k = sys.version_info < (3,)
-py27 = sys.version_info >= (2, 7)
-jython = sys.platform.startswith("java")
win32 = sys.platform.startswith("win")
pypy = hasattr(sys, "pypy_version_info")
@@ -34,7 +31,7 @@ def inspect_getargspec(func):
nargs = co.co_argcount
names = co.co_varnames
- nkwargs = co.co_kwonlyargcount if py3k else 0
+ nkwargs = co.co_kwonlyargcount
args = list(names[:nargs])
nargs += nkwargs
@@ -49,99 +46,23 @@ def inspect_getargspec(func):
return ArgSpec(args, varargs, varkw, func.__defaults__)
-if py3k:
- from io import StringIO
- import builtins as compat_builtins
- from urllib.parse import quote_plus, unquote_plus
- from html.entities import codepoint2name, name2codepoint
+def octal(lit):
+ return eval("0o" + lit)
- string_types = (str,)
- binary_type = bytes
- text_type = str
- from io import BytesIO as byte_buffer
+def load_module(module_id, path):
+ spec = util.spec_from_file_location(module_id, path)
+ module = util.module_from_spec(spec)
+ spec.loader.exec_module(module)
+ return module
- def u(s):
- return s
- def b(s):
- return s.encode("latin-1")
-
- def octal(lit):
- return eval("0o" + lit)
-
-
-else:
- import __builtin__ as compat_builtins # noqa
-
- try:
- from cStringIO import StringIO
- except:
- from StringIO import StringIO
-
- byte_buffer = StringIO
-
- from urllib import quote_plus, unquote_plus # noqa
- from htmlentitydefs import codepoint2name, name2codepoint # noqa
-
- string_types = (basestring,) # noqa
- binary_type = str
- text_type = unicode # noqa
-
- def u(s):
- return unicode(s, "utf-8") # noqa
-
- def b(s):
- return s
-
- def octal(lit):
- return eval("0" + lit)
-
-
-if py3k:
- from importlib import machinery, util
-
- if hasattr(util, 'module_from_spec'):
- # Python 3.5+
- def load_module(module_id, path):
- spec = util.spec_from_file_location(module_id, path)
- module = util.module_from_spec(spec)
- spec.loader.exec_module(module)
- return module
- else:
- def load_module(module_id, path):
- module = machinery.SourceFileLoader(module_id, path).load_module()
- del sys.modules[module_id]
- return module
-
-else:
- import imp
-
- def load_module(module_id, path):
- fp = open(path, "rb")
- try:
- module = imp.load_source(module_id, path, fp)
- del sys.modules[module_id]
- return module
- finally:
- 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 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():
diff --git a/mako/exceptions.py b/mako/exceptions.py
index ea7b20d..a5f9370 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -68,7 +68,7 @@ class TopLevelLookupException(TemplateLookupException):
pass
-class RichTraceback(object):
+class RichTraceback:
"""Pull the current exception from the ``sys`` traceback and extracts
Mako-specific template information.
@@ -106,7 +106,7 @@ class RichTraceback(object):
def _init_message(self):
"""Find a unicode representation of self.error"""
try:
- self.message = compat.text_type(self.error)
+ self.message = str(self.error)
except UnicodeError:
try:
self.message = str(self.error)
@@ -114,8 +114,8 @@ class RichTraceback(object):
# Fallback to args as neither unicode nor
# str(Exception(u'\xe6')) work in Python < 2.6
self.message = self.error.args[0]
- if not isinstance(self.message, compat.text_type):
- self.message = compat.text_type(self.message, "ascii", "replace")
+ if not isinstance(self.message, str):
+ self.message = str(self.message, "ascii", "replace")
def _get_reformatted_records(self, records):
for rec in records:
@@ -170,17 +170,6 @@ class RichTraceback(object):
)
except KeyError:
# A normal .py file (not a Template)
- if not compat.py3k:
- try:
- fp = open(filename, "rb")
- encoding = util.parse_encoding(fp)
- fp.close()
- except IOError:
- encoding = None
- if encoding:
- line = line.decode(encoding)
- else:
- line = line.decode("ascii", "replace")
new_trcback.append(
(
filename,
@@ -238,7 +227,7 @@ class RichTraceback(object):
# A normal .py file (not a Template)
fp = open(new_trcback[-1][0], "rb")
encoding = util.parse_encoding(fp)
- if compat.py3k and not encoding:
+ if not encoding:
encoding = "utf-8"
fp.seek(0)
self.source = fp.read()
diff --git a/mako/ext/babelplugin.py b/mako/ext/babelplugin.py
index 76bbc5b..d5c6b4b 100644
--- a/mako/ext/babelplugin.py
+++ b/mako/ext/babelplugin.py
@@ -15,7 +15,7 @@ class BabelMakoExtractor(MessageExtractor):
self.keywords = keywords
self.options = options
self.config = {
- "comment-tags": u" ".join(comment_tags),
+ "comment-tags": " ".join(comment_tags),
"encoding": options.get(
"input_encoding", options.get("encoding", None)
),
diff --git a/mako/ext/extract.py b/mako/ext/extract.py
index ad2348a..66e3c19 100644
--- a/mako/ext/extract.py
+++ b/mako/ext/extract.py
@@ -4,14 +4,17 @@
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
+from io import BytesIO
+from io import StringIO
import re
-from mako import compat
from mako import lexer
from mako import parsetree
-class MessageExtractor(object):
+class MessageExtractor:
+ use_bytes = True
+
def process_file(self, fileobj):
template_node = lexer.Lexer(
fileobj.read(), input_encoding=self.config["encoding"]
@@ -90,7 +93,7 @@ class MessageExtractor(object):
comment[1] for comment in translator_comments
]
- if isinstance(code, compat.text_type):
+ if isinstance(code, str) and self.use_bytes:
code = code.encode(input_encoding, "backslashreplace")
used_translator_comments = False
@@ -99,7 +102,10 @@ class MessageExtractor(object):
# input string of the input is non-ascii)
# Also, because we added it, we have to subtract one from
# node.lineno
- code = compat.byte_buffer(compat.b("\n") + code)
+ if self.use_bytes:
+ code = BytesIO(b"\n" + code)
+ else:
+ code = StringIO("\n" + code)
for message in self.process_python(
code, node.lineno - 1, translator_strings
diff --git a/mako/ext/linguaplugin.py b/mako/ext/linguaplugin.py
index c40fa74..438258e 100644
--- a/mako/ext/linguaplugin.py
+++ b/mako/ext/linguaplugin.py
@@ -10,14 +10,13 @@ from lingua.extractors import Extractor
from lingua.extractors import get_extractor
from lingua.extractors import Message
-from mako import compat
from mako.ext.extract import MessageExtractor
class LinguaMakoExtractor(Extractor, MessageExtractor):
-
"""Mako templates"""
+ use_bytes = False
extensions = [".mako"]
default_config = {"encoding": "utf-8", "comment-tags": ""}
@@ -26,7 +25,7 @@ class LinguaMakoExtractor(Extractor, MessageExtractor):
self.filename = filename
self.python_extractor = get_extractor("x.py")
if fileobj is None:
- fileobj = open(filename, "rb")
+ fileobj = open(filename, "r")
must_close = True
else:
must_close = False
@@ -39,16 +38,16 @@ class LinguaMakoExtractor(Extractor, MessageExtractor):
def process_python(self, code, code_lineno, translator_strings):
source = code.getvalue().strip()
- if source.endswith(compat.b(":")):
+ if source.endswith(":"):
if source in (
- compat.b("try:"),
- compat.b("else:"),
- ) or source.startswith(compat.b("except")):
- source = compat.b("") # Ignore try/except and else
- elif source.startswith(compat.b("elif")):
+ "try:",
+ "else:",
+ ) or source.startswith("except"):
+ source = "" # Ignore try/except and else
+ elif source.startswith("elif"):
source = source[2:] # Replace "elif" with "if"
- source += compat.b("pass")
- code = io.BytesIO(source)
+ source += "pass"
+ code = io.StringIO(source)
for msg in self.python_extractor(
self.filename, self.options, code, code_lineno - 1
):
@@ -58,7 +57,7 @@ class LinguaMakoExtractor(Extractor, MessageExtractor):
msg.msgid,
msg.msgid_plural,
msg.flags,
- compat.u(" ").join(translator_strings + [msg.comment]),
+ " ".join(translator_strings + [msg.comment]),
msg.tcomment,
msg.location,
)
diff --git a/mako/ext/pygmentplugin.py b/mako/ext/pygmentplugin.py
index 943a67a..dcfe5c4 100644
--- a/mako/ext/pygmentplugin.py
+++ b/mako/ext/pygmentplugin.py
@@ -25,8 +25,6 @@ from pygments.token import Other
from pygments.token import String
from pygments.token import Text
-from mako import compat
-
class MakoLexer(RegexLexer):
name = "Mako"
@@ -144,10 +142,7 @@ pygments_html_formatter = HtmlFormatter(
def syntax_highlight(filename="", language=None):
mako_lexer = MakoLexer()
- if compat.py3k:
- python_lexer = Python3Lexer()
- else:
- python_lexer = PythonLexer()
+ python_lexer = Python3Lexer()
if filename.startswith("memory:") or language == "mako":
return lambda string: highlight(
string, mako_lexer, pygments_html_formatter
diff --git a/mako/ext/turbogears.py b/mako/ext/turbogears.py
index 722a6b4..e37349e 100644
--- a/mako/ext/turbogears.py
+++ b/mako/ext/turbogears.py
@@ -9,7 +9,7 @@ from mako.lookup import TemplateLookup
from mako.template import Template
-class TGPlugin(object):
+class TGPlugin:
"""TurboGears compatible Template Plugin."""
@@ -51,7 +51,7 @@ class TGPlugin(object):
def render(
self, info, format="html", fragment=False, template=None # noqa
):
- if isinstance(template, compat.string_types):
+ if isinstance(template, str):
template = self.load_template(template)
# Load extra vars func if provided
diff --git a/mako/filters.py b/mako/filters.py
index 0ae33ff..d6323b9 100644
--- a/mako/filters.py
+++ b/mako/filters.py
@@ -6,13 +6,11 @@
import codecs
+from html.entities import codepoint2name
+from html.entities import name2codepoint
import re
-
-from mako import compat
-from mako.compat import codepoint2name
-from mako.compat import name2codepoint
-from mako.compat import quote_plus
-from mako.compat import unquote_plus
+from urllib.parse import quote_plus
+from urllib.parse import unquote_plus
xml_escapes = {
"&": "&amp;",
@@ -70,15 +68,15 @@ def trim(string):
return string.strip()
-class Decode(object):
+class Decode:
def __getattr__(self, key):
def decode(x):
- if isinstance(x, compat.text_type):
+ if isinstance(x, str):
return x
- elif not isinstance(x, compat.binary_type):
+ elif not isinstance(x, bytes):
return decode(str(x))
else:
- return compat.text_type(x, encoding=key)
+ return str(x, encoding=key)
return decode
@@ -96,11 +94,11 @@ def is_ascii_str(text):
################################################################
-class XMLEntityEscaper(object):
+class XMLEntityEscaper:
def __init__(self, codepoint2name, name2codepoint):
self.codepoint2entity = dict(
[
- (c, compat.text_type("&%s;" % n))
+ (c, str("&%s;" % n))
for c, n in codepoint2name.items()
]
)
@@ -111,7 +109,7 @@ class XMLEntityEscaper(object):
Only characters corresponding to a named entity are replaced.
"""
- return compat.text_type(text).translate(self.codepoint2entity)
+ return str(text).translate(self.codepoint2entity)
def __escape(self, m):
codepoint = ord(m.group())
@@ -132,7 +130,7 @@ class XMLEntityEscaper(object):
The return value is guaranteed to be ASCII.
"""
return self.__escapable.sub(
- self.__escape, compat.text_type(text)
+ self.__escape, str(text)
).encode("ascii")
# XXX: This regexp will not match all valid XML entity names__.
@@ -190,7 +188,7 @@ def htmlentityreplace_errors(ex):
# Handle encoding errors
bad_text = ex.object[ex.start : ex.end]
text = _html_entities_escaper.escape(bad_text)
- return (compat.text_type(text), ex.end)
+ return (str(text), ex.end)
raise ex
@@ -205,15 +203,12 @@ DEFAULT_ESCAPES = {
"u": "filters.url_escape",
"trim": "filters.trim",
"entity": "filters.html_entities_escape",
- "unicode": "unicode",
+ "unicode": "str",
"decode": "decode",
"str": "str",
"n": "n",
}
-if compat.py3k:
- DEFAULT_ESCAPES.update({"unicode": "str"})
-
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 6226e26..05aa2d9 100644
--- a/mako/lexer.py
+++ b/mako/lexer.py
@@ -9,7 +9,6 @@
import codecs
import re
-from mako import compat
from mako import exceptions
from mako import parsetree
from mako.pygen import adjust_whitespace
@@ -17,12 +16,11 @@ from mako.pygen import adjust_whitespace
_regexp_cache = {}
-class Lexer(object):
+class Lexer:
def __init__(
self,
text,
filename=None,
- disable_unicode=False,
input_encoding=None,
preprocessor=None,
):
@@ -36,14 +34,8 @@ class Lexer(object):
self.tag = []
self.control_line = []
self.ternary_stack = []
- self.disable_unicode = disable_unicode
self.encoding = input_encoding
- if compat.py3k and disable_unicode:
- raise exceptions.UnsupportedError(
- "Mako for Python 3 does not " "support disabling Unicode"
- )
-
if preprocessor is None:
self.preprocessor = []
elif not hasattr(preprocessor, "__iter__"):
@@ -199,7 +191,7 @@ class Lexer(object):
or raw if decode_raw=False
"""
- if isinstance(text, compat.text_type):
+ if isinstance(text, str):
m = self._coding_re.match(text)
encoding = m and m.group(1) or known_encoding or "utf-8"
return encoding, text
@@ -241,7 +233,7 @@ class Lexer(object):
def parse(self):
self.encoding, self.text = self.decode_raw_stream(
- self.text, not self.disable_unicode, self.encoding, self.filename
+ self.text, True, self.encoding, self.filename
)
for preproc in self.preprocessor:
diff --git a/mako/lookup.py b/mako/lookup.py
index 476326d..57d0de4 100644
--- a/mako/lookup.py
+++ b/mako/lookup.py
@@ -19,7 +19,7 @@ except:
import dummy_threading as threading
-class TemplateCollection(object):
+class TemplateCollection:
"""Represent a collection of :class:`.Template` objects,
identifiable via URI.
@@ -161,7 +161,6 @@ class TemplateLookup(TemplateCollection):
collection_size=-1,
format_exceptions=False,
error_handler=None,
- disable_unicode=False,
bytestring_passthrough=False,
output_encoding=None,
encoding_errors="strict",
@@ -207,7 +206,6 @@ class TemplateLookup(TemplateCollection):
"format_exceptions": format_exceptions,
"error_handler": error_handler,
"include_error_handler": include_error_handler,
- "disable_unicode": disable_unicode,
"bytestring_passthrough": bytestring_passthrough,
"output_encoding": output_encoding,
"cache_impl": cache_impl,
diff --git a/mako/parsetree.py b/mako/parsetree.py
index 801e48a..54aaa56 100644
--- a/mako/parsetree.py
+++ b/mako/parsetree.py
@@ -15,7 +15,7 @@ from mako import filters
from mako import util
-class Node(object):
+class Node:
"""base class for a Node in the parse tree."""
diff --git a/mako/pygen.py b/mako/pygen.py
index 947721f..bae285a 100644
--- a/mako/pygen.py
+++ b/mako/pygen.py
@@ -11,7 +11,7 @@ import re
from mako import exceptions
-class PythonPrinter(object):
+class PythonPrinter:
def __init__(self, stream):
# indentation counter
self.indent = 0
diff --git a/mako/pyparser.py b/mako/pyparser.py
index b16672d..b441132 100644
--- a/mako/pyparser.py
+++ b/mako/pyparser.py
@@ -20,20 +20,12 @@ from mako import exceptions
from mako import util
from mako.compat import arg_stringname
-if compat.py3k:
- # words that cannot be assigned to (notably
- # smaller than the total keys in __builtins__)
- reserved = set(["True", "False", "None", "print"])
+# words that cannot be assigned to (notably
+# smaller than the total keys in __builtins__)
+reserved = set(["True", "False", "None", "print"])
- # the "id" attribute on a function node
- arg_id = operator.attrgetter("arg")
-else:
- # words that cannot be assigned to (notably
- # smaller than the total keys in __builtins__)
- reserved = set(["True", "False", "None"])
-
- # the "id" attribute on a function node
- arg_id = operator.attrgetter("id")
+# the "id" attribute on a function node
+arg_id = operator.attrgetter("arg")
util.restore__ast(_ast)
@@ -85,18 +77,16 @@ class FindIdentifiers(_ast_util.NodeVisitor):
self.visit(n)
self.in_assign_targets = in_a
- 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.visit(node.type)
- for statement in node.body:
- self.visit(statement)
+ 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)
def visit_Lambda(self, node, *args):
self._visit_function(node, True)
@@ -215,25 +205,18 @@ class ParseFunc(_ast_util.NodeVisitor):
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]
+ 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.kwdefaults = node.args.kw_defaults
self.listener.varargs = node.args.vararg
self.listener.kwargs = node.args.kwarg
-class ExpressionGenerator(object):
+class ExpressionGenerator:
def __init__(self, astnode):
self.generator = _ast_util.SourceGenerator(" " * 4)
self.generator.visit(astnode)
diff --git a/mako/runtime.py b/mako/runtime.py
index 465908e..bf31d28 100644
--- a/mako/runtime.py
+++ b/mako/runtime.py
@@ -7,16 +7,17 @@
"""provides runtime services for templates, including Context,
Namespace, and various helper functions."""
+import builtins
import functools
+from io import StringIO
import sys
from mako import compat
from mako import exceptions
from mako import util
-from mako.compat import compat_builtins
-class Context(object):
+class Context:
"""Provides runtime namespace, output buffer, and various
callstacks for templates.
@@ -103,7 +104,7 @@ class Context(object):
if key in self._data:
return self._data[key]
else:
- return compat_builtins.__dict__[key]
+ return builtins.__dict__[key]
def _push_writer(self):
"""push a capturing buffer onto this Context and return
@@ -135,7 +136,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, builtins.__dict__.get(key, default))
def write(self, string):
"""Write a string to this :class:`.Context` object's
@@ -216,7 +217,7 @@ class CallerStack(list):
self.nextcaller = self.pop()
-class Undefined(object):
+class Undefined:
"""Represents an undefined value in a template.
@@ -240,7 +241,7 @@ UNDEFINED = Undefined()
STOP_RENDERING = ""
-class LoopStack(object):
+class LoopStack:
"""a stack for LoopContexts that implements the context manager protocol
to automatically pop off the top of the stack on context exit
@@ -280,7 +281,7 @@ class LoopStack(object):
return iter(self._top)
-class LoopContext(object):
+class LoopContext:
"""A magic loop variable.
Automatically accessible in any ``% for`` block.
@@ -346,7 +347,7 @@ class LoopContext(object):
return values[self.index % len(values)]
-class _NSAttr(object):
+class _NSAttr:
def __init__(self, parent):
self.__parent = parent
@@ -360,7 +361,7 @@ class _NSAttr(object):
raise AttributeError(key)
-class Namespace(object):
+class Namespace:
"""Provides access to collections of rendering methods, which
can be local, from other templates, or from imported modules.
@@ -862,12 +863,11 @@ def _render(template, callable_, args, data, as_unicode=False):
output of the given template and template callable."""
if as_unicode:
- buf = util.FastEncodingBuffer(as_unicode=True)
+ buf = util.FastEncodingBuffer()
elif template.bytestring_passthrough:
- buf = compat.StringIO()
+ buf = StringIO()
else:
buf = util.FastEncodingBuffer(
- as_unicode=as_unicode,
encoding=template.output_encoding,
errors=template.encoding_errors,
)
@@ -956,7 +956,7 @@ def _render_error(template, context, error):
error_template = exceptions.html_error_template()
if context._outputting_as_unicode:
context._buffer_stack[:] = [
- util.FastEncodingBuffer(as_unicode=True)
+ util.FastEncodingBuffer()
]
else:
context._buffer_stack[:] = [
diff --git a/mako/template.py b/mako/template.py
index 5ed2320..1f11e73 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -25,7 +25,7 @@ from mako import util
from mako.lexer import Lexer
-class Template(object):
+class Template:
r"""Represents a compiled template.
@@ -55,11 +55,10 @@ class Template(object):
:param bytestring_passthrough: When ``True``, and ``output_encoding`` is
set to ``None``, and :meth:`.Template.render` is used to render,
- the `StringIO` or `cStringIO` buffer will be used instead of the
+ 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. This flag is forced
- to ``True`` if ``disable_unicode`` is also configured.
+ through to the buffer.
.. versionadded:: 0.4
Added to provide the same behavior as that of the previous series.
@@ -94,9 +93,6 @@ class Template(object):
:param default_filters: List of string filter names that will
be applied to all expressions. See :ref:`filtering_default_filters`.
- :param disable_unicode: Disables all awareness of Python Unicode
- objects. See :ref:`unicode_disabled`.
-
:param enable_loop: When ``True``, enable the ``loop`` context variable.
This can be set to ``False`` to support templates that may
be making usage of the name "``loop``". Individual templates can
@@ -255,7 +251,6 @@ class Template(object):
cache_url=None,
module_filename=None,
input_encoding=None,
- disable_unicode=False,
module_writer=None,
bytestring_passthrough=False,
default_filters=None,
@@ -294,26 +289,13 @@ class Template(object):
self.input_encoding = input_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
- self.disable_unicode = disable_unicode
- self.bytestring_passthrough = bytestring_passthrough or disable_unicode
+ self.bytestring_passthrough = bytestring_passthrough
self.enable_loop = enable_loop
self.strict_undefined = strict_undefined
self.module_writer = module_writer
- if compat.py3k and disable_unicode:
- raise exceptions.UnsupportedError(
- "Mako for Python 3 does not " "support disabling Unicode"
- )
- elif output_encoding and disable_unicode:
- raise exceptions.UnsupportedError(
- "output_encoding must be set to "
- "None when disable_unicode is used."
- )
if default_filters is None:
- if compat.py3k or self.disable_unicode:
- self.default_filters = ["str"]
- else:
- self.default_filters = ["unicode"]
+ self.default_filters = ["str"]
else:
self.default_filters = default_filters
self.buffer_filters = buffer_filters
@@ -463,7 +445,7 @@ class Template(object):
If the template specifies an output encoding, the string
will be encoded accordingly, else the output is raw (raw
- output uses `cStringIO` and can't handle multibyte
+ output uses `StringIO` and can't handle multibyte
characters). A :class:`.Context` object is created corresponding
to the given data. Arguments that are explicitly declared
by this template's internal rendering method are also
@@ -541,7 +523,6 @@ class ModuleTemplate(Template):
template_source=None,
output_encoding=None,
encoding_errors="strict",
- disable_unicode=False,
bytestring_passthrough=False,
format_exceptions=False,
error_handler=None,
@@ -559,20 +540,9 @@ class ModuleTemplate(Template):
self.input_encoding = module._source_encoding
self.output_encoding = output_encoding
self.encoding_errors = encoding_errors
- self.disable_unicode = disable_unicode
- self.bytestring_passthrough = bytestring_passthrough or disable_unicode
+ self.bytestring_passthrough = bytestring_passthrough
self.enable_loop = module._enable_loop
- if compat.py3k and disable_unicode:
- raise exceptions.UnsupportedError(
- "Mako for Python 3 does not " "support disabling Unicode"
- )
- elif output_encoding and disable_unicode:
- raise exceptions.UnsupportedError(
- "output_encoding must be set to "
- "None when disable_unicode is used."
- )
-
self.module = module
self.filename = template_filename
ModuleInfo(
@@ -622,7 +592,7 @@ class DefTemplate(Template):
return self.parent.get_def(name)
-class ModuleInfo(object):
+class ModuleInfo:
"""Stores information about a module currently loaded into
memory, provides reverse lookups of template source, module
@@ -683,7 +653,7 @@ class ModuleInfo(object):
def source(self):
if self.template_source is not None:
if self.module._source_encoding and not isinstance(
- self.template_source, compat.text_type
+ self.template_source, str
):
return self.template_source.decode(
self.module._source_encoding
@@ -702,7 +672,6 @@ def _compile(template, text, filename, generate_magic_comment):
lexer = template.lexer_cls(
text,
filename,
- disable_unicode=template.disable_unicode,
input_encoding=template.input_encoding,
preprocessor=template.preprocessor,
)
@@ -717,7 +686,6 @@ def _compile(template, text, filename, generate_magic_comment):
future_imports=template.future_imports,
source_encoding=lexer.encoding,
generate_magic_comment=generate_magic_comment,
- disable_unicode=template.disable_unicode,
strict_undefined=template.strict_undefined,
enable_loop=template.enable_loop,
reserved_names=template.reserved_names,
@@ -731,12 +699,10 @@ def _compile_text(template, text, filename):
template,
text,
filename,
- generate_magic_comment=template.disable_unicode,
+ generate_magic_comment=False,
)
cid = identifier
- if not compat.py3k and isinstance(cid, compat.text_type):
- cid = cid.encode()
module = types.ModuleType(cid)
code = compile(source, cid, "exec")
@@ -750,7 +716,7 @@ def _compile_module_file(template, text, filename, outputpath, module_writer):
template, text, filename, generate_magic_comment=True
)
- if isinstance(source, compat.text_type):
+ if isinstance(source, str):
source = source.encode(lexer.encoding or "ascii")
if module_writer:
@@ -767,10 +733,7 @@ def _compile_module_file(template, text, filename, outputpath, module_writer):
def _get_module_info_from_callable(callable_):
- if compat.py3k:
- return _get_module_info(callable_.__globals__["__name__"])
- else:
- return _get_module_info(callable_.func_globals["__name__"])
+ return _get_module_info(callable_.__globals__["__name__"])
def _get_module_info(filename):
diff --git a/mako/util.py b/mako/util.py
index 16e3c72..a34a8c1 100644
--- a/mako/util.py
+++ b/mako/util.py
@@ -3,8 +3,6 @@
#
# This module is part of Mako and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
-from __future__ import absolute_import
-
from ast import parse
import codecs
import collections
@@ -22,7 +20,7 @@ def update_wrapper(decorated, fn):
return decorated
-class PluginLoader(object):
+class PluginLoader:
def __init__(self, group):
self.group = group
self.impls = {}
@@ -76,7 +74,7 @@ def to_list(x, default=None):
return x
-class memoized_property(object):
+class memoized_property:
"""A read-only @property that is only evaluated once."""
@@ -92,7 +90,7 @@ class memoized_property(object):
return result
-class memoized_instancemethod(object):
+class memoized_instancemethod:
"""Decorate a method memoize its return value.
@@ -140,19 +138,15 @@ class SetLikeDict(dict):
return x
-class FastEncodingBuffer(object):
+class FastEncodingBuffer:
"""a very rudimentary buffer that is faster than StringIO,
- but doesn't crash on unicode data like cStringIO."""
+ and supports unicode data."""
- def __init__(self, encoding=None, errors="strict", as_unicode=False):
+ def __init__(self, encoding=None, errors="strict"):
self.data = collections.deque()
self.encoding = encoding
- if as_unicode:
- self.delim = compat.u("")
- else:
- self.delim = ""
- self.as_unicode = as_unicode
+ self.delim = ""
self.errors = errors
self.write = self.data.append
@@ -179,7 +173,7 @@ class LRUCache(dict):
is inexact.
"""
- class _Item(object):
+ class _Item:
def __init__(self, key, value):
self.key = key
self.value = value
@@ -308,7 +302,7 @@ def restore__ast(_ast):
m = compile(
"""\
def foo(): pass
-class Bar(object): pass
+class Bar: pass
if False: pass
baz = 'mako'
1 + 2 - 3 * 4 / 5