Skip to content

Commit d0fd7df

Browse files
committed
Revert "Revert "Prefix the entire setup.py chroot. (pantsbuild#12359)" (pantsbuild#12370)"
This reverts commit 9f5ff78. [ci skip-rust]
1 parent 40469dc commit d0fd7df

File tree

4 files changed

+45
-29
lines changed

4 files changed

+45
-29
lines changed

src/python/pants/BUILD

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ python_distribution(
2828
# used when creating the wheel, which is a good thing. We should be setting this ABI to ensure
2929
# consumers of pantsbuild.pants are using a compatible interpreter.
3030
# TODO(7344): the tuple syntax for ext_modules is deprecated. Use Extension once we support it.
31-
ext_modules=[('native_engine', {'sources': ['src/pants/dummy.c']})],
31+
ext_modules=[('native_engine', {'sources': ['pants/dummy.c']})],
3232
).with_binaries(
3333
pants='src/python/pants/bin:pants',
3434
)

src/python/pants/backend/python/goals/setup_py.py

+24-16
Original file line numberDiff line numberDiff line change
@@ -405,10 +405,6 @@ async def package_python_dist(
405405
return BuiltPackage(rel_chroot, (BuiltPackageArtifact(dirname),))
406406

407407

408-
# We write .py sources into the chroot under this dir.
409-
CHROOT_SOURCE_ROOT = "src"
410-
411-
412408
SETUP_BOILERPLATE = """
413409
# DO NOT EDIT THIS FILE -- AUTOGENERATED BY PANTS
414410
# Target: {target_address_spec}
@@ -433,22 +429,40 @@ async def run_setup_py(req: RunSetupPyRequest, setuptools: Setuptools) -> RunSet
433429
interpreter_constraints=req.interpreter_constraints,
434430
),
435431
)
432+
433+
# We prefix the entire chroot, and run with this prefix as the cwd, so that we can capture any
434+
# changes setup made within it (e.g., when running 'develop') without also capturing other
435+
# artifacts of the pex process invocation.
436+
chroot_prefix = "chroot"
437+
436438
# The setuptools dist dir, created by it under the chroot (not to be confused with
437439
# pants's own dist dir, at the buildroot).
438-
dist_dir = "dist/"
440+
dist_dir = "dist"
441+
442+
prefixed_chroot = await Get(Digest, AddPrefix(req.chroot.digest, chroot_prefix))
443+
444+
# setup.py basically always expects to be run with the cwd as its own directory
445+
# (e.g., paths in it are relative to that directory). This is true of the setup.py
446+
# we generate and is overwhelmingly likely to be true for existing setup.py files,
447+
# as there is no robust way to run them otherwise.
448+
setup_script_reldir, setup_script_name = os.path.split(req.chroot.setup_script)
449+
working_directory = os.path.join(chroot_prefix, setup_script_reldir)
450+
439451
result = await Get(
440452
ProcessResult,
441453
VenvPexProcess(
442454
setuptools_pex,
443-
argv=(req.chroot.setup_script, *req.args),
444-
input_digest=req.chroot.digest,
455+
argv=(setup_script_name, *req.args),
456+
input_digest=prefixed_chroot,
457+
working_directory=working_directory,
445458
# setuptools commands that create dists write them to the distdir.
446459
# TODO: Could there be other useful files to capture?
447-
output_directories=(dist_dir,),
460+
output_directories=(dist_dir,), # Relative to the working_directory.
448461
description=f"Run setuptools for {req.exported_target.target.address}",
449462
level=LogLevel.DEBUG,
450463
),
451464
)
465+
# Note that output_digest paths are relative to the working_directory.
452466
output_digest = await Get(Digest, RemovePrefix(result.output_digest, dist_dir))
453467
return RunSetupPyResult(output_digest)
454468

@@ -535,7 +549,6 @@ async def generate_chroot(request: SetupPyChrootRequest) -> SetupPyChroot:
535549
# specified `SetupKwargs(_allow_banned_keys=True)`.
536550
setup_kwargs.update(
537551
{
538-
"package_dir": {"": CHROOT_SOURCE_ROOT, **setup_kwargs.get("package_dir", {})},
539552
"packages": (*sources.packages, *(setup_kwargs.get("packages", []))),
540553
"namespace_packages": (
541554
*sources.namespace_packages,
@@ -595,13 +608,8 @@ async def generate_chroot(request: SetupPyChrootRequest) -> SetupPyChroot:
595608
FileContent("setup.py", setup_py_content),
596609
FileContent("MANIFEST.in", "include *.py".encode()),
597610
]
598-
extra_files_digest, src_digest = await MultiGet(
599-
Get(Digest, CreateDigest(files_to_create)),
600-
# Nest the sources under the src/ prefix.
601-
Get(Digest, AddPrefix(sources.digest, CHROOT_SOURCE_ROOT)),
602-
)
603-
604-
chroot_digest = await Get(Digest, MergeDigests((src_digest, extra_files_digest)))
611+
extra_files_digest = await Get(Digest, CreateDigest(files_to_create))
612+
chroot_digest = await Get(Digest, MergeDigests((sources.digest, extra_files_digest)))
605613
return SetupPyChroot(
606614
chroot_digest, "setup.py", FinalizedSetupKwargs(setup_kwargs, address=target.address)
607615
)

src/python/pants/backend/python/goals/setup_py_test.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -285,13 +285,13 @@ def test_generate_chroot(chroot_rule_runner: RuleRunner) -> None:
285285
assert_chroot(
286286
chroot_rule_runner,
287287
[
288-
"src/files/README.txt",
289-
"src/foo/qux/__init__.py",
290-
"src/foo/qux/qux.py",
291-
"src/foo/qux/qux.pyi",
292-
"src/foo/resources/js/code.js",
293-
"src/foo/__init__.py",
294-
"src/foo/foo.py",
288+
"files/README.txt",
289+
"foo/qux/__init__.py",
290+
"foo/qux/qux.py",
291+
"foo/qux/qux.pyi",
292+
"foo/resources/js/code.js",
293+
"foo/__init__.py",
294+
"foo/foo.py",
295295
"setup.py",
296296
"MANIFEST.in",
297297
],
@@ -300,7 +300,6 @@ def test_generate_chroot(chroot_rule_runner: RuleRunner) -> None:
300300
"name": "foo",
301301
"version": "1.2.3",
302302
"plugin_demo": "hello world",
303-
"package_dir": {"": "src"},
304303
"packages": ("foo", "foo.qux"),
305304
"namespace_packages": ("foo",),
306305
"package_data": {"foo": ("resources/js/code.js",)},
@@ -378,13 +377,12 @@ def test_binary_shorthand(chroot_rule_runner: RuleRunner) -> None:
378377
)
379378
assert_chroot(
380379
chroot_rule_runner,
381-
["src/project/app.py", "setup.py", "MANIFEST.in"],
380+
["project/app.py", "setup.py", "MANIFEST.in"],
382381
"setup.py",
383382
{
384383
"name": "bin",
385384
"version": "1.1.1",
386385
"plugin_demo": "hello world",
387-
"package_dir": {"": "src"},
388386
"packages": ("project",),
389387
"namespace_packages": (),
390388
"install_requires": (),

src/python/pants/engine/process_test.py

+12-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
import pytest
77

8-
from pants.engine.fs import EMPTY_DIGEST, CreateDigest, Digest, DigestContents, FileContent
8+
from pants.engine.fs import EMPTY_DIGEST, CreateDigest, Digest, DigestContents, FileContent, \
9+
Directory
910
from pants.engine.internals.scheduler import ExecutionError
1011
from pants.engine.process import (
1112
BinaryPathRequest,
@@ -74,11 +75,20 @@ def test_env(rule_runner: RuleRunner) -> None:
7475
assert b"VAR2=VAL" in result.stdout
7576

7677

77-
def test_output_digest(rule_runner: RuleRunner) -> None:
78+
@pytest.mark.parametrize("working_directory", ["", "subdir"])
79+
def test_output_digest(rule_runner: RuleRunner, working_directory) -> None:
80+
# Test that the output files are relative to the working directory, both in how
81+
# they're specified, and their paths in the output_digest.
82+
input_digest = rule_runner.request(
83+
Digest,
84+
[CreateDigest([Directory(working_directory)])],
85+
) if working_directory else EMPTY_DIGEST
7886
process = Process(
87+
input_digest=input_digest,
7988
argv=("/bin/bash", "-c", "echo -n 'European Burmese' > roland"),
8089
description="echo roland",
8190
output_files=("roland",),
91+
working_directory=working_directory,
8292
)
8393
result = rule_runner.request(ProcessResult, [process])
8494
assert result.output_digest == Digest(

0 commit comments

Comments
 (0)