@@ -17,26 +17,15 @@ def __init__(self, stderr, output_file):
1717 # by looking at the directory structure.
1818 def dig_wheel (self , whl ):
1919 mapping = {}
20- wheel_name = get_wheel_name (whl )
2120 with zipfile .ZipFile (whl , "r" ) as zip_file :
2221 for path in zip_file .namelist ():
2322 if is_metadata (path ):
24- continue
25- ext = pathlib .Path (path ).suffix
26- if ext == ".py" or ext == ".so" :
27- # Note the '/' here means that the __init__.py is not in the
28- # root of the wheel, therefore we can index the directory
29- # where this file is as an importable package.
30- if path .endswith ("/__init__.py" ):
31- module = path [: - len ("/__init__.py" )].replace ("/" , "." )
32- mapping [module ] = wheel_name
33- # Always index the module file.
34- if ext == ".so" :
35- # Also remove extra metadata that is embeded as part of
36- # the file name as an extra extension.
37- ext = "" .join (pathlib .Path (path ).suffixes )
38- module = path [: - len (ext )].replace ("/" , "." )
39- mapping [module ] = wheel_name
23+ if data_has_purelib_or_platlib (path ):
24+ module_for_path (path , whl , mapping )
25+ else :
26+ continue
27+ else :
28+ module_for_path (path , whl , mapping )
4029 return mapping
4130
4231 # run is the entrypoint for the generator.
@@ -73,6 +62,44 @@ def is_metadata(path):
7362 return top_level .endswith (".dist-info" ) or top_level .endswith (".data" )
7463
7564
65+ # The .data is allowed to contain a full purelib or platlib directory
66+ # These get unpacked into site-packages, so require indexing too.
67+ # This is the same if "Root-Is-Purelib: true" is set and the files are at the root.
68+ # Ref: https://peps.python.org/pep-0427/#what-s-the-deal-with-purelib-vs-platlib
69+ def data_has_purelib_or_platlib (path ):
70+ maybe_lib = path .split ("/" )[1 ].lower ()
71+ return is_metadata (path ) and (
72+ maybe_lib == "purelib" or maybe_lib == "platlib"
73+ )
74+
75+
76+
77+ def module_for_path (path , whl , mapping ):
78+ ext = pathlib .Path (path ).suffix
79+ if ext == ".py" or ext == ".so" :
80+ if "purelib" in path or "platlib" in path :
81+ root = "/" .join (path .split ("/" )[2 :])
82+ else :
83+ root = path
84+
85+ wheel_name = get_wheel_name (whl )
86+
87+ if root .endswith ("/__init__.py" ):
88+ # Note the '/' here means that the __init__.py is not in the
89+ # root of the wheel, therefore we can index the directory
90+ # where this file is as an importable package.
91+ module = root [: - len ("/__init__.py" )].replace ("/" , "." )
92+ mapping [module ] = wheel_name
93+
94+ # Always index the module file.
95+ if ext == ".so" :
96+ # Also remove extra metadata that is embeded as part of
97+ # the file name as an extra extension.
98+ ext = '' .join (pathlib .Path (root ).suffixes )
99+ module = root [: - len (ext )].replace ("/" , "." )
100+ mapping [module ] = wheel_name
101+
102+
76103if __name__ == "__main__" :
77104 output_file = sys .argv [1 ]
78105 wheels = sys .argv [2 :]
0 commit comments