Skip to content

Commit bf614c9

Browse files
jaracomiss-islington
authored andcommitted
pythongh-135276: Refresh zipfile.Path from zipp 3.23 (pythonGH-135277)
Apply changes from zipp 3.23 (cherry picked from commit 8d6eb0c) Co-authored-by: Jason R. Coombs <jaraco@jaraco.com>
1 parent 0a8fbb3 commit bf614c9

File tree

8 files changed

+64
-28
lines changed

8 files changed

+64
-28
lines changed

Lib/test/test_zipfile/_path/_test_params.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import types
21
import functools
2+
import types
33

44
from ._itertools import always_iterable
55

Lib/test/test_zipfile/_path/test_complexity.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,8 @@
88

99
from ._functools import compose
1010
from ._itertools import consume
11-
1211
from ._support import import_or_skip
1312

14-
1513
big_o = import_or_skip('big_o')
1614
pytest = import_or_skip('pytest')
1715

Lib/test/test_zipfile/_path/test_path.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import contextlib
12
import io
23
import itertools
3-
import contextlib
44
import pathlib
55
import pickle
66
import stat
@@ -10,12 +10,11 @@
1010
import zipfile
1111
import zipfile._path
1212

13-
from test.support.os_helper import temp_dir, FakePath
13+
from test.support.os_helper import FakePath, temp_dir
1414

1515
from ._functools import compose
1616
from ._itertools import Counter
17-
18-
from ._test_params import parameterize, Invoked
17+
from ._test_params import Invoked, parameterize
1918

2019

2120
class jaraco:
@@ -194,10 +193,10 @@ def test_encoding_warnings(self, alpharep):
194193
"""EncodingWarning must blame the read_text and open calls."""
195194
assert sys.flags.warn_default_encoding
196195
root = zipfile.Path(alpharep)
197-
with self.assertWarns(EncodingWarning) as wc:
196+
with self.assertWarns(EncodingWarning) as wc: # noqa: F821 (astral-sh/ruff#13296)
198197
root.joinpath("a.txt").read_text()
199198
assert __file__ == wc.filename
200-
with self.assertWarns(EncodingWarning) as wc:
199+
with self.assertWarns(EncodingWarning) as wc: # noqa: F821 (astral-sh/ruff#13296)
201200
root.joinpath("a.txt").open("r").close()
202201
assert __file__ == wc.filename
203202

@@ -365,6 +364,17 @@ def test_root_name(self, alpharep):
365364
root = zipfile.Path(alpharep)
366365
assert root.name == 'alpharep.zip' == root.filename.name
367366

367+
@pass_alpharep
368+
def test_root_on_disk(self, alpharep):
369+
"""
370+
The name/stem of the root should match the zipfile on disk.
371+
372+
This condition must hold across platforms.
373+
"""
374+
root = zipfile.Path(self.zipfile_ondisk(alpharep))
375+
assert root.name == 'alpharep.zip' == root.filename.name
376+
assert root.stem == 'alpharep' == root.filename.stem
377+
368378
@pass_alpharep
369379
def test_suffix(self, alpharep):
370380
"""
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
11
from . import test_path
22

3-
43
__name__ == '__main__' and test_path.build_alpharep_fixture().extractall('alpharep')

Lib/zipfile/_path/__init__.py

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,19 @@
77
for more detail.
88
"""
99

10+
import functools
1011
import io
11-
import posixpath
12-
import zipfile
1312
import itertools
14-
import contextlib
1513
import pathlib
14+
import posixpath
1615
import re
1716
import stat
1817
import sys
18+
import zipfile
1919

20+
from ._functools import save_method_args
2021
from .glob import Translator
2122

22-
2323
__all__ = ['Path']
2424

2525

@@ -86,13 +86,12 @@ class InitializedState:
8686
Mix-in to save the initialization state for pickling.
8787
"""
8888

89+
@save_method_args
8990
def __init__(self, *args, **kwargs):
90-
self.__args = args
91-
self.__kwargs = kwargs
9291
super().__init__(*args, **kwargs)
9392

9493
def __getstate__(self):
95-
return self.__args, self.__kwargs
94+
return self._saved___init__.args, self._saved___init__.kwargs
9695

9796
def __setstate__(self, state):
9897
args, kwargs = state
@@ -181,22 +180,27 @@ class FastLookup(CompleteDirs):
181180
"""
182181

183182
def namelist(self):
184-
with contextlib.suppress(AttributeError):
185-
return self.__names
186-
self.__names = super().namelist()
187-
return self.__names
183+
return self._namelist
184+
185+
@functools.cached_property
186+
def _namelist(self):
187+
return super().namelist()
188188

189189
def _name_set(self):
190-
with contextlib.suppress(AttributeError):
191-
return self.__lookup
192-
self.__lookup = super()._name_set()
193-
return self.__lookup
190+
return self._name_set_prop
191+
192+
@functools.cached_property
193+
def _name_set_prop(self):
194+
return super()._name_set()
194195

195196

196197
def _extract_text_encoding(encoding=None, *args, **kwargs):
197198
# compute stack level so that the caller of the caller sees any warning.
198199
is_pypy = sys.implementation.name == 'pypy'
199-
stack_level = 3 + is_pypy
200+
# PyPy no longer special cased after 7.3.19 (or maybe 7.3.18)
201+
# See jaraco/zipp#143
202+
is_old_pypi = is_pypy and sys.pypy_version_info < (7, 3, 19)
203+
stack_level = 3 + is_old_pypi
200204
return io.text_encoding(encoding, stack_level), args, kwargs
201205

202206

@@ -351,7 +355,7 @@ def open(self, mode='r', *args, pwd=None, **kwargs):
351355
return io.TextIOWrapper(stream, encoding, *args, **kwargs)
352356

353357
def _base(self):
354-
return pathlib.PurePosixPath(self.at or self.root.filename)
358+
return pathlib.PurePosixPath(self.at) if self.at else self.filename
355359

356360
@property
357361
def name(self):

Lib/zipfile/_path/_functools.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import collections
2+
import functools
3+
4+
5+
# from jaraco.functools 4.0.2
6+
def save_method_args(method):
7+
"""
8+
Wrap a method such that when it is called, the args and kwargs are
9+
saved on the method.
10+
"""
11+
args_and_kwargs = collections.namedtuple('args_and_kwargs', 'args kwargs') # noqa: PYI024
12+
13+
@functools.wraps(method)
14+
def wrapper(self, /, *args, **kwargs):
15+
attr_name = '_saved_' + method.__name__
16+
attr = args_and_kwargs(args, kwargs)
17+
setattr(self, attr_name, attr)
18+
return method(self, *args, **kwargs)
19+
20+
return wrapper

Lib/zipfile/_path/glob.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import os
22
import re
33

4-
54
_default_seps = os.sep + str(os.altsep) * bool(os.altsep)
65

76

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Synchronized zipfile.Path with zipp 3.23, including improved performance of
2+
:meth:`zipfile.Path.open` for non-reading modes, rely on
3+
:func:`functools.cached_property` to cache values on the instance. Rely on
4+
``save_method_args`` to save the initialization method arguments. Fixed
5+
``.name``, ``.stem`` and other basename-based properties on Windows when
6+
working with a zipfile on disk.

0 commit comments

Comments
 (0)