diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2023-02-20 21:01:58 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-02-20 21:01:58 (GMT) |
commit | 36854bbb240e417c0df6f0014924fcc899388186 (patch) | |
tree | c0b3e543bac2a8507e09a4324acafae0d36ba7f4 /Lib/zipfile | |
parent | 84181c14040ed2befe7f1a55b4f560c80fa61154 (diff) | |
download | cpython-36854bbb240e417c0df6f0014924fcc899388186.zip cpython-36854bbb240e417c0df6f0014924fcc899388186.tar.gz cpython-36854bbb240e417c0df6f0014924fcc899388186.tar.bz2 |
gh-101566: Sync with zipp 3.14. (GH-102018)
Diffstat (limited to 'Lib/zipfile')
-rw-r--r-- | Lib/zipfile/_path.py | 63 |
1 files changed, 60 insertions, 3 deletions
diff --git a/Lib/zipfile/_path.py b/Lib/zipfile/_path.py index 7c7a6a0..c2c804e 100644 --- a/Lib/zipfile/_path.py +++ b/Lib/zipfile/_path.py @@ -4,6 +4,8 @@ import zipfile import itertools import contextlib import pathlib +import re +import fnmatch __all__ = ['Path'] @@ -93,7 +95,7 @@ class CompleteDirs(InitializedState, zipfile.ZipFile): return _dedupe(_difference(as_dirs, names)) def namelist(self): - names = super(CompleteDirs, self).namelist() + names = super().namelist() return names + list(self._implied_dirs(names)) def _name_set(self): @@ -109,6 +111,17 @@ class CompleteDirs(InitializedState, zipfile.ZipFile): dir_match = name not in names and dirname in names return dirname if dir_match else name + def getinfo(self, name): + """ + Supplement getinfo for implied dirs. + """ + try: + return super().getinfo(name) + except KeyError: + if not name.endswith('/') or name not in self._name_set(): + raise + return zipfile.ZipInfo(filename=name) + @classmethod def make(cls, source): """ @@ -138,13 +151,13 @@ class FastLookup(CompleteDirs): def namelist(self): with contextlib.suppress(AttributeError): return self.__names - self.__names = super(FastLookup, self).namelist() + self.__names = super().namelist() return self.__names def _name_set(self): with contextlib.suppress(AttributeError): return self.__lookup - self.__lookup = super(FastLookup, self)._name_set() + self.__lookup = super()._name_set() return self.__lookup @@ -246,6 +259,18 @@ class Path: self.root = FastLookup.make(root) self.at = at + def __eq__(self, other): + """ + >>> Path(zipfile.ZipFile(io.BytesIO(), 'w')) == 'foo' + False + """ + if self.__class__ is not other.__class__: + return NotImplemented + return (self.root, self.at) == (other.root, other.at) + + def __hash__(self): + return hash((self.root, self.at)) + def open(self, mode='r', *args, pwd=None, **kwargs): """ Open this entry as text or binary following the semantics @@ -316,6 +341,38 @@ class Path: subs = map(self._next, self.root.namelist()) return filter(self._is_child, subs) + def match(self, path_pattern): + return pathlib.Path(self.at).match(path_pattern) + + def is_symlink(self): + """ + Return whether this path is a symlink. Always false (python/cpython#82102). + """ + return False + + def _descendants(self): + for child in self.iterdir(): + yield child + if child.is_dir(): + yield from child._descendants() + + def glob(self, pattern): + if not pattern: + raise ValueError(f"Unacceptable pattern: {pattern!r}") + + matches = re.compile(fnmatch.translate(pattern)).fullmatch + return ( + child + for child in self._descendants() + if matches(str(child.relative_to(self))) + ) + + def rglob(self, pattern): + return self.glob(f'**/{pattern}') + + def relative_to(self, other, *extra): + return posixpath.relpath(str(self), str(other.joinpath(*extra))) + def __str__(self): return posixpath.join(self.root.filename, self.at) |