]> git.ipfire.org Git - thirdparty/jinja.git/commitdiff
remove more compat code
authorDavid Lord <davidism@gmail.com>
Tue, 28 Jan 2020 06:57:02 +0000 (22:57 -0800)
committerDavid Lord <davidism@gmail.com>
Wed, 5 Feb 2020 16:37:40 +0000 (08:37 -0800)
13 files changed:
src/jinja2/asyncfilters.py
src/jinja2/asyncsupport.py
src/jinja2/compiler.py
src/jinja2/debug.py
src/jinja2/environment.py
src/jinja2/filters.py
src/jinja2/lexer.py
src/jinja2/nodes.py
src/jinja2/sandbox.py
src/jinja2/utils.py
tests/test_api.py
tests/test_ext.py
tests/test_security.py

index 3d98dbcc00de104a584b0707df8f0d4e8bbe1376..3caee858090cbb7054d9cd5f130052ae683b9416 100644 (file)
@@ -146,8 +146,7 @@ ASYNC_FILTERS = {
     "groupby": do_groupby,
     "join": do_join,
     "list": do_list,
-    # we intentionally do not support do_last because that would be
-    # ridiculous
+    # we intentionally do not support do_last because it may not be safe in async
     "reject": do_reject,
     "rejectattr": do_rejectattr,
     "map": do_map,
index ae4958f6dae72785dbb786ac98c47a3f24c6d656..d7d6259a31c5e9e29006bfcea5e9a987f0378e59 100644 (file)
@@ -1,7 +1,5 @@
 # -*- coding: utf-8 -*-
-"""The code for async support. Importing this patches Jinja on supported
-Python versions.
-"""
+"""The code for async support. Importing this patches Jinja."""
 import asyncio
 import inspect
 from functools import update_wrapper
index 8965b320d38aff0e31614d9257e707082d36e907..8b7203bb4d02329c81c73aa13f32e8429b0f8e79 100644 (file)
@@ -681,6 +681,7 @@ class CodeGenerator(NodeVisitor):
 
         from .runtime import exported
 
+        self.writeline("from __future__ import generator_stop")  # Python < 3.7
         self.writeline("from jinja2.runtime import " + ", ".join(exported))
 
         if self.environment.is_async:
index 2854a9f7730469245bd5f6ddff4a4a4ed359964d..a0efa29ab0d1637ef740b4605567b20e48374b56 100644 (file)
@@ -23,14 +23,9 @@ def rewrite_traceback_stack(source=None):
     if isinstance(exc_value, TemplateSyntaxError) and not exc_value.translated:
         exc_value.translated = True
         exc_value.source = source
-
-        try:
-            # Remove the old traceback on Python 3, otherwise the frames
-            # from the compiler still show up.
-            exc_value.with_traceback(None)
-        except AttributeError:
-            pass
-
+        # Remove the old traceback, otherwise the frames from the
+        # compiler still show up.
+        exc_value.with_traceback(None)
         # Outside of runtime, so the frame isn't executing template
         # code, but it still needs to point at the template.
         tb = fake_traceback(
@@ -121,7 +116,7 @@ def fake_traceback(exc_value, tb, filename, lineno):
         for attr in (
             "argcount",
             "posonlyargcount",  # Python 3.8
-            "kwonlyargcount",  # Python 3
+            "kwonlyargcount",
             "nlocals",
             "stacksize",
             "flags",
index da7a09f3e9cfd11d0f7d6cc71361ea4a74431d0a..247f7bf158cb8e55f0767ce22d08228a58184351 100644 (file)
@@ -247,9 +247,8 @@ class Environment(object):
             See :ref:`bytecode-cache` for more information.
 
         `enable_async`
-            If set to true this enables async template execution which allows
-            you to take advantage of newer Python features.  This requires
-            Python 3.6 or later.
+            If set to true this enables async template execution which
+            allows using async functions and generators.
     """
 
     #: if this environment is sandboxed.  Modifying this variable won't make
@@ -470,12 +469,11 @@ class Environment(object):
     def call_filter(
         self, name, value, args=None, kwargs=None, context=None, eval_ctx=None
     ):
-        """Invokes a filter on a value the same way the compiler does it.
+        """Invokes a filter on a value the same way the compiler does.
 
-        Note that on Python 3 this might return a coroutine in case the
-        filter is running from an environment in async mode and the filter
-        supports async execution.  It's your responsibility to await this
-        if needed.
+        This might return a coroutine if the filter is running from an
+        environment in async mode and the filter supports async
+        execution. It's your responsibility to await this if needed.
 
         .. versionadded:: 2.7
         """
index 9000083dc4e9d4518077479ab8c82d6f53ce1bb5..0675f54f86ef4d91e19d61accad1bc4426e9c329 100644 (file)
@@ -564,13 +564,9 @@ def do_filesizeformat(value, binary=False):
         return "%.1f %s" % ((base * bytes / unit), prefix)
 
 
-def do_pprint(value, verbose=False):
-    """Pretty print a variable. Useful for debugging.
-
-    With Jinja 1.2 onwards you can pass it a parameter.  If this parameter
-    is truthy the output will be more verbose (this requires `pretty`)
-    """
-    return pformat(value, verbose=verbose)
+def do_pprint(value):
+    """Pretty print a variable. Useful for debugging."""
+    return pformat(value)
 
 
 @evalcontextfilter
@@ -595,8 +591,8 @@ def do_urlize(
 
        {{ mytext|urlize(40, target='_blank') }}
 
-    .. versionchanged:: 2.8+
-       The *target* parameter was added.
+    .. versionchanged:: 2.8
+       The ``target`` parameter was added.
     """
     policies = eval_ctx.environment.policies
     rel = set((rel or "").split() or [])
index 0f32335c57baf69708c053b8bcb0c36b7b9d9432..4988f7e35fb004b0df1e69fb51509f038c61f22f 100644 (file)
@@ -10,6 +10,7 @@ from collections import deque
 from operator import itemgetter
 from sys import intern
 
+from ._identifier import pattern as name_re
 from .exceptions import TemplateSyntaxError
 from .utils import LRUCache
 
@@ -38,20 +39,6 @@ float_re = re.compile(
     re.IGNORECASE | re.VERBOSE,
 )
 
-try:
-    # check if this Python supports Unicode identifiers
-    compile("föö", "<unknown>", "eval")
-except SyntaxError:
-    # Python 2, no Unicode support, use ASCII identifiers
-    name_re = re.compile(r"[a-zA-Z_][a-zA-Z0-9_]*")
-    check_ident = False
-else:
-    # Unicode support, import generated re pattern and set flag to use
-    # str.isidentifier to validate during lexing.
-    from ._identifier import pattern as name_re
-
-    check_ident = True
-
 # internal the tokens and keep references to them
 TOKEN_ADD = intern("add")
 TOKEN_ASSIGN = intern("assign")
@@ -632,7 +619,7 @@ class Lexer(object):
                 token = value
             elif token == TOKEN_NAME:
                 value = str(value)
-                if check_ident and not value.isidentifier():
+                if not value.isidentifier():
                     raise TemplateSyntaxError(
                         "Invalid character in identifier", lineno, name, filename
                     )
index 924b0aa020624ee8d325b38b7d51592ccd2a425b..1989fcf059b8399f1e0fa32e0211675ac9346428 100644 (file)
@@ -212,15 +212,13 @@ class Node(metaclass=NodeType):
         return self
 
     def __eq__(self, other):
-        return type(self) is type(other) and tuple(self.iter_fields()) == tuple(
-            other.iter_fields()
-        )
+        if type(self) is not type(other):
+            return NotImplemented
 
-    def __ne__(self, other):
-        return not self.__eq__(other)
+        return tuple(self.iter_fields()) == tuple(other.iter_fields())
 
-    # Restore Python 2 hashing behavior on Python 3
-    __hash__ = object.__hash__
+    def __hash__(self):
+        return hash(tuple(self.iter_fields()))
 
     def __repr__(self):
         return "%s(%s)" % (
@@ -649,11 +647,6 @@ class Filter(Expr):
         if eval_ctx.volatile or self.node is None:
             raise Impossible()
 
-        # we have to be careful here because we call filter_ below.
-        # if this variable would be called filter, 2to3 would wrap the
-        # call in a list because it is assuming we are talking about the
-        # builtin filter function here which no longer returns a list in
-        # python 3.  because of that, do not rename filter_ to filter!
         filter_ = self.environment.filters.get(self.name)
 
         if filter_ is None or getattr(filter_, "contextfilter", False) is True:
index 639fcdb5afc37cb7cb0ade5aafecc3bcb5350c71..1263c77fc3b94e5ed219e2dceb0560efe9e9b092 100644 (file)
@@ -4,6 +4,7 @@ Useful when the template itself comes from an untrusted source.
 """
 import operator
 import types
+from _string import formatter_field_name_split
 from collections import abc
 from collections import deque
 from string import Formatter
@@ -183,10 +184,8 @@ def is_internal_attribute(obj, attr):
 
 def modifies_known_mutable(obj, attr):
     """This function checks if an attribute on a builtin mutable object
-    (list, dict, set or deque) would modify it if called.  It also supports
-    the "user"-versions of the objects (`sets.Set`, `UserDict.*` etc.) and
-    with Python 2.6 onwards the abstract base classes `MutableSet`,
-    `MutableMapping`, and `MutableSequence`.
+    (list, dict, set or deque) or the corresponding ABCs would modify it
+    if called.
 
     >>> modifies_known_mutable({}, "clear")
     True
@@ -426,15 +425,6 @@ class ImmutableSandboxedEnvironment(SandboxedEnvironment):
         return not modifies_known_mutable(obj, attr)
 
 
-# This really is not a public API apparently.
-try:
-    from _string import formatter_field_name_split
-except ImportError:
-
-    def formatter_field_name_split(field_name):
-        return field_name._formatter_field_name_split()
-
-
 class SandboxedFormatterMixin(object):
     def __init__(self, env):
         self._env = env
index e80f7ebb44eab2670023c51a8973b17182835511..dfc518f2b128c898df07ac2e42c3ee43cf471bfd 100644 (file)
@@ -169,18 +169,12 @@ def object_type_repr(obj):
     return "%s object" % name
 
 
-def pformat(obj, verbose=False):
-    """Prettyprint an object.  Either use the `pretty` library or the
-    builtin `pprint`.
+def pformat(obj):
+    """Format an object using :func:`pprint.pformat`.
     """
-    try:
-        from pretty import pretty
-
-        return pretty(obj, verbose=verbose)
-    except ImportError:
-        from pprint import pformat
+    from pprint import pformat
 
-        return pformat(obj)
+    return pformat(obj)
 
 
 def urlize(text, trim_url_limit=None, rel=None, target=None):
index 0c262dc4b85bb6244c08370fb41465e44ff03bee..76e0534271f307b26cb4211e9fded662862a794b 100644 (file)
@@ -32,7 +32,6 @@ class TestExtendedAPI(object):
         from jinja2.sandbox import SandboxedEnvironment
 
         for env in Environment(), SandboxedEnvironment():
-            # the |list is necessary for python3
             tmpl = env.from_string("{{ foo.items()|list }}")
             assert tmpl.render(foo={"items": 42}) == "[('items', 42)]"
             tmpl = env.from_string('{{ foo|attr("items")()|list }}')
index b083b758a936728ae66942c859bbcdc6eb935d7c..03e94e7628bfe52c770345b4d2cdbb893a08a9d2 100644 (file)
@@ -340,14 +340,12 @@ class TestInternationalization(object):
         from jinja2.ext import babel_extract
 
         source = BytesIO(
+            b"""
+            {{ gettext('Hello World') }}
+            {% trans %}Hello World{% endtrans %}
+            {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
             """
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        """.encode(
-                "ascii"
-            )
-        )  # make python 3 happy
+        )
         assert list(babel_extract(source, ("gettext", "ngettext", "_"), [], {})) == [
             (2, "gettext", u"Hello World", []),
             (3, "gettext", u"Hello World", []),
@@ -358,15 +356,13 @@ class TestInternationalization(object):
         from jinja2.ext import babel_extract
 
         source = BytesIO(
+            b"""
+            {{ gettext(' Hello  \n  World') }}
+            {% trans trimmed %} Hello  \n  World{% endtrans %}
+            {% trans trimmed %}{{ users }} \n user
+            {%- pluralize %}{{ users }} \n users{% endtrans %}
             """
-        {{ gettext(' Hello  \n  World') }}
-        {% trans trimmed %} Hello  \n  World{% endtrans %}
-        {% trans trimmed %}{{ users }} \n user
-        {%- pluralize %}{{ users }} \n users{% endtrans %}
-        """.encode(
-                "ascii"
-            )
-        )  # make python 3 happy
+        )
         assert list(babel_extract(source, ("gettext", "ngettext", "_"), [], {})) == [
             (2, "gettext", u" Hello  \n  World", []),
             (4, "gettext", u"Hello World", []),
@@ -377,15 +373,13 @@ class TestInternationalization(object):
         from jinja2.ext import babel_extract
 
         source = BytesIO(
+            b"""
+            {{ gettext(' Hello  \n  World') }}
+            {% trans %} Hello  \n  World{% endtrans %}
+            {% trans %}{{ users }} \n user
+            {%- pluralize %}{{ users }} \n users{% endtrans %}
             """
-        {{ gettext(' Hello  \n  World') }}
-        {% trans %} Hello  \n  World{% endtrans %}
-        {% trans %}{{ users }} \n user
-        {%- pluralize %}{{ users }} \n users{% endtrans %}
-        """.encode(
-                "ascii"
-            )
-        )  # make python 3 happy
+        )
         opts = {"trimmed": "true"}
         assert list(babel_extract(source, ("gettext", "ngettext", "_"), [], opts)) == [
             (2, "gettext", u" Hello  \n  World", []),
@@ -397,16 +391,14 @@ class TestInternationalization(object):
         from jinja2.ext import babel_extract
 
         source = BytesIO(
+            b"""
+            {# trans first #}
+            {{ gettext('Hello World') }}
+            {% trans %}Hello World{% endtrans %}{# trans second #}
+            {#: third #}
+            {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
             """
-        {# trans first #}
-        {{ gettext('Hello World') }}
-        {% trans %}Hello World{% endtrans %}{# trans second #}
-        {#: third #}
-        {% trans %}{{ users }} user{% pluralize %}{{ users }} users{% endtrans %}
-        """.encode(
-                "utf-8"
-            )
-        )  # make python 3 happy
+        )
         assert list(
             babel_extract(source, ("gettext", "ngettext", "_"), ["trans", ":"], {})
         ) == [
index 7c049fc177d9f0670b16acbb3967269a2252c376..43057ec695e4afa02cdca117fa65255c03040a71 100644 (file)
@@ -151,9 +151,6 @@ class TestStringFormat(object):
 
 
 @pytest.mark.sandbox
-@pytest.mark.skipif(
-    not hasattr(str, "format_map"), reason="requires str.format_map method"
-)
 class TestStringFormatMap(object):
     def test_basic_format_safety(self):
         env = SandboxedEnvironment()