From: David Lord Date: Mon, 30 Mar 2020 17:54:57 +0000 (-0700) Subject: Merge branch '2.11.x' X-Git-Tag: 3.0.0rc1~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c074fd5ecb7af70b2f864c9ef545fffd38dc203b;p=thirdparty%2Fjinja.git Merge branch '2.11.x' --- c074fd5ecb7af70b2f864c9ef545fffd38dc203b diff --cc CHANGES.rst index e7542118,b16ed2b4..c2f51f56 --- a/CHANGES.rst +++ b/CHANGES.rst @@@ -20,7 -9,19 +20,19 @@@ Unrelease :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` + by wrapping the input in :func:`soft_str`. :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` + Version 2.11.1 -------------- diff --cc src/jinja2/loaders.py index b02cc357,457c4b59..d5c45c49 --- a/src/jinja2/loaders.py +++ b/src/jinja2/loaders.py @@@ -207,36 -215,18 +207,36 @@@ class FileSystemLoader(BaseLoader) class PackageLoader(BaseLoader): - """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:: + """Load templates from a directory in a Python package. - loader = PackageLoader('mypackage', 'views') + :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. - If the package path is not given, ``'templates'`` is assumed. + The following example looks up templates in the ``pages`` directory + within the ``project.ui`` package. - 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. + .. 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 ++ .. versionchanged:: 3.0 + No longer uses ``setuptools`` as a dependency. + - .. versionchanged:: 2.11.0 ++ .. versionchanged:: 3.0 + Limited PEP 420 namespace package support. """ def __init__(self, package_name, package_path="templates", encoding="utf-8"): diff --cc src/jinja2/utils.py index 99293cd6,94581ca8..b373950e --- a/src/jinja2/utils.py +++ b/src/jinja2/utils.py @@@ -158,20 -165,30 +158,21 @@@ def object_type_repr(obj) return "None" elif obj is Ellipsis: return "Ellipsis" - # __builtin__ in 2.x, builtins in 3.x - if obj.__class__.__module__ in ("__builtin__", "builtins"): - name = obj.__class__.__name__ - else: - name = f"{obj.__class__.__module__}.{obj.__class__.__name__}" - return f"{name} object" + + cls = type(obj) + - # __builtin__ in 2.x, builtins in 3.x - if cls.__module__ in ("__builtin__", "builtins"): - name = cls.__name__ - else: - name = cls.__module__ + "." + cls.__name__ ++ if cls.__module__ == "builtins": ++ return f"{cls.__name__} object" + - return "%s object" % name ++ return f"{cls.__module__}.{cls.__name__} object" -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 --cc tests/test_api.py index 0655c479,7a1cae86..2679e8fb --- a/tests/test_api.py +++ b/tests/test_api.py @@@ -267,6 -269,21 +267,21 @@@ class TestUndefined 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): ++ class Error: + @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 = []