Skip to content

Commit ee7c54b

Browse files
authored
chore: always use starlark-based extraction for wheels (bazel-contrib#3748)
Currently, the Python `installer` library is used for extracting a wheel when Bazel 7 is used. This library only outputs platform-specific extractions, and it was hard-coded to use a unixy style install. This ends up hiding Windows `pythonw`-based scripts and entry points because those are normalized to simply `python` on unix. To fix, use the Starlark-based extraction logic instead. This is a simpler implementation that extracts the wheels mostly as-is, which allows build-phase logic to handle platform-specific differences. This also makes the Starlark based extraction work for Bazel 8.3 and earlier, which previously didn't support it.
1 parent b87cf67 commit ee7c54b

10 files changed

Lines changed: 10 additions & 323 deletions

File tree

python/private/pypi/whl_installer/BUILD.bazel

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ py_library(
55
name = "lib",
66
srcs = [
77
"arguments.py",
8-
"wheel.py",
98
"wheel_installer.py",
109
],
1110
visibility = [

python/private/pypi/whl_installer/arguments.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,6 @@ def parser(**kwargs: Any) -> argparse.ArgumentParser:
5555
help="Use 'pip download' instead of 'pip wheel'. Disables building wheels from source, but allows use of "
5656
"--platform, --python-version, --implementation, and --abi in --extra_pip_args.",
5757
)
58-
parser.add_argument(
59-
"--whl-file",
60-
type=pathlib.Path,
61-
help="Extract a whl file to be used within Bazel.",
62-
)
6358
return parser
6459

6560

python/private/pypi/whl_installer/wheel.py

Lines changed: 0 additions & 105 deletions
This file was deleted.

python/private/pypi/whl_installer/wheel_installer.py

Lines changed: 1 addition & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,7 @@
2525
from tempfile import NamedTemporaryFile
2626
from typing import Dict, List, Optional, Set, Tuple
2727

28-
from pip._vendor.packaging.utils import canonicalize_name
29-
30-
from python.private.pypi.whl_installer import arguments, wheel
28+
from python.private.pypi.whl_installer import arguments
3129

3230

3331
def _configure_reproducible_wheels() -> None:
@@ -55,63 +53,13 @@ def _configure_reproducible_wheels() -> None:
5553
os.environ["PYTHONHASHSEED"] = "0"
5654

5755

58-
def _parse_requirement_for_extra(
59-
requirement: str,
60-
) -> Tuple[Optional[str], Optional[Set[str]]]:
61-
"""Given a requirement string, returns the requirement name and set of extras, if extras specified.
62-
Else, returns (None, None)
63-
"""
64-
65-
# https://www.python.org/dev/peps/pep-0508/#grammar
66-
extras_pattern = re.compile(
67-
r"^\s*([0-9A-Za-z][0-9A-Za-z_.\-]*)\s*\[\s*([0-9A-Za-z][0-9A-Za-z_.\-]*(?:\s*,\s*[0-9A-Za-z][0-9A-Za-z_.\-]*)*)\s*\]"
68-
)
69-
70-
matches = extras_pattern.match(requirement)
71-
if matches:
72-
return (
73-
canonicalize_name(matches.group(1)),
74-
{extra.strip() for extra in matches.group(2).split(",")},
75-
)
76-
77-
return None, None
78-
79-
80-
def _extract_wheel(
81-
wheel_file: str,
82-
extras: Dict[str, Set[str]],
83-
installation_dir: Path = Path("."),
84-
) -> None:
85-
"""Extracts wheel into given directory and creates py_library and filegroup targets.
86-
87-
Args:
88-
wheel_file: the filepath of the .whl
89-
installation_dir: the destination directory for installation of the wheel.
90-
extras: a list of extras to add as dependencies for the installed wheel
91-
"""
92-
93-
whl = wheel.Wheel(wheel_file)
94-
whl.unzip(installation_dir)
95-
96-
9756
def main() -> None:
9857
args = arguments.parser(description=__doc__).parse_args()
9958
deserialized_args = dict(vars(args))
10059
arguments.deserialize_structured_args(deserialized_args)
10160

10261
_configure_reproducible_wheels()
10362

104-
if args.whl_file:
105-
whl = Path(args.whl_file)
106-
107-
name, extras_for_pkg = _parse_requirement_for_extra(args.requirement)
108-
extras = {name: extras_for_pkg} if extras_for_pkg and name else dict()
109-
_extract_wheel(
110-
wheel_file=whl,
111-
extras=extras,
112-
)
113-
return
114-
11563
pip_args = (
11664
[sys.executable, "-m", "pip"]
11765
+ (["--isolated"] if args.isolated else [])

python/private/pypi/whl_library.bzl

Lines changed: 7 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
""
1616

17-
load("@rules_python_internal//:rules_python_config.bzl", rp_config = "config")
1817
load("//python/private:auth.bzl", "AUTH_ATTRS", "get_auth")
1918
load("//python/private:envsubst.bzl", "envsubst")
2019
load("//python/private:is_standalone_interpreter.bzl", "is_standalone_interpreter")
@@ -261,22 +260,6 @@ def _create_repository_execution_environment(rctx, python_interpreter, logger =
261260
env[_CPPFLAGS] = " ".join(cppflags)
262261
return env
263262

264-
def _extract_whl_py(rctx, *, python_interpreter, args, whl_path, environment, logger):
265-
pypi_repo_utils.execute_checked(
266-
rctx,
267-
op = "whl_library.ExtractWheel({}, {})".format(rctx.attr.name, whl_path),
268-
python = python_interpreter,
269-
arguments = args + [
270-
"--whl-file",
271-
whl_path,
272-
],
273-
srcs = rctx.attr._python_srcs,
274-
environment = environment,
275-
quiet = rctx.attr.quiet,
276-
timeout = rctx.attr.timeout,
277-
logger = logger,
278-
)
279-
280263
def _get_entry_points(rctx, install_dir_path, metadata):
281264
dist_info_dir = "{}-{}.dist-info".format(
282265
metadata.name.replace("-", "_"),
@@ -376,11 +359,10 @@ def _whl_library_impl(rctx):
376359
# build deps from PyPI (e.g. `flit_core`) if they are missing.
377360
extra_pip_args.extend(["--find-links", "."])
378361

379-
enable_pipstar_extract = rp_config.bazel_8_or_later
380-
381-
# When pipstar is enabled, Python isn't used, so there's no need
382-
# to setup env vars to run Python, unless we need to build an sdist
383-
if enable_pipstar_extract and whl_path and not rctx.attr.whl_patches:
362+
# When we already have a wheel and there are no patches, Python isn't used,
363+
# so there's no need to setup env vars to run Python, unless we need to
364+
# build an sdist or resolve a requirement.
365+
if whl_path and not rctx.attr.whl_patches:
384366
environment = {}
385367
args = []
386368
python_interpreter = None
@@ -446,17 +428,7 @@ def _whl_library_impl(rctx):
446428
timeout = rctx.attr.timeout,
447429
)
448430

449-
if enable_pipstar_extract:
450-
whl_extract(rctx, whl_path = whl_path, logger = logger)
451-
else:
452-
_extract_whl_py(
453-
rctx,
454-
python_interpreter = python_interpreter,
455-
args = args,
456-
whl_path = whl_path,
457-
environment = environment,
458-
logger = logger,
459-
)
431+
whl_extract(rctx, whl_path = whl_path, logger = logger)
460432

461433
install_dir_path = whl_path.dirname.get_child("site-packages")
462434
metadata = whl_metadata(
@@ -513,9 +485,8 @@ repo(
513485
_remove_files(rctx, "BUILD", "BUILD.bazel")
514486
rctx.file("BUILD.bazel", build_file_contents)
515487

516-
if enable_pipstar_extract:
517-
if hasattr(rctx, "repo_metadata"):
518-
return rctx.repo_metadata(reproducible = True)
488+
if hasattr(rctx, "repo_metadata"):
489+
return rctx.repo_metadata(reproducible = True)
519490

520491
return None
521492

@@ -632,7 +603,6 @@ way to define whl_library and move whl patching to a separate place. INTERNAL US
632603
"_python_srcs": attr.label_list(
633604
# Used as a default value in a rule to ensure we fetch the dependencies.
634605
default = [
635-
Label("//python/private/pypi/whl_installer:wheel.py"),
636606
Label("//python/private/pypi/whl_installer:wheel_installer.py"),
637607
Label("//python/private/pypi/whl_installer:arguments.py"),
638608
] + record_files.values(),
Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,12 @@
11
load("//python:py_test.bzl", "py_test")
22

3-
alias(
4-
name = "lib",
5-
actual = "//python/private/pypi/whl_installer:lib",
6-
)
7-
83
py_test(
94
name = "arguments_test",
105
size = "small",
116
srcs = [
127
"arguments_test.py",
138
],
149
deps = [
15-
":lib",
16-
],
17-
)
18-
19-
py_test(
20-
name = "wheel_installer_test",
21-
size = "small",
22-
srcs = [
23-
"wheel_installer_test.py",
24-
],
25-
data = ["//examples/wheel:minimal_with_py_package"],
26-
deps = [
27-
":lib",
10+
"//python/private/pypi/whl_installer:lib",
2811
],
2912
)

tests/pypi/whl_installer/arguments_test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import json
1616
import unittest
1717

18-
from python.private.pypi.whl_installer import arguments, wheel
18+
from python.private.pypi.whl_installer import arguments
1919

2020

2121
class ArgumentsTestCase(unittest.TestCase):

0 commit comments

Comments
 (0)