• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pantsbuild / pants / 25441711719

06 May 2026 02:31PM UTC coverage: 92.915%. Remained the same
25441711719

push

github

web-flow
use sha pin (with comment) format for generated actions (#23312)

Per the GitHub Action best practices we recently enabled at #23249, we
should pin each action to a SHA so that the reference is actually
immutable.

This will -- I hope -- knock out a large chunk of the 421 alerts we
currently get from zizmor. The next followup would then be upgrades and
harmonizing the generated and none-generated pins.

Notice: This idea was suggested by Claude while going over pinact output
and I was surprised to see that post processing the yaml wasn't too
gross.

92206 of 99237 relevant lines covered (92.91%)

4.04 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.92
/src/python/pants/backend/python/framework/stevedore/python_target_dependencies.py
1
# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
2✔
5

6
from collections import defaultdict
2✔
7
from collections.abc import Iterable, Mapping
2✔
8
from dataclasses import dataclass
2✔
9

10
from pants.backend.python.framework.stevedore.target_types import (
2✔
11
    AllStevedoreExtensionTargets,
12
    StevedoreExtensionTargets,
13
    StevedoreNamespace,
14
    StevedoreNamespacesField,
15
    StevedoreNamespacesProviderTargetsRequest,
16
)
17
from pants.backend.python.target_types import (
2✔
18
    PythonDistribution,
19
    PythonDistributionEntryPointsField,
20
    PythonTestsDependenciesField,
21
    PythonTestsGeneratorTarget,
22
    PythonTestTarget,
23
)
24
from pants.backend.python.util_rules.entry_points import (
2✔
25
    GetEntryPointDependenciesRequest,
26
    get_filtered_entry_point_dependencies,
27
)
28
from pants.engine.rules import Rule, collect_rules, implicitly, rule
2✔
29
from pants.engine.target import (
2✔
30
    AllTargets,
31
    FieldSet,
32
    InferDependenciesRequest,
33
    InferredDependencies,
34
    Target,
35
)
36
from pants.engine.unions import UnionRule
2✔
37
from pants.util.frozendict import FrozenDict
2✔
38
from pants.util.logging import LogLevel
2✔
39

40
# -----------------------------------------------------------------------------------------------
41
# Utility rules to analyze all StevedoreNamespace entry_points
42
# -----------------------------------------------------------------------------------------------
43

44

45
@rule(
2✔
46
    desc=f"Find all `{PythonDistribution.alias}` targets with `{StevedoreNamespace.alias}` entry_points",
47
    level=LogLevel.DEBUG,
48
)
49
async def find_all_python_distributions_with_any_stevedore_entry_points(
2✔
50
    targets: AllTargets,
51
) -> AllStevedoreExtensionTargets:
52
    # This only supports specifying stevedore_namespace entry points in the
53
    # `entry_points` field of a `python_distribution`, not the `provides` field.
54
    # Use this: `python_distribution(entry_points={...})`
55
    # NOT this: `python_distribution(provides=python_artifact(entry_points={...}))`
56
    return AllStevedoreExtensionTargets(
2✔
57
        tgt
58
        for tgt in targets
59
        if tgt.has_field(PythonDistributionEntryPointsField)
60
        and any(
61
            # namespace aka category aka group
62
            isinstance(namespace, StevedoreNamespace)
63
            for namespace in (tgt[PythonDistributionEntryPointsField].value or {}).keys()
64
        )
65
    )
66

67

68
@dataclass(frozen=True)
2✔
69
class StevedoreExtensions:
2✔
70
    """A mapping of stevedore namespaces to a list of targets that provide them.
71

72
    Effectively, the targets are StevedoreExtension targets.
73
    """
74

75
    mapping: FrozenDict[StevedoreNamespace, tuple[Target, ...]]
2✔
76

77

78
@rule(
2✔
79
    desc=f"Create map of `{StevedoreNamespace.alias}` to `{PythonDistribution.alias}` targets",
80
    level=LogLevel.DEBUG,
81
)
82
async def map_stevedore_extensions(
2✔
83
    stevedore_extensions: AllStevedoreExtensionTargets,
84
) -> StevedoreExtensions:
85
    mapping: Mapping[StevedoreNamespace, list[Target]] = defaultdict(list)
2✔
86
    for tgt in stevedore_extensions:
2✔
87
        # namespace aka category aka group
88
        for namespace in (tgt[PythonDistributionEntryPointsField].value or {}).keys():
2✔
89
            if isinstance(namespace, StevedoreNamespace):
2✔
90
                mapping[namespace].append(tgt)
2✔
91
    return StevedoreExtensions(
2✔
92
        FrozenDict((k, tuple(sorted(v))) for k, v in sorted(mapping.items()))
93
    )
94

95

96
@rule(
2✔
97
    desc=f"Find `{PythonDistribution.alias}` targets with entry_points in selected `{StevedoreNamespace.alias}`s",
98
    level=LogLevel.DEBUG,
99
)
100
async def find_python_distributions_with_entry_points_in_stevedore_namespaces(
2✔
101
    request: StevedoreNamespacesProviderTargetsRequest,
102
    stevedore_extensions: StevedoreExtensions,
103
) -> StevedoreExtensionTargets:
104
    namespaces: StevedoreNamespacesField = request.stevedore_namespaces
2✔
105
    if namespaces.value is None:
2✔
106
        return StevedoreExtensionTargets(())
×
107

108
    return StevedoreExtensionTargets(
2✔
109
        {
110
            tgt
111
            for namespace in namespaces.value
112
            for tgt in stevedore_extensions.mapping.get(StevedoreNamespace(namespace), ())
113
        }
114
    )
115

116

117
# -----------------------------------------------------------------------------------------------
118
# Dependencies for `python_test` and `python_tests` targets
119
# -----------------------------------------------------------------------------------------------
120

121

122
@dataclass(frozen=True)
2✔
123
class PythonTestsStevedoreNamespaceInferenceFieldSet(FieldSet):
2✔
124
    required_fields = (PythonTestsDependenciesField, StevedoreNamespacesField)
2✔
125

126
    stevedore_namespaces: StevedoreNamespacesField
2✔
127

128

129
class InferStevedoreNamespacesDependencies(InferDependenciesRequest):
2✔
130
    infer_from = PythonTestsStevedoreNamespaceInferenceFieldSet
2✔
131

132

133
@rule(
2✔
134
    desc=f"Infer dependencies based on `{StevedoreNamespacesField.alias}` field.",
135
    level=LogLevel.DEBUG,
136
)
137
async def infer_stevedore_namespaces_dependencies(
2✔
138
    request: InferStevedoreNamespacesDependencies,
139
) -> InferredDependencies:
140
    requested_namespaces: StevedoreNamespacesField = request.field_set.stevedore_namespaces
1✔
141
    if requested_namespaces.value is None:
1✔
142
        return InferredDependencies(())
×
143

144
    targets = await find_python_distributions_with_entry_points_in_stevedore_namespaces(
1✔
145
        StevedoreNamespacesProviderTargetsRequest(requested_namespaces), **implicitly()
146
    )
147

148
    requested_namespaces_value = requested_namespaces.value
1✔
149
    entry_point_dependencies = await get_filtered_entry_point_dependencies(
1✔
150
        GetEntryPointDependenciesRequest(
151
            targets,
152
            lambda tgt, ns: ns in requested_namespaces_value,
153
            lambda tgt, ns, ep_name: True,
154
        )
155
    )
156

157
    return InferredDependencies(entry_point_dependencies.addresses)
1✔
158

159

160
def rules() -> Iterable[Rule | UnionRule]:
2✔
161
    return (
2✔
162
        *collect_rules(),
163
        PythonTestsGeneratorTarget.register_plugin_field(StevedoreNamespacesField),
164
        PythonTestTarget.register_plugin_field(StevedoreNamespacesField),
165
        UnionRule(InferDependenciesRequest, InferStevedoreNamespacesDependencies),
166
    )
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc