Skip to content

Commit 73cdd55

Browse files
authored
Merge pull request #142 from jaraco/backport-gh-123429
Backport python/cpython#123429
2 parents c33aedc + 2c3c6b5 commit 73cdd55

3 files changed

Lines changed: 37 additions & 20 deletions

File tree

newsfragments/142.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Backported simplified tests from python/cpython#123424.

tests/compat/py313.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import os
2+
import sys
3+
import time
4+
5+
6+
def _for_archive(self, archive):
7+
"""Resolve suitable defaults from the archive.
8+
9+
Resolve the date_time, compression attributes, and external attributes
10+
to suitable defaults as used by :method:`ZipFile.writestr`.
11+
12+
Return self.
13+
"""
14+
# gh-91279: Set the SOURCE_DATE_EPOCH to a specific timestamp
15+
epoch = os.environ.get('SOURCE_DATE_EPOCH')
16+
get_time = int(epoch) if epoch else time.time()
17+
self.date_time = time.localtime(get_time)[:6]
18+
19+
self.compress_type = archive.compression
20+
self.compress_level = archive.compresslevel
21+
if self.filename.endswith('/'): # pragma: no cover
22+
self.external_attr = 0o40775 << 16 # drwxrwxr-x
23+
self.external_attr |= 0x10 # MS-DOS directory flag
24+
else:
25+
self.external_attr = 0o600 << 16 # ?rw-------
26+
return self
27+
28+
29+
ForArchive = type(
30+
'ForArchive',
31+
(),
32+
dict(_for_archive=_for_archive) if sys.version_info < (3, 14) else dict(),
33+
)

tests/test_path.py

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import pickle
66
import stat
77
import sys
8-
import time
98
import unittest
109

1110
import jaraco.itertools
@@ -15,6 +14,7 @@
1514

1615
from ._test_params import Invoked, parameterize
1716
from .compat.py39.os_helper import FakePath, temp_dir # type: ignore[import-not-found]
17+
from .compat.py313 import ForArchive
1818

1919

2020
def _make_link(info: zipfile.ZipInfo): # type: ignore[name-defined]
@@ -628,7 +628,7 @@ def test_backslash_not_separator(self):
628628
"""
629629
data = io.BytesIO()
630630
zf = zipfile.ZipFile(data, "w")
631-
zf.writestr(DirtyZipInfo.for_name("foo\\bar", zf), b"content")
631+
zf.writestr(DirtyZipInfo("foo\\bar")._for_archive(zf), b"content")
632632
zf.filename = ''
633633
root = zipfile.Path(zf)
634634
(first,) = root.iterdir()
@@ -643,28 +643,11 @@ def test_interface(self, alpharep):
643643
assert isinstance(zf, Traversable)
644644

645645

646-
class DirtyZipInfo(zipfile.ZipInfo):
646+
class DirtyZipInfo(zipfile.ZipInfo, ForArchive):
647647
"""
648648
Bypass name sanitization.
649649
"""
650650

651651
def __init__(self, filename, *args, **kwargs):
652652
super().__init__(filename, *args, **kwargs)
653653
self.filename = filename
654-
655-
@classmethod
656-
def for_name(cls, name, archive):
657-
"""
658-
Construct the same way that ZipFile.writestr does.
659-
660-
TODO: extract this functionality and re-use
661-
"""
662-
self = cls(filename=name, date_time=time.localtime(time.time())[:6])
663-
self.compress_type = archive.compression
664-
self.compress_level = archive.compresslevel
665-
if self.filename.endswith('/'): # pragma: no cover
666-
self.external_attr = 0o40775 << 16 # drwxrwxr-x
667-
self.external_attr |= 0x10 # MS-DOS directory flag
668-
else:
669-
self.external_attr = 0o600 << 16 # ?rw-------
670-
return self

0 commit comments

Comments
 (0)