Skip to content

Commit 03f74c2

Browse files
authored
Merge branch 'bazel-contrib:main' into tfall/fix-rules-python-gazelle-plugin-requirements-data-paths
2 parents 69477af + e40b609 commit 03f74c2

19 files changed

Lines changed: 443 additions & 163 deletions

.bazelci/presubmit.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
buildifier:
1717
# keep these arguments in sync with .pre-commit-config.yaml
1818
# Use a specific version to avoid skew issues when new versions are released.
19-
version: 6.1.0
19+
version: 8.2.1
2020
warnings: "all"
2121
# NOTE: Minimum supported version is 7.x
2222
.minimum_supported_version: &minimum_supported_version

.bcr/gazelle/presubmit.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ bcr_test_module:
1616
module_path: "examples/bzlmod_build_file_generation"
1717
matrix:
1818
platform: ["debian11", "macos", "ubuntu2004", "windows"]
19-
# last_rc is to get latest 8.x release. Replace with 8.x when available.
20-
bazel: [7.x, last_rc]
19+
bazel: [7.x, 8.x]
2120
tasks:
2221
run_tests:
2322
name: "Run test module"

.bcr/presubmit.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ bcr_test_module:
1616
module_path: "examples/bzlmod"
1717
matrix:
1818
platform: ["debian11", "macos", "ubuntu2004", "windows"]
19-
# last_rc is to get latest 8.x release. Replace with 8.x when available.
20-
bazel: [7.x, last_rc]
19+
bazel: [7.x, 8.x]
2120
tasks:
2221
run_tests:
2322
name: "Run test module"

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ repos:
2121
hooks:
2222
- id: check-merge-conflict
2323
- repo: https://github.com/keith/pre-commit-buildifier
24-
rev: 6.1.0
24+
rev: 8.2.1
2525
hooks:
2626
- id: buildifier
2727
args: &args

CHANGELOG.md

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,31 @@ A brief description of the categories of changes:
2323
<!--
2424
BEGIN_UNRELEASED_TEMPLATE
2525
26+
{#v0-0-0}
27+
## Unreleased
28+
29+
[0.0.0]: https://github.com/bazel-contrib/rules_python/releases/tag/0.0.0
30+
31+
{#v0-0-0-removed}
32+
### Removed
33+
* Nothing removed.
34+
35+
{#v0-0-0-changed}
36+
### Changed
37+
* Nothing changed.
38+
39+
{#v0-0-0-fixed}
40+
### Fixed
41+
* Nothing fixed.
42+
43+
{#v0-0-0-added}
44+
### Added
45+
* Nothing added.
46+
47+
END_UNRELEASED_TEMPLATE
48+
-->
49+
50+
2651
{#v0-0-0}
2752
## Unreleased
2853

@@ -46,16 +71,16 @@ BEGIN_UNRELEASED_TEMPLATE
4671
implementation assumes that it is always four levels below the runfiles
4772
directory, leading to incorrect path checks
4873
([#3085](https://github.com/bazel-contrib/rules_python/issues/3085)).
74+
* (toolchains) local toolchains now tell the `sys.abiflags` value of the
75+
underlying runtime.
76+
* (performance) 90% reduction in py_binary/py_test analysis phase cost.
77+
([#3381](https://github.com/bazel-contrib/rules_python/pull/3381)).
4978

5079
{#v0-0-0-added}
5180
### Added
5281
* (toolchains) `3.9.25` Python toolchain from [20251031] release.
5382

5483
[20251031]: https://github.com/astral-sh/python-build-standalone/releases/tag/20251031
55-
56-
END_UNRELEASED_TEMPLATE
57-
-->
58-
5984
{#v1-7-0}
6085
## [1.7.0] - 2025-10-11
6186

docs/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
load("@bazel_skylib//rules:build_test.bzl", "build_test")
1616
load("@dev_pip//:requirements.bzl", "requirement")
1717
load("//python/private:bzlmod_enabled.bzl", "BZLMOD_ENABLED") # buildifier: disable=bzl-visibility
18+
load("//python/private:common_labels.bzl", "labels") # buildifier: disable=bzl-visibility
1819
load("//python/uv:lock.bzl", "lock") # buildifier: disable=bzl-visibility
1920
load("//sphinxdocs:readthedocs.bzl", "readthedocs_install")
2021
load("//sphinxdocs:sphinx.bzl", "sphinx_build_binary", "sphinx_docs")
@@ -161,6 +162,10 @@ readthedocs_install(
161162

162163
sphinx_build_binary(
163164
name = "sphinx-build",
165+
config_settings = {
166+
labels.BOOTSTRAP_IMPL: "script",
167+
labels.VENVS_SITE_PACKAGES: "yes",
168+
},
164169
target_compatible_with = _TARGET_COMPATIBLE_WITH,
165170
deps = [
166171
requirement("sphinx"),

examples/multi_python_versions/MODULE.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use_repo(
3535

3636
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
3737
use_repo(pip, "pypi")
38+
3839
pip.parse(
3940
hub_name = "pypi",
4041
python_version = "3.9",

examples/pip_parse_vendored/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
33
load("@bazel_skylib//rules:write_file.bzl", "write_file")
44
load("@rules_python//python:pip.bzl", "compile_pip_requirements")
55
load("@rules_python//python:py_test.bzl", "py_test")
6+
load("@rules_shell//shell:sh_binary.bzl", "sh_binary")
67
load("//:requirements.bzl", "all_data_requirements", "all_requirements", "all_whl_requirements", "requirement")
78

89
# This rule adds a convenient way to update the requirements.txt

examples/pip_parse_vendored/WORKSPACE

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,3 +39,19 @@ pip_parse(
3939
load("//:requirements.bzl", "install_deps")
4040

4141
install_deps()
42+
43+
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
44+
45+
# See https://github.com/bazelbuild/rules_shell/releases/tag/v0.2.0
46+
http_archive(
47+
name = "rules_shell",
48+
sha256 = "410e8ff32e018b9efd2743507e7595c26e2628567c42224411ff533b57d27c28",
49+
strip_prefix = "rules_shell-0.2.0",
50+
url = "https://github.com/bazelbuild/rules_shell/releases/download/v0.2.0/rules_shell-v0.2.0.tar.gz",
51+
)
52+
53+
load("@rules_shell//shell:repositories.bzl", "rules_shell_dependencies", "rules_shell_toolchains")
54+
55+
rules_shell_dependencies()
56+
57+
rules_shell_toolchains()

python/private/get_local_runtime_info.py

Lines changed: 53 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
1514
"""Returns information about the local Python runtime as JSON."""
1615

1716
import json
@@ -38,7 +37,9 @@ def _search_directories(get_config, base_executable):
3837
# On MacOS, the LDLIBRARY may be a relative path under /Library/Frameworks,
3938
# such as "Python.framework/Versions/3.12/Python", not a file under the
4039
# LIBDIR/LIBPL directory, so include PYTHONFRAMEWORKPREFIX.
41-
lib_dirs = [get_config(x) for x in ("PYTHONFRAMEWORKPREFIX", "LIBPL", "LIBDIR")]
40+
lib_dirs = [
41+
get_config(x) for x in ("PYTHONFRAMEWORKPREFIX", "LIBPL", "LIBDIR")
42+
]
4243

4344
# On Debian, with multiarch enabled, prior to Python 3.10, `LIBDIR` didn't
4445
# tell the location of the libs, just the base directory. The `MULTIARCH`
@@ -55,8 +56,8 @@ def _search_directories(get_config, base_executable):
5556

5657
if not _IS_DARWIN:
5758
for exec_dir in (
58-
os.path.dirname(base_executable) if base_executable else None,
59-
get_config("BINDIR"),
59+
os.path.dirname(base_executable) if base_executable else None,
60+
get_config("BINDIR"),
6061
):
6162
if not exec_dir:
6263
continue
@@ -67,16 +68,28 @@ def _search_directories(get_config, base_executable):
6768
lib_dirs.append(os.path.join(exec_dir, "lib"))
6869
lib_dirs.append(os.path.join(exec_dir, "libs"))
6970
else:
70-
# On most systems the executable is in a bin/ directory and the libraries
71-
# are in a sibling lib/ directory.
71+
# On most non-windows systems the executable is in a bin/ directory and
72+
# the libraries are in a sibling lib/ directory.
7273
lib_dirs.append(os.path.join(os.path.dirname(exec_dir), "lib"))
7374

7475
# Dedup and remove empty values, keeping the order.
7576
lib_dirs = [v for v in lib_dirs if v]
7677
return {k: None for k in lib_dirs}.keys()
7778

7879

79-
def _search_library_names(get_config):
80+
def _get_shlib_suffix(get_config) -> str:
81+
"""Returns the suffix for shared libraries."""
82+
if _IS_DARWIN:
83+
return ".dylib"
84+
if _IS_WINDOWS:
85+
return ".dll"
86+
suffix = get_config("SHLIB_SUFFIX")
87+
if not suffix:
88+
suffix = ".so"
89+
return suffix
90+
91+
92+
def _search_library_names(get_config, shlib_suffix):
8093
"""Returns a list of library files to search for shared libraries."""
8194
# Quoting configure.ac in the cpython code base:
8295
# "INSTSONAME is the name of the shared library that will be use to install
@@ -90,8 +103,7 @@ def _search_library_names(get_config):
90103
#
91104
# A typical LIBRARY is 'libpythonX.Y.a' on Linux.
92105
lib_names = [
93-
get_config(x)
94-
for x in (
106+
get_config(x) for x in (
95107
"LDLIBRARY",
96108
"INSTSONAME",
97109
"PY3LIBRARY",
@@ -104,26 +116,24 @@ def _search_library_names(get_config):
104116
# The suffix and version are set here to the default values for the OS,
105117
# since they are used below to construct "default" library names.
106118
if _IS_DARWIN:
107-
suffix = ".dylib"
108119
prefix = "lib"
109120
elif _IS_WINDOWS:
110-
suffix = ".dll"
111121
prefix = ""
112122
else:
113-
suffix = get_config("SHLIB_SUFFIX")
114123
prefix = "lib"
115-
if not suffix:
116-
suffix = ".so"
117124

118125
version = get_config("VERSION")
119126

120127
# Ensure that the pythonXY.dll files are included in the search.
121-
lib_names.append(f"{prefix}python{version}{suffix}")
128+
lib_names.append(f"{prefix}python{version}{shlib_suffix}")
122129

123130
# If there are ABIFLAGS, also add them to the python version lib search.
124131
abiflags = get_config("ABIFLAGS") or get_config("abiflags") or ""
125132
if abiflags:
126-
lib_names.append(f"{prefix}python{version}{abiflags}{suffix}")
133+
lib_names.append(f"{prefix}python{version}{abiflags}{shlib_suffix}")
134+
135+
# Add the abi-version includes to the search list.
136+
lib_names.append(f"{prefix}python{sys.version_info.major}{shlib_suffix}")
127137

128138
# Dedup and remove empty values, keeping the order.
129139
lib_names = [v for v in lib_names if v]
@@ -138,30 +148,31 @@ def _get_python_library_info(base_executable):
138148
# construct library paths such as python3.12, so ensure it exists.
139149
if not config_vars.get("VERSION"):
140150
if sys.platform == "win32":
141-
config_vars["VERSION"] = f"{sys.version_info.major}{sys.version_info.minor}"
151+
config_vars["VERSION"] = (
152+
f"{sys.version_info.major}{sys.version_info.minor}")
142153
else:
143154
config_vars["VERSION"] = (
144-
f"{sys.version_info.major}.{sys.version_info.minor}"
145-
)
155+
f"{sys.version_info.major}.{sys.version_info.minor}")
146156

157+
shlib_suffix = _get_shlib_suffix(config_vars.get)
147158
search_directories = _search_directories(config_vars.get, base_executable)
148-
search_libnames = _search_library_names(config_vars.get)
149-
150-
def _add_if_exists(target, path):
151-
if os.path.exists(path) or os.path.isdir(path):
152-
target[path] = None
159+
search_libnames = _search_library_names(config_vars.get, shlib_suffix)
153160

154161
interface_libraries = {}
155162
dynamic_libraries = {}
156163
static_libraries = {}
164+
157165
for root_dir in search_directories:
158166
for libname in search_libnames:
167+
# Check whether the library exists.
159168
composed_path = os.path.join(root_dir, libname)
160-
if libname.endswith(".a"):
161-
_add_if_exists(static_libraries, composed_path)
162-
continue
169+
if os.path.exists(composed_path) or os.path.isdir(composed_path):
170+
if libname.endswith(".a"):
171+
static_libraries[composed_path] = None
172+
else:
173+
dynamic_libraries[composed_path] = None
163174

164-
_add_if_exists(dynamic_libraries, composed_path)
175+
interface_path = None
165176
if libname.endswith(".dll"):
166177
# On windows a .lib file may be an "import library" or a static library.
167178
# The file could be inspected to determine which it is; typically python
@@ -172,14 +183,20 @@ def _add_if_exists(target, path):
172183
#
173184
# See: https://docs.python.org/3/extending/windows.html
174185
# https://learn.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-creation
175-
_add_if_exists(
176-
interface_libraries, os.path.join(root_dir, libname[:-3] + "lib")
177-
)
186+
interface_path = os.path.join(root_dir, libname[:-3] + "lib")
178187
elif libname.endswith(".so"):
179188
# It's possible, though unlikely, that interface stubs (.ifso) exist.
180-
_add_if_exists(
181-
interface_libraries, os.path.join(root_dir, libname[:-2] + "ifso")
182-
)
189+
interface_path = os.path.join(root_dir, libname[:-2] + "ifso")
190+
191+
# Check whether an interface library exists.
192+
if interface_path and os.path.exists(interface_path):
193+
interface_libraries[interface_path] = None
194+
195+
# Non-windows typically has abiflags.
196+
if hasattr(sys, "abiflags"):
197+
abiflags = sys.abiflags
198+
else:
199+
abiflags = ""
183200

184201
# When no libraries are found it's likely that the python interpreter is not
185202
# configured to use shared or static libraries (minilinux). If this seems
@@ -188,6 +205,8 @@ def _add_if_exists(target, path):
188205
"dynamic_libraries": list(dynamic_libraries.keys()),
189206
"static_libraries": list(static_libraries.keys()),
190207
"interface_libraries": list(interface_libraries.keys()),
208+
"shlib_suffix": "" if _IS_WINDOWS else shlib_suffix,
209+
"abi_flags": abiflags,
191210
}
192211

193212

0 commit comments

Comments
 (0)