Skip to content

Commit c9b70d1

Browse files
mattemalexeagle
andauthored
fix(gazelle): handle purelib and platlib packages that don't set 'Root-Is-Purelib: true' (bazel-contrib#768)
Co-authored-by: Alex Eagle <alex@aspect.dev>
1 parent 0609001 commit c9b70d1

File tree

1 file changed

+44
-17
lines changed

1 file changed

+44
-17
lines changed

gazelle/modules_mapping/generator.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
76103
if __name__ == "__main__":
77104
output_file = sys.argv[1]
78105
wheels = sys.argv[2:]

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy