diff --git a/Lib/test/test_zipfile/_path/test_path.py b/Lib/test/test_zipfile/_path/test_path.py index 90885dbbe39b92..f95b019f64a11b 100644 --- a/Lib/test/test_zipfile/_path/test_path.py +++ b/Lib/test/test_zipfile/_path/test_path.py @@ -472,6 +472,18 @@ def test_glob_recursive(self, alpharep): 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 @@ def test_malformed_paths(self): '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 42f9fded21198e..7cfa8d220c39b5 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 4a2e665e27078a..d5213533ad2270 100644 --- a/Lib/zipfile/_path/glob.py +++ b/Lib/zipfile/_path/glob.py @@ -2,6 +2,19 @@ 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 00000000000000..c2a1e64d1f6db1 --- /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.