mirror of https://github.com/python/cpython
[3.13] gh-122903: Honor directories in zipfile.Path.glob. (GH-122908) (#122926)
(cherry picked from commit 6aa35f3002
)
This commit is contained in:
parent
8c7348939d
commit
59d0d335cf
|
@ -101,7 +101,7 @@ class TestPath(unittest.TestCase):
|
|||
def test_iterdir_and_types(self, alpharep):
|
||||
root = zipfile.Path(alpharep)
|
||||
assert root.is_dir()
|
||||
a, k, b, g, j = root.iterdir()
|
||||
a, n, b, g, j = root.iterdir()
|
||||
assert a.is_file()
|
||||
assert b.is_dir()
|
||||
assert g.is_dir()
|
||||
|
@ -121,7 +121,7 @@ class TestPath(unittest.TestCase):
|
|||
@pass_alpharep
|
||||
def test_iterdir_on_file(self, alpharep):
|
||||
root = zipfile.Path(alpharep)
|
||||
a, k, b, g, j = root.iterdir()
|
||||
a, n, b, g, j = root.iterdir()
|
||||
with self.assertRaises(ValueError):
|
||||
a.iterdir()
|
||||
|
||||
|
@ -136,7 +136,7 @@ class TestPath(unittest.TestCase):
|
|||
@pass_alpharep
|
||||
def test_open(self, alpharep):
|
||||
root = zipfile.Path(alpharep)
|
||||
a, k, b, g, j = root.iterdir()
|
||||
a, n, b, g, j = root.iterdir()
|
||||
with a.open(encoding="utf-8") as strm:
|
||||
data = strm.read()
|
||||
self.assertEqual(data, "content of a")
|
||||
|
@ -240,7 +240,7 @@ class TestPath(unittest.TestCase):
|
|||
@pass_alpharep
|
||||
def test_read(self, alpharep):
|
||||
root = zipfile.Path(alpharep)
|
||||
a, k, b, g, j = root.iterdir()
|
||||
a, n, b, g, j = root.iterdir()
|
||||
assert a.read_text(encoding="utf-8") == "content of a"
|
||||
# Also check positional encoding arg (gh-101144).
|
||||
assert a.read_text("utf-8") == "content of a"
|
||||
|
@ -306,7 +306,7 @@ class TestPath(unittest.TestCase):
|
|||
reflect that change.
|
||||
"""
|
||||
root = zipfile.Path(alpharep)
|
||||
a, k, b, g, j = root.iterdir()
|
||||
a, n, b, g, j = root.iterdir()
|
||||
alpharep.writestr('foo.txt', 'foo')
|
||||
alpharep.writestr('bar/baz.txt', 'baz')
|
||||
assert any(child.name == 'foo.txt' for child in root.iterdir())
|
||||
|
@ -475,6 +475,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)
|
||||
|
|
|
@ -250,7 +250,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::
|
||||
|
||||
|
@ -466,8 +469,7 @@ class Path:
|
|||
prefix = re.escape(self.at)
|
||||
tr = Translator(seps='/')
|
||||
matches = re.compile(prefix + tr.translate(pattern)).fullmatch
|
||||
names = (data.filename for data in self.root.filelist)
|
||||
return map(self._next, filter(matches, names))
|
||||
return map(self._next, filter(matches, self.root.namelist()))
|
||||
|
||||
def rglob(self, pattern):
|
||||
return self.glob(f'**/{pattern}')
|
||||
|
|
|
@ -28,7 +28,7 @@ class Translator:
|
|||
"""
|
||||
Given a glob pattern, produce a regex that matches it.
|
||||
"""
|
||||
return self.extend(self.translate_core(pattern))
|
||||
return self.extend(self.match_dirs(self.translate_core(pattern)))
|
||||
|
||||
def extend(self, pattern):
|
||||
r"""
|
||||
|
@ -41,6 +41,14 @@ class Translator:
|
|||
"""
|
||||
return rf'(?s:{pattern})\Z'
|
||||
|
||||
def match_dirs(self, pattern):
|
||||
"""
|
||||
Ensure that zipfile.Path directory names are matched.
|
||||
|
||||
zipfile.Path directory names always end in a slash.
|
||||
"""
|
||||
return rf'{pattern}[/]?'
|
||||
|
||||
def translate_core(self, pattern):
|
||||
r"""
|
||||
Given a glob pattern, produce a regex that matches it.
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
``zipfile.Path.glob`` now correctly matches directories instead of
|
||||
silently omitting them.
|
Loading…
Reference in New Issue