1
1
"""Utility class to inspect an extracted wheel directory"""
2
2
import glob
3
3
import os
4
+ import stat
4
5
import zipfile
5
6
from typing import Dict , Optional , Set
6
7
7
8
import pkg_resources
8
9
import pkginfo
9
10
10
11
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
+
11
27
class Wheel :
12
28
"""Representation of the compressed .whl file"""
13
29
@@ -43,6 +59,19 @@ def dependencies(self, extras_requested: Optional[Set[str]] = None) -> Set[str]:
43
59
def unzip (self , directory : str ) -> None :
44
60
with zipfile .ZipFile (self .path , "r" ) as whl :
45
61
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 )
46
75
47
76
48
77
def get_dist_info (wheel_dir : str ) -> str :
0 commit comments