diff --git a/.bazelci/presubmit.yml b/.bazelci/presubmit.yml index 7e9d4dea53..01af217924 100644 --- a/.bazelci/presubmit.yml +++ b/.bazelci/presubmit.yml @@ -90,7 +90,7 @@ tasks: gazelle_extension_min: <<: *common_workspace_flags_min_bazel <<: *minimum_supported_version - name: "Gazelle: workspace, minumum supported Bazel version" + name: "Gazelle: workspace, minimum supported Bazel version" platform: ubuntu2004 build_targets: ["//..."] test_targets: ["//..."] @@ -338,7 +338,7 @@ tasks: integration_test_bzlmod_build_file_generation_windows: <<: *reusable_build_test_all # coverage is not supported on Windows - name: "examples/bzlmod_build_file_generateion: Windows" + name: "examples/bzlmod_build_file_generation: Windows" working_directory: examples/bzlmod_build_file_generation platform: windows diff --git a/.bazelrc b/.bazelrc index 7e744fb67a..f7f31aed98 100644 --- a/.bazelrc +++ b/.bazelrc @@ -4,8 +4,8 @@ # (Note, we cannot use `common --deleted_packages` because the bazel version command doesn't support it) # To update these lines, execute # `bazel run @rules_bazel_integration_test//tools:update_deleted_packages` -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,tests/modules/other/nspkg_single -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,tests/modules/other/nspkg_single +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/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data +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/another_module,tests/modules/other,tests/modules/other/nspkg_delta,tests/modules/other/nspkg_gamma,tests/modules/other/nspkg_single,tests/modules/other/simple_v1,tests/modules/other/simple_v2,tests/modules/other/with_external_data test --test_output=errors diff --git a/CHANGELOG.md b/CHANGELOG.md index e48e3d4f3d..488f1054a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,22 +47,20 @@ BEGIN_UNRELEASED_TEMPLATE END_UNRELEASED_TEMPLATE --> -{#v0-0-0} -## Unreleased +{#1-5-0} +## [1.5.0] - 2025-06-11 -[0.0.0]: https://github.com/bazel-contrib/rules_python/releases/tag/0.0.0 +[1.5.0]: https://github.com/bazel-contrib/rules_python/releases/tag/1.5.0 -{#v0-0-0-changed} +{#1-5-0-changed} ### Changed -* If using the (deprecated) autodetecting/runtime_env toolchain, then the Python - version specified at build-time *must* match the Python version used at - runtime (the {obj}`--@rules_python//python/config_settings:python_version` - flag and the {attr}`python_version` attribute control the build-time version - for a target). If they don't match, dependencies won't be importable. (Such a - misconfiguration was unlikely to work to begin with; this is called out as an - FYI). -* (rules) {obj}`--bootstrap_impl=script` is the default for non-Windows. +* (toolchain) Bundled toolchain version updates: + * 3.9 now references 3.9.23 + * 3.10 now references 3.10.18 + * 3.11 now references 3.11.13 + * 3.12 now references 3.12.11 + * 3.13 now references 3.13.4 * (rules) On Windows, {obj}`--bootstrap_impl=system_python` is forced. This allows setting `--bootstrap_impl=script` in bazelrc for mixed-platform environments. @@ -72,8 +70,9 @@ END_UNRELEASED_TEMPLATE * (py_wheel) py_wheel always creates zip64-capable wheel zips * (providers) (experimental) {obj}`PyInfo.venv_symlinks` replaces `PyInfo.site_packages_symlinks` +* (deps) Updating setuptools to patch CVE-2025-47273. -{#v0-0-0-fixed} +{#1-5-0-fixed} ### Fixed * (rules) PyInfo provider is now advertised by py_test, py_binary, and py_library; @@ -99,8 +98,10 @@ END_UNRELEASED_TEMPLATE * (pypi) Correctly aggregate the sources when the hashes specified in the lockfile differ by platform even though the same version is used. Fixes [#2648](https://github.com/bazel-contrib/rules_python/issues/2648). * (pypi) `compile_pip_requirements` test rule works behind the proxy +* (toolchains) The hermetic toolchains now correctly statically advertise the + `releaselevel` and `serial` for pre-release hermetic toolchains ({gh-issue}`2837`). -{#v0-0-0-added} +{#1-5-0-added} ### Added * Repo utilities `execute_unchecked`, `execute_checked`, and `execute_checked_stdout` now support `log_stdout` and `log_stderr` keyword arg booleans. When these are `True` @@ -121,8 +122,9 @@ END_UNRELEASED_TEMPLATE * (rules) Added support for a using constraints files with `compile_pip_requirements`. Useful when an intermediate dependency needs to be upgraded to pull in security patches. +* (toolchains): 3.14.0b2 has been added as a preview. -{#v0-0-0-removed} +{#1-5-0-removed} ### Removed * Nothing removed. diff --git a/MODULE.bazel b/MODULE.bazel index 144e130c1b..77fa12d113 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -86,6 +86,7 @@ bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True) bazel_dep(name = "bazel_ci_rules", version = "1.0.0", dev_dependency = True) bazel_dep(name = "rules_pkg", version = "1.0.1", dev_dependency = True) bazel_dep(name = "other", version = "0", dev_dependency = True) +bazel_dep(name = "another_module", version = "0", dev_dependency = True) # Extra gazelle plugin deps so that WORKSPACE.bzlmod can continue including it for e2e tests. # We use `WORKSPACE.bzlmod` because it is impossible to have dev-only local overrides. @@ -116,6 +117,11 @@ local_path_override( path = "tests/modules/other", ) +local_path_override( + module_name = "another_module", + path = "tests/modules/another_module", +) + dev_python = use_extension( "//python/extensions:python.bzl", "python", diff --git a/docs/api/rules_python/python/config_settings/index.md b/docs/api/rules_python/python/config_settings/index.md index ae84d40b13..989ebf1128 100644 --- a/docs/api/rules_python/python/config_settings/index.md +++ b/docs/api/rules_python/python/config_settings/index.md @@ -167,7 +167,7 @@ Default: `//python/config_settings:_pip_env_marker_default_config` This flag points to a target providing {obj}`EnvMarkerInfo`, which determines the values used when environment markers are resolved at build time. -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: :::: @@ -245,12 +245,8 @@ Values: ::::{bzl:flag} bootstrap_impl Determine how programs implement their startup process. -The default for this depends on the platform: -* Windows: `system_python` (**always** used) -* Other: `script` - Values: -* `system_python`: Use a bootstrap that requires a system Python available +* `system_python`: (default) Use a bootstrap that requires a system Python available in order to start programs. This requires {obj}`PyRuntimeInfo.bootstrap_template` to be a Python program. * `script`: Use a bootstrap that uses an arbitrary executable script (usually a @@ -273,11 +269,6 @@ instead. :::{versionadded} 0.33.0 ::: -:::{versionchanged} VERSION_NEXT_FEATURE -* The default for non-Windows changed from `system_python` to `script`. -* On Windows, the value is forced to `system_python`. -::: - :::: ::::{bzl:flag} current_config diff --git a/docs/environment-variables.md b/docs/environment-variables.md index 26c171095d..8a51bcbfd2 100644 --- a/docs/environment-variables.md +++ b/docs/environment-variables.md @@ -65,7 +65,7 @@ The default became `1` if unspecified When `1`, the rules_python Starlark implementation of the pypi/pip integration is used instead of the legacy Python scripts. -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: :::: diff --git a/docs/requirements.txt b/docs/requirements.txt index 87c13aa8ba..cfeb0cbf31 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -17,9 +17,9 @@ babel==2.17.0 \ --hash=sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d \ --hash=sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2 # via sphinx -certifi==2025.1.31 \ - --hash=sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651 \ - --hash=sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe +certifi==2025.6.15 \ + --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \ + --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b # via requests charset-normalizer==3.4.1 \ --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \ @@ -291,9 +291,9 @@ readthedocs-sphinx-ext==2.2.5 \ --hash=sha256:ee5fd5b99db9f0c180b2396cbce528aa36671951b9526bb0272dbfce5517bd27 \ --hash=sha256:f8c56184ea011c972dd45a90122568587cc85b0127bc9cf064d17c68bc809daa # via rules-python-docs (docs/pyproject.toml) -requests==2.32.3 \ - --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ - --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 +requests==2.32.4 \ + --hash=sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c \ + --hash=sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422 # via # readthedocs-sphinx-ext # sphinx diff --git a/docs/toolchains.md b/docs/toolchains.md index 57d43d27f1..668a458156 100644 --- a/docs/toolchains.md +++ b/docs/toolchains.md @@ -305,7 +305,7 @@ that can be used with `target_settings`. Some particular ones of note are: {flag}`--py_linux_libc` and {flag}`--py_freethreaded`, among others. ::: -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 Added support for custom platform names, `target_compatible_with`, and `target_settings` with `single_version_platform_override`. ::: @@ -436,8 +436,8 @@ local_runtime_repo = use_repo_rule( ) local_runtime_toolchains_repo = use_repo_rule( - "@rules_python//python/local_toolchains:repos.bzl" - "local_runtime_toolchains_repo" + "@rules_python//python/local_toolchains:repos.bzl", + "local_runtime_toolchains_repo", dev_dependency = True, ) diff --git a/internal_dev_deps.bzl b/internal_dev_deps.bzl index f2b33e279e..e6ade4035c 100644 --- a/internal_dev_deps.bzl +++ b/internal_dev_deps.bzl @@ -48,6 +48,11 @@ def rules_python_internal_deps(): path = "tests/modules/other", ) + local_repository( + name = "another_module", + path = "tests/modules/another_module", + ) + http_archive( name = "bazel_skylib", sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f", diff --git a/python/config_settings/BUILD.bazel b/python/config_settings/BUILD.bazel index ee15828fa5..b11580c4cb 100644 --- a/python/config_settings/BUILD.bazel +++ b/python/config_settings/BUILD.bazel @@ -90,7 +90,7 @@ string_flag( rp_string_flag( name = "bootstrap_impl", - build_setting_default = BootstrapImplFlag.SCRIPT, + build_setting_default = BootstrapImplFlag.SYSTEM_PYTHON, override = select({ # Windows doesn't yet support bootstrap=script, so force disable it ":_is_windows": BootstrapImplFlag.SYSTEM_PYTHON, diff --git a/python/features.bzl b/python/features.bzl index b678a45241..e3d1ffdf61 100644 --- a/python/features.bzl +++ b/python/features.bzl @@ -35,7 +35,7 @@ def _features_typedef(): True if the `PyInfo.venv_symlinks` field is available. - :::{versionadded} VERSION_NEXT_FEATURE + :::{versionadded} 1.5.0 ::: :::: diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel index b319919305..8bcc6eaebe 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -450,11 +450,13 @@ bzl_library( ":attributes_bzl", ":common_bzl", ":flags_bzl", + ":normalize_name_bzl", ":precompile_bzl", ":py_cc_link_params_info_bzl", ":py_internal_bzl", ":rule_builders_bzl", ":toolchain_types_bzl", + ":version_bzl", "@bazel_skylib//lib:dicts", "@bazel_skylib//rules:common_settings", ], diff --git a/python/private/attributes.bzl b/python/private/attributes.bzl index ad8cba2e6c..641fa13a23 100644 --- a/python/private/attributes.bzl +++ b/python/private/attributes.bzl @@ -156,12 +156,6 @@ def copy_common_test_kwargs(kwargs): if key in kwargs } -CC_TOOLCHAIN = { - # NOTE: The `cc_helper.find_cpp_toolchain()` function expects the attribute - # name to be this name. - "_cc_toolchain": attr.label(default = "@bazel_tools//tools/cpp:current_cc_toolchain"), -} - # The common "data" attribute definition. DATA_ATTRS = { # NOTE: The "flags" attribute is deprecated, but there isn't an alternative @@ -260,7 +254,7 @@ The order of this list can matter because it affects the order that information from dependencies is merged in, which can be relevant depending on the ordering mode of depsets that are merged. -* {obj}`PyInfo.venv_symlinks` uses topological ordering. +* {obj}`PyInfo.venv_symlinks` uses default ordering. See {obj}`PyInfo` for more information about the ordering of its depsets and how its fields are merged. diff --git a/python/private/common.bzl b/python/private/common.bzl index e49dbad20c..96f8ebeab4 100644 --- a/python/private/common.bzl +++ b/python/private/common.bzl @@ -331,7 +331,7 @@ def collect_runfiles(ctx, files = depset()): # If the target is a File, then add that file to the runfiles. # Otherwise, add the target's **data runfiles** to the runfiles. # - # Note that, contray to best practice, the default outputs of the + # Note that, contrary to best practice, the default outputs of the # targets in `data` are *not* added, nor are the default runfiles. # # This ends up being important for several reasons, some of which are @@ -396,9 +396,8 @@ def create_py_info( implicit_pyc_files: {type}`depset[File]` Implicitly generated pyc files that a binary can choose to include. imports: depset of strings; the import path values to propagate. - venv_symlinks: {type}`list[tuple[str, str]]` tuples of - `(runfiles_path, site_packages_path)` for symlinks to create - in the consuming binary's venv site packages. + venv_symlinks: {type}`list[VenvSymlinkEntry]` instances for + symlinks to create in the consuming binary's venv. Returns: A tuple of the PyInfo instance and a depset of the @@ -426,7 +425,7 @@ def create_py_info( else: # TODO(b/228692666): Remove this once non-PyInfo targets are no # longer supported in `deps`. - files = target.files.to_list() + files = target[DefaultInfo].files.to_list() for f in files: if f.extension == "py": py_info.transitive_sources.add(f) @@ -450,7 +449,7 @@ def create_py_info( info = _get_py_info(target) py_info.merge_uses_shared_libraries(info.uses_shared_libraries) else: - files = target.files.to_list() + files = target[DefaultInfo].files.to_list() for f in files: py_info.merge_uses_shared_libraries(cc_helper.is_valid_shared_library_artifact(f)) if py_info.get_uses_shared_libraries(): diff --git a/python/private/hermetic_runtime_repo_setup.bzl b/python/private/hermetic_runtime_repo_setup.bzl index f944b0b914..98adba51d0 100644 --- a/python/private/hermetic_runtime_repo_setup.bzl +++ b/python/private/hermetic_runtime_repo_setup.bzl @@ -195,6 +195,14 @@ def define_hermetic_runtime_toolchain_impl( values = {"collect_code_coverage": "true"}, visibility = ["//visibility:private"], ) + if not version_info.pre: + releaselevel = "final" + else: + releaselevel = { + "a": "alpha", + "b": "beta", + "rc": "candidate", + }.get(version_info.pre[0]) py_runtime( name = "py3_runtime", @@ -204,6 +212,8 @@ def define_hermetic_runtime_toolchain_impl( "major": str(version_info.release[0]), "micro": str(version_info.release[2]), "minor": str(version_info.release[1]), + "releaselevel": releaselevel, + "serial": str(version_info.pre[1]) if version_info.pre else "0", }, coverage_tool = select({ # Convert empty string to None diff --git a/python/private/local_runtime_toolchains_repo.bzl b/python/private/local_runtime_toolchains_repo.bzl index 004ca664ad..8ef5ee9728 100644 --- a/python/private/local_runtime_toolchains_repo.bzl +++ b/python/private/local_runtime_toolchains_repo.bzl @@ -96,7 +96,7 @@ conditions are met, typically values from `@platforms`. See the [Local toolchains] docs for examples and further information. -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, ), @@ -145,7 +145,7 @@ The `target_settings` attribute, which handles `config_setting` values, instead of constraints. ::: -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, ), @@ -183,7 +183,7 @@ The `target_compatible_with` attribute, which handles *constraint* values, instead of `config_settings`. ::: -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, ), diff --git a/python/private/py_executable.bzl b/python/private/py_executable.bzl index 7c3e0cb757..7e50247e61 100644 --- a/python/private/py_executable.bzl +++ b/python/private/py_executable.bzl @@ -650,10 +650,6 @@ def _create_venv_symlinks(ctx, venv_dir_map): # maps venv-relative path to the runfiles path it should point to entries = depset( - # NOTE: Topological ordering is used so that dependencies closer to the - # binary have precedence in creating their symlinks. This allows the - # binary a modicum of control over the result. - order = "topological", transitive = [ dep[PyInfo].venv_symlinks for dep in ctx.attr.deps @@ -680,43 +676,52 @@ def _create_venv_symlinks(ctx, venv_dir_map): return venv_files def _build_link_map(entries): - # dict[str kind, dict[str rel_path, str link_to_path]] - link_map = {} + # dict[str package, dict[str kind, dict[str rel_path, str link_to_path]]] + pkg_link_map = {} + + # dict[str package, str version] + version_by_pkg = {} + for entry in entries: - kind = entry.kind - kind_map = link_map.setdefault(kind, {}) - if entry.venv_path in kind_map: - # We ignore duplicates by design. The dependency closer to the - # binary gets precedence due to the topological ordering. + link_map = pkg_link_map.setdefault(entry.package, {}) + kind_map = link_map.setdefault(entry.kind, {}) + + if version_by_pkg.setdefault(entry.package, entry.version) != entry.version: + # We ignore duplicates by design. + continue + elif entry.venv_path in kind_map: + # We ignore duplicates by design. continue else: kind_map[entry.venv_path] = entry.link_to_path - # An empty link_to value means to not create the site package symlink. - # Because of the topological ordering, this allows binaries to remove - # entries by having an earlier dependency produce empty link_to values. - for kind, kind_map in link_map.items(): - for dir_path, link_to in kind_map.items(): - if not link_to: - kind_map.pop(dir_path) + # An empty link_to value means to not create the site package symlink. Because of the + # ordering, this allows binaries to remove entries by having an earlier dependency produce + # empty link_to values. + for link_map in pkg_link_map.values(): + for kind, kind_map in link_map.items(): + for dir_path, link_to in kind_map.items(): + if not link_to: + kind_map.pop(dir_path) # dict[str kind, dict[str rel_path, str link_to_path]] keep_link_map = {} # Remove entries that would be a child path of a created symlink. # Earlier entries have precedence to match how exact matches are handled. - for kind, kind_map in link_map.items(): - keep_kind_map = keep_link_map.setdefault(kind, {}) - for _ in range(len(kind_map)): - if not kind_map: - break - dirname, value = kind_map.popitem() - keep_kind_map[dirname] = value - prefix = dirname + "/" # Add slash to prevent /X matching /XY - for maybe_suffix in kind_map.keys(): - maybe_suffix += "/" # Add slash to prevent /X matching /XY - if maybe_suffix.startswith(prefix) or prefix.startswith(maybe_suffix): - kind_map.pop(maybe_suffix) + for link_map in pkg_link_map.values(): + for kind, kind_map in link_map.items(): + keep_kind_map = keep_link_map.setdefault(kind, {}) + for _ in range(len(kind_map)): + if not kind_map: + break + dirname, value = kind_map.popitem() + keep_kind_map[dirname] = value + prefix = dirname + "/" # Add slash to prevent /X matching /XY + for maybe_suffix in kind_map.keys(): + maybe_suffix += "/" # Add slash to prevent /X matching /XY + if maybe_suffix.startswith(prefix) or prefix.startswith(maybe_suffix): + kind_map.pop(maybe_suffix) return keep_link_map def _map_each_identity(v): diff --git a/python/private/py_info.bzl b/python/private/py_info.bzl index 2a2f4554e3..31df5cfbde 100644 --- a/python/private/py_info.bzl +++ b/python/private/py_info.bzl @@ -67,11 +67,24 @@ the venv to create the path under. A runfiles-root relative path that `venv_path` will symlink to. If `None`, it means to not create a symlink. +""", + "package": """ +:type: str | None + +Represents the PyPI package name that the code originates from. It is normalized according to the +PEP440 with all `-` replaced with `_`, i.e. the same as the package name in the hub repository that +it would come from. """, "venv_path": """ :type: str A path relative to the `kind` directory within the venv. +""", + "version": """ +:type: str | None + +Represents the PyPI package version that the code originates from. It is normalized according to the +PEP440 standard. """, }, ) @@ -296,30 +309,10 @@ This field is currently unused in Bazel and may go away in the future. "venv_symlinks": """ :type: depset[VenvSymlinkEntry] -A depset with `topological` ordering. - - -Tuples of `(runfiles_path, site_packages_path)`. Where -* `runfiles_path` is a runfiles-root relative path. It is the path that - has the code to make importable. If `None` or empty string, then it means - to not create a site packages directory with the `site_packages_path` - name. -* `site_packages_path` is a path relative to the site-packages directory of - the venv for whatever creates the venv (typically py_binary). It makes - the code in `runfiles_path` available for import. Note that this - is created as a "raw" symlink (via `declare_symlink`). - :::{include} /_includes/experimental_api.md ::: -:::{tip} -The topological ordering means dependencies earlier and closer to the consumer -have precedence. This allows e.g. a binary to add dependencies that override -values from further way dependencies, such as forcing symlinks to point to -specific paths or preventing symlinks from being created. -::: - -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, }, @@ -375,9 +368,6 @@ def _PyInfoBuilder_typedef(): :::{field} venv_symlinks :type: DepsetBuilder[tuple[str | None, str]] - - NOTE: This depset has `topological` order - ::: """ def _PyInfoBuilder_new(): @@ -417,7 +407,7 @@ def _PyInfoBuilder_new(): transitive_pyc_files = builders.DepsetBuilder(), transitive_pyi_files = builders.DepsetBuilder(), transitive_sources = builders.DepsetBuilder(), - venv_symlinks = builders.DepsetBuilder(order = "topological"), + venv_symlinks = builders.DepsetBuilder(), ) return self diff --git a/python/private/py_library.bzl b/python/private/py_library.bzl index fabc880a8d..24adb5f3ca 100644 --- a/python/private/py_library.bzl +++ b/python/private/py_library.bzl @@ -41,6 +41,7 @@ load( "runfiles_root_path", ) load(":flags.bzl", "AddSrcsToRunfilesFlag", "PrecompileFlag", "VenvsSitePackages") +load(":normalize_name.bzl", "normalize_name") load(":precompile.bzl", "maybe_precompile") load(":py_cc_link_params_info.bzl", "PyCcLinkParamsInfo") load(":py_info.bzl", "PyInfo", "VenvSymlinkEntry", "VenvSymlinkKind") @@ -52,6 +53,7 @@ load( "EXEC_TOOLS_TOOLCHAIN_TYPE", TOOLCHAIN_TYPE = "TARGET_TOOLCHAIN_TYPE", ) +load(":version.bzl", "version") _py_builtins = py_internal @@ -84,20 +86,22 @@ under the binary's venv site-packages directory that should be made available (i namespace packages]( https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#native-namespace-packages). However, the *content* of the files cannot be taken into account, merely their -presence or absense. Stated another way: [pkgutil-style namespace packages]( +presence or absence. Stated another way: [pkgutil-style namespace packages]( https://packaging.python.org/en/latest/guides/packaging-namespace-packages/#pkgutil-style-namespace-packages) won't be understood as namespace packages; they'll be seen as regular packages. This will likely lead to conflicts with other targets that contribute to the namespace. -:::{tip} -This attributes populates {obj}`PyInfo.venv_symlinks`, which is -a topologically ordered depset. This means dependencies closer and earlier -to a consumer have precedence. See {obj}`PyInfo.venv_symlinks` for -more information. +:::{seealso} +This attributes populates {obj}`PyInfo.venv_symlinks`. ::: :::{versionadded} 1.4.0 ::: +:::{versionchanged} 1.5.0 +The topological order has been removed and if 2 different versions of the same PyPI +package are observed, the behaviour has no guarantees except that it is deterministic +and that only one package version will be included. +::: """, ), "_add_srcs_to_runfiles_flag": lambda: attrb.Label( @@ -157,7 +161,8 @@ def py_library_impl(ctx, *, semantics): imports = [] venv_symlinks = [] - imports, venv_symlinks = _get_imports_and_venv_symlinks(ctx, semantics) + package, version_str = _get_package_and_version(ctx) + imports, venv_symlinks = _get_imports_and_venv_symlinks(ctx, semantics, package, version_str) cc_info = semantics.get_cc_info_for_library(ctx) py_info, deps_transitive_sources, builtins_py_info = create_py_info( @@ -206,16 +211,46 @@ Source files are no longer added to the runfiles directly. ::: """ -def _get_imports_and_venv_symlinks(ctx, semantics): +def _get_package_and_version(ctx): + """Return package name and version + + If the package comes from PyPI then it will have a `.dist-info` as part of `data`, which + allows us to get the name of the package and its version. + """ + dist_info_metadata = None + for d in ctx.files.data: + # work on case insensitive FSes + if d.basename.lower() != "metadata": + continue + + if d.dirname.endswith(".dist-info"): + dist_info_metadata = d + + if not dist_info_metadata: + return None, None + + # in order to be able to have replacements in the venv, we have to add a + # third value into the venv_symlinks, which would be the normalized + # package name. This allows us to ensure that we can replace the `dist-info` + # directories by checking if the package key is there. + dist_info_dir = paths.basename(dist_info_metadata.dirname) + package, _, _suffix = dist_info_dir.rpartition(".dist-info") + package, _, version_str = package.rpartition("-") + return ( + normalize_name(package), # will have no dashes + version.normalize(version_str), # will have no dashes either + ) + +def _get_imports_and_venv_symlinks(ctx, semantics, package, version_str): imports = depset() - venv_symlinks = depset() + venv_symlinks = [] if VenvsSitePackages.is_enabled(ctx): - venv_symlinks = _get_venv_symlinks(ctx) + venv_symlinks = _get_venv_symlinks(ctx, package, version_str) else: imports = collect_imports(ctx, semantics) return imports, venv_symlinks -def _get_venv_symlinks(ctx): +def _get_venv_symlinks(ctx, package, version_str): imports = ctx.attr.imports if len(imports) == 0: fail("When venvs_site_packages is enabled, exactly one `imports` " + @@ -236,50 +271,61 @@ def _get_venv_symlinks(ctx): # Append slash to prevent incorrectly prefix-string matches site_packages_root += "/" - # We have to build a list of (runfiles path, site-packages path) pairs of - # the files to create in the consuming binary's venv site-packages directory. - # To minimize the number of files to create, we just return the paths - # to the directories containing the code of interest. + # We have to build a list of (runfiles path, site-packages path) pairs of the files to + # create in the consuming binary's venv site-packages directory. To minimize the number of + # files to create, we just return the paths to the directories containing the code of + # interest. + # + # However, namespace packages complicate matters: multiple distributions install in the + # same directory in site-packages. This works out because they don't overlap in their + # files. Typically, they install to different directories within the namespace package + # directory. We also need to ensure that we can handle a case where the main package (e.g. + # airflow) has directories only containing data files and then namespace packages coming + # along and being next to it. # - # However, namespace packages complicate matters: multiple - # distributions install in the same directory in site-packages. This - # works out because they don't overlap in their files. Typically, they - # install to different directories within the namespace package - # directory. Namespace package directories are simply directories - # within site-packages that *don't* have an `__init__.py` file, which - # can be arbitrarily deep. Thus, we simply have to look for the - # directories that _do_ have an `__init__.py` file and treat those as - # the path to symlink to. - - repo_runfiles_dirname = None - dirs_with_init = {} # dirname -> runfile path + # Lastly we have to assume python modules just being `.py` files (e.g. typing-extensions) + # is just a single Python file. + + dir_symlinks = {} # dirname -> runfile path venv_symlinks = [] - for src in ctx.files.srcs: - if src.extension not in PYTHON_FILE_EXTENSIONS: - continue + for src in ctx.files.srcs + ctx.files.data + ctx.files.pyi_srcs: path = _repo_relative_short_path(src.short_path) if not path.startswith(site_packages_root): continue path = path.removeprefix(site_packages_root) dir_name, _, filename = path.rpartition("/") - if dir_name and filename.startswith("__init__."): - dirs_with_init[dir_name] = None - repo_runfiles_dirname = runfiles_root_path(ctx, src.short_path).partition("/")[0] - elif not dir_name: - repo_runfiles_dirname = runfiles_root_path(ctx, src.short_path).partition("/")[0] + if dir_name in dir_symlinks: + # we already have this dir, this allows us to short-circuit since most of the + # ctx.files.data might share the same directories as ctx.files.srcs + continue + runfiles_dir_name, _, _ = runfiles_root_path(ctx, src.short_path).partition("/") + if dir_name: + # This can be either: + # * a directory with libs (e.g. numpy.libs, created by auditwheel) + # * a directory with `__init__.py` file that potentially also needs to be + # symlinked. + # * `.dist-info` directory + # + # This could be also regular files, that just need to be symlinked, so we will + # add the directory here. + dir_symlinks[dir_name] = runfiles_dir_name + elif src.extension in PYTHON_FILE_EXTENSIONS: # This would be files that do not have directories and we just need to add - # direct symlinks to them as is: - venv_symlinks.append(VenvSymlinkEntry( + # direct symlinks to them as is, we only allow Python files in here + entry = VenvSymlinkEntry( kind = VenvSymlinkKind.LIB, - link_to_path = paths.join(repo_runfiles_dirname, site_packages_root, filename), + link_to_path = paths.join(runfiles_dir_name, site_packages_root, filename), + package = package, + version = version_str, venv_path = filename, - )) + ) + venv_symlinks.append(entry) # Sort so that we encounter `foo` before `foo/bar`. This ensures we # see the top-most explicit package first. - dirnames = sorted(dirs_with_init.keys()) + dirnames = sorted(dir_symlinks.keys()) first_level_explicit_packages = [] for d in dirnames: is_sub_package = False @@ -292,11 +338,16 @@ def _get_venv_symlinks(ctx): first_level_explicit_packages.append(d) for dirname in first_level_explicit_packages: - venv_symlinks.append(VenvSymlinkEntry( + prefix = dir_symlinks[dirname] + entry = VenvSymlinkEntry( kind = VenvSymlinkKind.LIB, - link_to_path = paths.join(repo_runfiles_dirname, site_packages_root, dirname), + link_to_path = paths.join(prefix, site_packages_root, dirname), + package = package, + version = version_str, venv_path = dirname, - )) + ) + venv_symlinks.append(entry) + return venv_symlinks def _repo_relative_short_path(short_path): diff --git a/python/private/py_runtime_info.bzl b/python/private/py_runtime_info.bzl index d2ae17e360..efe14b2c06 100644 --- a/python/private/py_runtime_info.bzl +++ b/python/private/py_runtime_info.bzl @@ -334,7 +334,7 @@ to meet two criteria: interpreter. This typically requires the Python version to be known at build-time and match at runtime. -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, "zip_main_template": """ diff --git a/python/private/py_runtime_rule.bzl b/python/private/py_runtime_rule.bzl index 6dadcfeac3..861014e117 100644 --- a/python/private/py_runtime_rule.bzl +++ b/python/private/py_runtime_rule.bzl @@ -360,7 +360,7 @@ Whether this runtime supports virtualenvs created at build time. See {obj}`PyRuntimeInfo.supports_build_time_venv` for docs. -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 ::: """, default = True, diff --git a/python/private/py_wheel.bzl b/python/private/py_wheel.bzl index ffc24f6846..cfd4efdcda 100644 --- a/python/private/py_wheel.bzl +++ b/python/private/py_wheel.bzl @@ -480,7 +480,7 @@ def _py_wheel_impl(ctx): args.add("--no_compress") for target, filename in ctx.attr.extra_distinfo_files.items(): - target_files = target.files.to_list() + target_files = target[DefaultInfo].files.to_list() if len(target_files) != 1: fail( "Multi-file target listed in extra_distinfo_files %s", @@ -493,7 +493,7 @@ def _py_wheel_impl(ctx): ) for target, filename in ctx.attr.data_files.items(): - target_files = target.files.to_list() + target_files = target[DefaultInfo].files.to_list() if len(target_files) != 1: fail( "Multi-file target listed in data_files %s", diff --git a/python/private/pypi/deps.bzl b/python/private/pypi/deps.bzl index 31a5201659..73b30c69ee 100644 --- a/python/private/pypi/deps.bzl +++ b/python/private/pypi/deps.bzl @@ -76,8 +76,8 @@ _RULE_DEPS = [ ), ( "pypi__setuptools", - "https://files.pythonhosted.org/packages/de/88/70c5767a0e43eb4451c2200f07d042a4bcd7639276003a9c54a68cfcc1f8/setuptools-70.0.0-py3-none-any.whl", - "54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4", + "https://files.pythonhosted.org/packages/90/99/158ad0609729111163fc1f674a5a42f2605371a4cf036d0441070e2f7455/setuptools-78.1.1-py3-none-any.whl", + "c3a9c4211ff4c309edb8b8c4f1cbfa7ae324c4ba9f91ff254e3d305b9fd54561", ), ( "pypi__tomli", diff --git a/python/private/pypi/env_marker_info.bzl b/python/private/pypi/env_marker_info.bzl index b483436d98..c3c5ec69ed 100644 --- a/python/private/pypi/env_marker_info.bzl +++ b/python/private/pypi/env_marker_info.bzl @@ -8,7 +8,7 @@ The values to use during environment marker evaluation. The {obj}`--//python/config_settings:pip_env_marker_config` flag. ::: -:::{versionadded} VERSION_NEXT_FEATURE +:::{versionadded} 1.5.0 """, fields = { "env": """ diff --git a/python/private/pypi/extension.bzl b/python/private/pypi/extension.bzl index b79be6e038..867abe0898 100644 --- a/python/private/pypi/extension.bzl +++ b/python/private/pypi/extension.bzl @@ -263,7 +263,7 @@ def _create_whl_repos( repo_name = "{}_{}".format(pip_name, repo.repo_name) if repo_name in whl_libraries: - fail("Attempting to creating a duplicate library {} for {}".format( + fail("attempting to create a duplicate library {} for {}".format( repo_name, whl.name, )) diff --git a/python/private/pypi/simpleapi_download.bzl b/python/private/pypi/simpleapi_download.bzl index 164d4e8dbd..a3ba9691cd 100644 --- a/python/private/pypi/simpleapi_download.bzl +++ b/python/private/pypi/simpleapi_download.bzl @@ -148,10 +148,11 @@ def simpleapi_download( if found_on_index[pkg] != attr.index_url } - # buildifier: disable=print - print("You can use the following `index_url_overrides` to avoid the 404 warnings:\n{}".format( - render.dict(index_url_overrides), - )) + if index_url_overrides: + # buildifier: disable=print + print("You can use the following `index_url_overrides` to avoid the 404 warnings:\n{}".format( + render.dict(index_url_overrides), + )) return contents diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl index 3529566c49..518d17163f 100644 --- a/python/private/pypi/whl_library_targets.bzl +++ b/python/private/pypi/whl_library_targets.bzl @@ -336,7 +336,7 @@ def whl_library_targets( Label("//python/config_settings:is_venvs_site_packages"): [], "//conditions:default": create_inits( srcs = srcs + data + pyi_srcs, - ignore_dirnames = [], # If you need to ignore certain folders, you can patch rules_python here to do so. + ignored_dirnames = [], # If you need to ignore certain folders, you can patch rules_python here to do so. root = "site-packages", ), }) diff --git a/python/private/python.bzl b/python/private/python.bzl index 8e23668879..6eb8a3742e 100644 --- a/python/private/python.bzl +++ b/python/private/python.bzl @@ -1240,7 +1240,7 @@ The values should be one of the values in `@platforms//cpu` Docs for [Registering custom runtimes] ::: -:::{{versionadded}} VERSION_NEXT_FEATURE +:::{{versionadded}} 1.5.0 ::: """, ), @@ -1265,7 +1265,7 @@ The values should be one of the values in `@platforms//os` Docs for [Registering custom runtimes] ::: -:::{{versionadded}} VERSION_NEXT_FEATURE +:::{{versionadded}} 1.5.0 ::: """, ), @@ -1288,7 +1288,7 @@ Other values are allowed, in which case, `target_compatible_with`, `target_settings`, `os_name`, and `arch` should be specified so the toolchain is only used when appropriate. -:::{{versionchanged}} VERSION_NEXT_FEATURE +:::{{versionchanged}} 1.5.0 Arbitrary platform strings allowed. ::: """.format( @@ -1320,7 +1320,7 @@ If set, `target_settings`, `os_name`, and `arch` should also be set. Docs for [Registering custom runtimes] ::: -:::{{versionadded}} VERSION_NEXT_FEATURE +:::{{versionadded}} 1.5.0 ::: """, ), @@ -1334,7 +1334,7 @@ If set, `target_compatible_with`, `os_name`, and `arch` should also be set. Docs for [Registering custom runtimes] ::: -:::{{versionadded}} VERSION_NEXT_FEATURE +:::{{versionadded}} 1.5.0 ::: """, ), diff --git a/python/uv/private/uv_toolchain.bzl b/python/uv/private/uv_toolchain.bzl index 8c7f1b4b8c..bd82e7452f 100644 --- a/python/uv/private/uv_toolchain.bzl +++ b/python/uv/private/uv_toolchain.bzl @@ -24,7 +24,7 @@ def _uv_toolchain_impl(ctx): uv = ctx.attr.uv default_info = DefaultInfo( - files = uv.files, + files = uv[DefaultInfo].files, runfiles = uv[DefaultInfo].default_runfiles, ) uv_toolchain_info = UvToolchainInfo( diff --git a/python/versions.bzl b/python/versions.bzl index e712a2e126..44af7baf69 100644 --- a/python/versions.bzl +++ b/python/versions.bzl @@ -186,6 +186,21 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.9.23": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "f1a60528b6088ee8b8a34ca0e960998f4f664bed300ec0bbfe9d66ccbda74e50", + "aarch64-unknown-linux-gnu": "2871cf240bce3c021de829d73da04026febd7a775d1a1a1b37603ec6419fb6c1", + "ppc64le-unknown-linux-gnu": "2ba44a8e084a4661dbe50c0f0e3cf0a57227c6f1cff13fc2ae2f4d8ceae699fc", + "riscv64-unknown-linux-gnu": "7a735aebfc8b19a8af1f03e28babaf18a46cf8db0a931343dac1269376a1f693", + "s390x-unknown-linux-gnu": "27cfc030f782e2683c664e41dcef36051467c98676e133cbef04d4b7155ac4aa", + "x86_64-apple-darwin": "debd576badb6fdabb793ec9956512102f5a813c837449b1fe007c0af977db36c", + "x86_64-pc-windows-msvc": "28fbf2026929e00a300466220917c7029a69331700badb34b1691f1a99aa38e3", + "x86_64-unknown-linux-gnu": "21440e51aee78f3d92faf9375a90713542d8332e83d94c284f8f3d52c58eb5ca", + "x86_64-unknown-linux-musl": "7a881405a41cb4edf8c0d7c469c2f4759f601bc6f3c47978424a1ab1d0f1fada", + }, + "strip_prefix": "python", + }, "3.10.2": { "url": "20220227/cpython-{python_version}+20220227-{platform}-{build}.tar.gz", "sha256": { @@ -321,6 +336,21 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.10.18": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "a6590f71f670c7d121ac4f068dc83e271cf03309b80b1fa5890ee4875b7b691d", + "aarch64-unknown-linux-gnu": "b4d7cfb2cb5163da1ae5955ae8b33ac0b356780483d2993099899cf59efaea70", + "ppc64le-unknown-linux-gnu": "36aeae5cc61ff07c78b061f1b6aac628998a380ad45fadc82b8764185544fd7f", + "riscv64-unknown-linux-gnu": "2f6dd270598b655db5da5d98d1c43e560f6fb46c67a8fd68ff9b11ee9f6d79ff", + "s390x-unknown-linux-gnu": "616e56fe69c97a1d0ff13c00f337b2a91c972323c5d9a1828fdfc4d764b440fa", + "x86_64-apple-darwin": "4d72c1c1dcd2c4fe80055ef1b24fe4146f2de938aea1e3676faf91476f3f17e8", + "x86_64-pc-windows-msvc": "867b6dbcdb71d8ebb709ff54fbca8ad43d05cc21e5c157f39745c4dc44c1f8e2", + "x86_64-unknown-linux-gnu": "58f88ed6117078fdbc98976c9bc83b918f1f9c0c2ec21b80a582104f4839861c", + "x86_64-unknown-linux-musl": "d782c0569d6d7e21a5ed195ad7b41d0af8456b031e0814714d18cdeaa876f262", + }, + "strip_prefix": "python", + }, "3.11.1": { "url": "20230116/cpython-{python_version}+20230116-{platform}-{build}.tar.gz", "sha256": { @@ -436,18 +466,18 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, - "3.11.11": { - "url": "20250317/cpython-{python_version}+20250317-{platform}-{build}.tar.gz", + "3.11.13": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.tar.gz", "sha256": { - "aarch64-apple-darwin": "19b147c7e4b742656da4cb6ba35bc3ea2f15aa5f4d1bbbc38d09e2e85551e927", - "aarch64-unknown-linux-gnu": "7d52b5206afe617de2899af477f5a1d275ecbce80fb8300301b254ebf1da5a90", - "ppc64le-unknown-linux-gnu": "17c049f70ce719adc89dd0ae26f4e6a28f6aaedc63c2efef6bbb9c112ea4d692", - "riscv64-unknown-linux-gnu": "83ed50713409576756f5708e8f0549a15c17071bea22b71f15e11a7084f09481", - "s390x-unknown-linux-gnu": "298507f1f8d962b1bb98cb506c99e7e0d291a63eb9117e1521141e6b3825fd56", - "x86_64-apple-darwin": "a870cd965e7dded5100d13b1d34cab1c32a92811e000d10fbfe9bbdb36cdaa0e", - "x86_64-pc-windows-msvc": "1cf5760eea0a9df3308ca2c4111b5cc18fd638b2a912dbe07606193e3f9aa123", - "x86_64-unknown-linux-gnu": "51e47bc0d1b9f4bf68dd395f7a39f60c58a87cde854cab47264a859eb666bb69", - "x86_64-unknown-linux-musl": "ee4d84f992c6a1df42096e26b970fe5938fd6c1eadd245894bc94c5737ff9977", + "aarch64-apple-darwin": "365037494ba4f53563c22292e49a8e4d0d495bcb6534fca9666bdd1b474abf36", + "aarch64-unknown-linux-gnu": "a5954f147e87d9bff3d9733ebb3e74fe997eec5b38eaf5cb4429038228962a16", + "ppc64le-unknown-linux-gnu": "9214126866418f290fda88832fa3e244630f918ebc8a4a9ee15ba922e9c98afd", + "riscv64-unknown-linux-gnu": "fd99008c3123f50ec2ad407c5c1e17c1a86590daaf88dae8e6f1fd28f099b7c2", + "s390x-unknown-linux-gnu": "e27ab1fff8bf9e507677252a03ed524c685a8629b56475e26ab6dd0f88465179", + "x86_64-apple-darwin": "b49044115a545e67d73f5265a613a25da7c9523431281aa7b94691f1013355af", + "x86_64-pc-windows-msvc": "c0f89e3776211147817d54084fa046e2603571e18ff2ae4a4a8ff84ca4f7defc", + "x86_64-unknown-linux-gnu": "d93a7699505ee0ac7dec0f09324ffb19a31cce3066a287bb1fe95285ce3ea0c7", + "x86_64-unknown-linux-musl": "499121bb917e5baeeb954f76bdbce36bb63af579ff1530966ae2280e8d812c5b", }, "strip_prefix": "python", }, @@ -559,6 +589,21 @@ TOOL_VERSIONS = { }, "strip_prefix": "python", }, + "3.12.11": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.tar.gz", + "sha256": { + "aarch64-apple-darwin": "9c5826a93ddc15e8aa08de1e6e65b3ae0d45ea8eb0c2e9547b80ff4121b870ce", + "aarch64-unknown-linux-gnu": "eb33bc5a87443daf2fd218109df811bc4e4ea5ef9aec4fad75aa55da0258b96f", + "ppc64le-unknown-linux-gnu": "7b90bc528c5ddf30579dec52926d68fa6d5c90b65e24fc185d5fe283fdf0cbd9", + "riscv64-unknown-linux-gnu": "0f3103675102e351762a8fe574eae20335552a246a45a006d2a9ca14ce0952f8", + "s390x-unknown-linux-gnu": "a7ff0432208450ccebd5d328f69b84cc7c25b4af54fbab44803ddb11a2da5028", + "x86_64-apple-darwin": "199631baa35f3747ddfa2f1e28fc062b97ccd15b94a60c9294d4d129a73c9e53", + "x86_64-pc-windows-msvc": "e05fa165841c416d60365ca2216cad570f05ae5d3d027b9ad3beaad0529dd8cc", + "x86_64-unknown-linux-gnu": "77ab3efe5c6637fe8da0fdfbff5de1730c3b824874fe1368917886908b4c517b", + "x86_64-unknown-linux-musl": "9dd768494c4a34abcec316bc4802e957db98ed283024b527c0c40dfefd08b6fe", + }, + "strip_prefix": "python", + }, "3.13.0": { "url": "20241016/cpython-{python_version}+20241016-{platform}-{build}.{ext}", "sha256": { @@ -674,16 +719,99 @@ TOOL_VERSIONS = { "x86_64-unknown-linux-gnu-freethreaded": "python/install", }, }, + "3.13.4": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.{ext}", + "sha256": { + "aarch64-apple-darwin": "c2ce6601b2668c7bd1f799986af5ddfbff36e88795741864aba6e578cb02ed7f", + "aarch64-unknown-linux-gnu": "3c2596ece08ffe17e11bc1f27aeb4ce1195d2490a83d695d36ef4933d5c5ca53", + "ppc64le-unknown-linux-gnu": "b3cc13ee177b8db1d3e9b2eac413484e3c6a356f97d91dc59de8d3fd8cf79d6b", + "riscv64-unknown-linux-gnu": "d1b989e57a9ce29f6c945eeffe0e9750c222fdd09e99d2f8d6b0d8532a523053", + "s390x-unknown-linux-gnu": "d1d19fb01961ac6476712fdd6c5031f74c83666f6f11aa066207e9a158f7e3d8", + "x86_64-apple-darwin": "79feb6ca68f3921d07af52d9db06cf134e6f36916941ea850ab0bc20f5ff638b", + "x86_64-pc-windows-msvc": "29ac3585cc2dcfd79e3fe380c272d00e9d34351fc456e149403c86d3fea34057", + "x86_64-unknown-linux-gnu": "44e5477333ebca298a7a0a316985c6c3533b8645f92a83f7f73c44033832bf32", + "x86_64-unknown-linux-musl": "a3afbfa94b9ff4d9fc426b47eb3c8446cada535075b8d51b7bdc9d9ab9911fc2", + "aarch64-apple-darwin-freethreaded": "278dccade56b4bbeecb9a613b77012cf5c1433a5e9b8ef99230d5e61f31d9e02", + "aarch64-unknown-linux-gnu-freethreaded": "b1c1bd6ab9ef95b464d92a6a911cef1a8d9f0b0f6a192f694ef18ed15d882edf", + "ppc64le-unknown-linux-gnu-freethreaded": "ed66ae213a62b286b9b7338b816ccd2815f5248b7a28a185dc8159fe004149ae", + "riscv64-unknown-linux-gnu-freethreaded": "913264545215236660e4178bc3e5b57a20a444a8deb5c11680c95afc960b4016", + "s390x-unknown-linux-gnu-freethreaded": "7556a38ab5e507c1ec22bc38f9859982bc956cab7f4de05a2faac114feb306db", + "x86_64-apple-darwin-freethreaded": "64ab7ac8c88002d9ba20a92f72945bfa350268e944a7922500af75d20330574d", + "x86_64-pc-windows-msvc-freethreaded": "9457504547edb2e0156bf76b53c7e4941c7f61c0eff9fd5f4d816d3df51c58e3", + "x86_64-unknown-linux-gnu-freethreaded": "864df6e6819e8f8e855ce30f34410fdc5867d0616e904daeb9a40e5806e970d7", + }, + "strip_prefix": { + "aarch64-apple-darwin": "python", + "aarch64-unknown-linux-gnu": "python", + "ppc64le-unknown-linux-gnu": "python", + "s390x-unknown-linux-gnu": "python", + "riscv64-unknown-linux-gnu": "python", + "x86_64-apple-darwin": "python", + "x86_64-pc-windows-msvc": "python", + "x86_64-unknown-linux-gnu": "python", + "x86_64-unknown-linux-musl": "python", + "aarch64-apple-darwin-freethreaded": "python/install", + "aarch64-unknown-linux-gnu-freethreaded": "python/install", + "ppc64le-unknown-linux-gnu-freethreaded": "python/install", + "riscv64-unknown-linux-gnu-freethreaded": "python/install", + "s390x-unknown-linux-gnu-freethreaded": "python/install", + "x86_64-apple-darwin-freethreaded": "python/install", + "x86_64-pc-windows-msvc-freethreaded": "python/install", + "x86_64-unknown-linux-gnu-freethreaded": "python/install", + }, + }, + "3.14.0b2": { + "url": "20250610/cpython-{python_version}+20250610-{platform}-{build}.{ext}", + "sha256": { + "aarch64-apple-darwin": "6607351d140e83feb6e11dbde46ab5f99fa9fe039bdbaa12611d26bda0ed9343", + "aarch64-unknown-linux-gnu": "cc388d567f7c23921e0bef8dcae959dfab9ee24d10aeeb23688b21eac402817f", + "ppc64le-unknown-linux-gnu": "f9379ecc5dc71f9c58adf03d5524176ec36e1b40c788d29c260df54d09ad351c", + "riscv64-unknown-linux-gnu": "e6fbe4f7928ec606edee1506752659bf59216fdb208c744d268082ec79b16f42", + "s390x-unknown-linux-gnu": "1cf32c1173adc1cb70952bb47c92177a196f9e83b7a874f09599682e92ba0010", + "x86_64-apple-darwin": "a6d8196b174409e0ce67829c4e4ee5005c4be20a2efb41116e0521ad1fa1a717", + "x86_64-pc-windows-msvc": "0d88ec80c6c3e3ac462368850c19d3930bf2b1a1a5fe89da60c8534d0fac1a01", + "x86_64-unknown-linux-gnu": "93b29eea5214d19f0420ef8e459b007e15ea58349d60811122c78241fe51cb92", + "x86_64-unknown-linux-musl": "90e90a58ebff3416eb5a3f93ecb59b6eda945e2b706f5c13b0ba85f6b2bee130", + "aarch64-apple-darwin-freethreaded": "af0f34aa0dcd02bd3d960a1572a1ed8a17d55b373a22866f05041aaf16f8607d", + "aarch64-unknown-linux-gnu-freethreaded": "e76c7ab98e1c0f86a6996d1ec775ba8497bf46aa8ffa8c7b0f2e761f37305329", + "ppc64le-unknown-linux-gnu-freethreaded": "df2ae00827406e247f1aaaec76ffc7963b909c81075fc9940eee1ea9f753dd16", + "riscv64-unknown-linux-gnu-freethreaded": "09e347cb5f29e0eafd1eba73105ea9d853184b55fbaf4746cebec217430d6db5", + "s390x-unknown-linux-gnu-freethreaded": "f911605eee0eb7845a69acaf8bfb2e1811c76e9a5e3980d97fae93135df4b773", + "x86_64-apple-darwin-freethreaded": "dd27d519cf2a04917cb566366d6539477791d1b2f1fb42037d9179f469ff55a9", + "x86_64-pc-windows-msvc-freethreaded": "da966a17e434094d8f10b719d93c782d82eaf5207f2843cbaa58c3d91a8f0e32", + "x86_64-unknown-linux-gnu-freethreaded": "abd60d3a302e9d9c32ec78581fb3a9903079c56ec7a949ce658a7950423f350a", + }, + "strip_prefix": { + "aarch64-apple-darwin": "python", + "aarch64-unknown-linux-gnu": "python", + "ppc64le-unknown-linux-gnu": "python", + "s390x-unknown-linux-gnu": "python", + "riscv64-unknown-linux-gnu": "python", + "x86_64-apple-darwin": "python", + "x86_64-pc-windows-msvc": "python", + "x86_64-unknown-linux-gnu": "python", + "x86_64-unknown-linux-musl": "python", + "aarch64-apple-darwin-freethreaded": "python/install", + "aarch64-unknown-linux-gnu-freethreaded": "python/install", + "ppc64le-unknown-linux-gnu-freethreaded": "python/install", + "riscv64-unknown-linux-gnu-freethreaded": "python/install", + "s390x-unknown-linux-gnu-freethreaded": "python/install", + "x86_64-apple-darwin-freethreaded": "python/install", + "x86_64-pc-windows-msvc-freethreaded": "python/install", + "x86_64-unknown-linux-gnu-freethreaded": "python/install", + }, + }, } # buildifier: disable=unsorted-dict-items MINOR_MAPPING = { "3.8": "3.8.20", - "3.9": "3.9.21", - "3.10": "3.10.16", - "3.11": "3.11.11", - "3.12": "3.12.9", - "3.13": "3.13.2", + "3.9": "3.9.23", + "3.10": "3.10.18", + "3.11": "3.11.13", + "3.12": "3.12.11", + "3.13": "3.13.4", + "3.14": "3.14.0b2", } def _generate_platforms(): diff --git a/sphinxdocs/private/sphinx.bzl b/sphinxdocs/private/sphinx.bzl index ee6b994e2e..c1efda3508 100644 --- a/sphinxdocs/private/sphinx.bzl +++ b/sphinxdocs/private/sphinx.bzl @@ -386,7 +386,7 @@ def _sphinx_source_tree_impl(ctx): _relocate(orig_file) for src_target, dest in ctx.attr.renamed_srcs.items(): - src_files = src_target.files.to_list() + src_files = src_target[DefaultInfo].files.to_list() if len(src_files) != 1: fail("A single file must be specified to be renamed. Target {} " + "generate {} files: {}".format( diff --git a/tests/modules/another_module/BUILD.bazel b/tests/modules/another_module/BUILD.bazel new file mode 100644 index 0000000000..3b56b6ee83 --- /dev/null +++ b/tests/modules/another_module/BUILD.bazel @@ -0,0 +1,5 @@ +filegroup( + name = "data", + srcs = ["another_module_data.txt"], + visibility = ["//visibility:public"], +) diff --git a/tests/modules/another_module/MODULE.bazel b/tests/modules/another_module/MODULE.bazel new file mode 100644 index 0000000000..8ed5a5543b --- /dev/null +++ b/tests/modules/another_module/MODULE.bazel @@ -0,0 +1 @@ +module(name = "another_module") diff --git a/tests/modules/another_module/another_module_data.txt b/tests/modules/another_module/another_module_data.txt new file mode 100644 index 0000000000..f742ebab60 --- /dev/null +++ b/tests/modules/another_module/another_module_data.txt @@ -0,0 +1 @@ +print("token") diff --git a/tests/modules/other/MODULE.bazel b/tests/modules/other/MODULE.bazel index 7cd3118b81..11a633d56b 100644 --- a/tests/modules/other/MODULE.bazel +++ b/tests/modules/other/MODULE.bazel @@ -1,3 +1,5 @@ module(name = "other") bazel_dep(name = "rules_python", version = "0") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "another_module", version = "0") diff --git a/tests/modules/other/simple_v1/BUILD.bazel b/tests/modules/other/simple_v1/BUILD.bazel new file mode 100644 index 0000000000..da5db8164a --- /dev/null +++ b/tests/modules/other/simple_v1/BUILD.bazel @@ -0,0 +1,14 @@ +load("@rules_python//python:py_library.bzl", "py_library") + +package(default_visibility = ["//visibility:public"]) + +py_library( + name = "simple_v1", + srcs = glob(["site-packages/**/*.py"]), + data = glob( + ["**/*"], + exclude = ["site-packages/**/*.py"], + ), + experimental_venvs_site_packages = "@rules_python//python/config_settings:venvs_site_packages", + imports = [package_name() + "/site-packages"], +) diff --git a/tests/modules/other/simple_v1/site-packages/simple-1.0.0.dist-info/METADATA b/tests/modules/other/simple_v1/site-packages/simple-1.0.0.dist-info/METADATA new file mode 100644 index 0000000000..ee76ec48a4 --- /dev/null +++ b/tests/modules/other/simple_v1/site-packages/simple-1.0.0.dist-info/METADATA @@ -0,0 +1 @@ +inside is v1 diff --git a/tests/modules/other/simple_v1/site-packages/simple/__init__.py b/tests/modules/other/simple_v1/site-packages/simple/__init__.py new file mode 100644 index 0000000000..5becc17c04 --- /dev/null +++ b/tests/modules/other/simple_v1/site-packages/simple/__init__.py @@ -0,0 +1 @@ +__version__ = "1.0.0" diff --git a/tests/modules/other/simple_v1/site-packages/simple_v1_extras/data.txt b/tests/modules/other/simple_v1/site-packages/simple_v1_extras/data.txt new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/modules/other/simple_v2/BUILD.bazel b/tests/modules/other/simple_v2/BUILD.bazel new file mode 100644 index 0000000000..45f83a5a88 --- /dev/null +++ b/tests/modules/other/simple_v2/BUILD.bazel @@ -0,0 +1,15 @@ +load("@rules_python//python:py_library.bzl", "py_library") + +package(default_visibility = ["//visibility:public"]) + +py_library( + name = "simple_v2", + srcs = glob(["site-packages/**/*.py"]), + data = glob( + ["**/*"], + exclude = ["site-packages/**/*.py"], + ), + experimental_venvs_site_packages = "@rules_python//python/config_settings:venvs_site_packages", + imports = [package_name() + "/site-packages"], + pyi_srcs = glob(["**/*.pyi"]), +) diff --git a/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/METADATA b/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/METADATA new file mode 100644 index 0000000000..ee76ec48a4 --- /dev/null +++ b/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/METADATA @@ -0,0 +1 @@ +inside is v1 diff --git a/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/licenses/LICENSE b/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/licenses/LICENSE new file mode 100644 index 0000000000..0cb5e79499 --- /dev/null +++ b/tests/modules/other/simple_v2/site-packages/simple-2.0.0.dist-info/licenses/LICENSE @@ -0,0 +1 @@ +Some License diff --git a/tests/modules/other/simple_v2/site-packages/simple.libs/data.so b/tests/modules/other/simple_v2/site-packages/simple.libs/data.so new file mode 100644 index 0000000000..f023e3b9ae --- /dev/null +++ b/tests/modules/other/simple_v2/site-packages/simple.libs/data.so @@ -0,0 +1,2 @@ +# This is usually created by auditwheel when processing linux wheels and including +# dependencies. diff --git a/tests/modules/other/simple_v2/site-packages/simple/__init__.py b/tests/modules/other/simple_v2/site-packages/simple/__init__.py new file mode 100644 index 0000000000..8c0d5d5bb2 --- /dev/null +++ b/tests/modules/other/simple_v2/site-packages/simple/__init__.py @@ -0,0 +1 @@ +__version__ = "2.0.0" diff --git a/tests/modules/other/simple_v2/site-packages/simple/__init__.pyi b/tests/modules/other/simple_v2/site-packages/simple/__init__.pyi new file mode 100644 index 0000000000..bb7b160deb --- /dev/null +++ b/tests/modules/other/simple_v2/site-packages/simple/__init__.pyi @@ -0,0 +1 @@ +# Intentionally empty diff --git a/tests/modules/other/with_external_data/BUILD.bazel b/tests/modules/other/with_external_data/BUILD.bazel new file mode 100644 index 0000000000..fc047aadab --- /dev/null +++ b/tests/modules/other/with_external_data/BUILD.bazel @@ -0,0 +1,23 @@ +load("@bazel_skylib//rules:copy_file.bzl", "copy_file") +load("@rules_python//python:py_library.bzl", "py_library") + +package(default_visibility = ["//visibility:public"]) + +# The users may include data through other repos via annotations and copy_file +# just add this edge case. +# +# NOTE: if the data is not copied to `site-packages/` then it will not +# appear. +copy_file( + name = "external_data", + src = "@another_module//:data", + out = "site-packages/external_data/another_module_data.txt", +) + +py_library( + name = "with_external_data", + srcs = ["site-packages/with_external_data.py"], + data = [":external_data"], + experimental_venvs_site_packages = "@rules_python//python/config_settings:venvs_site_packages", + imports = [package_name() + "/site-packages"], +) diff --git a/tests/modules/other/with_external_data/site-packages/with_external_data.py b/tests/modules/other/with_external_data/site-packages/with_external_data.py new file mode 100644 index 0000000000..ccd9dcef9e --- /dev/null +++ b/tests/modules/other/with_external_data/site-packages/with_external_data.py @@ -0,0 +1 @@ +# Intentionally blank diff --git a/tests/python/python_tests.bzl b/tests/python/python_tests.bzl index 116afa76ad..f0dc4825ac 100644 --- a/tests/python/python_tests.bzl +++ b/tests/python/python_tests.bzl @@ -304,11 +304,11 @@ def _test_toolchain_ordering(env): toolchain = [ _toolchain("3.10"), _toolchain("3.10.15"), - _toolchain("3.10.16"), - _toolchain("3.10.11"), + _toolchain("3.10.18"), + _toolchain("3.10.13"), _toolchain("3.11.1"), _toolchain("3.11.10"), - _toolchain("3.11.11", is_default = True), + _toolchain("3.11.13", is_default = True), ], ), _mod(name = "rules_python", toolchain = [_toolchain("3.11")]), @@ -320,14 +320,15 @@ def _test_toolchain_ordering(env): for t in py.toolchains ] - env.expect.that_str(py.default_python_version).equals("3.11.11") + env.expect.that_str(py.default_python_version).equals("3.11.13") env.expect.that_dict(py.config.minor_mapping).contains_exactly({ - "3.10": "3.10.16", - "3.11": "3.11.11", - "3.12": "3.12.9", - "3.13": "3.13.2", + "3.10": "3.10.18", + "3.11": "3.11.13", + "3.12": "3.12.11", + "3.13": "3.13.4", + "3.14": "3.14.0b2", "3.8": "3.8.20", - "3.9": "3.9.21", + "3.9": "3.9.23", }) env.expect.that_collection(got_versions).contains_exactly([ # First the full-version toolchains that are in minor_mapping @@ -336,13 +337,13 @@ def _test_toolchain_ordering(env): # The default version is always set in the `python_version` flag, so know, that # the default match will be somewhere in the first bunch. "3.10", - "3.10.16", + "3.10.18", "3.11", - "3.11.11", + "3.11.13", # Next, the rest, where we will match things based on the `python_version` being # the same "3.10.15", - "3.10.11", + "3.10.13", "3.11.1", "3.11.10", ]).in_order() diff --git a/tests/toolchains/defs.bzl b/tests/toolchains/defs.bzl index a883b0af33..25863d18c4 100644 --- a/tests/toolchains/defs.bzl +++ b/tests/toolchains/defs.bzl @@ -15,6 +15,7 @@ "" load("//python:versions.bzl", "PLATFORMS", "TOOL_VERSIONS") +load("//python/private:version.bzl", "version") # buildifier: disable=bzl-visibility load("//tests/support:py_reconfig.bzl", "py_reconfig_test") def define_toolchain_tests(name): @@ -38,13 +39,20 @@ def define_toolchain_tests(name): is_platform = "_is_{}".format(platform_key) target_compatible_with[is_platform] = [] + parsed = version.parse(python_version, strict = True) + expect_python_version = "{0}.{1}.{2}".format(*parsed.release) + if parsed.pre: + expect_python_version = "{0}{1}{2}".format( + expect_python_version, + *parsed.pre + ) py_reconfig_test( name = "python_{}_test".format(python_version), srcs = ["python_toolchain_test.py"], main = "python_toolchain_test.py", python_version = python_version, env = { - "EXPECT_PYTHON_VERSION": python_version, + "EXPECT_PYTHON_VERSION": expect_python_version, }, deps = ["//python/runfiles"], data = ["//tests/support:current_build_settings"], diff --git a/tests/toolchains/python_toolchain_test.py b/tests/toolchains/python_toolchain_test.py index 591d7dbe8a..63ed42488f 100644 --- a/tests/toolchains/python_toolchain_test.py +++ b/tests/toolchains/python_toolchain_test.py @@ -27,7 +27,18 @@ def test_expected_toolchain_matches(self): ) self.assertIn(expected, settings["toolchain_label"], msg) - actual = "{v.major}.{v.minor}.{v.micro}".format(v=sys.version_info) + if sys.version_info.releaselevel == "final": + actual = "{v.major}.{v.minor}.{v.micro}".format(v=sys.version_info) + elif sys.version_info.releaselevel in ["beta"]: + actual = ( + "{v.major}.{v.minor}.{v.micro}{v.releaselevel[0]}{v.serial}".format( + v=sys.version_info + ) + ) + else: + raise NotImplementedError( + "Unsupported release level, please update the test" + ) self.assertEqual(actual, expect_version) diff --git a/tests/toolchains/transitions/transitions_tests.bzl b/tests/toolchains/transitions/transitions_tests.bzl index bddd1745f0..ef071188bb 100644 --- a/tests/toolchains/transitions/transitions_tests.bzl +++ b/tests/toolchains/transitions/transitions_tests.bzl @@ -56,14 +56,21 @@ def _impl(ctx): exec_tools = ctx.toolchains[EXEC_TOOLS_TOOLCHAIN_TYPE].exec_tools got_version = exec_tools.exec_interpreter[platform_common.ToolchainInfo].py3_runtime.interpreter_version_info + got = "{}.{}.{}".format( + got_version.major, + got_version.minor, + got_version.micro, + ) + if got_version.releaselevel != "final": + got = "{}{}{}".format( + got, + got_version.releaselevel[0], + got_version.serial, + ) return [ TestInfo( - got = "{}.{}.{}".format( - got_version.major, - got_version.minor, - got_version.micro, - ), + got = got, want = ctx.attr.want_version, ), ] diff --git a/tests/venv_site_packages_libs/BUILD.bazel b/tests/venv_site_packages_libs/BUILD.bazel index d5a4fe6750..e64299e1ad 100644 --- a/tests/venv_site_packages_libs/BUILD.bazel +++ b/tests/venv_site_packages_libs/BUILD.bazel @@ -1,6 +1,20 @@ +load("//python:py_library.bzl", "py_library") load("//tests/support:py_reconfig.bzl", "py_reconfig_test") load("//tests/support:support.bzl", "SUPPORTS_BOOTSTRAP_SCRIPT") +py_library( + name = "user_lib", + deps = ["@other//simple_v1"], +) + +py_library( + name = "closer_lib", + deps = [ + ":user_lib", + "@other//simple_v2", + ], +) + py_reconfig_test( name = "venvs_site_packages_libs_test", srcs = ["bin.py"], @@ -9,10 +23,12 @@ py_reconfig_test( target_compatible_with = SUPPORTS_BOOTSTRAP_SCRIPT, venvs_site_packages = "yes", deps = [ + ":closer_lib", "//tests/venv_site_packages_libs/nspkg_alpha", "//tests/venv_site_packages_libs/nspkg_beta", "@other//nspkg_delta", "@other//nspkg_gamma", "@other//nspkg_single", + "@other//with_external_data", ], ) diff --git a/tests/venv_site_packages_libs/bin.py b/tests/venv_site_packages_libs/bin.py index 58572a2a1e..7e5838d2c2 100644 --- a/tests/venv_site_packages_libs/bin.py +++ b/tests/venv_site_packages_libs/bin.py @@ -1,7 +1,7 @@ import importlib -import os import sys import unittest +from pathlib import Path class VenvSitePackagesLibraryTest(unittest.TestCase): @@ -27,6 +27,53 @@ def test_imported_from_venv(self): self.assert_imported_from_venv("nspkg.subnspkg.gamma") self.assert_imported_from_venv("nspkg.subnspkg.delta") self.assert_imported_from_venv("single_file") + self.assert_imported_from_venv("simple") + + def test_data_is_included(self): + self.assert_imported_from_venv("simple") + module = importlib.import_module("simple") + module_path = Path(module.__file__) + + site_packages = module_path.parent.parent + + # Ensure that packages from simple v1 are not present + files = [p.name for p in site_packages.glob("*")] + self.assertIn("simple_v1_extras", files) + + def test_override_pkg(self): + self.assert_imported_from_venv("simple") + module = importlib.import_module("simple") + self.assertEqual( + "1.0.0", + module.__version__, + ) + + def test_dirs_from_replaced_package_are_not_present(self): + self.assert_imported_from_venv("simple") + module = importlib.import_module("simple") + module_path = Path(module.__file__) + + site_packages = module_path.parent.parent + dist_info_dirs = [p.name for p in site_packages.glob("*.dist-info")] + self.assertEqual( + ["simple-1.0.0.dist-info"], + dist_info_dirs, + ) + + # Ensure that packages from simple v1 are not present + files = [p.name for p in site_packages.glob("*")] + self.assertNotIn("simple.libs", files) + + def test_data_from_another_pkg_is_included_via_copy_file(self): + self.assert_imported_from_venv("simple") + module = importlib.import_module("simple") + module_path = Path(module.__file__) + + site_packages = module_path.parent.parent + # Ensure that packages from simple v1 are not present + d = site_packages / "external_data" + files = [p.name for p in d.glob("*")] + self.assertIn("another_module_data.txt", files) if __name__ == "__main__": diff --git a/tools/publish/requirements_darwin.txt b/tools/publish/requirements_darwin.txt index 483f88444e..af5bad246d 100644 --- a/tools/publish/requirements_darwin.txt +++ b/tools/publish/requirements_darwin.txt @@ -6,9 +6,9 @@ backports-tarfile==1.2.0 \ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991 # via jaraco-context -certifi==2025.1.31 \ - --hash=sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651 \ - --hash=sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe +certifi==2025.6.15 \ + --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \ + --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b # via requests charset-normalizer==3.4.1 \ --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \ diff --git a/tools/publish/requirements_linux.txt b/tools/publish/requirements_linux.txt index 62dbf1eb77..b2e9ccf5ab 100644 --- a/tools/publish/requirements_linux.txt +++ b/tools/publish/requirements_linux.txt @@ -6,9 +6,9 @@ backports-tarfile==1.2.0 \ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991 # via jaraco-context -certifi==2025.1.31 \ - --hash=sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651 \ - --hash=sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe +certifi==2025.6.15 \ + --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \ + --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b # via requests cffi==1.17.1 \ --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ diff --git a/tools/publish/requirements_universal.txt b/tools/publish/requirements_universal.txt index e4e876b176..8a7426e517 100644 --- a/tools/publish/requirements_universal.txt +++ b/tools/publish/requirements_universal.txt @@ -6,9 +6,9 @@ backports-tarfile==1.2.0 ; python_full_version < '3.12' \ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991 # via jaraco-context -certifi==2025.1.31 \ - --hash=sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651 \ - --hash=sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe +certifi==2025.6.15 \ + --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \ + --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b # via requests cffi==1.17.1 ; platform_python_implementation != 'PyPy' and sys_platform == 'linux' \ --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ diff --git a/tools/publish/requirements_windows.txt b/tools/publish/requirements_windows.txt index 043de9ecb1..11017aa4f9 100644 --- a/tools/publish/requirements_windows.txt +++ b/tools/publish/requirements_windows.txt @@ -6,9 +6,9 @@ backports-tarfile==1.2.0 \ --hash=sha256:77e284d754527b01fb1e6fa8a1afe577858ebe4e9dad8919e34c862cb399bc34 \ --hash=sha256:d75e02c268746e1b8144c278978b6e98e85de6ad16f8e4b0844a154557eca991 # via jaraco-context -certifi==2025.1.31 \ - --hash=sha256:3d5da6925056f6f18f119200434a4780a94263f10d1c21d032a6f6b2baa20651 \ - --hash=sha256:ca78db4565a652026a4db2bcdf68f2fb589ea80d0be70e03929ed730746b84fe +certifi==2025.6.15 \ + --hash=sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057 \ + --hash=sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b # via requests charset-normalizer==3.4.1 \ --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \