diff options
author | Jason R. Coombs <jaraco@jaraco.com> | 2020-10-25 18:45:05 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-10-25 18:45:05 (GMT) |
commit | d1a0a960ee493262fb95a0f5b795b5b6d75cecb8 (patch) | |
tree | 3c8081133e01ea92dc8e3bdb586757272e018824 /Lib/zipfile.py | |
parent | 14cdc215aa952d280c18626005d3aff967901d92 (diff) | |
download | cpython-d1a0a960ee493262fb95a0f5b795b5b6d75cecb8.zip cpython-d1a0a960ee493262fb95a0f5b795b5b6d75cecb8.tar.gz cpython-d1a0a960ee493262fb95a0f5b795b5b6d75cecb8.tar.bz2 |
bpo-42043: Add support for zipfile.Path subclasses (#22716)
* bpo-42043: Add support for zipfile.Path inheritance as introduced in zipp 3.2.0.
* Add blurb.
Diffstat (limited to 'Lib/zipfile.py')
-rw-r--r-- | Lib/zipfile.py | 39 |
1 files changed, 30 insertions, 9 deletions
diff --git a/Lib/zipfile.py b/Lib/zipfile.py index da3e40e..e1a50a3 100644 --- a/Lib/zipfile.py +++ b/Lib/zipfile.py @@ -16,6 +16,7 @@ import sys import threading import time import contextlib +import pathlib try: import zlib # We may need its compression method @@ -2210,6 +2211,7 @@ class FastLookup(CompleteDirs): ZipFile subclass to ensure implicit dirs exist and are resolved rapidly. """ + def namelist(self): with contextlib.suppress(AttributeError): return self.__names @@ -2241,7 +2243,7 @@ class Path: >>> zf.writestr('a.txt', 'content of a') >>> zf.writestr('b/c.txt', 'content of c') >>> zf.writestr('b/d/e.txt', 'content of e') - >>> zf.filename = 'abcde.zip' + >>> zf.filename = 'mem/abcde.zip' Path accepts the zipfile object itself or a filename @@ -2253,9 +2255,9 @@ class Path: >>> a, b = root.iterdir() >>> a - Path('abcde.zip', 'a.txt') + Path('mem/abcde.zip', 'a.txt') >>> b - Path('abcde.zip', 'b/') + Path('mem/abcde.zip', 'b/') name property: @@ -2266,7 +2268,7 @@ class Path: >>> c = b / 'c.txt' >>> c - Path('abcde.zip', 'b/c.txt') + Path('mem/abcde.zip', 'b/c.txt') >>> c.name 'c.txt' @@ -2284,8 +2286,21 @@ class Path: Coercion to string: - >>> str(c) - 'abcde.zip/b/c.txt' + >>> import os + >>> str(c).replace(os.sep, posixpath.sep) + 'mem/abcde.zip/b/c.txt' + + At the root, ``name``, ``filename``, and ``parent`` + resolve to the zipfile. Note these attributes are not + valid and will raise a ``ValueError`` if the zipfile + has no filename. + + >>> root.name + 'abcde.zip' + >>> str(root.filename).replace(os.sep, posixpath.sep) + 'mem/abcde.zip' + >>> str(root.parent) + 'mem' """ __repr = "{self.__class__.__name__}({self.root.filename!r}, {self.at!r})" @@ -2323,7 +2338,11 @@ class Path: @property def name(self): - return posixpath.basename(self.at.rstrip("/")) + return pathlib.Path(self.at).name or self.filename.name + + @property + def filename(self): + return pathlib.Path(self.root.filename).joinpath(self.at) def read_text(self, *args, **kwargs): with self.open('r', *args, **kwargs) as strm: @@ -2337,13 +2356,13 @@ class Path: return posixpath.dirname(path.at.rstrip("/")) == self.at.rstrip("/") def _next(self, at): - return Path(self.root, at) + return self.__class__(self.root, at) def is_dir(self): return not self.at or self.at.endswith("/") def is_file(self): - return not self.is_dir() + return self.exists() and not self.is_dir() def exists(self): return self.at in self.root._name_set() @@ -2368,6 +2387,8 @@ class Path: @property def parent(self): + if not self.at: + return self.filename.parent parent_at = posixpath.dirname(self.at.rstrip('/')) if parent_at: parent_at += '/' |