Skip to content

Commit 56eb36d

Browse files
committed
Merge branch 'main' of https://github.com/bazel-contrib/rules_python into feat.local.toolchains.target.settings
2 parents 362633a + ccbe5dc commit 56eb36d

37 files changed

+2054
-126
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

.editorconfig

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Unix-style newlines with a newline ending every file
2+
[*]
3+
end_of_line = lf
4+
insert_final_newline = true
5+
6+
# Set default charset
7+
[*]
8+
charset = utf-8
9+
10+
# Line width
11+
[*]
12+
max_line_length = 100
13+
14+
# 4 space indentation
15+
[*.{py,bzl}]
16+
indent_style = space
17+
indent_size = 4

CHANGELOG.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ END_UNRELEASED_TEMPLATE
5454

5555
{#v0-0-0-changed}
5656
### Changed
57+
5758
* (rules) On Windows, {obj}`--bootstrap_impl=system_python` is forced. This
5859
allows setting `--bootstrap_impl=script` in bazelrc for mixed-platform
5960
environments.
6061
* (rules) {obj}`pip_compile` now generates a `.test` target. The `_test` target is deprecated
6162
and will be removed in the next major release.
6263
([#2794](https://github.com/bazel-contrib/rules_python/issues/2794)
64+
* (py_wheel) py_wheel always creates zip64-capable wheel zips
6365

6466
{#v0-0-0-fixed}
6567
### Fixed
@@ -74,6 +76,8 @@ END_UNRELEASED_TEMPLATE
7476
* The {obj}`//python/runtime_env_toolchains:all` toolchain now works with it.
7577
* (rules) Better handle flakey platform.win32_ver() calls by calling them
7678
multiple times.
79+
* (tools/wheelmaker.py) Extras are now preserved in Requires-Dist metadata when using requires_file
80+
to specify the requirements.
7781

7882
{#v0-0-0-added}
7983
### Added
@@ -105,8 +109,6 @@ END_UNRELEASED_TEMPLATE
105109
* 3.12.9
106110
* 3.13.2
107111
* (pypi) Use `xcrun xcodebuild --showsdks` to find XCode root.
108-
* (pypi) The `bzlmod` extension will now generate smaller lock files for when
109-
using `experimental_index_url`.
110112
* (toolchains) Remove all but `3.8.20` versions of the Python `3.8` interpreter who has
111113
reached EOL. If users still need other versions of the `3.8` interpreter, please supply
112114
the URLs manually {bzl:obj}`python.toolchain` or {bzl:obj}`python_register_toolchains` calls.
@@ -122,13 +124,6 @@ END_UNRELEASED_TEMPLATE
122124
[PR #2746](https://github.com/bazel-contrib/rules_python/pull/2746).
123125
* (rules) {attr}`py_binary.srcs` and {attr}`py_test.srcs` is no longer mandatory when
124126
`main_module` is specified (for `--bootstrap_impl=script`)
125-
* (pypi) From now on the `Requires-Dist` from the wheel metadata is analysed in
126-
the loading phase instead of repository rule phase giving better caching
127-
performance when the target platforms are changed (e.g. target python
128-
versions). This is preparatory work for stabilizing the cross-platform wheel
129-
support. From now on the usage of `experimental_target_platforms` should be
130-
avoided and the `requirements_by_platform` values should be instead used to
131-
specify the target platforms for the given dependencies.
132127

133128
[20250317]: https://github.com/astral-sh/python-build-standalone/releases/tag/20250317
134129

CONTRIBUTING.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,55 @@ The `legacy_foo` arg was removed
173173
:::
174174
```
175175

176+
## Style and idioms
177+
178+
For the most part, we just accept whatever the code formatters do, so there
179+
isn't much style to enforce.
180+
181+
Some miscellanous style, idioms, and conventions we have are:
182+
183+
### Markdown/Sphinx Style
184+
185+
* Use colons for prose sections of text, e.g. `:::{note}`, not backticks.
186+
* Use backticks for code blocks.
187+
* Max line length: 100.
188+
189+
### BUILD/bzl Style
190+
191+
* When a macro generates public targets, use a dot (`.`) to separate the
192+
user-provided name from the generted name. e.g. `foo(name="x")` generates
193+
`x.test`. The `.` is our convention to communicate that it's a generated
194+
target, and thus one should look for `name="x"` when searching for the
195+
definition.
196+
* The different build phases shouldn't load code that defines objects that
197+
aren't valid for their phase. e.g.
198+
* The bzlmod phase shouldn't load code defining regular rules or providers.
199+
* The repository phase shouldn't load code defining module extensions, regular
200+
rules, or providers.
201+
* The loading phase shouldn't load code defining module extensions or
202+
repository rules.
203+
* Loading utility libraries or generic code is OK, but should strive to load
204+
code that is usable for its phase. e.g. loading-phase code shouldn't
205+
load utility code that is predominately only usable to the bzlmod phase.
206+
* Providers should be in their own files. This allows implementing a custom rule
207+
that implements the provider without loading a specific implementation.
208+
* One rule per file is preferred, but not required. The goal is that defining an
209+
e.g. library shouldn't incur loading all the code for binaries, tests,
210+
packaging, etc; things that may be niche or uncommonly used.
211+
* Separate files should be used to expose public APIs. This ensures our public
212+
API is well defined and prevents accidentally exposing a package-private
213+
symbol as a public symbol.
214+
215+
:::{note}
216+
The public API file's docstring becomes part of the user-facing docs. That
217+
file's docstring must be used for module-level API documentation.
218+
:::
219+
* Repository rules should have name ending in `_repo`. This helps distinguish
220+
them from regular rules.
221+
* Each bzlmod extension, the "X" of `use_repo("//foo:foo.bzl", "X")` should be
222+
in its own file. The path given in the `use_repo()` expression is the identity
223+
Bazel uses and cannot be changed.
224+
176225
## Generated files
177226

178227
Some checked-in files are generated and need to be updated when a new PR is

docs/environment-variables.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,19 @@ When `1`, the rules_python will warn users about deprecated functionality that w
4646
be removed in a subsequent major `rules_python` version. Defaults to `0` if unset.
4747
:::
4848

49-
:::{envvar} RULES_PYTHON_ENABLE_PYSTAR
49+
::::{envvar} RULES_PYTHON_ENABLE_PYSTAR
5050

5151
When `1`, the rules_python Starlark implementation of the core rules is used
52-
instead of the Bazel-builtin rules. Note this requires Bazel 7+.
52+
instead of the Bazel-builtin rules. Note this requires Bazel 7+. Defaults
53+
to `1`.
54+
55+
:::{versionadded} 0.26.0
56+
Defaults to `0` if unspecified.
57+
:::
58+
:::{versionchanged} 0.40.0
59+
The default became `1` if unspecified
5360
:::
61+
::::
5462

5563
::::{envvar} RULES_PYTHON_EXTRACT_ROOT
5664

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/test_publish.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ def test_upload_and_query_simple_api(self):
104104
</head>
105105
<body>
106106
<h1>Links for example-minimal-library</h1>
107-
<a href="/packages/example_minimal_library-0.0.1-py3-none-any.whl#sha256=a73acae23590c7a8d4365c888c1f12f0399b7af27169ea99fc7a00f402833926">example_minimal_library-0.0.1-py3-none-any.whl</a><br>
107+
<a href="/packages/example_minimal_library-0.0.1-py3-none-any.whl#sha256=ef5afd9f6c3ff569ef7e5b2799d3a2ec9675d029414f341e0abd7254d6b9a25d">example_minimal_library-0.0.1-py3-none-any.whl</a><br>
108108
</body>
109109
</html>"""
110110
self.assertEqual(

examples/wheel/wheel_test.py

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ def test_py_library_wheel(self):
8585
],
8686
)
8787
self.assertFileSha256Equal(
88-
filename, "a73acae23590c7a8d4365c888c1f12f0399b7af27169ea99fc7a00f402833926"
88+
filename, "ef5afd9f6c3ff569ef7e5b2799d3a2ec9675d029414f341e0abd7254d6b9a25d"
8989
)
9090

9191
def test_py_package_wheel(self):
@@ -110,7 +110,7 @@ def test_py_package_wheel(self):
110110
],
111111
)
112112
self.assertFileSha256Equal(
113-
filename, "a76001500453dbd1d778821dcaba165d56db502c854cef9381dd3f8f89caee11"
113+
filename, "39bec133cf79431e8d057eae550cd91aa9dfbddfedb53d98ebd36e3ade2753d0"
114114
)
115115

116116
def test_customized_wheel(self):
@@ -206,7 +206,7 @@ def test_customized_wheel(self):
206206
second = second.main:s""",
207207
)
208208
self.assertFileSha256Equal(
209-
filename, "941c0d79f4ca67cfa0028248bd0606db7fc69953ff9c7c73ac26a3e6d3c23587"
209+
filename, "685f68fc6665f53c9b769fd1ba12cce9937ab7f40ef4e60c82ef2de8653935de"
210210
)
211211

212212
def test_filename_escaping(self):
@@ -278,7 +278,7 @@ def test_custom_package_root_wheel(self):
278278
for line in record_contents.splitlines():
279279
self.assertFalse(line.startswith("/"))
280280
self.assertFileSha256Equal(
281-
filename, "7bd959b7efe9e325b30a6559177a1a4f22ac7a68fade310845916276110e9287"
281+
filename, "2fbfc3baaf6fccca0f97d02316b8344507fe6c8136991a66ee5f162235adb19f"
282282
)
283283

284284
def test_custom_package_root_multi_prefix_wheel(self):
@@ -312,7 +312,7 @@ def test_custom_package_root_multi_prefix_wheel(self):
312312
for line in record_contents.splitlines():
313313
self.assertFalse(line.startswith("/"))
314314
self.assertFileSha256Equal(
315-
filename, "caf51e22bdcd3c6c766c8903319ce717daeb6caac577d14e16326a8597981854"
315+
filename, "3e67971ca1e8a9ba36a143df7532e641f5661c56235e41d818309316c955ba58"
316316
)
317317

318318
def test_custom_package_root_multi_prefix_reverse_order_wheel(self):
@@ -346,7 +346,7 @@ def test_custom_package_root_multi_prefix_reverse_order_wheel(self):
346346
for line in record_contents.splitlines():
347347
self.assertFalse(line.startswith("/"))
348348
self.assertFileSha256Equal(
349-
filename, "9e8c0baa408b829dec691a5e8d3bc040be0bbfcc95c0eee19e1e5ffadea4a059"
349+
filename, "372ef9e11fb79f1952172993718a326b5adda192d94884b54377c34b44394982"
350350
)
351351

352352
def test_python_requires_wheel(self):
@@ -371,7 +371,7 @@ def test_python_requires_wheel(self):
371371
""",
372372
)
373373
self.assertFileSha256Equal(
374-
filename, "b47f3eaf4f9fa4685a58c7415ba1feddd39635ae26c18473504f7d7e62e8ce07"
374+
filename, "10a325ba8f77428b5cfcff6345d508f5eb77c140889eb62490d7382f60d4ebfe"
375375
)
376376

377377
def test_python_abi3_binary_wheel(self):
@@ -436,7 +436,7 @@ def test_rule_creates_directory_and_is_included_in_wheel(self):
436436
],
437437
)
438438
self.assertFileSha256Equal(
439-
filename, "d8e874b807e5574bd11a9312c58ce7fe7055afb80412d0d0e7ed21fc9223cd53"
439+
filename, "85e44c43cc19ccae9fe2e1d629230203aa11791bed1f7f68a069fb58d1c93cd2"
440440
)
441441

442442
def test_rule_expands_workspace_status_keys_in_wheel_metadata(self):
@@ -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()

0 commit comments

Comments
 (0)