From: Jason R. Coombs Date: Mon, 12 Aug 2024 01:03:03 +0000 (-0400) Subject: [3.12] gh-122903: Honor directories in zipfile.Path.glob. (GH-122908) (#122927) X-Git-Tag: v3.12.6~73 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f511a939b07a4ae2e561392e88edb5707ec02028;p=thirdparty%2FPython%2Fcpython.git [3.12] gh-122903: Honor directories in zipfile.Path.glob. (GH-122908) (#122927) (cherry picked from commit 6aa35f3002dda25858d47e702e750e2871e42a7c) --- diff --git a/Lib/test/test_zipfile/_path/test_path.py b/Lib/test/test_zipfile/_path/test_path.py index 90885dbbe39b..f95b019f64a1 100644 --- a/Lib/test/test_zipfile/_path/test_path.py +++ b/Lib/test/test_zipfile/_path/test_path.py @@ -472,6 +472,18 @@ class TestPath(unittest.TestCase): assert list(root.glob("**/*.txt")) == list(root.rglob("*.txt")) + @pass_alpharep + def test_glob_dirs(self, alpharep): + root = zipfile.Path(alpharep) + assert list(root.glob('b')) == [zipfile.Path(alpharep, "b/")] + assert list(root.glob('b*')) == [zipfile.Path(alpharep, "b/")] + + @pass_alpharep + def test_glob_subdir(self, alpharep): + root = zipfile.Path(alpharep) + assert list(root.glob('g/h')) == [zipfile.Path(alpharep, "g/h/")] + assert list(root.glob('g*/h*')) == [zipfile.Path(alpharep, "g/h/")] + @pass_alpharep def test_glob_subdirs(self, alpharep): root = zipfile.Path(alpharep) @@ -594,3 +606,10 @@ class TestPath(unittest.TestCase): 'two-slash.txt', 'parent.txt', ] + + @pass_alpharep + def test_interface(self, alpharep): + from importlib.resources.abc import Traversable + + zf = zipfile.Path(alpharep) + assert isinstance(zf, Traversable) diff --git a/Lib/zipfile/_path/__init__.py b/Lib/zipfile/_path/__init__.py index 42f9fded2119..7cfa8d220c39 100644 --- a/Lib/zipfile/_path/__init__.py +++ b/Lib/zipfile/_path/__init__.py @@ -236,7 +236,10 @@ def _extract_text_encoding(encoding=None, *args, **kwargs): class Path: """ - A pathlib-compatible interface for zip files. + A :class:`importlib.resources.abc.Traversable` interface for zip files. + + Implements many of the features users enjoy from + :class:`pathlib.Path`. Consider a zip file with this structure:: diff --git a/Lib/zipfile/_path/glob.py b/Lib/zipfile/_path/glob.py index 4a2e665e2707..d5213533ad22 100644 --- a/Lib/zipfile/_path/glob.py +++ b/Lib/zipfile/_path/glob.py @@ -2,6 +2,19 @@ import re def translate(pattern): + return match_dirs(translate_core(pattern)) + + +def match_dirs(pattern): + """ + Ensure that zipfile.Path directory names are matched. + + zipfile.Path directory names always end in a slash. + """ + return rf'{pattern}[/]?' + + +def translate_core(pattern): r""" Given a glob pattern, produce a regex that matches it. diff --git a/Misc/NEWS.d/next/Library/2024-08-11-14-23-07.gh-issue-122903.xktZta.rst b/Misc/NEWS.d/next/Library/2024-08-11-14-23-07.gh-issue-122903.xktZta.rst new file mode 100644 index 000000000000..c2a1e64d1f6d --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-08-11-14-23-07.gh-issue-122903.xktZta.rst @@ -0,0 +1,2 @@ +``zipfile.Path.glob`` now correctly matches directories instead of +silently omitting them.