diff --git a/CHANGELOG.md b/CHANGELOG.md index 355f1fe9ef..0a2dc413ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -93,6 +93,8 @@ END_UNRELEASED_TEMPLATE also retrieved from the URL as opposed to only the `--hash` parameter. Fixes [#2363](https://github.com/bazel-contrib/rules_python/issues/2363). * (pypi) `whl_library` now infers file names from its `urls` attribute correctly. +* (pypi) When running under `bazel test`, be sure that temporary `requirements` file + remains writable. * (py_test, py_binary) Allow external files to be used for main {#v0-0-0-added} diff --git a/python/private/pypi/dependency_resolver/dependency_resolver.py b/python/private/pypi/dependency_resolver/dependency_resolver.py index ada0763558..a42821c458 100644 --- a/python/private/pypi/dependency_resolver/dependency_resolver.py +++ b/python/private/pypi/dependency_resolver/dependency_resolver.py @@ -151,9 +151,16 @@ def main( requirements_out = os.path.join( os.environ["TEST_TMPDIR"], os.path.basename(requirements_file) + ".out" ) + # Why this uses shutil.copyfileobj: + # # Those two files won't necessarily be on the same filesystem, so we can't use os.replace # or shutil.copyfile, as they will fail with OSError: [Errno 18] Invalid cross-device link. - shutil.copy(resolved_requirements_file, requirements_out) + # + # Further, shutil.copy preserves the source file's mode, and so if + # our source file is read-only (the default under Perforce Helix), + # this scratch file will also be read-only, defeating its purpose. + with open(resolved_requirements_file, "rb") as fsrc, open(requirements_out, "wb") as fdst: + shutil.copyfileobj(fsrc, fdst) update_command = ( os.getenv("CUSTOM_COMPILE_COMMAND") or f"bazel run {target_label_prefix}.update"