Skip to content

Allow pants export --resolve to take targets#23415

Open
wisechengyi wants to merge 7 commits into
pantsbuild:mainfrom
wisechengyi:export-to-take-targets
Open

Allow pants export --resolve to take targets#23415
wisechengyi wants to merge 7 commits into
pantsbuild:mainfrom
wisechengyi:export-to-take-targets

Conversation

@wisechengyi

@wisechengyi wisechengyi commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the guard that rejected target specs in the export goal
  • When targets are provided with --resolve, the exported virtualenv contains only the 3rd-party requirements transitively needed by those targets (via Pex native lockfile subsetting)
  • When no targets are provided, the existing full-resolve behavior is unchanged

Example usage:

pants export --resolve=python-default src/python/my_service:my_service

Test plan

  • Existing test_export_venv_new_codepath, test_export_tool, and test_export_codegen_outputs still pass (full-resolve path unchanged)
  • New test_export_venv_filtered_by_targets verifies targets flow through the rule chain and the transitive-closure branch is taken

Adhoc tests

Full resolve (no targets) — baseline unchanged:

$ pants export --resolve=python-default
Wrote mutable virtualenv for python-default (using Python 3.14.3) to dist/export/python/virtualenvs/python-default/3.14.3
# 30+ packages installed

Filtered by a source target with no 3rd-party deps (src/python/pants/core/goals/export.py):

$ pants export --resolve=python-default src/python/pants/core/goals/export.py
Wrote mutable virtualenv for python-default (using Python 3.14.3) to dist/export/python/virtualenvs/python-default/3.14.3
# site-packages: colors  packaging  pip  typing_extensions  (PEX builtins only — no extra 3rd-party deps)

Filtered by a test file with pytest in its transitive closure (src/python/pants/backend/python/goals/export_test.py):

$ pants dependencies --transitive src/python/pants/backend/python/goals/export_test.py | grep 3rdparty
3rdparty/python#ansicolors
3rdparty/python#hdrhistogram
3rdparty/python#packaging
3rdparty/python#pytest
3rdparty/python#toml
3rdparty/python#types-toml
3rdparty/python#typing-extensions

$ pants export --resolve=python-default src/python/pants/backend/python/goals/export_test.py
Wrote mutable virtualenv for python-default (using Python 3.14.3) to dist/export/python/virtualenvs/python-default/3.14.3
# site-packages: hdrh  iniconfig  pluggy  pygments  pytest  _pytest  setuptools  toml  toml-stubs  ...

pytest and its transitive deps are present; unrelated packages from the full resolve are absent.

🤖 Generated with Claude Code

Previously the export goal rejected any target specs. Now, when targets
are provided alongside `--resolve`, only the 3rd-party requirements
transitively needed by those targets are included in the exported
virtualenv (via Pex native lockfile subsetting). Exporting without
targets retains the existing full-resolve behavior.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wisechengyi
wisechengyi marked this pull request as draft June 10, 2026 21:55
@wisechengyi wisechengyi changed the title Allow pants export --resolve to filter by target transitive deps Allow pants export --resolve to take targets Jun 10, 2026
…pendency graph

Models A→B,C; B→req_x→req_y; C→req_z and asserts that transitive req_strings
correctly includes only the packages reachable from each root target.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wisechengyi wisechengyi added the backend: Python Python backend-related issues label Jun 10, 2026
Yi Cheng and others added 3 commits June 10, 2026 22:22
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wisechengyi
wisechengyi marked this pull request as ready for review June 10, 2026 22:38
Yi Cheng and others added 2 commits June 10, 2026 23:05
Also filter transitive req_strings by resolve to exclude shared deps
that may appear in multiple resolves' closures.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@wisechengyi
wisechengyi requested a review from benjyw June 11, 2026 00:36
Comment on lines +561 to +573
wrong_resolve = [
tgt.address
for tgt in transitive_tgts.roots
if tgt.has_field(PythonResolveField)
and tgt[PythonResolveField].normalized_value(python_setup) != resolve
]
if wrong_resolve:
raise ExportError(
f"The following targets do not belong to the resolve `{resolve}` "
f"and cannot be used to filter its export:\n"
+ "\n".join(f" {addr}" for addr in wrong_resolve)
+ f"\nEnsure all targets belong to the `{resolve}` resolve."
)

@wisechengyi wisechengyi Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potentially worth reviewing whether this is an overkill. E.g. do we need to care at export phase? For targets that can't build due to diverging resolves, is it okay to ignore the failure during export?

@cburroughs

Copy link
Copy Markdown
Contributor

Thanks for the contribution. We've just branched for 2.33.x, so merging this pull request now will come out in 2.34.x, please move the release notes updates to docs/notes/2.34.x.md if that's appropriate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend: Python Python backend-related issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants