From a531bceb7f604bfdc8441a84096e8d799a76e4ce Mon Sep 17 00:00:00 2001 From: Rahul Mehta Date: Fri, 18 Oct 2024 09:12:34 -0400 Subject: [PATCH] fix: use shutil instead of cp during pbs bootstrap --- .../python_build_standalone/rules.py | 38 +++++++++---------- .../rules_integration_test.py | 1 + 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/python/pants/backend/python/providers/python_build_standalone/rules.py b/src/python/pants/backend/python/providers/python_build_standalone/rules.py index 2d8e2725bad..4e032b2eb66 100644 --- a/src/python/pants/backend/python/providers/python_build_standalone/rules.py +++ b/src/python/pants/backend/python/providers/python_build_standalone/rules.py @@ -5,8 +5,10 @@ import collections.abc import functools import json +import os +import shutil import textwrap -from typing import Iterable, TypedDict, cast +from typing import Iterable, TypedDict, Union, cast from pants.backend.python.subsystems.setup import PythonSetup from pants.backend.python.util_rules.interpreter_constraints import InterpreterConstraints @@ -40,6 +42,8 @@ PBS_NAMED_CACHE_NAME = "python_build_standalone" PBS_APPEND_ONLY_CACHES = FrozenDict({PBS_NAMED_CACHE_NAME: PBS_SANDBOX_NAME}) +StrPath = Union[str, bytes, os.PathLike] + class PBSPythonInfo(TypedDict): url: str @@ -190,7 +194,7 @@ async def get_python( ) pbs_py_info = versions_info[python_version][platform.value] - downloaded_python = await Get( + await Get( DownloadedExternalTool, ExternalToolRequest( DownloadFile( @@ -204,25 +208,12 @@ async def get_python( ), ) - await Get( - ProcessResult, - Process( - [ - cp.path, - "--recursive", - "--no-clobber", - "python", - f"{PBS_SANDBOX_NAME}/{python_version}", - ], - level=LogLevel.DEBUG, - input_digest=downloaded_python.digest, - description=f"Install Python {python_version}", - append_only_caches=PBS_APPEND_ONLY_CACHES, - # Don't cache, we want this to always be run so that we can assume for the rest of the - # session the named_cache destination for this Python is valid, as the Python ecosystem - # mainly assumes absolute paths for Python interpreters. - cache_scope=ProcessCacheScope.PER_SESSION, - ), + # Copy the python binary into the sandbox + shutil.copytree( + "python", + f"{PBS_SANDBOX_NAME}/{python_version}", + dirs_exist_ok=True, + copy_function=_copy_no_clobber, ) python_path = named_caches_dir.val / PBS_NAMED_CACHE_NAME / python_version / "bin" / "python3" @@ -242,3 +233,8 @@ def rules(): *external_tools_rules(), UnionRule(PythonProvider, PBSPythonProvider), ) + + +def _copy_no_clobber(src: StrPath, dst: StrPath) -> None: + if not os.path.exists(dst): + shutil.copy2(src, dst) diff --git a/src/python/pants/backend/python/providers/python_build_standalone/rules_integration_test.py b/src/python/pants/backend/python/providers/python_build_standalone/rules_integration_test.py index f519bd126d8..58bc651afac 100644 --- a/src/python/pants/backend/python/providers/python_build_standalone/rules_integration_test.py +++ b/src/python/pants/backend/python/providers/python_build_standalone/rules_integration_test.py @@ -72,6 +72,7 @@ def run_run_request( return mocked_console[1].get_stdout().strip() +@pytest.mark.platform_specific_behavior @pytest.mark.parametrize("py_version", ["3.8.*", "3.9.*", "3.9.10"]) def test_using_pbs(rule_runner, py_version): rule_runner.write_files(