From f40038e14b17ad2ea17292bb3a6438ec28a7fc3b Mon Sep 17 00:00:00 2001 From: Mark Elliot <123787712+mark-thm@users.noreply.github.com> Date: Wed, 30 Oct 2024 12:11:53 -0400 Subject: [PATCH] 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 Co-authored-by: Richard Levasseur --- CHANGELOG.md | 2 ++ examples/bzlmod/MODULE.bazel.lock | 6 ++-- python/private/BUILD.bazel | 6 ++++ python/private/glob_excludes.bzl | 32 +++++++++++++++++++ .../private/hermetic_runtime_repo_setup.bzl | 4 +-- python/private/pypi/BUILD.bazel | 1 + python/private/pypi/deps.bzl | 4 +-- python/private/pypi/whl_library_targets.bzl | 4 +-- python/private/util.bzl | 2 ++ .../whl_library_targets_tests.bzl | 15 +++++++-- 10 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 python/private/glob_excludes.bzl diff --git a/CHANGELOG.md b/CHANGELOG.md index e85cfb46f2..028f0ed0a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,8 @@ A brief description of the categories of changes: * (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 c41380c6be..d36ec9fa0f 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 7741e553ce..7399b104e0 100644 --- a/python/private/BUILD.bazel +++ b/python/private/BUILD.bazel @@ -173,6 +173,12 @@ bzl_library( srcs = ["full_version.bzl"], ) +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"], diff --git a/python/private/glob_excludes.bzl b/python/private/glob_excludes.bzl new file mode 100644 index 0000000000..c98afe0ae2 --- /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 4b5a3c6810..cf9a5a6b1d 100644 --- a/python/private/hermetic_runtime_repo_setup.bzl +++ b/python/private/hermetic_runtime_repo_setup.bzl @@ -17,6 +17,7 @@ load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library") 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 @@ def define_hermetic_runtime_toolchain_impl( # 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 @@ def define_hermetic_runtime_toolchain_impl( "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 9be355c0c3..20afe70771 100644 --- a/python/private/pypi/BUILD.bazel +++ b/python/private/pypi/BUILD.bazel @@ -86,6 +86,7 @@ bzl_library( 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 e07d9aa8db..8949ed4abe 100644 --- a/python/private/pypi/deps.bzl +++ b/python/private/pypi/deps.bzl @@ -101,6 +101,7 @@ _GENERIC_WHEEL = """\ 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_library( "**/*.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 1798b9d775..a303bdcd9a 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 @@ def whl_library_targets( if hasattr(rules, "py_library"): _data_exclude = [ - "**/* *", "**/*.py", "**/*.pyc", "**/*.pyc.*", # During pyc creation, temp files named *.pyc.NNNN are created @@ -230,7 +230,7 @@ def whl_library_targets( # 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 033920d3bf..33261befaf 100644 --- a/python/private/util.bzl +++ b/python/private/util.bzl @@ -99,6 +99,8 @@ def define_bazel_6_provider(doc, fields, **kwargs): 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 9694eeec48..e69eb0f0e9 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 @@ def _test_whl_and_library_deps(env): ), "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 @@ def _test_group(env): "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({