fix: allow spaces in whl_librarys (#2334)
Fixes #617.
Modern `setuptools` versions contain files critical to setuptools
functionality loaded proactively on module load that contain spaces.
Bazel 7.4.0+ now supports files with spaces in their names.
---------
Co-authored-by: Richard Levasseur <richardlev@gmail.com>
Co-authored-by: Richard Levasseur <rlevasseur@google.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e85cfb4..028f0ed 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -39,6 +39,8 @@
* (bzlmod) Generate `config_setting` values for all available toolchains instead
of only the registered toolchains, which restores the previous behaviour that
`bzlmod` users would have observed.
+* (pypi) (Bazel 7.4+) Allow spaces in filenames included in `whl_library`s
+ ([617](https://github.com/bazelbuild/rules_python/issues/617)).
{#v0-0-0-added}
### Added
diff --git a/examples/bzlmod/MODULE.bazel.lock b/examples/bzlmod/MODULE.bazel.lock
index c41380c..d36ec9f 100644
--- a/examples/bzlmod/MODULE.bazel.lock
+++ b/examples/bzlmod/MODULE.bazel.lock
@@ -1392,13 +1392,13 @@
},
"@@rules_python~//python/extensions:pip.bzl%pip": {
"general": {
- "bzlTransitiveDigest": "g9NnJTZcM2BjPelxHHLy0ZyhFd+8XAb86u9OvNIOhFo=",
+ "bzlTransitiveDigest": "ovGr2x1QDHBffYRqtz5fRgBCvBIG9xO/6Lk2UEnqj48=",
"usagesDigest": "MChlcSw99EuW3K7OOoMcXQIdcJnEh6YmfyjJm+9mxIg=",
"recordedFileInputs": {
"@@other_module~//requirements_lock_3_11.txt": "a7d0061366569043d5efcf80e34a32c732679367cb3c831c4cdc606adc36d314",
"@@rules_python~//python/private/pypi/whl_installer/platform.py": "b944b908b25a2f97d6d9f491504ad5d2507402d7e37c802ee878783f87f2aa11",
"@@//requirements_lock_3_10.txt": "5e7083982a7e60f34998579a0ae83b520d46ab8f2552cc51337217f024e6def5",
- "@@rules_python~~internal_deps~pypi__packaging//BUILD.bazel": "8d36246aeefaab4b26fb9c1175cfaf13df5b6f1587e6753f1e78b132bad74795",
+ "@@rules_python~~internal_deps~pypi__packaging//BUILD.bazel": "16cf02cdc6cd989d8a92b551d406abea3fe597b1524ba5fa88f0410010671d7f",
"@@//whl_mods/appended_build_content.BUILD": "87745b00382c66e5efbd7cb44a08fc3edbf7fd5099cf593f87599188f1557a9e",
"@@//requirements_lock_3_9.txt": "6a4990586366467d1e7d56d9f2ec9bafdd7e17fb29dc959aa5a6b0395c22eac7",
"@@rules_python~~internal_deps~pypi__packaging//packaging-24.0.dist-info/RECORD": "be1aea790359b4c2c9ea83d153c1a57c407742a35b95ee36d00723509f5ed5dd",
@@ -6299,7 +6299,7 @@
},
"@@rules_python~//python/private/pypi:pip.bzl%pip_internal": {
"general": {
- "bzlTransitiveDigest": "ctc7nzMsQfNG16wSXLqbix2k99rf614qJRwcd/2RxGI=",
+ "bzlTransitiveDigest": "OP8sZohIIGi+NNlfo7dAnU3yGo3Ea4xAU6TgzbPbCgw=",
"usagesDigest": "LYtSAPzhPjmfD9vF39mCED1UQSvHEo2Hv+aK5Z4ZWWc=",
"recordedFileInputs": {
"@@rules_python~//tools/publish/requirements_linux.txt": "8175b4c8df50ae2f22d1706961884beeb54e7da27bd2447018314a175981997d",
diff --git a/python/private/BUILD.bazel b/python/private/BUILD.bazel
index 7741e55..7399b10 100644
--- a/python/private/BUILD.bazel
+++ b/python/private/BUILD.bazel
@@ -174,6 +174,12 @@
)
bzl_library(
+ name = "glob_excludes_bzl",
+ srcs = ["glob_excludes.bzl"],
+ deps = [":util_bzl"],
+)
+
+bzl_library(
name = "internal_config_repo_bzl",
srcs = ["internal_config_repo.bzl"],
deps = [":bzlmod_enabled_bzl"],
diff --git a/python/private/glob_excludes.bzl b/python/private/glob_excludes.bzl
new file mode 100644
index 0000000..c98afe0
--- /dev/null
+++ b/python/private/glob_excludes.bzl
@@ -0,0 +1,32 @@
+# Copyright 2024 The Bazel Authors. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"Utilities for glob exclusions."
+
+load(":util.bzl", "IS_BAZEL_7_4_OR_HIGHER")
+
+def _version_dependent_exclusions():
+ """Returns glob exclusions that are sensitive to Bazel version.
+
+ Returns:
+ a list of glob exclusion patterns
+ """
+ if IS_BAZEL_7_4_OR_HIGHER:
+ return []
+ else:
+ return ["**/* *"]
+
+glob_excludes = struct(
+ version_dependent_exclusions = _version_dependent_exclusions,
+)
diff --git a/python/private/hermetic_runtime_repo_setup.bzl b/python/private/hermetic_runtime_repo_setup.bzl
index 4b5a3c6..cf9a5a6 100644
--- a/python/private/hermetic_runtime_repo_setup.bzl
+++ b/python/private/hermetic_runtime_repo_setup.bzl
@@ -17,6 +17,7 @@
load("//python:py_runtime.bzl", "py_runtime")
load("//python:py_runtime_pair.bzl", "py_runtime_pair")
load("//python/cc:py_cc_toolchain.bzl", "py_cc_toolchain")
+load(":glob_excludes.bzl", "glob_excludes")
load(":py_exec_tools_toolchain.bzl", "py_exec_tools_toolchain")
load(":semver.bzl", "semver")
@@ -64,7 +65,6 @@
# Platform-agnostic filegroup can't match on all patterns.
allow_empty = True,
exclude = [
- "**/* *", # Bazel does not support spaces in file names.
# Unused shared libraries. `python` executable and the `:libpython` target
# depend on `libpython{python_version}.so.1.0`.
"lib/libpython{major}.{minor}.so".format(**version_dict),
@@ -74,7 +74,7 @@
"lib/python{major}.{minor}/**/test/**".format(**version_dict),
"lib/python{major}.{minor}/**/tests/**".format(**version_dict),
"**/__pycache__/*.pyc.*", # During pyc creation, temp files named *.pyc.NNN are created
- ] + extra_files_glob_exclude,
+ ] + glob_excludes.version_dependent_exclusions() + extra_files_glob_exclude,
),
)
cc_import(
diff --git a/python/private/pypi/BUILD.bazel b/python/private/pypi/BUILD.bazel
index 9be355c..20afe70 100644
--- a/python/private/pypi/BUILD.bazel
+++ b/python/private/pypi/BUILD.bazel
@@ -86,6 +86,7 @@
srcs = ["deps.bzl"],
deps = [
"//python/private:bazel_tools_bzl",
+ "//python/private:glob_excludes_bzl",
],
)
diff --git a/python/private/pypi/deps.bzl b/python/private/pypi/deps.bzl
index e07d9aa..8949ed4 100644
--- a/python/private/pypi/deps.bzl
+++ b/python/private/pypi/deps.bzl
@@ -101,6 +101,7 @@
package(default_visibility = ["//visibility:public"])
load("@rules_python//python:defs.bzl", "py_library")
+load("@rules_python//python/private:glob_excludes.bzl", "glob_excludes")
py_library(
name = "lib",
@@ -111,11 +112,10 @@
"**/*.py",
"**/*.pyc",
"**/*.pyc.*", # During pyc creation, temp files named *.pyc.NNN are created
- "**/* *",
"**/*.dist-info/RECORD",
"BUILD",
"WORKSPACE",
- ]),
+ ] + glob_excludes.version_dependent_exclusions()),
# This makes this directory a top-level in the python import
# search path for anything that depends on this.
imports = ["."],
diff --git a/python/private/pypi/whl_library_targets.bzl b/python/private/pypi/whl_library_targets.bzl
index 1798b9d..a303bdc 100644
--- a/python/private/pypi/whl_library_targets.bzl
+++ b/python/private/pypi/whl_library_targets.bzl
@@ -17,6 +17,7 @@
load("@bazel_skylib//rules:copy_file.bzl", "copy_file")
load("//python:py_binary.bzl", "py_binary")
load("//python:py_library.bzl", "py_library")
+load("//python/private:glob_excludes.bzl", "glob_excludes")
load("//python/private:normalize_name.bzl", "normalize_name")
load(
":labels.bzl",
@@ -222,7 +223,6 @@
if hasattr(rules, "py_library"):
_data_exclude = [
- "**/* *",
"**/*.py",
"**/*.pyc",
"**/*.pyc.*", # During pyc creation, temp files named *.pyc.NNNN are created
@@ -230,7 +230,7 @@
# of generated files produced when wheels are installed. The file is ignored to avoid
# Bazel caching issues.
"**/*.dist-info/RECORD",
- ]
+ ] + glob_excludes.version_dependent_exclusions()
for item in data_exclude:
if item not in _data_exclude:
_data_exclude.append(item)
diff --git a/python/private/util.bzl b/python/private/util.bzl
index 033920d..33261be 100644
--- a/python/private/util.bzl
+++ b/python/private/util.bzl
@@ -99,6 +99,8 @@
return provider("Stub, not used", fields = []), None
return provider(doc = doc, fields = fields, **kwargs)
+IS_BAZEL_7_4_OR_HIGHER = hasattr(native, "legacy_globals")
+
IS_BAZEL_7_OR_HIGHER = hasattr(native, "starlark_doc_extract")
# Bazel 5.4 has a bug where every access of testing.ExecutionInfo is a
diff --git a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
index 9694eee..e69eb0f 100644
--- a/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
+++ b/tests/pypi/whl_library_targets/whl_library_targets_tests.bzl
@@ -15,6 +15,7 @@
""
load("@rules_testing//lib:test_suite.bzl", "test_suite")
+load("//python/private:glob_excludes.bzl", "glob_excludes") # buildifier: disable=bzl-visibility
load("//python/private/pypi:whl_library_targets.bzl", "whl_library_targets") # buildifier: disable=bzl-visibility
_tests = []
@@ -246,7 +247,12 @@
),
"data": [] + _glob(
["site-packages/**/*"],
- exclude = ["**/* *", "**/*.py", "**/*.pyc", "**/*.pyc.*", "**/*.dist-info/RECORD"],
+ exclude = [
+ "**/*.py",
+ "**/*.pyc",
+ "**/*.pyc.*",
+ "**/*.dist-info/RECORD",
+ ] + glob_excludes.version_dependent_exclusions(),
),
"imports": ["site-packages"],
"deps": [
@@ -312,7 +318,12 @@
"srcs": _glob(["site-packages/**/*.py"], exclude = [], allow_empty = True),
"data": [] + _glob(
["site-packages/**/*"],
- exclude = ["**/* *", "**/*.py", "**/*.pyc", "**/*.pyc.*", "**/*.dist-info/RECORD"],
+ exclude = [
+ "**/*.py",
+ "**/*.pyc",
+ "**/*.pyc.*",
+ "**/*.dist-info/RECORD",
+ ] + glob_excludes.version_dependent_exclusions(),
),
"imports": ["site-packages"],
"deps": ["@pypi_bar_baz//:pkg"] + _select({