Skip to content

Commit 2c3fc1b

Browse files
committed
Merge remote-tracking branch 'upstream/main' into HEAD
2 parents 9730855 + 084865d commit 2c3fc1b

File tree

15 files changed

+211
-50
lines changed

15 files changed

+211
-50
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@ jobs:
4242
# Use GH feature to populate the changelog automatically
4343
generate_release_notes: true
4444
body_path: release_notes.txt
45+
prerelease: ${{ contains(github.ref, '-rc') }}
4546
fail_on_unmatched_files: true
4647
files: rules_python-*.tar.gz

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Other changes:
8080
otherwise empty) virtual env is used to customize `sys.path` initialization.
8181
* (deps) bazel_skylib 1.7.0 (workspace; bzlmod already specifying that version)
8282
* (deps) bazel_features 1.21.0; necessary for compatiblity with Bazel 8 rc3
83+
* (deps) stardoc 0.7.2 to support Bazel 8.
8384

8485
{#v0-0-0-fixed}
8586
### Fixed
@@ -94,6 +95,11 @@ Other changes:
9495
([2169](https://github.com/bazelbuild/rules_python/issues/2169)).
9596
* (workspace) Corrected protobuf's name to com_google_protobuf, the name is
9697
hardcoded in Bazel, WORKSPACE mode.
98+
* (pypi): {bzl:obj}`compile_pip_requirements` no longer fails on Windows when `--enable_runfiles` is not enabled.
99+
* (pypi): {bzl:obj}`compile_pip_requirements` now correctly updates files in the source tree on Windows when `--windows_enable_symlinks` is not enabled.
100+
* (repositories): Add libs/python3.lib and pythonXY.dll to the `libpython` target
101+
defined by a repository template. This enables stable ABI builds of Python extensions
102+
on Windows (by defining Py_LIMITED_API).
97103

98104
{#v0-0-0-added}
99105
### Added
@@ -111,6 +117,7 @@ Other changes:
111117
* (providers) Added {obj}`py_runtime_info.site_init_template` and
112118
{obj}`PyRuntimeInfo.site_init_template` for specifying the template to use to
113119
initialize the interpreter via venv startup hooks.
120+
* (runfiles) (Bazel 7.4+) Added support for spaces and newlines in runfiles paths
114121

115122
{#v0-0-0-removed}
116123
### Removed

MODULE.bazel

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ pip.parse(
7171
use_repo(pip, "rules_python_publish_deps")
7272

7373
# Not a dev dependency to allow usage of //sphinxdocs code, which refers to stardoc repos.
74-
bazel_dep(name = "stardoc", version = "0.7.1", repo_name = "io_bazel_stardoc")
74+
bazel_dep(name = "stardoc", version = "0.7.2", repo_name = "io_bazel_stardoc")
7575

7676
# ===== DEV ONLY DEPS AND SETUP BELOW HERE =====
77-
bazel_dep(name = "rules_bazel_integration_test", version = "0.26.1", dev_dependency = True)
77+
bazel_dep(name = "rules_bazel_integration_test", version = "0.27.0", dev_dependency = True)
7878
bazel_dep(name = "rules_testing", version = "0.6.0", dev_dependency = True)
7979
bazel_dep(name = "rules_shell", version = "0.3.0", dev_dependency = True)
8080
bazel_dep(name = "rules_multirun", version = "0.9.0", dev_dependency = True)

python/private/hermetic_runtime_repo_setup.bzl

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,14 @@ def define_hermetic_runtime_toolchain_impl(
8989
}),
9090
system_provided = True,
9191
)
92+
cc_import(
93+
name = "abi3_interface",
94+
interface_library = select({
95+
_IS_FREETHREADED: "libs/python3t.lib",
96+
"//conditions:default": "libs/python3.lib",
97+
}),
98+
system_provided = True,
99+
)
92100

93101
native.filegroup(
94102
name = "includes",
@@ -97,7 +105,7 @@ def define_hermetic_runtime_toolchain_impl(
97105
cc_library(
98106
name = "python_headers",
99107
deps = select({
100-
"@bazel_tools//src/conditions:windows": [":interface"],
108+
"@bazel_tools//src/conditions:windows": [":interface", ":abi3_interface"],
101109
"//conditions:default": None,
102110
}),
103111
hdrs = [":includes"],
@@ -156,15 +164,22 @@ def define_hermetic_runtime_toolchain_impl(
156164
"lib/libpython{major}.{minor}t.dylib".format(**version_dict),
157165
],
158166
":is_freethreaded_windows": [
159-
"python3.dll",
167+
"python3t.dll",
168+
"python{major}{minor}t.dll".format(**version_dict),
160169
"libs/python{major}{minor}t.lib".format(**version_dict),
170+
"libs/python3t.lib",
161171
],
162172
"@platforms//os:linux": [
163173
"lib/libpython{major}.{minor}.so".format(**version_dict),
164174
"lib/libpython{major}.{minor}.so.1.0".format(**version_dict),
165175
],
166176
"@platforms//os:macos": ["lib/libpython{major}.{minor}.dylib".format(**version_dict)],
167-
"@platforms//os:windows": ["python3.dll", "libs/python{major}{minor}.lib".format(**version_dict)],
177+
"@platforms//os:windows": [
178+
"python3.dll",
179+
"python{major}{minor}.dll".format(**version_dict),
180+
"libs/python{major}{minor}.lib".format(**version_dict),
181+
"libs/python3.lib",
182+
],
168183
}),
169184
)
170185

python/private/pypi/dependency_resolver/dependency_resolver.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,19 +170,26 @@ def main(
170170

171171
if UPDATE:
172172
print("Updating " + requirements_file_relative)
173+
174+
# Make sure the output file for pip_compile exists. It won't if we are on Windows and --enable_runfiles is not set.
175+
if not os.path.exists(requirements_file_relative):
176+
os.makedirs(os.path.dirname(requirements_file_relative), exist_ok=True)
177+
shutil.copy(resolved_requirements_file, requirements_file_relative)
178+
173179
if "BUILD_WORKSPACE_DIRECTORY" in os.environ:
174180
workspace = os.environ["BUILD_WORKSPACE_DIRECTORY"]
175181
requirements_file_tree = os.path.join(workspace, requirements_file_relative)
182+
absolute_output_file = Path(requirements_file_relative).absolute()
176183
# In most cases, requirements_file will be a symlink to the real file in the source tree.
177184
# If symlinks are not enabled (e.g. on Windows), then requirements_file will be a copy,
178185
# and we should copy the updated requirements back to the source tree.
179-
if not os.path.samefile(resolved_requirements_file, requirements_file_tree):
186+
if not absolute_output_file.samefile(requirements_file_tree):
180187
atexit.register(
181188
lambda: shutil.copy(
182-
resolved_requirements_file, requirements_file_tree
189+
absolute_output_file, requirements_file_tree
183190
)
184191
)
185-
cli(argv)
192+
cli(argv, standalone_mode = False)
186193
requirements_file_relative_path = Path(requirements_file_relative)
187194
content = requirements_file_relative_path.read_text()
188195
content = content.replace(absolute_path_prefix, "")

python/private/pypi/extension.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def _create_whl_repos(
6868
pip_attr,
6969
whl_overrides,
7070
simpleapi_cache,
71+
evaluate_markers = evaluate_markers,
7172
available_interpreters = INTERPRETER_LABELS,
7273
simpleapi_download = simpleapi_download):
7374
"""create all of the whl repositories
@@ -78,6 +79,7 @@ def _create_whl_repos(
7879
whl_overrides: {type}`dict[str, struct]` - per-wheel overrides.
7980
simpleapi_cache: {type}`dict` - an opaque dictionary used for caching the results from calling
8081
SimpleAPI evaluating all of the tag class invocations {bzl:obj}`pip.parse`.
82+
evaluate_markers: the function to use to evaluate markers.
8183
simpleapi_download: Used for testing overrides
8284
available_interpreters: {type}`dict[str, Label]` The dictionary of available
8385
interpreters that have been registered using the `python` bzlmod extension.

python/private/pypi/pkg_aliases.bzl

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,31 @@ load(":whl_target_platforms.bzl", "whl_target_platforms")
3636
# it. It is more of an internal consistency check.
3737
_VERSION_NONE = (0, 0)
3838

39+
_CONFIG_SETTINGS_PKG = str(Label("//python/config_settings:BUILD.bazel")).partition(":")[0]
40+
3941
_NO_MATCH_ERROR_TEMPLATE = """\
4042
No matching wheel for current configuration's Python version.
4143
4244
The current build configuration's Python version doesn't match any of the Python
43-
wheels available for this wheel. This wheel supports the following Python
45+
wheels available for this distribution. This distribution supports the following Python
4446
configuration settings:
4547
{config_settings}
4648
4749
To determine the current configuration's Python version, run:
4850
`bazel config <config id>` (shown further below)
49-
and look for
50-
{rules_python}//python/config_settings:python_version
5151
52-
If the value is missing, then the "default" Python version is being used,
53-
which has a "null" version value and will not match version constraints.
54-
"""
52+
and look for one of:
53+
{settings_pkg}:python_version
54+
{settings_pkg}:pip_whl
55+
{settings_pkg}:pip_whl_glibc_version
56+
{settings_pkg}:pip_whl_muslc_version
57+
{settings_pkg}:pip_whl_osx_arch
58+
{settings_pkg}:pip_whl_osx_version
59+
{settings_pkg}:py_freethreaded
60+
{settings_pkg}:py_linux_libc
61+
62+
If the value is missing, then the default value is being used, see documentation:
63+
{docs_url}/python/config_settings"""
5564

5665
def _no_match_error(actual):
5766
if type(actual) != type({}):
@@ -68,7 +77,8 @@ def _no_match_error(actual):
6877
for value in (key if type(key) == "tuple" else [key])
6978
])),
7079
).lstrip(),
71-
rules_python = "rules_python",
80+
settings_pkg = _CONFIG_SETTINGS_PKG,
81+
docs_url = "https://rules-python.readthedocs.io/en/latest/api/rules_python",
7282
)
7383

7484
def pkg_aliases(

python/private/pypi/render_pkg_aliases.bzl

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,17 @@ If the value is missing, then the "default" Python version is being used,
4444
which has a "null" version value and will not match version constraints.
4545
"""
4646

47-
NO_MATCH_ERROR_MESSAGE_TEMPLATE_V2 = """\
48-
No matching wheel for current configuration's Python version.
49-
50-
The current build configuration's Python version doesn't match any of the Python
51-
wheels available for this wheel. This wheel supports the following Python
52-
configuration settings:
53-
{config_settings}
54-
55-
To determine the current configuration's Python version, run:
56-
`bazel config <config id>` (shown further below)
57-
and look for
58-
{rules_python}//python/config_settings:python_version
59-
60-
If the value is missing, then the "default" Python version is being used,
61-
which has a "null" version value and will not match version constraints.
62-
"""
63-
6447
def _repr_dict(*, value_repr = repr, **kwargs):
6548
return {k: value_repr(v) for k, v in kwargs.items() if v}
6649

6750
def _repr_config_setting(alias):
68-
if alias.filename:
51+
if alias.filename or alias.target_platforms:
6952
return render.call(
7053
"whl_config_setting",
7154
**_repr_dict(
7255
filename = alias.filename,
7356
target_platforms = alias.target_platforms,
57+
config_setting = alias.config_setting,
7458
version = alias.version,
7559
)
7660
)

python/private/pypi/whl_config_setting.bzl

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,13 @@
1414

1515
"A small function to create an alias for a whl distribution"
1616

17-
def whl_config_setting(*, repo = None, version = None, config_setting = None, filename = None, target_platforms = None):
17+
def whl_config_setting(*, version = None, config_setting = None, filename = None, target_platforms = None):
1818
"""The bzl_packages value used by by the render_pkg_aliases function.
1919
2020
This contains the minimum amount of information required to generate correct
2121
aliases in a hub repository.
2222
2323
Args:
24-
repo: str, the repo of where to find the things to be aliased.
2524
version: optional(str), the version of the python toolchain that this
2625
whl alias is for. If not set, then non-version aware aliases will be
2726
constructed. This is mainly used for better error messages when there
@@ -43,7 +42,6 @@ def whl_config_setting(*, repo = None, version = None, config_setting = None, fi
4342
return struct(
4443
config_setting = config_setting,
4544
filename = filename,
46-
repo = repo,
4745
# Make the struct hashable
4846
target_platforms = tuple(target_platforms) if target_platforms else None,
4947
version = version,

python/runfiles/runfiles.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -58,13 +58,24 @@ def _LoadRunfiles(path: str) -> Dict[str, str]:
5858
result = {}
5959
with open(path, "r") as f:
6060
for line in f:
61-
line = line.strip()
62-
if line:
63-
tokens = line.split(" ", 1)
64-
if len(tokens) == 1:
65-
result[line] = line
66-
else:
67-
result[tokens[0]] = tokens[1]
61+
line = line.rstrip("\n")
62+
if line.startswith(" "):
63+
# In lines that start with a space, spaces, newlines, and backslashes are escaped as \s, \n, and \b in
64+
# link and newlines and backslashes are escaped in target.
65+
escaped_link, escaped_target = line[1:].split(" ", maxsplit=1)
66+
link = (
67+
escaped_link.replace(r"\s", " ")
68+
.replace(r"\n", "\n")
69+
.replace(r"\b", "\\")
70+
)
71+
target = escaped_target.replace(r"\n", "\n").replace(r"\b", "\\")
72+
else:
73+
link, target = line.split(" ", maxsplit=1)
74+
75+
if target:
76+
result[link] = target
77+
else:
78+
result[link] = link
6879
return result
6980

7081
def _GetRunfilesDir(self) -> str:

0 commit comments

Comments
 (0)