Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/notes/2.32.x.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ For those language ecosystems that use separate type checkers from compilers (So

For `generate-lockfiles`, typos in the name of a resolve now give "Did you mean?" style suggestions.

The `find-links` automatically injected by `pants.backend.plugin_development` is no longer injected into *all* Python resolves, only the resolve associated with `pants_requirements(name="pants")`. Having extraneous un-scoped `find-links` can materially affect dependency resolution time. In some real world user reports, this results in a >30% improvements in `generate-lockfiles` wall time.

#### Publish

`PublishFieldSet` now has a `check_skip_request` hook to enable preemptive skips of packaging requests for targets where the publishing will be skipped (such as when a `skip_push=True` field exists).
Expand Down
8 changes: 4 additions & 4 deletions src/python/pants/backend/python/goals/lockfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,13 @@ async def setup_user_lockfile_requests(
return UserGenerateLockfiles()

resolve_to_requirements_fields = defaultdict(set)
find_links: set[str] = set()
resolve_to_find_links: dict[str, set[str]] = defaultdict(set)
for tgt in all_targets:
if not tgt.has_fields((PythonRequirementResolveField, PythonRequirementsField)):
continue
resolve = tgt[PythonRequirementResolveField].normalized_value(python_setup)
resolve_to_requirements_fields[resolve].add(tgt[PythonRequirementsField])
find_links.update(tgt[PythonRequirementFindLinksField].value or ())
resolve_to_find_links[resolve].update(tgt[PythonRequirementFindLinksField].value or ())

tools = ExportableTool.filter_for_subclasses(union_membership, PythonToolBase)

Expand All @@ -379,7 +379,7 @@ async def setup_user_lockfile_requests(
requirements=PexRequirements.req_strings_from_requirement_fields(
resolve_to_requirements_fields[resolve]
),
find_links=FrozenOrderedSet(find_links),
find_links=FrozenOrderedSet(resolve_to_find_links[resolve]),
interpreter_constraints=InterpreterConstraints(
python_setup.resolves_to_interpreter_constraints.get(
resolve, python_setup.interpreter_constraints
Expand Down Expand Up @@ -408,7 +408,7 @@ async def setup_user_lockfile_requests(
out.add(
GeneratePythonLockfile(
requirements=FrozenOrderedSet(sorted(tool.requirements)),
find_links=FrozenOrderedSet(find_links),
find_links=FrozenOrderedSet(),
interpreter_constraints=ic,
resolve_name=resolve,
lockfile_dest=DEFAULT_TOOL_LOCKFILE,
Expand Down
52 changes: 52 additions & 0 deletions src/python/pants/backend/python/goals/lockfile_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,58 @@ def test_multiple_resolves() -> None:
}


def test_find_links_scoped_to_resolve() -> None:
rule_runner = PythonRuleRunner(
rules=[
setup_user_lockfile_requests,
*PythonSetup.rules(),
QueryRule(UserGenerateLockfiles, [RequestedPythonUserResolveNames]),
],
target_types=[PythonRequirementTarget],
)
rule_runner.write_files(
{
"BUILD": dedent(
"""\
# Using the underscore field directly instead of pulling all of
# pants.backend.plugin_development into the test
python_requirement(
name='a',
requirements=['a'],
resolve='a',
_find_links=['https://example.com/wheels'],
)
python_requirement(
name='b',
requirements=['b'],
resolve='b',
)
"""
),
}
)
rule_runner.set_options(
[
"--python-resolves={'a': 'a.lock', 'b': 'b.lock'}",
"--python-enable-resolves",
],
env_inherit=PYTHON_BOOTSTRAP_ENV,
)
result = rule_runner.request(
UserGenerateLockfiles, [RequestedPythonUserResolveNames(["a", "b"])]
)
assert all(isinstance(r, GeneratePythonLockfile) for r in result)
result_by_resolve = {r.resolve_name: r for r in result}
assert isinstance(result_by_resolve["a"], GeneratePythonLockfile)
assert isinstance(result_by_resolve["b"], GeneratePythonLockfile)

assert result_by_resolve["a"].requirements == FrozenOrderedSet(["a"])
assert result_by_resolve["b"].requirements == FrozenOrderedSet(["b"])

assert result_by_resolve["a"].find_links == FrozenOrderedSet(["https://example.com/wheels"])
assert result_by_resolve["b"].find_links == FrozenOrderedSet([])


def test_empty_requirements(rule_runner: PythonRuleRunner) -> None:
with pytest.raises(ExecutionError) as excinfo:
json.loads(
Expand Down
Loading