From 89310770585ed0fb8d10c46cf8d6f447bb807467 Mon Sep 17 00:00:00 2001 From: David Lord Date: Mon, 4 Oct 2021 17:39:39 -0700 Subject: [PATCH] omit curdir from PackageLoader root path fixes compatibility with zip imports Co-authored-by: kuepe-sl --- CHANGES.rst | 3 +++ src/jinja2/loaders.py | 4 +++- tests/test_loader.py | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index eb51581d..90c5bdf3 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,9 @@ Version 3.0.2 ``StrictUndefined`` for the ``in`` operator. :issue:`1448` - Imported macros have access to the current template globals in async environments. :issue:`1494` +- ``PackageLoader`` will not include a current directory (.) path + segment. This allows loading templates from the root of a zip + import. :issue:`1467` Version 3.0.1 diff --git a/src/jinja2/loaders.py b/src/jinja2/loaders.py index db04f0f6..513c858a 100644 --- a/src/jinja2/loaders.py +++ b/src/jinja2/loaders.py @@ -270,12 +270,14 @@ class PackageLoader(BaseLoader): package_path: "str" = "templates", encoding: str = "utf-8", ) -> None: + package_path = os.path.normpath(package_path).rstrip(os.path.sep) + + # normpath preserves ".", which isn't valid in zip paths. if package_path == os.path.curdir: package_path = "" elif package_path[:2] == os.path.curdir + os.path.sep: package_path = package_path[2:] - package_path = os.path.normpath(package_path).rstrip(os.path.sep) self.package_path = package_path self.package_name = package_name self.encoding = encoding diff --git a/tests/test_loader.py b/tests/test_loader.py index 63fc39ba..1533d023 100644 --- a/tests/test_loader.py +++ b/tests/test_loader.py @@ -339,6 +339,17 @@ def test_package_zip_list(package_zip_loader): assert package_zip_loader.list_templates() == ["foo/test.html", "test.html"] +@pytest.mark.parametrize("package_path", ["", ".", "./"]) +def test_package_zip_omit_curdir(package_zip_loader, package_path): + """PackageLoader should not add or include "." or "./" in the root + path, it is invalid in zip paths. + """ + loader = PackageLoader("t_pack", package_path) + assert loader.package_path == "" + source, _, _ = loader.get_source(None, "templates/foo/test.html") + assert source.rstrip() == "FOO" + + def test_pep_451_import_hook(): class ImportHook(importlib.abc.MetaPathFinder, importlib.abc.Loader): def find_spec(self, name, path=None, target=None): -- 2.47.2