From: David Lord Date: Tue, 28 Jan 2020 06:57:02 +0000 (-0800) Subject: remove more compat code X-Git-Tag: 3.0.0a1~2^2~5 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=60293416db69782fd048a7820667afa4ae7c423b;p=thirdparty%2Fjinja.git remove more compat code --- diff --git a/src/jinja2/asyncfilters.py b/src/jinja2/asyncfilters.py index 3d98dbcc..3caee858 100644 --- a/src/jinja2/asyncfilters.py +++ b/src/jinja2/asyncfilters.py @@ -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, diff --git a/src/jinja2/asyncsupport.py b/src/jinja2/asyncsupport.py index ae4958f6..d7d6259a 100644 --- a/src/jinja2/asyncsupport.py +++ b/src/jinja2/asyncsupport.py @@ -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 diff --git a/src/jinja2/compiler.py b/src/jinja2/compiler.py index 8965b320..8b7203bb 100644 --- a/src/jinja2/compiler.py +++ b/src/jinja2/compiler.py @@ -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: diff --git a/src/jinja2/debug.py b/src/jinja2/debug.py index 2854a9f7..a0efa29a 100644 --- a/src/jinja2/debug.py +++ b/src/jinja2/debug.py @@ -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", diff --git a/src/jinja2/environment.py b/src/jinja2/environment.py index da7a09f3..247f7bf1 100644 --- a/src/jinja2/environment.py +++ b/src/jinja2/environment.py @@ -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 """ diff --git a/src/jinja2/filters.py b/src/jinja2/filters.py index 9000083d..0675f54f 100644 --- a/src/jinja2/filters.py +++ b/src/jinja2/filters.py @@ -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 []) diff --git a/src/jinja2/lexer.py b/src/jinja2/lexer.py index 0f32335c..4988f7e3 100644 --- a/src/jinja2/lexer.py +++ b/src/jinja2/lexer.py @@ -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öö", "", "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 ) diff --git a/src/jinja2/nodes.py b/src/jinja2/nodes.py index 924b0aa0..1989fcf0 100644 --- a/src/jinja2/nodes.py +++ b/src/jinja2/nodes.py @@ -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: diff --git a/src/jinja2/sandbox.py b/src/jinja2/sandbox.py index 639fcdb5..1263c77f 100644 --- a/src/jinja2/sandbox.py +++ b/src/jinja2/sandbox.py @@ -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 diff --git a/src/jinja2/utils.py b/src/jinja2/utils.py index e80f7ebb..dfc518f2 100644 --- a/src/jinja2/utils.py +++ b/src/jinja2/utils.py @@ -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): diff --git a/tests/test_api.py b/tests/test_api.py index 0c262dc4..76e05342 100644 --- a/tests/test_api.py +++ b/tests/test_api.py @@ -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 }}') diff --git a/tests/test_ext.py b/tests/test_ext.py index b083b758..03e94e76 100644 --- a/tests/test_ext.py +++ b/tests/test_ext.py @@ -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", ":"], {}) ) == [ diff --git a/tests/test_security.py b/tests/test_security.py index 7c049fc1..43057ec6 100644 --- a/tests/test_security.py +++ b/tests/test_security.py @@ -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()