Skip to content

Commit 76b221e

Browse files
authored
fix: requires_file preserves extras that package depends on (#2807)
When requirements are passed in through `requires_file` the extras are not preserved. eg if the contents of requires file is `example[extras]==1.1.1`, bazel will currently write to the METADATA file `Requires-Dist: example==1.1.1`. This PR attempts to fix that by adding that back if there are any extras. The expected output should be `Requires-Dist: example[extras]==1.1.1`
1 parent 189e30d commit 76b221e

File tree

5 files changed

+87
-5
lines changed

5 files changed

+87
-5
lines changed

.bazelrc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
# (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it)
55
# To update these lines, execute
66
# `bazel run @rules_bazel_integration_test//tools:update_deleted_packages`
7-
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
8-
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/pythonconfig,gazelle/python/private,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
7+
build --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/python/private,gazelle/pythonconfig,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
8+
query --deleted_packages=examples/build_file_generation,examples/build_file_generation/random_number_generator,examples/bzlmod,examples/bzlmod/entry_points,examples/bzlmod/entry_points/tests,examples/bzlmod/libs/my_lib,examples/bzlmod/other_module,examples/bzlmod/other_module/other_module/pkg,examples/bzlmod/patches,examples/bzlmod/py_proto_library,examples/bzlmod/py_proto_library/example.com/another_proto,examples/bzlmod/py_proto_library/example.com/proto,examples/bzlmod/runfiles,examples/bzlmod/tests,examples/bzlmod/tests/other_module,examples/bzlmod/whl_mods,examples/bzlmod_build_file_generation,examples/bzlmod_build_file_generation/other_module/other_module/pkg,examples/bzlmod_build_file_generation/runfiles,examples/multi_python_versions/libs/my_lib,examples/multi_python_versions/requirements,examples/multi_python_versions/tests,examples/pip_parse,examples/pip_parse_vendored,examples/pip_repository_annotations,examples/py_proto_library,examples/py_proto_library/example.com/another_proto,examples/py_proto_library/example.com/proto,gazelle,gazelle/manifest,gazelle/manifest/generate,gazelle/manifest/hasher,gazelle/manifest/test,gazelle/modules_mapping,gazelle/python,gazelle/python/private,gazelle/pythonconfig,tests/integration/compile_pip_requirements,tests/integration/compile_pip_requirements_test_from_external_repo,tests/integration/custom_commands,tests/integration/ignore_root_user_error,tests/integration/ignore_root_user_error/submodule,tests/integration/local_toolchains,tests/integration/pip_parse,tests/integration/pip_parse/empty,tests/integration/py_cc_toolchain_registered,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma
99

1010
test --test_output=errors
1111

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ END_UNRELEASED_TEMPLATE
7474
* The {obj}`//python/runtime_env_toolchains:all` toolchain now works with it.
7575
* (rules) Better handle flakey platform.win32_ver() calls by calling them
7676
multiple times.
77+
* (tools/wheelmaker.py) Extras are now preserved in Requires-Dist metadata when using requires_file
78+
to specify the requirements.
7779

7880
{#v0-0-0-added}
7981
### Added

examples/wheel/BUILD.bazel

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,17 @@ wheel; python_version == "3.11" or python_version == "3.12" # Example comment
313313
""".splitlines(),
314314
)
315315

316+
write_file(
317+
name = "requires_dist_depends_on_extras_file",
318+
out = "requires_dist_depends_on_extras.txt",
319+
content = """\
320+
# Requirements file
321+
--index-url https://pypi.com
322+
323+
extra_requires[example]==0.0.1
324+
""".splitlines(),
325+
)
326+
316327
# py_wheel can use text files to specify their requirements. This
317328
# can be convenient for users of `compile_pip_requirements` who have
318329
# granular `requirements.in` files per package. This target shows
@@ -374,6 +385,22 @@ py_wheel(
374385
deps = [":example_pkg"],
375386
)
376387

388+
py_wheel(
389+
name = "requires_dist_depends_on_extras",
390+
distribution = "requires_dist_depends_on_extras",
391+
requires = [
392+
"extra_requires[example]==0.0.1",
393+
],
394+
version = "0.0.1",
395+
)
396+
397+
py_wheel(
398+
name = "requires_dist_depends_on_extras_using_file",
399+
distribution = "requires_dist_depends_on_extras_using_file",
400+
requires_file = ":requires_dist_depends_on_extras.txt",
401+
version = "0.0.1",
402+
)
403+
377404
py_test(
378405
name = "wheel_test",
379406
srcs = ["wheel_test.py"],
@@ -391,6 +418,8 @@ py_test(
391418
":minimal_with_py_package",
392419
":python_abi3_binary_wheel",
393420
":python_requires_in_a_package",
421+
":requires_dist_depends_on_extras",
422+
":requires_dist_depends_on_extras_using_file",
394423
":requires_files",
395424
":use_rule_with_dir_in_outs",
396425
],

examples/wheel/wheel_test.py

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,56 @@ def test_extra_requires(self):
565565
requires,
566566
)
567567

568+
def test_requires_dist_depends_on_extras(self):
569+
filename = self._get_path("requires_dist_depends_on_extras-0.0.1-py3-none-any.whl")
570+
571+
with zipfile.ZipFile(filename) as zf:
572+
self.assertAllEntriesHasReproducibleMetadata(zf)
573+
metadata_file = None
574+
for f in zf.namelist():
575+
if os.path.basename(f) == "METADATA":
576+
metadata_file = f
577+
self.assertIsNotNone(metadata_file)
578+
579+
requires = []
580+
with zf.open(metadata_file) as fp:
581+
for line in fp:
582+
if line.startswith(b"Requires-Dist:"):
583+
requires.append(line.decode("utf-8").strip())
584+
585+
print(requires)
586+
self.assertEqual(
587+
[
588+
"Requires-Dist: extra_requires[example]==0.0.1",
589+
],
590+
requires,
591+
)
592+
593+
def test_requires_dist_depends_on_extras_file(self):
594+
filename = self._get_path("requires_dist_depends_on_extras_using_file-0.0.1-py3-none-any.whl")
595+
596+
with zipfile.ZipFile(filename) as zf:
597+
self.assertAllEntriesHasReproducibleMetadata(zf)
598+
metadata_file = None
599+
for f in zf.namelist():
600+
if os.path.basename(f) == "METADATA":
601+
metadata_file = f
602+
self.assertIsNotNone(metadata_file)
603+
604+
requires = []
605+
with zf.open(metadata_file) as fp:
606+
for line in fp:
607+
if line.startswith(b"Requires-Dist:"):
608+
requires.append(line.decode("utf-8").strip())
609+
610+
print(requires)
611+
self.assertEqual(
612+
[
613+
"Requires-Dist: extra_requires[example]==0.0.1",
614+
],
615+
requires,
616+
)
617+
568618

569619
if __name__ == "__main__":
570620
unittest.main()

tools/wheelmaker.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -562,13 +562,14 @@ def main() -> None:
562562

563563
def get_new_requirement_line(reqs_text, extra):
564564
req = Requirement(reqs_text.strip())
565+
req_extra_deps = f"[{','.join(req.extras)}]" if req.extras else ""
565566
if req.marker:
566567
if extra:
567-
return f"Requires-Dist: {req.name}{req.specifier}; ({req.marker}) and {extra}"
568+
return f"Requires-Dist: {req.name}{req_extra_deps}{req.specifier}; ({req.marker}) and {extra}"
568569
else:
569-
return f"Requires-Dist: {req.name}{req.specifier}; {req.marker}"
570+
return f"Requires-Dist: {req.name}{req_extra_deps}{req.specifier}; {req.marker}"
570571
else:
571-
return f"Requires-Dist: {req.name}{req.specifier}; {extra}".strip(" ;")
572+
return f"Requires-Dist: {req.name}{req_extra_deps}{req.specifier}; {extra}".strip(" ;")
572573

573574
for meta_line in metadata.splitlines():
574575
if not meta_line.startswith("Requires-Dist: "):

0 commit comments

Comments
 (0)