Skip to content

Commit d47c554

Browse files
authored
Merge pull request #1 from abravalheri/avoid-overriding-zipfile
Avoid overriding zipfile
2 parents 069735f + c9d369c commit d47c554

File tree

3 files changed

+35
-40
lines changed

3 files changed

+35
-40
lines changed

setuptools/archive_util.py

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -100,29 +100,37 @@ def unpack_zipfile(filename, extract_dir, progress_filter=default_filter):
100100
raise UnrecognizedFormat("%s is not a zip file" % (filename,))
101101

102102
with zipfile.ZipFile(filename) as z:
103-
for info in z.infolist():
104-
name = info.filename
103+
_unpack_zipfile_obj(z, extract_dir, progress_filter)
105104

106-
# don't extract absolute paths or ones with .. in them
107-
if name.startswith('/') or '..' in name.split('/'):
108-
continue
109105

110-
target = os.path.join(extract_dir, *name.split('/'))
111-
target = progress_filter(name, target)
112-
if not target:
113-
continue
114-
if name.endswith('/'):
115-
# directory
116-
ensure_directory(target)
117-
else:
118-
# file
119-
ensure_directory(target)
120-
data = z.read(info.filename)
121-
with open(target, 'wb') as f:
122-
f.write(data)
123-
unix_attributes = info.external_attr >> 16
124-
if unix_attributes:
125-
os.chmod(target, unix_attributes)
106+
def _unpack_zipfile_obj(zipfile_obj, extract_dir, progress_filter=default_filter):
107+
"""Internal/private API used by other parts of setuptools.
108+
Similar to ``unpack_zipfile``, but receives an already opened :obj:`zipfile.ZipFile`
109+
object instead of a filename.
110+
"""
111+
for info in zipfile_obj.infolist():
112+
name = info.filename
113+
114+
# don't extract absolute paths or ones with .. in them
115+
if name.startswith('/') or '..' in name.split('/'):
116+
continue
117+
118+
target = os.path.join(extract_dir, *name.split('/'))
119+
target = progress_filter(name, target)
120+
if not target:
121+
continue
122+
if name.endswith('/'):
123+
# directory
124+
ensure_directory(target)
125+
else:
126+
# file
127+
ensure_directory(target)
128+
data = zipfile_obj.read(info.filename)
129+
with open(target, 'wb') as f:
130+
f.write(data)
131+
unix_attributes = info.external_attr >> 16
132+
if unix_attributes:
133+
os.chmod(target, unix_attributes)
126134

127135

128136
def _resolve_tar_file_or_dir(tar_obj, tar_member_obj):

setuptools/tests/test_wheel.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ def sys_tags():
618618
'onnxruntime-0.1.2-cp36-cp36m-manylinux1_x86_64.whl').is_compatible()
619619

620620

621-
@pytest.mark.skipif(sys.platform == 'win32', reason='non-Windows only')
622621
def test_wheel_mode():
623622
@contextlib.contextmanager
624623
def build_wheel(extra_file_defs=None, **kwargs):
@@ -699,4 +698,6 @@ def build_wheel(extra_file_defs=None, **kwargs):
699698
base = pathlib.Path(install_dir) / w.egg_name()
700699
script_sh = base / "EGG-INFO" / "scripts" / "script.sh"
701700
assert script_sh.exists()
702-
assert oct(stat.S_IMODE(script_sh.stat().st_mode)) == "0o777"
701+
if sys.platform != 'win32':
702+
# Editable file mode has no effect on Windows
703+
assert oct(stat.S_IMODE(script_sh.stat().st_mode)) == "0o777"

setuptools/wheel.py

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from setuptools.extern.packaging.tags import sys_tags
1616
from setuptools.extern.packaging.utils import canonicalize_name
1717
from setuptools.command.egg_info import write_requirements
18+
from setuptools.archive_util import _unpack_zipfile_obj
1819

1920

2021
WHEEL_NAME = re.compile(
@@ -27,20 +28,6 @@
2728
"__import__('pkg_resources').declare_namespace(__name__)\n"
2829

2930

30-
class ZipFilePreserveMode(zipfile.ZipFile):
31-
""" Extended ZipFile class to preserve file mode """
32-
def _extract_member(self, member, targetpath, pwd):
33-
if not isinstance(member, zipfile.ZipInfo):
34-
member = self.getinfo(member)
35-
36-
targetpath = super()._extract_member(member, targetpath, pwd)
37-
38-
attr = member.external_attr >> 16
39-
if attr != 0:
40-
os.chmod(targetpath, attr)
41-
return targetpath
42-
43-
4431
def unpack(src_dir, dst_dir):
4532
'''Move everything under `src_dir` to `dst_dir`, and delete the former.'''
4633
for dirpath, dirnames, filenames in os.walk(src_dir):
@@ -105,7 +92,7 @@ def get_dist_info(self, zf):
10592

10693
def install_as_egg(self, destination_eggdir):
10794
'''Install wheel as an egg directory.'''
108-
with ZipFilePreserveMode(self.filename) as zf:
95+
with zipfile.ZipFile(self.filename) as zf:
10996
self._install_as_egg(destination_eggdir, zf)
11097

11198
def _install_as_egg(self, destination_eggdir, zf):
@@ -135,8 +122,7 @@ def get_metadata(name):
135122
raise ValueError(
136123
'unsupported wheel format version: %s' % wheel_version)
137124
# Extract to target directory.
138-
os.mkdir(destination_eggdir)
139-
zf.extractall(destination_eggdir)
125+
_unpack_zipfile_obj(zf, destination_eggdir)
140126
# Convert metadata.
141127
dist_info = os.path.join(destination_eggdir, dist_info)
142128
dist = pkg_resources.Distribution.from_location(

0 commit comments

Comments
 (0)