Hello community,

here is the log from the commit of package python-Jinja2 for openSUSE:Factory 
checked in at 2020-05-04 18:33:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Jinja2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-Jinja2.new.2738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Jinja2"

Mon May  4 18:33:18 2020 rev:40 rq:800008 version:2.11.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Jinja2/python-Jinja2.changes      
2020-04-14 16:28:48.915988662 +0200
+++ /work/SRC/openSUSE:Factory/.python-Jinja2.new.2738/python-Jinja2.changes    
2020-05-04 18:33:48.164230349 +0200
@@ -1,0 +2,31 @@
+Mon May  4 09:35:51 UTC 2020 - Johannes Grassler <[email protected]>
+
+- update to 2.11.1
+  * Fix a bug that caused callable objects with __getattr__, like
+    :class:~unittest.mock.Mock to be treated as a
+    :func:contextfunction. :issue:1145
+  * Update wordcount filter to trigger :class:Undefined methods
+    by wrapping the input in :func:soft_unicode. :pr:1160
+  * Fix a hang when displaying tracebacks on Python 32-bit.
+    :issue:1162
+  * Showing an undefined error for an object that raises
+    AttributeError on access doesn't cause a recursion error.
+    :issue:1177
+  * Revert changes to :class:~loaders.PackageLoader from 2.10 which
+    removed the dependency on setuptools and pkg_resources, and added
+    limited support for namespace packages. The changes caused issues
+    when using Pytest. Due to the difficulty in supporting Python 2 and
+    :pep:451 simultaneously, the changes are reverted until 3.0.
+    :pr:1182
+  * Fix line numbers in error messages when newlines are stripped.
+    :pr:1178
+  * The special namespace() assignment object in templates works in
+    async environments. :issue:1180
+  * Fix whitespace being removed before tags in the middle of lines when
+    lstrip_blocks is enabled. :issue:1138
+  * :class:~nativetypes.NativeEnvironment doesn't evaluate
+    intermediate strings during rendering. This prevents early
+    evaluation which could change the value of an expression.
+    :issue:1186
+  
+-------------------------------------------------------------------

Old:
----
  Jinja2-2.11.1.tar.gz

New:
----
  Jinja2-2.11.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Jinja2.spec ++++++
--- /var/tmp/diff_new_pack.6uYTDT/_old  2020-05-04 18:33:50.168234410 +0200
+++ /var/tmp/diff_new_pack.6uYTDT/_new  2020-05-04 18:33:50.172234418 +0200
@@ -24,7 +24,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define oldpython python
 Name:           python-Jinja2
-Version:        2.11.1
+Version:        2.11.2
 Release:        0
 Summary:        A template engine written in pure Python
 License:        BSD-3-Clause

++++++ Jinja2-2.11.1.tar.gz -> Jinja2-2.11.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/CHANGES.rst 
new/Jinja2-2.11.2/CHANGES.rst
--- old/Jinja2-2.11.1/CHANGES.rst       2020-01-30 19:05:13.000000000 +0100
+++ new/Jinja2-2.11.2/CHANGES.rst       2020-04-13 18:13:48.000000000 +0200
@@ -1,5 +1,38 @@
 .. currentmodule:: jinja2
 
+Version 2.11.2
+--------------
+
+Released 2020-04-13
+
+-   Fix a bug that caused callable objects with ``__getattr__``, like
+    :class:`~unittest.mock.Mock` to be treated as a
+    :func:`contextfunction`. :issue:`1145`
+-   Update ``wordcount`` filter to trigger :class:`Undefined` methods
+    by wrapping the input in :func:`soft_unicode`. :pr:`1160`
+-   Fix a hang when displaying tracebacks on Python 32-bit.
+    :issue:`1162`
+-   Showing an undefined error for an object that raises
+    ``AttributeError`` on access doesn't cause a recursion error.
+    :issue:`1177`
+-   Revert changes to :class:`~loaders.PackageLoader` from 2.10 which
+    removed the dependency on setuptools and pkg_resources, and added
+    limited support for namespace packages. The changes caused issues
+    when using Pytest. Due to the difficulty in supporting Python 2 and
+    :pep:`451` simultaneously, the changes are reverted until 3.0.
+    :pr:`1182`
+-   Fix line numbers in error messages when newlines are stripped.
+    :pr:`1178`
+-   The special ``namespace()`` assignment object in templates works in
+    async environments. :issue:`1180`
+-   Fix whitespace being removed before tags in the middle of lines when
+    ``lstrip_blocks`` is enabled. :issue:`1138`
+-   :class:`~nativetypes.NativeEnvironment` doesn't evaluate
+    intermediate strings during rendering. This prevents early
+    evaluation which could change the value of an expression.
+    :issue:`1186`
+
+
 Version 2.11.1
 --------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/PKG-INFO new/Jinja2-2.11.2/PKG-INFO
--- old/Jinja2-2.11.1/PKG-INFO  2020-01-30 19:07:56.746518400 +0100
+++ new/Jinja2-2.11.2/PKG-INFO  2020-04-13 18:14:13.635887100 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: Jinja2
-Version: 2.11.1
+Version: 2.11.2
 Summary: A very fast and expressive template engine.
 Home-page: https://palletsprojects.com/p/jinja/
 Author: Armin Ronacher
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/docs/api.rst 
new/Jinja2-2.11.2/docs/api.rst
--- old/Jinja2-2.11.1/docs/api.rst      2020-01-29 16:26:55.000000000 +0100
+++ new/Jinja2-2.11.2/docs/api.rst      2020-04-13 16:18:12.000000000 +0200
@@ -5,9 +5,10 @@
     :noindex:
     :synopsis: public Jinja API
 
-This document describes the API to Jinja and not the template language.  It
-will be most useful as reference to those implementing the template interface
-to the application and not those who are creating Jinja templates.
+This document describes the API to Jinja and not the template language
+(for that, see :doc:`/templates`). It will be most useful as reference
+to those implementing the template interface to the application and not
+those who are creating Jinja templates.
 
 Basics
 ------
@@ -529,37 +530,38 @@
 Async Support
 -------------
 
-Starting with version 2.9, Jinja also supports the Python `async` and
-`await` constructs.  As far as template designers go this feature is
-entirely opaque to them however as a developer you should be aware of how
-it's implemented as it influences what type of APIs you can safely expose
-to the template environment.
-
-First you need to be aware that by default async support is disabled as
-enabling it will generate different template code behind the scenes which
-passes everything through the asyncio event loop.  This is important to
-understand because it has some impact to what you are doing:
-
-*   template rendering will require an event loop to be set for the
-    current thread (``asyncio.get_event_loop`` needs to return one)
-*   all template generation code internally runs async generators which
-    means that you will pay a performance penalty even if the non sync
-    methods are used!
-*   The sync methods are based on async methods if the async mode is
-    enabled which means that `render` for instance will internally invoke
-    `render_async` and run it as part of the current event loop until the
-    execution finished.
+.. versionadded:: 2.9
+
+Jinja supports the Python ``async`` and ``await`` syntax. For the
+template designer, this support (when enabled) is entirely transparent,
+templates continue to look exactly the same. However, developers should
+be aware of the implementation as it affects what types of APIs you can
+use.
+
+By default, async support is disabled. Enabling it will cause the
+environment to compile different code behind the scenes in order to
+handle async and sync code in an asyncio event loop. This has the
+following implications:
+
+-   Template rendering requires an event loop to be available to the
+    current thread. :func:`asyncio.get_event_loop` must return an event
+    loop.
+-   The compiled code uses ``await`` for functions and attributes, and
+    uses ``async for`` loops. In order to support using both async and
+    sync functions in this context, a small wrapper is placed around
+    all calls and access, which add overhead compared to purely async
+    code.
+-   Sync methods and filters become wrappers around their corresponding
+    async implementations where needed. For example, ``render`` invokes
+    ``async_render``, and ``|map`` supports async iterables.
 
 Awaitable objects can be returned from functions in templates and any
-function call in a template will automatically await the result.  This
-means that you can provide a method that asynchronously loads data
-from a database if you so desire and from the template designer's point of
-view this is just another function they can call.  This means that the
-``await`` you would normally issue in Python is implied.  However this
-only applies to function calls.  If an attribute for instance would be an
-awaitable object then this would not result in the expected behavior.
+function call in a template will automatically await the result. The
+``await`` you would normally add in Python is implied. For example, you
+can provide a method that asynchronously loads data from a database, and
+from the template designer's point of view it can be called like any
+other function.
 
-Likewise iterations with a `for` loop support async iterators.
 
 .. _policies:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/Jinja2.egg-info/PKG-INFO 
new/Jinja2-2.11.2/src/Jinja2.egg-info/PKG-INFO
--- old/Jinja2-2.11.1/src/Jinja2.egg-info/PKG-INFO      2020-01-30 
19:07:56.000000000 +0100
+++ new/Jinja2-2.11.2/src/Jinja2.egg-info/PKG-INFO      2020-04-13 
18:14:13.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: Jinja2
-Version: 2.11.1
+Version: 2.11.2
 Summary: A very fast and expressive template engine.
 Home-page: https://palletsprojects.com/p/jinja/
 Author: Armin Ronacher
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/Jinja2.egg-info/SOURCES.txt 
new/Jinja2-2.11.2/src/Jinja2.egg-info/SOURCES.txt
--- old/Jinja2-2.11.1/src/Jinja2.egg-info/SOURCES.txt   2020-01-30 
19:07:56.000000000 +0100
+++ new/Jinja2-2.11.2/src/Jinja2.egg-info/SOURCES.txt   2020-04-13 
18:14:13.000000000 +0200
@@ -91,7 +91,6 @@
 tests/test_tests.py
 tests/test_utils.py
 tests/res/__init__.py
-tests/res/package.zip
 tests/res/templates/broken.html
 tests/res/templates/mojibake.txt
 tests/res/templates/syntaxerror.html
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/__init__.py 
new/Jinja2-2.11.2/src/jinja2/__init__.py
--- old/Jinja2-2.11.1/src/jinja2/__init__.py    2020-01-30 19:05:04.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/__init__.py    2020-04-13 18:12:03.000000000 
+0200
@@ -41,4 +41,4 @@
 from .utils import is_undefined
 from .utils import select_autoescape
 
-__version__ = "2.11.1"
+__version__ = "2.11.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/asyncfilters.py 
new/Jinja2-2.11.2/src/jinja2/asyncfilters.py
--- old/Jinja2-2.11.1/src/jinja2/asyncfilters.py        2020-01-29 
16:32:24.000000000 +0100
+++ new/Jinja2-2.11.2/src/jinja2/asyncfilters.py        2020-04-13 
16:18:12.000000000 +0200
@@ -26,17 +26,16 @@
 
 def dualfilter(normal_filter, async_filter):
     wrap_evalctx = False
-    if getattr(normal_filter, "environmentfilter", False):
+    if getattr(normal_filter, "environmentfilter", False) is True:
 
         def is_async(args):
             return args[0].is_async
 
         wrap_evalctx = False
     else:
-        if not getattr(normal_filter, "evalcontextfilter", False) and not 
getattr(
-            normal_filter, "contextfilter", False
-        ):
-            wrap_evalctx = True
+        has_evalctxfilter = getattr(normal_filter, "evalcontextfilter", False) 
is True
+        has_ctxfilter = getattr(normal_filter, "contextfilter", False) is True
+        wrap_evalctx = not has_evalctxfilter and not has_ctxfilter
 
         def is_async(args):
             return args[0].environment.is_async
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/compiler.py 
new/Jinja2-2.11.2/src/jinja2/compiler.py
--- old/Jinja2-2.11.1/src/jinja2/compiler.py    2020-01-30 18:55:16.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/compiler.py    2020-04-13 16:18:12.000000000 
+0200
@@ -1307,13 +1307,13 @@
             def finalize(value):
                 return default(env_finalize(value))
 
-            if getattr(env_finalize, "contextfunction", False):
+            if getattr(env_finalize, "contextfunction", False) is True:
                 src += "context, "
                 finalize = None  # noqa: F811
-            elif getattr(env_finalize, "evalcontextfunction", False):
+            elif getattr(env_finalize, "evalcontextfunction", False) is True:
                 src += "context.eval_ctx, "
                 finalize = None
-            elif getattr(env_finalize, "environmentfunction", False):
+            elif getattr(env_finalize, "environmentfunction", False) is True:
                 src += "environment, "
 
                 def finalize(value):
@@ -1689,11 +1689,11 @@
         func = self.environment.filters.get(node.name)
         if func is None:
             self.fail("no filter named %r" % node.name, node.lineno)
-        if getattr(func, "contextfilter", False):
+        if getattr(func, "contextfilter", False) is True:
             self.write("context, ")
-        elif getattr(func, "evalcontextfilter", False):
+        elif getattr(func, "evalcontextfilter", False) is True:
             self.write("context.eval_ctx, ")
-        elif getattr(func, "environmentfilter", False):
+        elif getattr(func, "environmentfilter", False) is True:
             self.write("environment, ")
 
         # if the filter node is None we are inside a filter block
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/debug.py 
new/Jinja2-2.11.2/src/jinja2/debug.py
--- old/Jinja2-2.11.1/src/jinja2/debug.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/debug.py       2020-04-13 16:18:12.000000000 
+0200
@@ -245,10 +245,7 @@
     class _CTraceback(ctypes.Structure):
         _fields_ = [
             # Extra PyObject slots when compiled with Py_TRACE_REFS.
-            (
-                "PyObject_HEAD",
-                ctypes.c_byte * (32 if hasattr(sys, "getobjects") else 16),
-            ),
+            ("PyObject_HEAD", ctypes.c_byte * object().__sizeof__()),
             # Only care about tb_next as an object, not a traceback.
             ("tb_next", ctypes.py_object),
         ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/environment.py 
new/Jinja2-2.11.2/src/jinja2/environment.py
--- old/Jinja2-2.11.1/src/jinja2/environment.py 2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/environment.py 2020-04-13 16:18:12.000000000 
+0200
@@ -492,20 +492,20 @@
         if func is None:
             fail_for_missing_callable("no filter named %r", name)
         args = [value] + list(args or ())
-        if getattr(func, "contextfilter", False):
+        if getattr(func, "contextfilter", False) is True:
             if context is None:
                 raise TemplateRuntimeError(
                     "Attempted to invoke context filter without context"
                 )
             args.insert(0, context)
-        elif getattr(func, "evalcontextfilter", False):
+        elif getattr(func, "evalcontextfilter", False) is True:
             if eval_ctx is None:
                 if context is not None:
                     eval_ctx = context.eval_ctx
                 else:
                     eval_ctx = EvalContext(self)
             args.insert(0, eval_ctx)
-        elif getattr(func, "environmentfilter", False):
+        elif getattr(func, "environmentfilter", False) is True:
             args.insert(0, self)
         return func(*args, **(kwargs or {}))
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/filters.py 
new/Jinja2-2.11.2/src/jinja2/filters.py
--- old/Jinja2-2.11.1/src/jinja2/filters.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/filters.py     2020-04-13 16:18:12.000000000 
+0200
@@ -761,7 +761,7 @@
 
 def do_wordcount(s):
     """Count the words in that string."""
-    return len(_word_re.findall(s))
+    return len(_word_re.findall(soft_unicode(s)))
 
 
 def do_int(value, default=0, base=10):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/lexer.py 
new/Jinja2-2.11.2/src/jinja2/lexer.py
--- old/Jinja2-2.11.1/src/jinja2/lexer.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/lexer.py       2020-04-13 16:18:12.000000000 
+0200
@@ -681,6 +681,8 @@
         source_length = len(source)
         balancing_stack = []
         lstrip_unless_re = self.lstrip_unless_re
+        newlines_stripped = 0
+        line_starting = True
 
         while 1:
             # tokenizer loop
@@ -717,7 +719,9 @@
 
                         if strip_sign == "-":
                             # Strip all whitespace between the text and the 
tag.
-                            groups = (text.rstrip(),) + groups[1:]
+                            stripped = text.rstrip()
+                            newlines_stripped = text[len(stripped) 
:].count("\n")
+                            groups = (stripped,) + groups[1:]
                         elif (
                             # Not marked for preserving whitespace.
                             strip_sign != "+"
@@ -728,11 +732,11 @@
                         ):
                             # The start of text between the last newline and 
the tag.
                             l_pos = text.rfind("\n") + 1
-
-                            # If there's only whitespace between the newline 
and the
-                            # tag, strip it.
-                            if not lstrip_unless_re.search(text, l_pos):
-                                groups = (text[:l_pos],) + groups[1:]
+                            if l_pos > 0 or line_starting:
+                                # If there's only whitespace between the 
newline and the
+                                # tag, strip it.
+                                if not lstrip_unless_re.search(text, l_pos):
+                                    groups = (text[:l_pos],) + groups[1:]
 
                     for idx, token in enumerate(tokens):
                         # failure group
@@ -758,7 +762,8 @@
                             data = groups[idx]
                             if data or token not in ignore_if_empty:
                                 yield lineno, token, data
-                            lineno += data.count("\n")
+                            lineno += data.count("\n") + newlines_stripped
+                            newlines_stripped = 0
 
                 # strings as token just are yielded as it.
                 else:
@@ -790,6 +795,8 @@
                         yield lineno, tokens, data
                     lineno += data.count("\n")
 
+                line_starting = m.group()[-1:] == "\n"
+
                 # fetch new position into new variable so that we can check
                 # if there is a internal parsing error which would result
                 # in an infinite loop
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/loaders.py 
new/Jinja2-2.11.2/src/jinja2/loaders.py
--- old/Jinja2-2.11.1/src/jinja2/loaders.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/loaders.py     2020-04-13 16:18:12.000000000 
+0200
@@ -3,11 +3,9 @@
 sources.
 """
 import os
-import pkgutil
 import sys
 import weakref
 from hashlib import sha1
-from importlib import import_module
 from os import path
 from types import ModuleType
 
@@ -217,141 +215,75 @@
 
 
 class PackageLoader(BaseLoader):
-    """Load templates from a directory in a Python package.
+    """Load templates from python eggs or packages.  It is constructed with
+    the name of the python package and the path to the templates in that
+    package::
 
-    :param package_name: Import name of the package that contains the
-        template directory.
-    :param package_path: Directory within the imported package that
-        contains the templates.
-    :param encoding: Encoding of template files.
+        loader = PackageLoader('mypackage', 'views')
 
-    The following example looks up templates in the ``pages`` directory
-    within the ``project.ui`` package.
+    If the package path is not given, ``'templates'`` is assumed.
 
-    .. code-block:: python
-
-        loader = PackageLoader("project.ui", "pages")
-
-    Only packages installed as directories (standard pip behavior) or
-    zip/egg files (less common) are supported. The Python API for
-    introspecting data in packages is too limited to support other
-    installation methods the way this loader requires.
-
-    There is limited support for :pep:`420` namespace packages. The
-    template directory is assumed to only be in one namespace
-    contributor. Zip files contributing to a namespace are not
-    supported.
-
-    .. versionchanged:: 2.11.0
-        No longer uses ``setuptools`` as a dependency.
-
-    .. versionchanged:: 2.11.0
-        Limited PEP 420 namespace package support.
+    Per default the template encoding is ``'utf-8'`` which can be changed
+    by setting the `encoding` parameter to something else.  Due to the nature
+    of eggs it's only possible to reload templates if the package was loaded
+    from the file system and not a zip file.
     """
 
     def __init__(self, package_name, package_path="templates", 
encoding="utf-8"):
-        if package_path == os.path.curdir:
-            package_path = ""
-        elif package_path[:2] == os.path.curdir + os.path.sep:
-            package_path = package_path[2:]
+        from pkg_resources import DefaultProvider
+        from pkg_resources import get_provider
+        from pkg_resources import ResourceManager
 
-        package_path = os.path.normpath(package_path).rstrip(os.path.sep)
-        self.package_path = package_path
-        self.package_name = package_name
+        provider = get_provider(package_name)
         self.encoding = encoding
-
-        # Make sure the package exists. This also makes namespace
-        # packages work, otherwise get_loader returns None.
-        import_module(package_name)
-        self._loader = loader = pkgutil.get_loader(package_name)
-
-        # Zip loader's archive attribute points at the zip.
-        self._archive = getattr(loader, "archive", None)
-        self._template_root = None
-
-        if hasattr(loader, "get_filename"):
-            # A standard directory package, or a zip package.
-            self._template_root = os.path.join(
-                os.path.dirname(loader.get_filename(package_name)), 
package_path
-            )
-        elif hasattr(loader, "_path"):
-            # A namespace package, limited support. Find the first
-            # contributor with the template directory.
-            for root in loader._path:
-                root = os.path.join(root, package_path)
-
-                if os.path.isdir(root):
-                    self._template_root = root
-                    break
-
-        if self._template_root is None:
-            raise ValueError(
-                "The %r package was not installed in a way that"
-                " PackageLoader understands." % package_name
-            )
+        self.manager = ResourceManager()
+        self.filesystem_bound = isinstance(provider, DefaultProvider)
+        self.provider = provider
+        self.package_path = package_path
 
     def get_source(self, environment, template):
-        p = os.path.join(self._template_root, *split_template_path(template))
-
-        if self._archive is None:
-            # Package is a directory.
-            if not os.path.isfile(p):
-                raise TemplateNotFound(template)
+        pieces = split_template_path(template)
+        p = "/".join((self.package_path,) + tuple(pieces))
 
-            with open(p, "rb") as f:
-                source = f.read()
+        if not self.provider.has_resource(p):
+            raise TemplateNotFound(template)
 
-            mtime = os.path.getmtime(p)
+        filename = uptodate = None
 
-            def up_to_date():
-                return os.path.isfile(p) and os.path.getmtime(p) == mtime
+        if self.filesystem_bound:
+            filename = self.provider.get_resource_filename(self.manager, p)
+            mtime = path.getmtime(filename)
 
-        else:
-            # Package is a zip file.
-            try:
-                source = self._loader.get_data(p)
-            except OSError:
-                raise TemplateNotFound(template)
-
-            # Could use the zip's mtime for all template mtimes, but
-            # would need to safely reload the module if it's out of
-            # date, so just report it as always current.
-            up_to_date = None
+            def uptodate():
+                try:
+                    return path.getmtime(filename) == mtime
+                except OSError:
+                    return False
 
-        return source.decode(self.encoding), p, up_to_date
+        source = self.provider.get_resource_string(self.manager, p)
+        return source.decode(self.encoding), filename, uptodate
 
     def list_templates(self):
-        results = []
+        path = self.package_path
 
-        if self._archive is None:
-            # Package is a directory.
-            offset = len(self._template_root)
-
-            for dirpath, _, filenames in os.walk(self._template_root):
-                dirpath = dirpath[offset:].lstrip(os.path.sep)
-                results.extend(
-                    os.path.join(dirpath, name).replace(os.path.sep, "/")
-                    for name in filenames
-                )
-        else:
-            if not hasattr(self._loader, "_files"):
-                raise TypeError(
-                    "This zip import does not have the required"
-                    " metadata to list templates."
-                )
-
-            # Package is a zip file.
-            prefix = (
-                self._template_root[len(self._archive) :].lstrip(os.path.sep)
-                + os.path.sep
-            )
-            offset = len(prefix)
+        if path[:2] == "./":
+            path = path[2:]
+        elif path == ".":
+            path = ""
+
+        offset = len(path)
+        results = []
 
-            for name in self._loader._files.keys():
-                # Find names under the templates directory that aren't 
directories.
-                if name.startswith(prefix) and name[-1] != os.path.sep:
-                    results.append(name[offset:].replace(os.path.sep, "/"))
+        def _walk(path):
+            for filename in self.provider.resource_listdir(path):
+                fullname = path + "/" + filename
+
+                if self.provider.resource_isdir(fullname):
+                    _walk(fullname)
+                else:
+                    results.append(fullname[offset:].lstrip("/"))
 
+        _walk(path)
         results.sort()
         return results
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/nativetypes.py 
new/Jinja2-2.11.2/src/jinja2/nativetypes.py
--- old/Jinja2-2.11.1/src/jinja2/nativetypes.py 2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/nativetypes.py 2020-04-13 18:11:28.000000000 
+0200
@@ -1,4 +1,3 @@
-import types
 from ast import literal_eval
 from itertools import chain
 from itertools import islice
@@ -11,7 +10,7 @@
 from .environment import Template
 
 
-def native_concat(nodes, preserve_quotes=True):
+def native_concat(nodes):
     """Return a native Python type from the list of compiled nodes. If
     the result is a single node, its value is returned. Otherwise, the
     nodes are concatenated as strings. If the result can be parsed with
@@ -19,9 +18,6 @@
     the string is returned.
 
     :param nodes: Iterable of nodes to concatenate.
-    :param preserve_quotes: Whether to re-wrap literal strings with
-        quotes, to preserve quotes around expressions for later parsing.
-        Should be ``False`` in :meth:`NativeEnvironment.render`.
     """
     head = list(islice(nodes, 2))
 
@@ -31,29 +27,17 @@
     if len(head) == 1:
         raw = head[0]
     else:
-        if isinstance(nodes, types.GeneratorType):
-            nodes = chain(head, nodes)
-        raw = u"".join([text_type(v) for v in nodes])
+        raw = u"".join([text_type(v) for v in chain(head, nodes)])
 
     try:
-        literal = literal_eval(raw)
+        return literal_eval(raw)
     except (ValueError, SyntaxError, MemoryError):
         return raw
 
-    # If literal_eval returned a string, re-wrap with the original
-    # quote character to avoid dropping quotes between expression nodes.
-    # Without this, "'{{ a }}', '{{ b }}'" results in "a, b", but should
-    # be ('a', 'b').
-    if preserve_quotes and isinstance(literal, str):
-        return "{quote}{}{quote}".format(literal, quote=raw[0])
-
-    return literal
-
 
 class NativeCodeGenerator(CodeGenerator):
     """A code generator which renders Python types by not adding
-    ``to_string()`` around output nodes, and using :func:`native_concat`
-    to convert complex strings back to Python types if possible.
+    ``to_string()`` around output nodes.
     """
 
     @staticmethod
@@ -61,7 +45,7 @@
         return value
 
     def _output_const_repr(self, group):
-        return repr(native_concat(group))
+        return repr(u"".join([text_type(v) for v in group]))
 
     def _output_child_to_const(self, node, frame, finalize):
         const = node.as_const(frame.eval_ctx)
@@ -100,10 +84,9 @@
         Otherwise, the string is returned.
         """
         vars = dict(*args, **kwargs)
+
         try:
-            return native_concat(
-                self.root_render_func(self.new_context(vars)), 
preserve_quotes=False
-            )
+            return native_concat(self.root_render_func(self.new_context(vars)))
         except Exception:
             return self.environment.handle_exception()
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/nodes.py 
new/Jinja2-2.11.2/src/jinja2/nodes.py
--- old/Jinja2-2.11.1/src/jinja2/nodes.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/nodes.py       2020-04-13 16:18:12.000000000 
+0200
@@ -671,7 +671,7 @@
         # 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):
+        if filter_ is None or getattr(filter_, "contextfilter", False) is True:
             raise Impossible()
 
         # We cannot constant handle async filters, so we need to make sure
@@ -684,9 +684,9 @@
         args, kwargs = args_as_const(self, eval_ctx)
         args.insert(0, self.node.as_const(eval_ctx))
 
-        if getattr(filter_, "evalcontextfilter", False):
+        if getattr(filter_, "evalcontextfilter", False) is True:
             args.insert(0, eval_ctx)
-        elif getattr(filter_, "environmentfilter", False):
+        elif getattr(filter_, "environmentfilter", False) is True:
             args.insert(0, self.environment)
 
         try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/runtime.py 
new/Jinja2-2.11.2/src/jinja2/runtime.py
--- old/Jinja2-2.11.1/src/jinja2/runtime.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/runtime.py     2020-04-13 16:18:12.000000000 
+0200
@@ -280,11 +280,11 @@
                     break
 
         if callable(__obj):
-            if getattr(__obj, "contextfunction", 0):
+            if getattr(__obj, "contextfunction", False) is True:
                 args = (__self,) + args
-            elif getattr(__obj, "evalcontextfunction", 0):
+            elif getattr(__obj, "evalcontextfunction", False) is True:
                 args = (__self.eval_ctx,) + args
-            elif getattr(__obj, "environmentfunction", 0):
+            elif getattr(__obj, "environmentfunction", False) is True:
                 args = (__self.environment,) + args
         try:
             return __obj(*args, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/src/jinja2/utils.py 
new/Jinja2-2.11.2/src/jinja2/utils.py
--- old/Jinja2-2.11.1/src/jinja2/utils.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/src/jinja2/utils.py       2020-04-13 16:18:12.000000000 
+0200
@@ -165,11 +165,15 @@
         return "None"
     elif obj is Ellipsis:
         return "Ellipsis"
+
+    cls = type(obj)
+
     # __builtin__ in 2.x, builtins in 3.x
-    if obj.__class__.__module__ in ("__builtin__", "builtins"):
-        name = obj.__class__.__name__
+    if cls.__module__ in ("__builtin__", "builtins"):
+        name = cls.__name__
     else:
-        name = obj.__class__.__module__ + "." + obj.__class__.__name__
+        name = cls.__module__ + "." + cls.__name__
+
     return "%s object" % name
 
 
@@ -693,7 +697,8 @@
         self.__attrs = dict(*args, **kwargs)
 
     def __getattribute__(self, name):
-        if name == "_Namespace__attrs":
+        # __class__ is needed for the awaitable check in async mode
+        if name in {"_Namespace__attrs", "__class__"}:
             return object.__getattribute__(self, name)
         try:
             return self.__attrs[name]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/conftest.py 
new/Jinja2-2.11.2/tests/conftest.py
--- old/Jinja2-2.11.1/tests/conftest.py 2020-01-29 16:32:24.000000000 +0100
+++ new/Jinja2-2.11.2/tests/conftest.py 2020-04-13 16:18:12.000000000 +0200
@@ -14,50 +14,6 @@
     return False
 
 
-def pytest_configure(config):
-    """Register custom marks for test categories."""
-    custom_markers = [
-        "api",
-        "byte_code_cache",
-        "core_tags",
-        "debug",
-        "escapeUrlizeTarget",
-        "ext",
-        "extended",
-        "filesystemloader",
-        "filter",
-        "for_loop",
-        "helpers",
-        "if_condition",
-        "imports",
-        "includes",
-        "inheritance",
-        "lexer",
-        "lexnparse",
-        "loaders",
-        "loremIpsum",
-        "lowlevel",
-        "lrucache",
-        "lstripblocks",
-        "macros",
-        "meta",
-        "moduleloader",
-        "parser",
-        "regression",
-        "sandbox",
-        "set",
-        "streaming",
-        "syntax",
-        "test_tests",
-        "tokenstream",
-        "undefined",
-        "utils",
-        "with_",
-    ]
-    for mark in custom_markers:
-        config.addinivalue_line("markers", mark + ": test category")
-
-
 @pytest.fixture
 def env():
     """returns a new environment."""
Binary files old/Jinja2-2.11.1/tests/res/package.zip and 
new/Jinja2-2.11.2/tests/res/package.zip differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_api.py 
new/Jinja2-2.11.2/tests/test_api.py
--- old/Jinja2-2.11.1/tests/test_api.py 2020-01-29 16:32:24.000000000 +0100
+++ new/Jinja2-2.11.2/tests/test_api.py 2020-04-13 16:18:12.000000000 +0200
@@ -25,8 +25,6 @@
 from jinja2.utils import evalcontextfunction
 
 
[email protected]
[email protected]
 class TestExtendedAPI(object):
     def test_item_and_attribute(self, env):
         from jinja2.sandbox import SandboxedEnvironment
@@ -163,8 +161,6 @@
             t.render(total=MAX_RANGE + 1)
 
 
[email protected]
[email protected]
 class TestMeta(object):
     def test_find_undeclared_variables(self, env):
         ast = env.parse("{% set foo = 42 %}{{ bar + foo }}")
@@ -218,8 +214,6 @@
         assert list(i) == ["foo.html", "bar.html", None]
 
 
[email protected]
[email protected]
 class TestStreaming(object):
     def test_basic_streaming(self, env):
         t = env.from_string(
@@ -261,8 +255,6 @@
             shutil.rmtree(tmp)
 
 
[email protected]
[email protected]
 class TestUndefined(object):
     def test_stopiteration_is_undefined(self):
         def test():
@@ -277,6 +269,21 @@
         with pytest.raises(AttributeError):
             Undefined("Foo").__dict__
 
+    def test_undefined_attribute_error(self):
+        # Django's LazyObject turns the __class__ attribute into a
+        # property that resolves the wrapped function. If that wrapped
+        # function raises an AttributeError, printing the repr of the
+        # object in the undefined message would cause a RecursionError.
+        class Error(object):
+            @property
+            def __class__(self):
+                raise AttributeError()
+
+        u = Undefined(obj=Error(), name="hello")
+
+        with pytest.raises(UndefinedError):
+            getattr(u, "recursion", None)
+
     def test_logging_undefined(self):
         _messages = []
 
@@ -400,8 +407,6 @@
             Undefined(obj=42, name="upper")()
 
 
[email protected]
[email protected]
 class TestLowLevel(object):
     def test_custom_code_generator(self):
         class CustomCodeGenerator(CodeGenerator):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_async.py 
new/Jinja2-2.11.2/tests/test_async.py
--- old/Jinja2-2.11.1/tests/test_async.py       2020-01-30 18:55:16.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_async.py       2020-04-13 16:18:12.000000000 
+0200
@@ -130,7 +130,6 @@
     return env
 
 
[email protected]
 class TestAsyncImports(object):
     def test_context_imports(self, test_env_async):
         t = test_env_async.from_string('{% import "module" as m %}{{ m.test() 
}}')
@@ -180,8 +179,6 @@
         assert not hasattr(m, "notthere")
 
 
[email protected]
[email protected]
 class TestAsyncIncludes(object):
     def test_context_include(self, test_env_async):
         t = test_env_async.from_string('{% include "header" %}')
@@ -279,8 +276,6 @@
         assert t.render().strip() == "(FOO)"
 
 
[email protected]_tags
[email protected]_loop
 class TestAsyncForLoop(object):
     def test_simple(self, test_env_async):
         tmpl = test_env_async.from_string("{% for item in seq %}{{ item }}{% 
endfor %}")
@@ -583,3 +578,14 @@
     def test_awaitable_property_slicing(self, test_env_async):
         t = test_env_async.from_string("{% for x in a.b[:1] %}{{ x }}{% endfor 
%}")
         assert t.render(a=dict(b=[1, 2, 3])) == "1"
+
+
+def test_namespace_awaitable(test_env_async):
+    async def _test():
+        t = test_env_async.from_string(
+            '{% set ns = namespace(foo="Bar") %}{{ ns.foo }}'
+        )
+        actual = await t.render_async()
+        assert actual == "Bar"
+
+    run(_test())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_bytecode_cache.py 
new/Jinja2-2.11.2/tests/test_bytecode_cache.py
--- old/Jinja2-2.11.1/tests/test_bytecode_cache.py      2020-01-29 
16:32:24.000000000 +0100
+++ new/Jinja2-2.11.2/tests/test_bytecode_cache.py      2020-04-13 
16:18:12.000000000 +0200
@@ -14,7 +14,6 @@
     return Environment(loader=package_loader, bytecode_cache=bytecode_cache)
 
 
[email protected]_code_cache
 class TestByteCodeCache(object):
     def test_simple(self, env):
         tmpl = env.get_template("test.html")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_core_tags.py 
new/Jinja2-2.11.2/tests/test_core_tags.py
--- old/Jinja2-2.11.1/tests/test_core_tags.py   2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_core_tags.py   2020-04-13 16:18:12.000000000 
+0200
@@ -13,8 +13,6 @@
     return Environment(trim_blocks=True)
 
 
[email protected]_tags
[email protected]_loop
 class TestForLoop(object):
     def test_simple(self, env):
         tmpl = env.from_string("{% for item in seq %}{{ item }}{% endfor %}")
@@ -305,8 +303,6 @@
         assert tmpl.render(x=0, seq=[1, 2, 3]) == "919293"
 
 
[email protected]_tags
[email protected]_condition
 class TestIfCondition(object):
     def test_simple(self, env):
         tmpl = env.from_string("""{% if true %}...{% endif %}""")
@@ -349,8 +345,6 @@
         assert tmpl.render() == "1"
 
 
[email protected]_tags
[email protected]
 class TestMacros(object):
     def test_simple(self, env_trim):
         tmpl = env_trim.from_string(
@@ -475,8 +469,6 @@
         assert tmpl.module.m(1, x=7) == "1|7|7"
 
 
[email protected]_tags
[email protected]
 class TestSet(object):
     def test_normal(self, env_trim):
         tmpl = env_trim.from_string("{% set foo = 1 %}{{ foo }}")
@@ -584,8 +576,6 @@
         assert tmpl.module.foo == u"11"
 
 
[email protected]_tags
[email protected]_
 class TestWith(object):
     def test_with(self, env):
         tmpl = env.from_string(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_debug.py 
new/Jinja2-2.11.2/tests/test_debug.py
--- old/Jinja2-2.11.1/tests/test_debug.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_debug.py       2020-04-13 16:18:12.000000000 
+0200
@@ -17,7 +17,6 @@
     return Environment(loader=filesystem_loader)
 
 
[email protected]
 class TestDebug(object):
     def assert_traceback_matches(self, callback, expected_tb):
         with pytest.raises(Exception) as exc_info:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_ext.py 
new/Jinja2-2.11.2/tests/test_ext.py
--- old/Jinja2-2.11.1/tests/test_ext.py 2020-01-29 16:32:24.000000000 +0100
+++ new/Jinja2-2.11.2/tests/test_ext.py 2020-04-13 16:18:12.000000000 +0200
@@ -167,7 +167,6 @@
             yield Token(lineno, "data", token.value[pos:])
 
 
[email protected]
 class TestExtensions(object):
     def test_extend_late(self):
         env = Environment()
@@ -267,7 +266,6 @@
             assert "'{}'".format(value) in out
 
 
[email protected]
 class TestInternationalization(object):
     def test_trans(self):
         tmpl = i18n_env.get_template("child.html")
@@ -418,7 +416,6 @@
         ]
 
 
[email protected]
 class TestScope(object):
     def test_basic_scope_behavior(self):
         # This is what the old with statement compiled down to
@@ -452,7 +449,6 @@
         assert tmpl.render(b=3, e=4) == "1|2|2|4|5"
 
 
[email protected]
 class TestNewstyleInternationalization(object):
     def test_trans(self):
         tmpl = newstyle_i18n_env.get_template("child.html")
@@ -544,7 +540,6 @@
         assert t.render() == "%(foo)s"
 
 
[email protected]
 class TestAutoEscape(object):
     def test_scoped_setting(self):
         env = Environment(extensions=["jinja2.ext.autoescape"], 
autoescape=True)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_filters.py 
new/Jinja2-2.11.2/tests/test_filters.py
--- old/Jinja2-2.11.1/tests/test_filters.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_filters.py     2020-04-13 16:18:12.000000000 
+0200
@@ -6,6 +6,8 @@
 
 from jinja2 import Environment
 from jinja2 import Markup
+from jinja2 import StrictUndefined
+from jinja2 import UndefinedError
 from jinja2._compat import implements_to_string
 from jinja2._compat import text_type
 
@@ -29,7 +31,6 @@
         return u"(%s,%s)" % (text_type(self.value1), text_type(self.value2))
 
 
[email protected]
 class TestFilter(object):
     def test_filter_calling(self, env):
         rv = env.call_filter("sum", [1, 2, 3])
@@ -370,6 +371,11 @@
         tmpl = env.from_string('{{ "foo bar baz"|wordcount }}')
         assert tmpl.render() == "3"
 
+        strict_env = Environment(undefined=StrictUndefined)
+        t = strict_env.from_string("{{ s|wordcount }}")
+        with pytest.raises(UndefinedError):
+            t.render()
+
     def test_block(self, env):
         tmpl = env.from_string("{% filter lower|escape %}<HEHE>{% endfilter 
%}")
         assert tmpl.render() == "&lt;hehe&gt;"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_imports.py 
new/Jinja2-2.11.2/tests/test_imports.py
--- old/Jinja2-2.11.1/tests/test_imports.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_imports.py     2020-04-13 16:18:12.000000000 
+0200
@@ -23,7 +23,6 @@
     return env
 
 
[email protected]
 class TestImports(object):
     def test_context_imports(self, test_env):
         t = test_env.from_string('{% import "module" as m %}{{ m.test() }}')
@@ -94,8 +93,6 @@
         assert not hasattr(m, "notthere")
 
 
[email protected]
[email protected]
 class TestIncludes(object):
     def test_context_include(self, test_env):
         t = test_env.from_string('{% include "header" %}')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_inheritance.py 
new/Jinja2-2.11.2/tests/test_inheritance.py
--- old/Jinja2-2.11.1/tests/test_inheritance.py 2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_inheritance.py 2020-04-13 16:18:12.000000000 
+0200
@@ -74,7 +74,6 @@
     )
 
 
[email protected]
 class TestInheritance(object):
     def test_layout(self, env):
         tmpl = env.get_template("layout")
@@ -233,7 +232,6 @@
         assert rv == ["43", "44", "45"]
 
 
[email protected]
 class TestBugFix(object):
     def test_fixed_macro_scoping_bug(self, env):
         assert (
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_lexnparse.py 
new/Jinja2-2.11.2/tests/test_lexnparse.py
--- old/Jinja2-2.11.1/tests/test_lexnparse.py   2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_lexnparse.py   2020-04-13 16:18:12.000000000 
+0200
@@ -27,8 +27,6 @@
     jinja_string_repr = repr
 
 
[email protected]
[email protected]
 class TestTokenStream(object):
     test_tokens = [
         Token(1, TOKEN_BLOCK_BEGIN, ""),
@@ -57,8 +55,6 @@
         ]
 
 
[email protected]
[email protected]
 class TestLexer(object):
     def test_raw1(self, env):
         tmpl = env.from_string(
@@ -182,9 +178,25 @@
         else:
             pytest.raises(TemplateSyntaxError, env.from_string, t)
 
+    def test_lineno_with_strip(self, env):
+        tokens = env.lex(
+            """\
+<html>
+    <body>
+    {%- block content -%}
+        <hr>
+        {{ item }}
+    {% endblock %}
+    </body>
+</html>"""
+        )
+        for tok in tokens:
+            lineno, token_type, value = tok
+            if token_type == "name" and value == "item":
+                assert lineno == 5
+                break
+
 
[email protected]
[email protected]
 class TestParser(object):
     def test_php_syntax(self, env):
         env = Environment("<?", "?>", "<?=", "?>", "<!--", "-->")
@@ -318,8 +330,6 @@
         assert_error("{% unknown_tag %}", "Encountered unknown tag 
'unknown_tag'.")
 
 
[email protected]
[email protected]
 class TestSyntax(object):
     def test_call(self, env):
         env = Environment()
@@ -575,8 +585,6 @@
         assert tmpl.render(foo={"bar": 42}) == "42"
 
 
[email protected]
[email protected]
 class TestLstripBlocks(object):
     def test_lstrip(self, env):
         env = Environment(lstrip_blocks=True, trim_blocks=False)
@@ -721,6 +729,98 @@
         )
         assert tmpl.render(seq=range(5)) == "".join("%s\n" % x for x in 
range(5))
 
+    def test_lstrip_blocks_outside_with_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=False)
+        tmpl = env.from_string(
+            "  {% if kvs %}(\n"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
+            "  ){% endif %}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "(\na=1 b=2 \n  )"
+
+    def test_lstrip_trim_blocks_outside_with_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=True)
+        tmpl = env.from_string(
+            "  {% if kvs %}(\n"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
+            "  ){% endif %}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "(\na=1 b=2   )"
+
+    def test_lstrip_blocks_inside_with_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=False)
+        tmpl = env.from_string(
+            "  ({% if kvs %}\n"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
+            "  {% endif %})"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "  (\na=1 b=2 \n)"
+
+    def test_lstrip_trim_blocks_inside_with_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=True)
+        tmpl = env.from_string(
+            "  ({% if kvs %}\n"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}\n"
+            "  {% endif %})"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "  (a=1 b=2 )"
+
+    def test_lstrip_blocks_without_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=False)
+        tmpl = env.from_string(
+            "  {% if kvs %}"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}"
+            "  {% endif %}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "   a=1 b=2   "
+
+    def test_lstrip_trim_blocks_without_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=True)
+        tmpl = env.from_string(
+            "  {% if kvs %}"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor %}"
+            "  {% endif %}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "   a=1 b=2   "
+
+    def test_lstrip_blocks_consume_after_without_new_line(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=False)
+        tmpl = env.from_string(
+            "  {% if kvs -%}"
+            "   {% for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}"
+            "  {% endif -%}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "a=1 b=2 "
+
+    def test_lstrip_trim_blocks_consume_before_without_new_line(self):
+        env = Environment(lstrip_blocks=False, trim_blocks=False)
+        tmpl = env.from_string(
+            "  {%- if kvs %}"
+            "   {%- for k, v in kvs %}{{ k }}={{ v }} {% endfor -%}"
+            "  {%- endif %}"
+        )
+        out = tmpl.render(kvs=[("a", 1), ("b", 2)])
+        assert out == "a=1 b=2 "
+
+    def test_lstrip_trim_blocks_comment(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=True)
+        tmpl = env.from_string(" {# 1 space #}\n  {# 2 spaces #}    {# 4 
spaces #}")
+        out = tmpl.render()
+        assert out == " " * 4
+
+    def test_lstrip_trim_blocks_raw(self):
+        env = Environment(lstrip_blocks=True, trim_blocks=True)
+        tmpl = env.from_string("{{x}}\n{%- raw %} {% endraw -%}\n{{ y }}")
+        out = tmpl.render(x=1, y=2)
+        assert out == "1 2"
+
     def test_php_syntax_with_manual(self, env):
         env = Environment(
             "<?", "?>", "<?=", "?>", "<!--", "-->", lstrip_blocks=True, 
trim_blocks=True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_loader.py 
new/Jinja2-2.11.2/tests/test_loader.py
--- old/Jinja2-2.11.1/tests/test_loader.py      2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_loader.py      2020-04-13 16:18:12.000000000 
+0200
@@ -10,14 +10,12 @@
 
 from jinja2 import Environment
 from jinja2 import loaders
-from jinja2 import PackageLoader
 from jinja2._compat import PY2
 from jinja2._compat import PYPY
 from jinja2.exceptions import TemplateNotFound
 from jinja2.loaders import split_template_path
 
 
[email protected]
 class TestLoaders(object):
     def test_dict_loader(self, dict_loader):
         env = Environment(loader=dict_loader)
@@ -117,8 +115,6 @@
         pytest.raises(TemplateNotFound, split_template_path, "../foo")
 
 
[email protected]
[email protected]
 class TestFileSystemLoader(object):
     searchpath = os.path.join(
         os.path.dirname(os.path.abspath(__file__)), "res", "templates"
@@ -186,8 +182,6 @@
         assert t.render() == expect
 
 
[email protected]
[email protected]
 class TestModuleLoader(object):
     archive = None
 
@@ -326,52 +320,3 @@
         self.mod_env = Environment(loader=mod_loader)
 
         self._test_common()
-
-
[email protected]()
-def package_dir_loader(monkeypatch):
-    monkeypatch.syspath_prepend(os.path.dirname(__file__))
-    return PackageLoader("res")
-
-
[email protected](
-    ("template", "expect"), [("foo/test.html", "FOO"), ("test.html", "BAR")]
-)
-def test_package_dir_source(package_dir_loader, template, expect):
-    source, name, up_to_date = package_dir_loader.get_source(None, template)
-    assert source.rstrip() == expect
-    assert name.endswith(os.path.join(*split_template_path(template)))
-    assert up_to_date()
-
-
-def test_package_dir_list(package_dir_loader):
-    templates = package_dir_loader.list_templates()
-    assert "foo/test.html" in templates
-    assert "test.html" in templates
-
-
[email protected]()
-def package_zip_loader(monkeypatch):
-    monkeypatch.syspath_prepend(
-        os.path.join(os.path.dirname(__file__), "res", "package.zip")
-    )
-    return PackageLoader("t_pack")
-
-
[email protected](
-    ("template", "expect"), [("foo/test.html", "FOO"), ("test.html", "BAR")]
-)
-def test_package_zip_source(package_zip_loader, template, expect):
-    source, name, up_to_date = package_zip_loader.get_source(None, template)
-    assert source.rstrip() == expect
-    assert name.endswith(os.path.join(*split_template_path(template)))
-    assert up_to_date is None
-
-
[email protected](
-    PYPY,
-    reason="PyPy's zipimporter doesn't have a _files attribute.",
-    raises=TypeError,
-)
-def test_package_zip_list(package_zip_loader):
-    assert package_zip_loader.list_templates() == ["foo/test.html", 
"test.html"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_nativetypes.py 
new/Jinja2-2.11.2/tests/test_nativetypes.py
--- old/Jinja2-2.11.1/tests/test_nativetypes.py 2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_nativetypes.py 2020-04-13 18:11:28.000000000 
+0200
@@ -134,6 +134,15 @@
     assert result == "--host='localhost' --user \"Jinja\""
 
 
+def test_no_intermediate_eval(env):
+    t = env.from_string("0.000{{ a }}")
+    result = t.render(a=7)
+    assert isinstance(result, float)
+    # If intermediate eval happened, 0.000 would render 0.0, then 7
+    # would be appended, resulting in 0.07.
+    assert result < 0.007  # TODO use math.isclose in Python 3
+
+
 def test_spontaneous_env():
     t = NativeTemplate("{{ true }}")
     assert isinstance(t.environment, NativeEnvironment)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_regression.py 
new/Jinja2-2.11.2/tests/test_regression.py
--- old/Jinja2-2.11.1/tests/test_regression.py  2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_regression.py  2020-04-13 16:18:12.000000000 
+0200
@@ -13,7 +13,6 @@
 from jinja2._compat import text_type
 
 
[email protected]
 class TestCorner(object):
     def test_assigned_scoping(self, env):
         t = env.from_string(
@@ -85,7 +84,6 @@
         assert t.render(wrapper=23) == "[1][2][3][4]23"
 
 
[email protected]
 class TestBug(object):
     def test_keyword_folding(self, env):
         env = Environment()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_runtime.py 
new/Jinja2-2.11.2/tests/test_runtime.py
--- old/Jinja2-2.11.1/tests/test_runtime.py     2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_runtime.py     2020-04-13 16:18:12.000000000 
+0200
@@ -54,3 +54,22 @@
     # groupby groups depend on the current position of the iterator. If
     # it was advanced early, the lists would appear empty.
     assert out == "1 [(1, 'a'), (1, 'b')]\n2 [(2, 'c')]\n3 [(3, 'd')]\n"
+
+
+def test_mock_not_contextfunction():
+    """If a callable class has a ``__getattr__`` that returns True-like
+    values for arbitrary attrs, it should not be incorrectly identified
+    as a ``contextfunction``.
+    """
+
+    class Calc(object):
+        def __getattr__(self, item):
+            return object()
+
+        def __call__(self, *args, **kwargs):
+            return len(args) + len(kwargs)
+
+    t = Template("{{ calc() }}")
+    out = t.render(calc=Calc())
+    # Would be "1" if context argument was passed.
+    assert out == "0"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_security.py 
new/Jinja2-2.11.2/tests/test_security.py
--- old/Jinja2-2.11.1/tests/test_security.py    2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_security.py    2020-04-13 16:18:12.000000000 
+0200
@@ -37,7 +37,6 @@
         return "PublicStuff"
 
 
[email protected]
 class TestSandbox(object):
     def test_unsafe(self, env):
         env = SandboxedEnvironment()
@@ -167,7 +166,6 @@
                 t.render(ctx)
 
 
[email protected]
 class TestStringFormat(object):
     def test_basic_format_safety(self):
         env = SandboxedEnvironment()
@@ -190,7 +188,6 @@
         assert t.render() == "a42b&lt;foo&gt;"
 
 
[email protected]
 @pytest.mark.skipif(
     not hasattr(str, "format_map"), reason="requires str.format_map method"
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_tests.py 
new/Jinja2-2.11.2/tests/test_tests.py
--- old/Jinja2-2.11.1/tests/test_tests.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_tests.py       2020-04-13 16:18:12.000000000 
+0200
@@ -9,7 +9,6 @@
     pass
 
 
[email protected]_tests
 class TestTestsCase(object):
     def test_defined(self, env):
         tmpl = env.from_string("{{ missing is defined }}|{{ true is defined 
}}")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Jinja2-2.11.1/tests/test_utils.py 
new/Jinja2-2.11.2/tests/test_utils.py
--- old/Jinja2-2.11.1/tests/test_utils.py       2020-01-29 16:32:24.000000000 
+0100
+++ new/Jinja2-2.11.2/tests/test_utils.py       2020-04-13 16:18:12.000000000 
+0200
@@ -18,8 +18,6 @@
 from jinja2.utils import urlize
 
 
[email protected]
[email protected]
 class TestLRUCache(object):
     def test_simple(self):
         d = LRUCache(3)
@@ -120,8 +118,6 @@
         assert len(d) == 2
 
 
[email protected]
[email protected]
 class TestHelpers(object):
     def test_object_type_repr(self):
         class X(object):
@@ -150,8 +146,6 @@
         assert not func("FOO.TXT")
 
 
[email protected]
[email protected]
 class TestEscapeUrlizeTarget(object):
     def test_escape_urlize_target(self):
         url = "http://example.org";
@@ -163,8 +157,6 @@
         )
 
 
[email protected]
[email protected]
 class TestLoremIpsum(object):
     def test_lorem_ipsum_markup(self):
         """Test that output of lorem_ipsum is Markup by default."""


Reply via email to