Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 229b03c

Browse filesBrowse files
Modify wheel#unzip to preserve file execute permissions. (bazel-contrib#46)
1 parent 536653b commit 229b03c
Copy full SHA for 229b03c

File tree

2 files changed

+30
-3
lines changed
Filter options

2 files changed

+30
-3
lines changed

‎extract_wheels/__init__.py

Copy file name to clipboardExpand all lines: extract_wheels/__init__.py
+1-3Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,7 @@ def main() -> None:
6767

6868
pip_args = [sys.executable, "-m", "pip", "wheel", "-r", args.requirements]
6969
# Assumes any errors are logged by pip so do nothing. This command will fail if pip fails
70-
subprocess.check_output(
71-
pip_args
72-
)
70+
subprocess.check_output(pip_args)
7371

7472
extras = requirements.parse_extras(args.requirements)
7573

‎extract_wheels/lib/wheel.py

Copy file name to clipboardExpand all lines: extract_wheels/lib/wheel.py
+29Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
11
"""Utility class to inspect an extracted wheel directory"""
22
import glob
33
import os
4+
import stat
45
import zipfile
56
from typing import Dict, Optional, Set
67

78
import pkg_resources
89
import pkginfo
910

1011

12+
def current_umask() -> int:
13+
"""Get the current umask which involves having to set it temporarily."""
14+
mask = os.umask(0)
15+
os.umask(mask)
16+
return mask
17+
18+
19+
def set_extracted_file_to_default_mode_plus_executable(path: str) -> None:
20+
"""
21+
Make file present at path have execute for user/group/world
22+
(chmod +x) is no-op on windows per python docs
23+
"""
24+
os.chmod(path, (0o777 & ~current_umask() | 0o111))
25+
26+
1127
class Wheel:
1228
"""Representation of the compressed .whl file"""
1329

@@ -43,6 +59,19 @@ def dependencies(self, extras_requested: Optional[Set[str]] = None) -> Set[str]:
4359
def unzip(self, directory: str) -> None:
4460
with zipfile.ZipFile(self.path, "r") as whl:
4561
whl.extractall(directory)
62+
# The following logic is borrowed from Pip:
63+
# https://github.com/pypa/pip/blob/cc48c07b64f338ac5e347d90f6cb4efc22ed0d0b/src/pip/_internal/utils/unpacking.py#L240
64+
for info in whl.infolist():
65+
name = info.filename
66+
# Do not attempt to modify directories.
67+
if name.endswith("/") or name.endswith("\\"):
68+
continue
69+
mode = info.external_attr >> 16
70+
# if mode and regular file and any execute permissions for
71+
# user/group/world?
72+
if mode and stat.S_ISREG(mode) and mode & 0o111:
73+
name = os.path.join(directory, name)
74+
set_extracted_file_to_default_mode_plus_executable(name)
4675

4776

4877
def get_dist_info(wheel_dir: str) -> str:

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.