From a1d70afb5974125a1a65f590418c7c371bbdb3e6 Mon Sep 17 00:00:00 2001 From: Federico Caselli Date: Mon, 13 Sep 2021 23:09:06 +0200 Subject: Modernize code - remove python 2 support - add github workflows - remove disable unicode - cleanup compat file - modernize setup - use pep517 Change-Id: Ic38dbf478046cec5d0815b468f0c235b4ea5e20c --- .github/workflows/run-on-pr.yaml | 43 +++ .github/workflows/run-test.yaml | 51 ++++ .gitignore | 1 + .travis.yml | 10 - LICENSE | 2 +- doc/build/filtering.rst | 4 +- doc/build/unicode.rst | 90 +----- doc/build/unreleased/disable_unicode.rst | 4 + doc/build/unreleased/py2.rst | 4 + examples/bench/basic.py | 22 +- examples/wsgi/run_wsgi.py | 6 - mako/__init__.py | 2 +- mako/_ast_util.py | 2 +- mako/ast.py | 11 +- mako/cache.py | 7 +- mako/codegen.py | 27 +- mako/compat.py | 109 +------- mako/exceptions.py | 21 +- mako/ext/babelplugin.py | 2 +- mako/ext/extract.py | 14 +- mako/ext/linguaplugin.py | 23 +- mako/ext/pygmentplugin.py | 7 +- mako/ext/turbogears.py | 4 +- mako/filters.py | 33 +-- mako/lexer.py | 14 +- mako/lookup.py | 4 +- mako/parsetree.py | 2 +- mako/pygen.py | 2 +- mako/pyparser.py | 51 ++-- mako/runtime.py | 26 +- mako/template.py | 61 +--- mako/util.py | 24 +- pyproject.toml | 7 + setup.cfg | 70 +++++ setup.py | 100 +------ test/__init__.py | 33 +-- test/ext/test_babelplugin.py | 17 +- test/ext/test_linguaplugin.py | 1 + test/templates/chs_unicode.html | 11 - test/templates/read_unicode.html | 10 - test/templates/runtimeerr.html | 4 - test/templates/unicode_arguments.html | 9 - test/templates/unicode_code.html | 7 - test/templates/unicode_expr.html | 2 - test/test_ast.py | 35 +-- test/test_cache.py | 7 +- test/test_cmd.py | 2 - test/test_def.py | 11 +- test/test_exceptions.py | 178 ++++-------- test/test_filters.py | 55 +--- test/test_inheritance.py | 24 +- test/test_lexer.py | 197 ++++--------- test/test_pygen.py | 2 +- test/test_template.py | 462 ++++++++++--------------------- test/test_tgplugin.py | 3 +- test/test_util.py | 5 +- tox.ini | 3 +- 57 files changed, 611 insertions(+), 1327 deletions(-) create mode 100644 .github/workflows/run-on-pr.yaml create mode 100644 .github/workflows/run-test.yaml delete mode 100644 .travis.yml create mode 100644 doc/build/unreleased/disable_unicode.rst create mode 100644 doc/build/unreleased/py2.rst create mode 100644 pyproject.toml delete mode 100644 test/templates/chs_unicode.html delete mode 100644 test/templates/read_unicode.html delete mode 100644 test/templates/runtimeerr.html delete mode 100644 test/templates/unicode_arguments.html delete mode 100644 test/templates/unicode_code.html delete mode 100644 test/templates/unicode_expr.html diff --git a/.github/workflows/run-on-pr.yaml b/.github/workflows/run-on-pr.yaml new file mode 100644 index 0000000..e263b5b --- /dev/null +++ b/.github/workflows/run-on-pr.yaml @@ -0,0 +1,43 @@ +name: Run tests on a pr + +on: + # run on pull request to master excluding changes that are only on doc or example folders + pull_request: + branches: + - master + paths-ignore: + - "doc/**" + +jobs: + run-test: + name: ${{ matrix.python-version }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + # run this job using this matrix + matrix: + os: + - "ubuntu-latest" + python-version: + - "3.9" + + fail-fast: false + + # steps to run in each job. Some are github actions, others run shell commands + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Set up python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + architecture: ${{ matrix.architecture }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade tox setuptools + pip list + + - name: Run tests + run: tox \ No newline at end of file diff --git a/.github/workflows/run-test.yaml b/.github/workflows/run-test.yaml new file mode 100644 index 0000000..79f846d --- /dev/null +++ b/.github/workflows/run-test.yaml @@ -0,0 +1,51 @@ +name: Run tests + +on: + # run on push in master or rel_* branches excluding changes are only on doc or example folders + push: + branches: + - master + - "rel_*" + # branches used to test the workflow + - "workflow_test_*" + paths-ignore: + - "docs/**" + +jobs: + run-test: + name: ${{ matrix.python-version }}-${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + # run this job using this matrix + matrix: + os: + - "ubuntu-latest" + - "windows-latest" + - "macos-latest" + python-version: + - "3.6" + - "3.7" + - "3.8" + - "3.9" + + fail-fast: false + + # steps to run in each job. Some are github actions, others run shell commands + steps: + - name: Checkout repo + uses: actions/checkout@v2 + + - name: Set up python + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + architecture: ${{ matrix.architecture }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + pip install --upgrade tox setuptools + pip list + + - name: Run tests + run: tox diff --git a/.gitignore b/.gitignore index 1485be1..870312a 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,4 @@ /man .tox/ .cache/ +.vscode diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 83a086e..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: python -python: - - "3.8" - - "3.7" - - "3.5" - - "2.7" -install: - - pip install -U tox-travis -script: - - tox diff --git a/LICENSE b/LICENSE index 1f835e9..2342a9d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2006-2020 the Mako authors and contributors . +Copyright 2006-2021 the Mako authors and contributors . Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/doc/build/filtering.rst b/doc/build/filtering.rst index 984d21c..3d0225e 100644 --- a/doc/build/filtering.rst +++ b/doc/build/filtering.rst @@ -101,9 +101,7 @@ In addition to the ``expression_filter`` argument, the :class:`.TemplateLookup` can specify filtering for all expression tags at the programmatic level. This array-based argument, when given its default argument of ``None``, will be internally set to -``["unicode"]`` (or ``["str"]`` on Python 3), except when -``disable_unicode=True`` is set in which case it defaults to -``["str"]``: +``["unicode"]`` (or ``["str"]`` on Python 3): .. sourcecode:: python diff --git a/doc/build/unicode.rst b/doc/build/unicode.rst index 2f77f6a..c48fce8 100644 --- a/doc/build/unicode.rst +++ b/doc/build/unicode.rst @@ -62,16 +62,7 @@ the storage format for strings. The "pass through encoded data" scheme is what template languages like Cheetah and earlier versions of Myghty do by -default. Mako as of version 0.2 also supports this mode of -operation when using Python 2, using the ``disable_unicode=True`` -flag. However, when using Mako in its default mode of -unicode-aware, it requires explicitness when dealing with -non-ASCII encodings. Additionally, if you ever need to handle -unicode strings and other kinds of encoding conversions more -intelligently, the usage of raw byte-strings quickly becomes a -nightmare, since you are sending the Python interpreter -collections of bytes for which it can make no intelligent -decisions with regards to encoding. In Python 3 Mako only allows +default. In Python 3 Mako only allows usage of native, unicode strings. In normal Mako operation, all parsed template constructs and @@ -255,82 +246,5 @@ which cannot handle encoding of non-ASCII ``unicode`` objects buffering. Otherwise, a custom Mako class called ``FastEncodingBuffer`` is used, which essentially is a super dumbed-down version of ``StringIO`` that gathers all strings into -a list and uses ``u''.join(elements)`` to produce the final output +a list and uses ``''.join(elements)`` to produce the final output -- it's markedly faster than ``StringIO``. - -.. _unicode_disabled: - -Saying to Heck with It: Disabling the Usage of Unicode Entirely -=============================================================== - -Some segments of Mako's userbase choose to make no usage of -Unicode whatsoever, and instead would prefer the "pass through" -approach; all string expressions in their templates return -encoded byte-strings, and they would like these strings to pass -right through. The only advantage to this approach is that -templates need not use ``u""`` for literal strings; there's an -arguable speed improvement as well since raw byte-strings -generally perform slightly faster than unicode objects in -Python. For these users, assuming they're sticking with Python -2, they can hit the ``disable_unicode=True`` flag as so: - -.. sourcecode:: python - - # -*- coding:utf-8 -*- - from mako.template import Template - - t = Template("drôle de petite voix m’a réveillé.", disable_unicode=True, input_encoding='utf-8') - print(t.code) - -The ``disable_unicode`` mode is strictly a Python 2 thing. It is -not supported at all in Python 3. - -The generated module source code will contain elements like -these: - -.. sourcecode:: python - - # -*- coding:utf-8 -*- - # ...more generated code ... - - def render_body(context,**pageargs): - context.caller_stack.push_frame() - try: - __M_locals = dict(pageargs=pageargs) - # SOURCE LINE 1 - context.write('dr\xc3\xb4le de petite voix m\xe2\x80\x99a r\xc3\xa9veill\xc3\xa9.') - return '' - finally: - context.caller_stack.pop_frame() - -Where above that the string literal used within :meth:`.Context.write` -is a regular byte-string. - -When ``disable_unicode=True`` is turned on, the ``default_filters`` -argument which normally defaults to ``["unicode"]`` now defaults -to ``["str"]`` instead. Setting ``default_filters`` to the empty list -``[]`` can remove the overhead of the ``str`` call. Also, in this -mode you **cannot** safely call :meth:`~.Template.render_unicode` -- you'll get -unicode/decode errors. - -The ``h`` filter (HTML escape) uses a less performant pure Python -escape function in non-unicode mode. This because -MarkupSafe only supports Python unicode objects for non-ASCII -strings. - -.. versionchanged:: 0.3.4 - In prior versions, it used ``cgi.escape()``, which has been replaced - with a function that also escapes single quotes. - -Rules for using ``disable_unicode=True`` ----------------------------------------- - -* Don't use this mode unless you really, really want to and you - absolutely understand what you're doing. -* Don't use this option just because you don't want to learn to - use Unicode properly; we aren't supporting user issues in this - mode of operation. We will however offer generous help for the - vast majority of users who stick to the Unicode program. -* Python 3 is unicode by default, and the flag is not available - when running on Python 3. - diff --git a/doc/build/unreleased/disable_unicode.rst b/doc/build/unreleased/disable_unicode.rst new file mode 100644 index 0000000..e15ca79 --- /dev/null +++ b/doc/build/unreleased/disable_unicode.rst @@ -0,0 +1,4 @@ +.. change:: + :tags: py3k + + Removed ``disable_unicode`` flag, that's no longer used in Python 3. diff --git a/doc/build/unreleased/py2.rst b/doc/build/unreleased/py2.rst new file mode 100644 index 0000000..c3e7f8d --- /dev/null +++ b/doc/build/unreleased/py2.rst @@ -0,0 +1,4 @@ +.. change:: + :tags: py3k + + Remove support for Python 2. Mako now requires Python >= 3.6 diff --git a/examples/bench/basic.py b/examples/bench/basic.py index 6835065..15482f6 100644 --- a/examples/bench/basic.py +++ b/examples/bench/basic.py @@ -28,20 +28,10 @@ # OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN # IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -from cgi import escape -import os -try: - from StringIO import StringIO -except ImportError: - from io import StringIO +from io import StringIO import sys import timeit -def u(stringlit): - if sys.version_info >= (3,): - return stringlit - else: - return stringlit.decode('latin1') __all__ = ['mako', 'mako_inheritance', 'jinja2', 'jinja2_inheritance', 'cheetah', 'django', 'myghty', 'genshi', 'kid'] @@ -50,7 +40,6 @@ __all__ = ['mako', 'mako_inheritance', 'jinja2', 'jinja2_inheritance', TITLE = 'Just a test' USER = 'joe' ITEMS = ['Number %d' % num for num in range(1, 15)] -U_ITEMS = [u(item) for item in ITEMS] def genshi(dirname, verbose=False): from genshi.template import TemplateLoader @@ -79,11 +68,10 @@ def myghty(dirname, verbose=False): def mako(dirname, verbose=False): from mako.template import Template from mako.lookup import TemplateLookup - disable_unicode = (sys.version_info < (3,)) - lookup = TemplateLookup(directories=[dirname], filesystem_checks=False, disable_unicode=disable_unicode) + lookup = TemplateLookup(directories=[dirname], filesystem_checks=False) template = lookup.get_template('template.html') def render(): - return template.render(title=TITLE, user=USER, list_items=U_ITEMS) + return template.render(title=TITLE, user=USER, list_items=ITEMS) if verbose: print(template.code + " " + render()) return render @@ -94,7 +82,7 @@ def jinja2(dirname, verbose=False): env = Environment(loader=FileSystemLoader(dirname)) template = env.get_template('template.html') def render(): - return template.render(title=TITLE, user=USER, list_items=U_ITEMS) + return template.render(title=TITLE, user=USER, list_items=ITEMS) if verbose: print(render()) return render @@ -106,7 +94,7 @@ def cheetah(dirname, verbose=False): template = Template(file=filename) def render(): template.__dict__.update({'title': TITLE, 'user': USER, - 'list_items': U_ITEMS}) + 'list_items': ITEMS}) return template.respond() if verbose: diff --git a/examples/wsgi/run_wsgi.py b/examples/wsgi/run_wsgi.py index 270022d..d013074 100644 --- a/examples/wsgi/run_wsgi.py +++ b/examples/wsgi/run_wsgi.py @@ -1,10 +1,4 @@ #!/usr/bin/python - -from __future__ import absolute_import -from __future__ import division -from __future__ import print_function -from __future__ import unicode_literals - import cgi, re, os, posixpath, mimetypes from mako.lookup import TemplateLookup from mako import exceptions 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 = { "&": "&", @@ -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 diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..b3193b9 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,7 @@ +[build-system] +build-backend = 'setuptools.build_meta' +requires = ['setuptools >= 47', 'wheel'] + +[tool.black] +line-length = 79 +target-version = ['py37'] diff --git a/setup.cfg b/setup.cfg index 88fe23f..63d50ba 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,3 +1,73 @@ +[metadata] +name = Mako +version = attr: mako.__version__ +description = A super-fast templating language that borrows the \ + best ideas from the existing templating languages. +long_description = file: README.rst +long_description_content_type = text/x-rst +url = https://www.makotemplates.org/ +author = Mike Bayer +author_email = mike@zzzcomputing.com +license = MIT +license_file = LICENSE +classifiers = + Development Status :: 5 - Production/Stable + License :: OSI Approved :: MIT License + Environment :: Web Environment + Intended Audience :: Developers + Programming Language :: Python + Programming Language :: Python :: 3 + Programming Language :: Python :: 3.6 + Programming Language :: Python :: 3.7 + Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 + Programming Language :: Python :: Implementation :: CPython + Programming Language :: Python :: Implementation :: PyPy + Topic :: Internet :: WWW/HTTP :: Dynamic Content +project_urls = + Documentation=https://docs.makotemplates.org + Issue Tracker=https://github.com/sqlalchemy/mako + +[options] +packages = find: +python_requires = >=3.6 +zip_safe = false + +install_requires = + MarkupSafe >= 0.9.2 + +[options.packages.find] +exclude = + test* + examples* + +[options.extras_require] +babel = + Babel +lingua = + lingua + +[options.entry_points] +python.templating.engines = + mako = mako.ext.turbogears:TGPlugin + +pygments.lexers = + mako = mako.ext.pygmentplugin:MakoLexer + html+mako = mako.ext.pygmentplugin:MakoHtmlLexer + xml+mako = mako.ext.pygmentplugin:MakoXmlLexer + js+mako = mako.ext.pygmentplugin:MakoJavascriptLexer + css+mako = mako.ext.pygmentplugin:MakoCssLexer + +babel.extractors = + mako = mako.ext.babelplugin:extract [babel] + +lingua.extractors= + mako = mako.ext.linguaplugin:LinguaMakoExtractor [lingua] + +console_scripts= + mako-render = mako.cmd:cmdline + [egg_info] tag_build = dev diff --git a/setup.py b/setup.py index 0be5a37..6068493 100644 --- a/setup.py +++ b/setup.py @@ -1,101 +1,3 @@ -import os -import re -import sys - -from setuptools import find_packages from setuptools import setup -from setuptools.command.test import test as TestCommand - -v = open(os.path.join(os.path.dirname(__file__), "mako", "__init__.py")) -VERSION = ( - re.compile(r".*__version__ = [\"'](.*?)[\"']", re.S) - .match(v.read()) - .group(1) -) -v.close() - -readme = os.path.join(os.path.dirname(__file__), "README.rst") - -install_requires = ["MarkupSafe>=0.9.2"] - - -class UseTox(TestCommand): - RED = 31 - RESET_SEQ = "\033[0m" - BOLD_SEQ = "\033[1m" - COLOR_SEQ = "\033[1;%dm" - - def run_tests(self): - sys.stderr.write( - "%s%spython setup.py test is deprecated by PyPA. Please invoke " - "'tox' with no arguments for a basic test run.\n%s" - % (self.COLOR_SEQ % self.RED, self.BOLD_SEQ, self.RESET_SEQ) - ) - sys.exit(1) - - -setup( - name="Mako", - version=VERSION, - description="A super-fast templating language that borrows the \ - best ideas from the existing templating languages.", - long_description=open(readme).read(), - python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: MIT License", - "Environment :: Web Environment", - "Intended Audience :: Developers", - "Programming Language :: Python", - "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: Implementation :: CPython", - "Programming Language :: Python :: Implementation :: PyPy", - "Topic :: Internet :: WWW/HTTP :: Dynamic Content", - ], - keywords="templates", - author="Mike Bayer", - author_email="mike@zzzcomputing.com", - url="https://www.makotemplates.org/", - project_urls={ - "Documentation": "https://docs.makotemplates.org", - "Issue Tracker": "https://github.com/sqlalchemy/mako", - }, - license="MIT", - packages=find_packages(".", exclude=["examples*", "test*"]), - cmdclass={"test": UseTox}, - zip_safe=False, - install_requires=install_requires, - entry_points=""" - [python.templating.engines] - mako = mako.ext.turbogears:TGPlugin - - [pygments.lexers] - mako = mako.ext.pygmentplugin:MakoLexer - html+mako = mako.ext.pygmentplugin:MakoHtmlLexer - xml+mako = mako.ext.pygmentplugin:MakoXmlLexer - js+mako = mako.ext.pygmentplugin:MakoJavascriptLexer - css+mako = mako.ext.pygmentplugin:MakoCssLexer - - [babel.extractors] - mako = mako.ext.babelplugin:extract [babel] - - [lingua.extractors] - mako = mako.ext.linguaplugin:LinguaMakoExtractor [lingua] - [console_scripts] - mako-render = mako.cmd:cmdline - """, - extras_require={ - 'babel': [ - 'Babel', - ], - 'lingua': [ - 'lingua', - ], - }, -) +setup() diff --git a/test/__init__.py b/test/__init__.py index 1770962..6c5047a 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -2,11 +2,10 @@ import contextlib import os import re import unittest +from unittest import mock # noqa -from mako import compat from mako.cache import CacheImpl from mako.cache import register_plugin -from mako.compat import py3k from mako.template import Template from mako.util import update_wrapper @@ -23,11 +22,9 @@ class TemplateTest(unittest.TestCase): def _file_path(self, filename): name, ext = os.path.splitext(filename) - - if py3k: - py3k_path = os.path.join(template_base, name + "_py3k" + ext) - if os.path.exists(py3k_path): - return py3k_path + py3k_path = os.path.join(template_base, name + "_py3k" + ext) + if os.path.exists(py3k_path): + return py3k_path return os.path.join(template_base, filename) @@ -38,7 +35,7 @@ class TemplateTest(unittest.TestCase): filters=None, unicode_=True, template_args=None, - **kw + **kw, ): t1 = self._file_template(filename, **kw) self._do_test( @@ -56,7 +53,7 @@ class TemplateTest(unittest.TestCase): filters=None, unicode_=True, template_args=None, - **kw + **kw, ): t1 = Template(text=source, **kw) self._do_test( @@ -98,12 +95,6 @@ def teardown(): shutil.rmtree(module_base, True) -if py3k: - from unittest import mock # noqa -else: - import mock # noqa - - @contextlib.contextmanager def raises(except_cls, message=None): try: @@ -112,9 +103,9 @@ def raises(except_cls, message=None): except except_cls as e: if message: assert re.search( - message, compat.text_type(e), re.UNICODE + message, str(e), re.UNICODE ), "%r !~ %s" % (message, e) - print(compat.text_type(e).encode("utf-8")) + print(str(e).encode("utf-8")) success = True # assert outside the block so it works for AssertionError too ! @@ -150,14 +141,6 @@ def skip_if(predicate, reason=None): return decorate -def requires_python_3(fn): - return skip_if(lambda: not py3k, "Requires Python 3.xx")(fn) - - -def requires_python_2(fn): - return skip_if(lambda: py3k, "Requires Python 2.xx")(fn) - - def requires_pygments_14(fn): try: import pygments diff --git a/test/ext/test_babelplugin.py b/test/ext/test_babelplugin.py index ca12444..bf21aa2 100644 --- a/test/ext/test_babelplugin.py +++ b/test/ext/test_babelplugin.py @@ -2,7 +2,6 @@ import io import os import unittest -from mako import compat from .. import skip_if from .. import template_base from .. import TemplateTest @@ -24,26 +23,24 @@ def skip(): class Test_extract(unittest.TestCase): @skip() def test_parse_python_expression(self): - input_ = io.BytesIO(compat.b('

${_("Message")}

')) + input_ = io.BytesIO(b'

${_("Message")}

') messages = list(extract(input_, ["_"], [], {})) - self.assertEqual(messages, [(1, "_", compat.u("Message"), [])]) + self.assertEqual(messages, [(1, "_", ("Message"), [])]) @skip() def test_python_gettext_call(self): - input_ = io.BytesIO(compat.b('

${_("Message")}

')) + input_ = io.BytesIO(b'

${_("Message")}

') messages = list(extract(input_, ["_"], [], {})) - self.assertEqual(messages, [(1, "_", compat.u("Message"), [])]) + self.assertEqual(messages, [(1, "_", ("Message"), [])]) @skip() def test_translator_comment(self): input_ = io.BytesIO( - compat.b( - """ + b"""

## TRANSLATORS: This is a comment. ${_("Message")}

""" - ) ) messages = list(extract(input_, ["_"], ["TRANSLATORS:"], {})) self.assertEqual( @@ -52,8 +49,8 @@ class Test_extract(unittest.TestCase): ( 4, "_", - compat.u("Message"), - [compat.u("TRANSLATORS: This is a comment.")], + ("Message"), + [("TRANSLATORS: This is a comment.")], ) ], ) diff --git a/test/ext/test_linguaplugin.py b/test/ext/test_linguaplugin.py index a563969..f505759 100644 --- a/test/ext/test_linguaplugin.py +++ b/test/ext/test_linguaplugin.py @@ -17,6 +17,7 @@ if lingua is not None: class MockOptions: keywords = [] domain = None + comment_tag = True def skip(): diff --git a/test/templates/chs_unicode.html b/test/templates/chs_unicode.html deleted file mode 100644 index 7b897e9..0000000 --- a/test/templates/chs_unicode.html +++ /dev/null @@ -1,11 +0,0 @@ -## -*- coding:utf-8 -*- -<% - msg = u'新中国的主席' -%> - -<%def name="welcome(who, place=u'北京')"> -Welcome ${who} to ${place}. - - -${name} 是 ${msg}
-${welcome(u'你')} diff --git a/test/templates/read_unicode.html b/test/templates/read_unicode.html deleted file mode 100644 index 50f00c3..0000000 --- a/test/templates/read_unicode.html +++ /dev/null @@ -1,10 +0,0 @@ -<% -try: - file_content = open(path) -except: - raise "Should never execute here" -doc_content = ''.join(file_content.readlines()) -file_content.close() -%> - -${unicode(doc_content, encoding='utf-8')} diff --git a/test/templates/runtimeerr.html b/test/templates/runtimeerr.html deleted file mode 100644 index 6b36b95..0000000 --- a/test/templates/runtimeerr.html +++ /dev/null @@ -1,4 +0,0 @@ -<% - print y - y = 10 -%> \ No newline at end of file diff --git a/test/templates/unicode_arguments.html b/test/templates/unicode_arguments.html deleted file mode 100644 index e6d7c2c..0000000 --- a/test/templates/unicode_arguments.html +++ /dev/null @@ -1,9 +0,0 @@ - -<%def name="my_def(x)"> - x is: ${x} - - -${my_def(u'drôle de petite voix m’a réveillé')} -<%self:my_def x='drôle de petite voix m’a réveillé'/> -<%self:my_def x="${u'drôle de petite voix m’a réveillé'}"/> -<%call expr="my_def(u'drôle de petite voix m’a réveillé')"/> diff --git a/test/templates/unicode_code.html b/test/templates/unicode_code.html deleted file mode 100644 index 700c043..0000000 --- a/test/templates/unicode_code.html +++ /dev/null @@ -1,7 +0,0 @@ -## -*- coding: utf-8 -*- -<% - x = u"drôle de petite voix m’a réveillé." -%> -% if x==u"drôle de petite voix m’a réveillé.": - hi, ${x} -% endif diff --git a/test/templates/unicode_expr.html b/test/templates/unicode_expr.html deleted file mode 100644 index cad7522..0000000 --- a/test/templates/unicode_expr.html +++ /dev/null @@ -1,2 +0,0 @@ -## -*- coding: utf-8 -*- -${u"Alors vous imaginez ma surprise, au lever du jour, quand une drôle de petite voix m’a réveillé. Elle disait: « S’il vous plaît… dessine-moi un mouton! »"} diff --git a/test/test_ast.py b/test/test_ast.py index ce6c082..daa7c6e 100644 --- a/test/test_ast.py +++ b/test/test_ast.py @@ -1,12 +1,9 @@ import unittest from mako import ast -from mako import compat from mako import exceptions from mako import pyparser from test import eq_ -from test import requires_python_2 -from test import requires_python_3 exception_kwargs = {"source": "", "lineno": 0, "pos": 0, "filename": ""} @@ -132,7 +129,7 @@ import foo.bar def test_locate_identifiers_8(self): code = """ -class Hi(object): +class Hi: foo = 7 def hoho(self): x = 5 @@ -187,7 +184,7 @@ def foo(): def test_locate_identifiers_13(self): code = """ def foo(): - class Bat(object): + class Bat: pass Bat """ @@ -198,7 +195,7 @@ def foo(): def test_locate_identifiers_14(self): code = """ def foo(): - class Bat(object): + class Bat: pass Bat @@ -208,18 +205,6 @@ print(Bat) eq_(parsed.declared_identifiers, set(["foo"])) eq_(parsed.undeclared_identifiers, set(["Bat"])) - @requires_python_2 - def test_locate_identifiers_15(self): - code = """ -def t1((x,y)): - return x+5, y+4 - -t2 = lambda (x,y):(x+5, y+4) -""" - parsed = ast.PythonCode(code, **exception_kwargs) - eq_(parsed.declared_identifiers, set(["t1", "t2"])) - eq_(parsed.undeclared_identifiers, set()) - def test_locate_identifiers_16(self): code = """ try: @@ -259,14 +244,9 @@ import x as bar parsed = ast.PythonFragment("try:", **exception_kwargs) - if compat.py3k: - parsed = ast.PythonFragment( - "except MyException as e:", **exception_kwargs - ) - else: - parsed = ast.PythonFragment( - "except MyException, e:", **exception_kwargs - ) + parsed = ast.PythonFragment( + "except MyException as e:", **exception_kwargs + ) eq_(parsed.declared_identifiers, set(["e"])) eq_(parsed.undeclared_identifiers, set(["MyException"])) @@ -299,7 +279,6 @@ import x as bar eq_(parsed.argnames, ["a", "b", "c", "args"]) eq_(parsed.kwargnames, ["kwargs"]) - @requires_python_3 def test_function_decl_3(self): """test getting the arguments from a fancy py3k function""" code = "def foo(a, b, *c, d, e, **f):pass" @@ -313,7 +292,7 @@ import x as bar x = 1 y = 2 - class F(object): + class F: def bar(self, a, b): return a + b diff --git a/test/test_cache.py b/test/test_cache.py index d662872..7c6e3a5 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -4,7 +4,6 @@ import unittest from mako import lookup from mako.cache import CacheImpl from mako.cache import register_plugin -from mako.compat import py27 from mako.ext import beaker_cache from mako.lookup import TemplateLookup from mako.template import Template @@ -17,7 +16,7 @@ if beaker_cache.has_beaker: import beaker -class SimpleBackend(object): +class SimpleBackend: def __init__(self): self.cache = {} @@ -601,7 +600,7 @@ class CacheTest(TemplateTest): assert m.kwargs["context"].get("x") == "bar" -class RealBackendTest(object): +class RealBackendTest: def test_cache_uses_current_context(self): t = Template( """ @@ -650,8 +649,6 @@ class BeakerCacheTest(RealBackendTest, CacheTest): def setUp(self): if not beaker_cache.has_beaker: raise unittest.SkipTest("Beaker is required for these tests.") - if not py27: - raise unittest.SkipTest("newer beakers not working w/ py26") def _install_mock_cache(self, template, implname=None): template.cache_args["manager"] = self._regions() diff --git a/test/test_cmd.py b/test/test_cmd.py index ac0db25..0dfa378 100644 --- a/test/test_cmd.py +++ b/test/test_cmd.py @@ -1,5 +1,3 @@ -from __future__ import with_statement - from contextlib import contextmanager import os diff --git a/test/test_def.py b/test/test_def.py index 99b929d..6505c1f 100644 --- a/test/test_def.py +++ b/test/test_def.py @@ -1,9 +1,7 @@ -from mako import compat from mako import lookup from mako.template import Template from test import assert_raises from test import eq_ -from test import requires_python_3 from test import TemplateTest from test.util import flatten_result from test.util import result_lines @@ -49,7 +47,6 @@ class DefTest(TemplateTest): """hello mycomp hi, 5, 6""", ) - @requires_python_3 def test_def_py3k_args(self): template = Template( """ @@ -86,12 +83,8 @@ class DefTest(TemplateTest): """ ) # check that "a" is declared in "b", but not in "c" - if compat.py3k: - assert "a" not in template.module.render_c.__code__.co_varnames - assert "a" in template.module.render_b.__code__.co_varnames - else: - assert "a" not in template.module.render_c.func_code.co_varnames - assert "a" in template.module.render_b.func_code.co_varnames + assert "a" not in template.module.render_c.__code__.co_varnames + assert "a" in template.module.render_b.__code__.co_varnames # then test output eq_(flatten_result(template.render()), "im b and heres a: im a") diff --git a/test/test_exceptions.py b/test/test_exceptions.py index 2ec46cf..b0e2bb1 100644 --- a/test/test_exceptions.py +++ b/test/test_exceptions.py @@ -1,9 +1,7 @@ # -*- coding: utf-8 -*- import sys -from mako import compat from mako import exceptions -from mako.compat import u from mako.lookup import TemplateLookup from mako.template import Template from test import requires_no_pygments_exceptions @@ -68,53 +66,29 @@ class ExceptionsTest(TemplateTest): """test the html_error_template with a Template containing UTF-8 chars""" - if compat.py3k: - code = """# -*- coding: utf-8 -*- + code = """# -*- coding: utf-8 -*- % if 2 == 2: /an error ${'привет'} % endif -""" - else: - code = """# -*- coding: utf-8 -*- -% if 2 == 2: /an error -${u'привет'} -% endif """ try: template = Template(code) template.render_unicode() except exceptions.CompileException: html_error = exceptions.html_error_template().render() - if compat.py3k: - assert ( - ( - "CompileException: Fragment 'if 2 == 2: /an " - "error' is not a partial control statement " - "at line: 2 char: 1" - ).encode(sys.getdefaultencoding(), "htmlentityreplace") - in html_error - ) - else: - assert ( + assert ( + ( "CompileException: Fragment 'if 2 == 2: /an " "error' is not a partial control statement " "at line: 2 char: 1" - ) in html_error + ).encode(sys.getdefaultencoding(), "htmlentityreplace") + in html_error + ) - if compat.py3k: - assert ( - "".encode(sys.getdefaultencoding(), "htmlentityreplace") - in html_error - ) - else: - assert ( - "'" - "привет" - ''}'.encode( - sys.getdefaultencoding(), "htmlentityreplace" - ) - in html_error - ) + assert ( + "".encode(sys.getdefaultencoding(), "htmlentityreplace") + in html_error + ) else: assert False, ( "This function should trigger a CompileException, " @@ -126,53 +100,30 @@ ${u'привет'} """test the html_error_template with a Template containing UTF-8 chars""" - if compat.py3k: - code = """# -*- coding: utf-8 -*- + code = """# -*- coding: utf-8 -*- % if 2 == 2: /an error ${'привет'} % endif -""" - else: - code = """# -*- coding: utf-8 -*- -% if 2 == 2: /an error -${u'привет'} -% endif """ try: template = Template(code) template.render_unicode() except exceptions.CompileException: html_error = exceptions.html_error_template().render() - if compat.py3k: - assert ( - ( - "CompileException: Fragment 'if 2 == 2: /an " - "error' is not a partial control statement " - "at line: 2 char: 1" - ).encode(sys.getdefaultencoding(), "htmlentityreplace") - in html_error - ) - else: - assert ( + assert ( + ( "CompileException: Fragment 'if 2 == 2: /an " "error' is not a partial control statement " "at line: 2 char: 1" - ) in html_error - - if compat.py3k: - assert ( - "${'привет'}".encode( - sys.getdefaultencoding(), "htmlentityreplace" - ) - in html_error - ) - else: - assert ( - u("${u'привет'}").encode( - sys.getdefaultencoding(), "htmlentityreplace" - ) - in html_error + ).encode(sys.getdefaultencoding(), "htmlentityreplace") + in html_error + ) + assert ( + "${'привет'}".encode( + sys.getdefaultencoding(), "htmlentityreplace" ) + in html_error + ) else: assert False, ( "This function should trigger a CompileException, " @@ -189,29 +140,22 @@ ${u'привет'} def test_py_utf8_html_error_template(self): try: - foo = u("日本") # noqa + foo = "日本" # noqa raise RuntimeError("test") except: html_error = exceptions.html_error_template().render() - if compat.py3k: - assert "RuntimeError: test" in html_error.decode("utf-8") - assert "foo = u("日本")" in html_error.decode( - "utf-8" - ) or "foo = u("日本")" in html_error.decode("utf-8") - else: - assert "RuntimeError: test" in html_error - assert ( - "foo = u("日本")" in html_error - or "foo = u("日本")" in html_error - ) + assert "RuntimeError: test" in html_error.decode("utf-8") + assert "foo = "日本"" in html_error.decode( + "utf-8" + ) or "foo = "日本"" in html_error.decode("utf-8") def test_py_unicode_error_html_error_template(self): try: - raise RuntimeError(u("日本")) + raise RuntimeError("日本") except: html_error = exceptions.html_error_template().render() assert ( - u("RuntimeError: 日本").encode("ascii", "ignore") in html_error + "RuntimeError: 日本".encode("ascii", "ignore") in html_error ) @requires_pygments_14 @@ -267,25 +211,13 @@ ${foobar} exceptions reported with format_exceptions=True""" l = TemplateLookup(format_exceptions=True) - if compat.py3k: - l.put_string( - "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" - ) - else: - l.put_string( - "foo.html", - """# -*- coding: utf-8 -*-\n${u'привет' + foobar}""", - ) + l.put_string( + "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" + ) - if compat.py3k: - assert "'привет'" in l.get_template( - "foo.html" - ).render().decode("utf-8") - else: - assert ( - "'прив" - "ет'" - ) in l.get_template("foo.html").render().decode("utf-8") + assert "'привет'" in l.get_template( + "foo.html" + ).render().decode("utf-8") @requires_no_pygments_exceptions def test_utf8_format_exceptions_no_pygments(self): @@ -293,31 +225,16 @@ ${foobar} exceptions reported with format_exceptions=True""" l = TemplateLookup(format_exceptions=True) - if compat.py3k: - l.put_string( - "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" - ) - else: - l.put_string( - "foo.html", - """# -*- coding: utf-8 -*-\n${u'привет' + foobar}""", - ) + l.put_string( + "foo.html", """# -*- coding: utf-8 -*-\n${'привет' + foobar}""" + ) - if compat.py3k: - assert ( - '
${'привет' + foobar}
' - in result_lines( - l.get_template("foo.html").render().decode("utf-8") - ) - ) - else: - assert ( - "${u'приве" - "т' + foobar}" - in result_lines( - l.get_template("foo.html").render().decode("utf-8") - ) + assert ( + '
${'привет' + foobar}
' + in result_lines( + l.get_template("foo.html").render().decode("utf-8") ) + ) def test_mod_no_encoding(self): @@ -358,10 +275,6 @@ ${foobar} except: t, v, tback = sys.exc_info() - if not compat.py3k: - # blow away tracebaack info - sys.exc_clear() - # and don't even send what we have. html_error = exceptions.html_error_template().render_unicode( error=v, traceback=None @@ -457,7 +370,8 @@ def broken(): t.render() except: text_error = exceptions.text_error_template().render_unicode() - assert """ + assert ( + """ File "base.html", line 5, in render_body %> body starts here File "foo.html", line 4, in render_foo @@ -466,6 +380,8 @@ def broken(): ${broken()} File "base.html", line 4, in broken raise RuntimeError("Something went wrong.") -""" in text_error +""" + in text_error + ) else: assert False diff --git a/test/test_filters.py b/test/test_filters.py index a58a01f..4def5f8 100644 --- a/test/test_filters.py +++ b/test/test_filters.py @@ -2,11 +2,8 @@ import unittest -from mako import compat -from mako.compat import u from mako.template import Template from test import eq_ -from test import requires_python_2 from test import TemplateTest from test.util import flatten_result from test.util import result_lines @@ -88,36 +85,6 @@ class FilterTest(TemplateTest): "foo <'some bar'>", ) - @requires_python_2 - def test_quoting_non_unicode(self): - t = Template( - """ - foo ${bar | h} - """, - disable_unicode=True, - output_encoding=None, - ) - - eq_( - flatten_result(t.render(bar="<'привет'>")), - "foo <'привет'>", - ) - - @requires_python_2 - def test_url_escaping_non_unicode(self): - t = Template( - """ - http://example.com/?bar=${bar | u}&v=1 - """, - disable_unicode=True, - output_encoding=None, - ) - - eq_( - flatten_result(t.render(bar="酒吧bar")), - "http://example.com/?bar=%E9%85%92%E5%90%A7bar&v=1", - ) - def test_def(self): t = Template( """ @@ -176,8 +143,8 @@ class FilterTest(TemplateTest): default_filters=["decode.utf8"], ) eq_( - t.render_unicode(x=u("voix m’a réveillé")).strip(), - u("some stuff.... voix m’a réveillé"), + t.render_unicode(x="voix m’a réveillé").strip(), + "some stuff.... voix m’a réveillé", ) def test_encode_filter_non_str(self): @@ -187,21 +154,7 @@ class FilterTest(TemplateTest): """, default_filters=["decode.utf8"], ) - eq_(t.render_unicode(x=3).strip(), u("some stuff.... 3")) - - @requires_python_2 - def test_encode_filter_non_str_we_return_bytes(self): - class Foo(object): - def __str__(self): - return compat.b("å") - - t = Template( - """# coding: utf-8 - some stuff.... ${x} - """, - default_filters=["decode.utf8"], - ) - eq_(t.render_unicode(x=Foo()).strip(), u("some stuff.... å")) + eq_(t.render_unicode(x=3).strip(), "some stuff.... 3") def test_custom_default(self): t = Template( @@ -347,7 +300,7 @@ data = {a: ${123}, b: ${"123"}}; t = Template( """ <%! - class Foo(object): + class Foo: foo = True def __str__(self): return "this is a" diff --git a/test/test_inheritance.py b/test/test_inheritance.py index e8ed74e..7217e33 100644 --- a/test/test_inheritance.py +++ b/test/test_inheritance.py @@ -1,6 +1,5 @@ import unittest -from mako import compat from mako import lookup from test.util import result_lines @@ -257,22 +256,13 @@ ${next.body()} """, ) - if compat.py3k: - assert result_lines( - collection.get_template("index").render_unicode(x=5, y=10) - ) == [ - "this is the base.", - "pageargs: (type: ) [('x', 5), ('y', 10)]", - "print 5, 10, 7", - ] - else: - assert result_lines( - collection.get_template("index").render_unicode(x=5, y=10) - ) == [ - "this is the base.", - "pageargs: (type: ) [('x', 5), ('y', 10)]", - "print 5, 10, 7", - ] + assert result_lines( + collection.get_template("index").render_unicode(x=5, y=10) + ) == [ + "this is the base.", + "pageargs: (type: ) [('x', 5), ('y', 10)]", + "print 5, 10, 7", + ] def test_pageargs_2(self): collection = lookup.TemplateLookup() diff --git a/test/test_lexer.py b/test/test_lexer.py index 9807961..2dbd924 100644 --- a/test/test_lexer.py +++ b/test/test_lexer.py @@ -25,13 +25,12 @@ def repr_arg(x): def _as_unicode(arg): - if isinstance(arg, compat.string_types): - return compat.text_type(arg) - elif isinstance(arg, dict): - return dict((_as_unicode(k), _as_unicode(v)) for k, v in arg.items()) + if isinstance(arg, dict): + return dict((k, _as_unicode(v)) for k, v in arg.items()) else: return arg + Node = None TemplateNode = None ControlLine = None @@ -59,7 +58,7 @@ for cls in list(parsetree.__dict__.values()): exec( ( """ -class %s(object): +class %s: def __init__(self, *args): self.args = [_as_unicode(arg) for arg in args] def __repr__(self): @@ -247,7 +246,7 @@ class LexerTest(TemplateTest): " % more code\n " "<%illegal compionent>/>\n" ' <%def name="laal()">def' - '\n\n\n ', + "\n\n\n ", (6, 16), ) ], @@ -515,10 +514,8 @@ class LexerTest(TemplateTest): ), ) - if compat.py3k: - - def test_code(self): - template = """text + def test_code(self): + template = """text <% print("hi") for x in range(1,5): @@ -529,59 +526,25 @@ more text import foo %> """ - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode( - {}, - [ - Text("text\n ", (1, 1)), - Code( - '\nprint("hi")\nfor x in range(1,5):\n ' - "print(x)\n \n", - False, - (2, 5), - ), - Text("\nmore text\n ", (6, 7)), - Code("\nimport foo\n \n", True, (8, 5)), - Text("\n", (10, 7)), - ], - ), - ) - - else: - - def test_code(self): - template = """text - <% - print "hi" - for x in range(1,5): - print x - %> -more text - <%! - import foo - %> -""" - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode( - {}, - [ - Text("text\n ", (1, 1)), - Code( - '\nprint "hi"\nfor x in range(1,5):\n ' - "print x\n \n", - False, - (2, 5), - ), - Text("\nmore text\n ", (6, 7)), - Code("\nimport foo\n \n", True, (8, 5)), - Text("\n", (10, 7)), - ], - ), - ) + nodes = Lexer(template).parse() + self._compare( + nodes, + TemplateNode( + {}, + [ + Text("text\n ", (1, 1)), + Code( + '\nprint("hi")\nfor x in range(1,5):\n ' + "print(x)\n \n", + False, + (2, 5), + ), + Text("\nmore text\n ", (6, 7)), + Code("\nimport foo\n \n", True, (8, 5)), + Text("\n", (10, 7)), + ], + ), + ) def test_code_and_tags(self): template = """ @@ -741,20 +704,11 @@ more text ) def test_tricky_code(self): - if compat.py3k: - template = """<% print('hi %>') %>""" - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode({}, [Code("print('hi %>') \n", False, (1, 1))]), - ) - else: - template = """<% print 'hi %>' %>""" - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode({}, [Code("print 'hi %>' \n", False, (1, 1))]), - ) + template = """<% print('hi %>') %>""" + nodes = Lexer(template).parse() + self._compare( + nodes, TemplateNode({}, [Code("print('hi %>') \n", False, (1, 1))]) + ) def test_tricky_code_2(self): template = """<% @@ -780,77 +734,42 @@ more text ), ) - if compat.py3k: - - def test_tricky_code_3(self): - template = """<% - print('hi') - # this is a comment - # another comment - x = 7 # someone's '''comment - print(''' - there - ''') - # someone else's comment + def test_tricky_code_3(self): + template = """<% + print('hi') + # this is a comment + # another comment + x = 7 # someone's '''comment + print(''' + there + ''') + # someone else's comment %> '''and now some text '''""" - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode( - {}, - [ - Code( - """ + nodes = Lexer(template).parse() + self._compare( + nodes, + TemplateNode( + {}, + [ + Code( + """ print('hi') # this is a comment # another comment x = 7 # someone's '''comment print(''' - there - ''') + there + ''') # someone else's comment """, - False, - (1, 1), - ), - Text(" '''and now some text '''", (10, 3)), - ], - ), - ) - - else: - - def test_tricky_code_3(self): - template = """<% - print 'hi' - # this is a comment - # another comment - x = 7 # someone's '''comment - print ''' - there - ''' - # someone else's comment -%> '''and now some text '''""" - nodes = Lexer(template).parse() - self._compare( - nodes, - TemplateNode( - {}, - [ - Code( - """\nprint 'hi'\n# this is a comment\n""" - """# another comment\nx = 7 """ - """# someone's '''comment\nprint '''\n """ - """there\n '''\n# someone else's """ - """comment\n\n""", - False, - (1, 1), - ), - Text(" '''and now some text '''", (10, 3)), - ], - ), - ) + False, + (1, 1), + ), + Text(" '''and now some text '''", (10, 3)), + ], + ), + ) def test_tricky_code_4(self): template = """<% foo = "\\"\\\\" %>""" diff --git a/test/test_pygen.py b/test/test_pygen.py index daa76de..b8c11db 100644 --- a/test/test_pygen.py +++ b/test/test_pygen.py @@ -1,6 +1,6 @@ +from io import StringIO import unittest -from mako.compat import StringIO from mako.pygen import adjust_whitespace from mako.pygen import PythonPrinter from test import eq_ diff --git a/test/test_template.py b/test/test_template.py index f9727be..4b0d271 100644 --- a/test/test_template.py +++ b/test/test_template.py @@ -3,11 +3,9 @@ import os import unittest -from mako import compat from mako import exceptions from mako import runtime from mako import util -from mako.compat import u from mako.ext.preprocessors import convert_comments from mako.lookup import TemplateLookup from mako.template import ModuleInfo @@ -17,14 +15,13 @@ from test import assert_raises from test import assert_raises_message from test import eq_ from test import module_base -from test import requires_python_2 from test import template_base from test import TemplateTest from test.util import flatten_result from test.util import result_lines -class ctx(object): +class ctx: def __init__(self, a, b): pass @@ -51,34 +48,23 @@ class EncodingTest(TemplateTest): except: #

Exception: Foobar

markup = html_error_template().render(full=False, css=False) - if compat.py3k: - assert ( - 'Foobar'.encode( - "ascii" - ) - not in markup - ) - assert ( - "<span style="color:red"" - ">Foobar</span>".encode("ascii") in markup - ) - else: - assert ( - 'Foobar' not in markup - ) - assert ( - "<span style="color:red"" - ">Foobar</span>" in markup - ) + assert ( + 'Foobar'.encode("ascii") + not in markup + ) + assert ( + "<span style="color:red"" + ">Foobar</span>".encode("ascii") in markup + ) def test_unicode(self): self._do_memory_test( - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -87,12 +73,12 @@ class EncodingTest(TemplateTest): def test_encoding_doesnt_conflict(self): self._do_memory_test( - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -101,14 +87,14 @@ class EncodingTest(TemplateTest): ) def test_unicode_arg(self): - val = u( + val = ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ) self._do_memory_test( "${val}", - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -119,7 +105,7 @@ class EncodingTest(TemplateTest): def test_unicode_file(self): self._do_file_test( "unicode.html", - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -129,7 +115,7 @@ class EncodingTest(TemplateTest): def test_unicode_file_code(self): self._do_file_test( "unicode_code.html", - u("""hi, drôle de petite voix m’a réveillé."""), + ("""hi, drôle de petite voix m’a réveillé."""), filters=flatten_result, ) @@ -139,19 +125,16 @@ class EncodingTest(TemplateTest): output_encoding="utf-8", default_filters=["decode.utf8"], ) - if compat.py3k: - template = lookup.get_template("/chs_unicode_py3k.html") - else: - template = lookup.get_template("/chs_unicode.html") + template = lookup.get_template("/chs_unicode_py3k.html") eq_( flatten_result(template.render_unicode(name="毛泽东")), - u("毛泽东 是 新中国的主席
Welcome 你 to 北京."), + ("毛泽东 是 新中国的主席
Welcome 你 to 北京."), ) def test_unicode_bom(self): self._do_file_test( "bom.html", - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -160,7 +143,7 @@ class EncodingTest(TemplateTest): self._do_file_test( "bommagic.html", - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -175,14 +158,14 @@ class EncodingTest(TemplateTest): ) def test_unicode_memory(self): - val = u( + val = ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ) self._do_memory_test( ("## -*- coding: utf-8 -*-\n" + val).encode("utf-8"), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -190,14 +173,14 @@ class EncodingTest(TemplateTest): ) def test_unicode_text(self): - val = u( + val = ( "<%text>Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ) self._do_memory_test( ("## -*- coding: utf-8 -*-\n" + val).encode("utf-8"), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -205,7 +188,7 @@ class EncodingTest(TemplateTest): ) def test_unicode_text_ccall(self): - val = u( + val = ( """ <%def name="foo()"> ${capture(caller.body)} @@ -218,7 +201,7 @@ quand une drôle de petite voix m’a réveillé. Elle disait: ) self._do_memory_test( ("## -*- coding: utf-8 -*-\n" + val).encode("utf-8"), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -227,43 +210,26 @@ quand une drôle de petite voix m’a réveillé. Elle disait: ) def test_unicode_literal_in_expr(self): - if compat.py3k: - self._do_memory_test( - u( - "## -*- coding: utf-8 -*-\n" - '${"Alors vous imaginez ma surprise, au lever du jour, ' - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: " - '« S’il vous plaît… dessine-moi un mouton! »"}\n' - ).encode("utf-8"), - u( - "Alors vous imaginez ma surprise, au lever du jour, " - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" - ), - filters=lambda s: s.strip(), - ) - else: - self._do_memory_test( - u( - "## -*- coding: utf-8 -*-\n" - '${u"Alors vous imaginez ma surprise, au lever du jour, ' - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: « S’il vous plaît… dessine-moi un " - 'mouton! »"}' - ).encode("utf-8"), - u( - "Alors vous imaginez ma surprise, au lever du jour, " - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" - ), - filters=lambda s: s.strip(), - ) + self._do_memory_test( + ( + "## -*- coding: utf-8 -*-\n" + '${"Alors vous imaginez ma surprise, au lever du jour, ' + "quand une drôle de petite voix m’a réveillé. " + "Elle disait: " + '« S’il vous plaît… dessine-moi un mouton! »"}\n' + ).encode("utf-8"), + ( + "Alors vous imaginez ma surprise, au lever du jour, " + "quand une drôle de petite voix m’a réveillé. " + "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" + ), + filters=lambda s: s.strip(), + ) def test_unicode_literal_in_expr_file(self): self._do_file_test( "unicode_expr.html", - u( + ( "Alors vous imaginez ma surprise, au lever du jour, " "quand une drôle de petite voix m’a réveillé. " "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" @@ -272,85 +238,49 @@ quand une drôle de petite voix m’a réveillé. Elle disait: ) def test_unicode_literal_in_code(self): - if compat.py3k: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <% - context.write("Alors vous imaginez ma surprise, au """ - """lever du jour, quand une drôle de petite voix m’a """ - """réveillé. Elle disait: """ - """« S’il vous plaît… dessine-moi un mouton! »") - %> - """ - ).encode("utf-8"), - u( - "Alors vous imaginez ma surprise, au lever du jour, " - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" - ), - filters=lambda s: s.strip(), - ) - else: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <% - context.write(u"Alors vous imaginez ma surprise, """ - """au lever du jour, quand une drôle de petite voix """ - """m’a réveillé. Elle disait: « S’il vous plaît… """ - """dessine-moi un mouton! »") - %> - """ - ).encode("utf-8"), - u( - "Alors vous imaginez ma surprise, au lever du jour, " - "quand une drôle de petite voix m’a réveillé. " - "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" - ), - filters=lambda s: s.strip(), - ) + self._do_memory_test( + ( + """## -*- coding: utf-8 -*- + <% + context.write("Alors vous imaginez ma surprise, au """ + """lever du jour, quand une drôle de petite voix m’a """ + """réveillé. Elle disait: """ + """« S’il vous plaît… dessine-moi un mouton! »") + %> + """ + ).encode("utf-8"), + ( + "Alors vous imaginez ma surprise, au lever du jour, " + "quand une drôle de petite voix m’a réveillé. " + "Elle disait: « S’il vous plaît… dessine-moi un mouton! »" + ), + filters=lambda s: s.strip(), + ) def test_unicode_literal_in_controlline(self): - if compat.py3k: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <% - x = "drôle de petite voix m’a réveillé." - %> - % if x=="drôle de petite voix m’a réveillé.": - hi, ${x} - % endif - """ - ).encode("utf-8"), - u("""hi, drôle de petite voix m’a réveillé."""), - filters=lambda s: s.strip(), - ) - else: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <% - x = u"drôle de petite voix m’a réveillé." - %> - % if x==u"drôle de petite voix m’a réveillé.": - hi, ${x} - % endif - """ - ).encode("utf-8"), - u("""hi, drôle de petite voix m’a réveillé."""), - filters=lambda s: s.strip(), - ) + self._do_memory_test( + ( + """## -*- coding: utf-8 -*- + <% + x = "drôle de petite voix m’a réveillé." + %> + % if x=="drôle de petite voix m’a réveillé.": + hi, ${x} + % endif + """ + ).encode("utf-8"), + ("""hi, drôle de petite voix m’a réveillé."""), + filters=lambda s: s.strip(), + ) def test_unicode_literal_in_tag(self): self._do_file_test( "unicode_arguments.html", [ - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), ], filters=result_lines, ) @@ -358,116 +288,66 @@ quand une drôle de petite voix m’a réveillé. Elle disait: self._do_memory_test( util.read_file(self._file_path("unicode_arguments.html")), [ - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), - u("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), + ("x is: drôle de petite voix m’a réveillé"), ], filters=result_lines, ) def test_unicode_literal_in_def(self): - if compat.py3k: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <%def name="bello(foo, bar)"> - Foo: ${ foo } - Bar: ${ bar } - - <%call expr="bello(foo='árvíztűrő tükörfúrógép', """ - """bar='ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')"> - """ - ).encode("utf-8"), - u( - """Foo: árvíztűrő tükörfúrógép """ - """Bar: ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" - ), - filters=flatten_result, - ) - - self._do_memory_test( - u( - "## -*- coding: utf-8 -*-\n" - """<%def name="hello(foo='árvíztűrő tükörfúrógép', """ - """bar='ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')">\n""" - "Foo: ${ foo }\n" - "Bar: ${ bar }\n" - "\n" - "${ hello() }" - ).encode("utf-8"), - u( - """Foo: árvíztűrő tükörfúrógép Bar: """ - """ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" - ), - filters=flatten_result, - ) - else: - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <%def name="bello(foo, bar)"> - Foo: ${ foo } - Bar: ${ bar } - - <%call expr="bello(foo=u'árvíztűrő tükörfúrógép', """ - """bar=u'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')"> - """ - ).encode("utf-8"), - u( - """Foo: árvíztűrő tükörfúrógép Bar: """ - """ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" - ), - filters=flatten_result, - ) + self._do_memory_test( + ( + """## -*- coding: utf-8 -*- + <%def name="bello(foo, bar)"> + Foo: ${ foo } + Bar: ${ bar } + + <%call expr="bello(foo='árvíztűrő tükörfúrógép', """ + """bar='ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')"> + """ + ).encode("utf-8"), + ( + """Foo: árvíztűrő tükörfúrógép """ + """Bar: ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" + ), + filters=flatten_result, + ) - self._do_memory_test( - u( - """## -*- coding: utf-8 -*- - <%def name="hello(foo=u'árvíztűrő tükörfúrógép', """ - """bar=u'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')"> - Foo: ${ foo } - Bar: ${ bar } - - ${ hello() }""" - ).encode("utf-8"), - u( - """Foo: árvíztűrő tükörfúrógép Bar: """ - """ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" - ), - filters=flatten_result, - ) + self._do_memory_test( + ( + "## -*- coding: utf-8 -*-\n" + """<%def name="hello(foo='árvíztűrő tükörfúrógép', """ + """bar='ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP')">\n""" + "Foo: ${ foo }\n" + "Bar: ${ bar }\n" + "\n" + "${ hello() }" + ).encode("utf-8"), + ( + """Foo: árvíztűrő tükörfúrógép Bar: """ + """ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP""" + ), + filters=flatten_result, + ) def test_input_encoding(self): """test the 'input_encoding' flag on Template, and that unicode objects arent double-decoded""" - if compat.py3k: - self._do_memory_test( - u("hello ${f('śląsk')}"), - u("hello śląsk"), - input_encoding="utf-8", - template_args={"f": lambda x: x}, - ) - - self._do_memory_test( - u("## -*- coding: utf-8 -*-\nhello ${f('śląsk')}"), - u("hello śląsk"), - template_args={"f": lambda x: x}, - ) - else: - self._do_memory_test( - u("hello ${f(u'śląsk')}"), - u("hello śląsk"), - input_encoding="utf-8", - template_args={"f": lambda x: x}, - ) + self._do_memory_test( + ("hello ${f('śląsk')}"), + ("hello śląsk"), + input_encoding="utf-8", + template_args={"f": lambda x: x}, + ) - self._do_memory_test( - u("## -*- coding: utf-8 -*-\nhello ${f(u'śląsk')}"), - u("hello śląsk"), - template_args={"f": lambda x: x}, - ) + self._do_memory_test( + ("## -*- coding: utf-8 -*-\nhello ${f('śląsk')}"), + ("hello śląsk"), + template_args={"f": lambda x: x}, + ) def test_raw_strings(self): """test that raw strings go straight thru with default_filters @@ -476,7 +356,7 @@ quand une drôle de petite voix m’a réveillé. Elle disait: """ self._do_memory_test( - u("## -*- coding: utf-8 -*-\nhello ${x}"), + ("## -*- coding: utf-8 -*-\nhello ${x}"), "hello śląsk", default_filters=[], template_args={"x": "śląsk"}, @@ -487,19 +367,19 @@ quand une drôle de petite voix m’a réveillé. Elle disait: # now, the way you *should* be doing it.... self._do_memory_test( - u("## -*- coding: utf-8 -*-\nhello ${x}"), - u("hello śląsk"), - template_args={"x": u("śląsk")}, + ("## -*- coding: utf-8 -*-\nhello ${x}"), + ("hello śląsk"), + template_args={"x": ("śląsk")}, ) def test_encoding(self): self._do_memory_test( - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" ), - u( + ( "Alors vous imaginez ma surprise, au lever du jour, quand " "une drôle de petite voix m’a réveillé. Elle disait: " "« S’il vous plaît… dessine-moi un mouton! »" @@ -510,13 +390,13 @@ quand une drôle de petite voix m’a réveillé. Elle disait: def test_encoding_errors(self): self._do_memory_test( - u( + ( """KGB (transliteration of "КГБ") is the Russian-language """ """abbreviation for Committee for State Security, """ """(Russian: Комит́ет Госуд́арственной Безоп́асности """ """(help·info); Komitet Gosudarstvennoy Bezopasnosti)""" ), - u( + ( """KGB (transliteration of "КГБ") is the Russian-language """ """abbreviation for Committee for State Security, """ """(Russian: Комит́ет Госуд́арственной Безоп́асности """ @@ -533,75 +413,13 @@ quand une drôle de petite voix m’a réveillé. Elle disait: filesystem_checks=True, output_encoding="utf-8", ) - if compat.py3k: - template = lookup.get_template("/read_unicode_py3k.html") - else: - template = lookup.get_template("/read_unicode.html") + template = lookup.get_template("/read_unicode_py3k.html") # TODO: I've no idea what encoding this file is, Python 3.1.2 # won't read the file even with open(...encoding='utf-8') unless # errors is specified. or if there's some quirk in 3.1.2 # since I'm pretty sure this test worked with py3k when I wrote it. template.render(path=self._file_path("internationalization.html")) - @requires_python_2 - def test_bytestring_passthru(self): - self._do_file_test( - "chs_utf8.html", - "毛泽东 是 新中国的主席
Welcome 你 to 北京. Welcome 你 to 北京.", - default_filters=[], - disable_unicode=True, - output_encoding=None, - template_args={"name": "毛泽东"}, - filters=flatten_result, - unicode_=False, - ) - - self._do_file_test( - "chs_utf8.html", - "毛泽东 是 新中国的主席
Welcome 你 to 北京. Welcome 你 to 北京.", - disable_unicode=True, - output_encoding=None, - template_args={"name": "毛泽东"}, - filters=flatten_result, - unicode_=False, - ) - - template = self._file_template( - "chs_utf8.html", output_encoding=None, disable_unicode=True - ) - self.assertRaises( - UnicodeDecodeError, template.render_unicode, name="毛泽东" - ) - - template = Template( - "${'Alors vous imaginez ma surprise, au lever" - " du jour, quand une drôle de petite voix m’a " - "réveillé. Elle disait: « S’il vous plaît… " - "dessine-moi un mouton! »'}", - output_encoding=None, - disable_unicode=True, - input_encoding="utf-8", - ) - assert ( - template.render() == "Alors vous imaginez ma surprise, " - "au lever du jour, quand une drôle de petite " - "voix m’a réveillé. Elle disait: « S’il vous " - "plaît… dessine-moi un mouton! »" - ) - template = Template( - "${'Alors vous imaginez ma surprise, au " - "lever du jour, quand une drôle de petite " - "voix m’a réveillé. Elle disait: « S’il " - "vous plaît… dessine-moi un mouton! »'}", - input_encoding="utf8", - output_encoding="utf8", - disable_unicode=False, - default_filters=[], - ) - # raises because expression contains an encoded bytestring which cannot - # be decoded - self.assertRaises(UnicodeDecodeError, template.render) - class PageArgsTest(TemplateTest): def test_basic(self): @@ -1094,7 +912,7 @@ class ReservedNameTest(TemplateTest): exceptions.NameConflictError, r"Reserved words passed to render\(\): %s" % name, Template("x").render, - **{name: "foo"} + **{name: "foo"}, ) def test_names_in_template(self): @@ -1361,13 +1179,13 @@ class RichTracebackTest(TemplateTest): if memory: if syntax: - source = u( + source = ( '## coding: utf-8\n<% print "m’a réveillé. ' "Elle disait: « S’il vous plaît… dessine-moi " "un mouton! » %>" ) else: - source = u( + source = ( '## coding: utf-8\n<% print u"m’a réveillé. ' "Elle disait: « S’il vous plaît… dessine-moi un " 'mouton! »" + str(5/0) %>' @@ -1817,7 +1635,7 @@ class LexerTest(TemplateTest): def _fixture(self): from mako.parsetree import TemplateNode, Text - class MyLexer(object): + class MyLexer: encoding = "ascii" def __init__(self, *arg, **kw): diff --git a/test/test_tgplugin.py b/test/test_tgplugin.py index df95d00..d69ddf9 100644 --- a/test/test_tgplugin.py +++ b/test/test_tgplugin.py @@ -1,4 +1,3 @@ -from mako import compat from mako.ext.turbogears import TGPlugin from test import template_base from test import TemplateTest @@ -48,5 +47,5 @@ class TestTGPlugin(TemplateTest): "this is index" ] assert result_lines( - tl.render({}, template=compat.u("/index.html")) + tl.render({}, template=("/index.html")) ) == ["this is index"] diff --git a/test/test_util.py b/test/test_util.py index 319a8c4..78096c1 100644 --- a/test/test_util.py +++ b/test/test_util.py @@ -7,7 +7,6 @@ import unittest from mako import compat from mako import exceptions from mako import util -from mako.compat import u from test import assert_raises_message from test import eq_ from test import skip_if @@ -30,7 +29,7 @@ class UtilTest(unittest.TestCase): eq_(buf.getvalue(), "string c string d") def test_fast_buffer_encoded(self): - s = u("drôl m’a rée « S’il") + s = ("drôl m’a rée « S’il") buf = util.FastEncodingBuffer(encoding="utf-8") buf.write(s[0:10]) buf.write(s[10:]) @@ -39,7 +38,7 @@ class UtilTest(unittest.TestCase): def test_read_file(self): fn = os.path.join(os.path.dirname(__file__), "test_util.py") data = util.read_file(fn, "rb") - assert "test_util" in str(data) # str() for py3k + assert b"test_util" in data @skip_if(lambda: compat.pypy, "Pypy does this differently") def test_load_module(self): diff --git a/tox.ini b/tox.ini index d3ef981..2478967 100644 --- a/tox.ini +++ b/tox.ini @@ -5,7 +5,6 @@ envlist = py cov_args=--cov=mako --cov-report term --cov-report xml deps=pytest>=3.1.0 - mock beaker markupsafe pygments @@ -17,7 +16,7 @@ deps=pytest>=3.1.0 setenv= cov: COVERAGE={[testenv]cov_args} -commands=py.test {env:COVERAGE:} {posargs} +commands=pytest {env:COVERAGE:} {posargs} [testenv:pep8] -- cgit v1.2.1