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

pantsbuild / pants / 24055979590

06 Apr 2026 11:17PM UTC coverage: 52.37% (-40.5%) from 92.908%
24055979590

Pull #23225

github

web-flow
Merge 67474653c into 542ca048d
Pull Request #23225: Add --test-show-all-batch-targets to expose all targets in batched pytest

6 of 17 new or added lines in 2 files covered. (35.29%)

23030 existing lines in 605 files now uncovered.

31643 of 60422 relevant lines covered (52.37%)

1.05 hits per line

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

74.6
/src/python/pants/backend/codegen/protobuf/python/python_protobuf_subsystem.py
1
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from dataclasses import dataclass
2✔
5

6
from pants.backend.codegen.protobuf.python.additional_fields import ProtobufPythonResolveField
2✔
7
from pants.backend.codegen.protobuf.target_types import (
2✔
8
    ProtobufDependenciesField,
9
    ProtobufGrpcToggleField,
10
)
11
from pants.backend.codegen.utils import find_python_runtime_library_or_raise_error
2✔
12
from pants.backend.python.dependency_inference.module_mapper import (
2✔
13
    PythonModuleOwnersRequest,
14
    map_module_to_address,
15
)
16
from pants.backend.python.dependency_inference.subsystem import (
2✔
17
    AmbiguityResolution,
18
    PythonInferSubsystem,
19
)
20
from pants.backend.python.subsystems.python_tool_base import PythonToolRequirementsBase
2✔
21
from pants.backend.python.subsystems.setup import PythonSetup
2✔
22
from pants.engine.rules import collect_rules, implicitly, rule
2✔
23
from pants.engine.target import FieldSet, InferDependenciesRequest, InferredDependencies
2✔
24
from pants.engine.unions import UnionRule
2✔
25
from pants.option.option_types import BoolOption
2✔
26
from pants.option.subsystem import Subsystem
2✔
27
from pants.source.source_root import SourceRootRequest, get_source_root
2✔
28
from pants.util.docutil import doc_url
2✔
29
from pants.util.strutil import help_text, softwrap
2✔
30

31
# pants: infer-dep(grpclib.lock*)
32
# pants: infer-dep(mypy_protobuf.lock*)
33

34

35
class PythonProtobufSubsystem(Subsystem):
2✔
36
    options_scope = "python-protobuf"
2✔
37
    help = help_text(
2✔
38
        f"""
39
        Options related to the Protobuf Python backend.
40

41
        See {doc_url("docs/python/integrations/protobuf-and-grpc")}.
42
        """
43
    )
44

45
    grpcio_plugin = BoolOption(
2✔
46
        default=True,
47
        help=softwrap(
48
            """
49
            Use the official `grpcio` plugin (https://pypi.org/project/grpcio/) to generate grpc
50
            service stubs.
51
            """
52
        ),
53
    )
54

55
    grpclib_plugin = BoolOption(
2✔
56
        default=False,
57
        help=softwrap(
58
            """
59
            Use the alternative `grpclib` plugin (https://github.com/vmagamedov/grpclib) to
60
            generate grpc service stubs.
61
            """
62
        ),
63
    )
64

65
    generate_type_stubs = BoolOption(
2✔
66
        default=False,
67
        mutually_exclusive_group="typestubs",
68
        help=softwrap(
69
            """
70
            If True, then configure `protoc` to also generate `.pyi` type stubs for each generated
71
            Python file. This option will work wih any recent version of `protoc` and should
72
            be preferred over the `--python-protobuf-mypy-plugin` option.
73
            """
74
        ),
75
    )
76

77
    mypy_plugin = BoolOption(
2✔
78
        default=False,
79
        mutually_exclusive_group="typestubs",
80
        help=softwrap(
81
            """
82
            Use the `mypy-protobuf` plugin (https://github.com/dropbox/mypy-protobuf) to also
83
            generate `.pyi` type stubs.
84

85
            Please prefer the `--python-protobuf-generate-type-stubs` option over this option
86
            since recent versions of `protoc` have the ability to directly generate type stubs.
87
            """
88
        ),
89
    )
90

91
    infer_runtime_dependency = BoolOption(
2✔
92
        default=True,
93
        help=softwrap(
94
            """
95
            If True, will add a dependency on a `python_requirement` target exposing the
96
            `protobuf` module (usually from the `protobuf` requirement). If the `protobuf_source`
97
            target sets `grpc=True`, will also add a dependency on the `python_requirement`
98
            target exposing the `grpcio` module.
99

100
            If `[python].enable_resolves` is set, Pants will only infer dependencies on
101
            `python_requirement` targets that use the same resolve as the particular
102
            `protobuf_source` / `protobuf_sources` target uses, which is set via its
103
            `python_resolve` field.
104

105
            Unless this option is disabled, Pants will error if no relevant target is found or
106
            if more than one is found which causes ambiguity.
107
            """
108
        ),
109
        advanced=True,
110
    )
111

112

113
class PythonProtobufMypyPlugin(PythonToolRequirementsBase):
2✔
114
    options_scope = "mypy-protobuf"
2✔
115
    help_short = "Configuration of the mypy-protobuf type stub generation plugin."
2✔
116

117
    default_requirements = ["mypy-protobuf>=3.4.0,<4"]
2✔
118

119
    register_interpreter_constraints = True
2✔
120

121
    default_lockfile_resource = ("pants.backend.codegen.protobuf.python", "mypy_protobuf.lock")
2✔
122

123

124
class PythonProtobufGrpclibPlugin(PythonToolRequirementsBase):
2✔
125
    options_scope = "python-grpclib-protobuf"
2✔
126
    help_short = "Configuration of the grpclib plugin."
2✔
127

128
    default_requirements = ["grpclib[protobuf]>=0.4,<1"]
2✔
129

130
    register_interpreter_constraints = True
2✔
131

132
    default_lockfile_resource = ("pants.backend.codegen.protobuf.python", "grpclib.lock")
2✔
133

134

135
@dataclass(frozen=True)
2✔
136
class PythonProtobufDependenciesInferenceFieldSet(FieldSet):
2✔
137
    required_fields = (
2✔
138
        ProtobufDependenciesField,
139
        ProtobufPythonResolveField,
140
        ProtobufGrpcToggleField,
141
    )
142

143
    dependencies: ProtobufDependenciesField
144
    python_resolve: ProtobufPythonResolveField
145
    grpc_toggle: ProtobufGrpcToggleField
146

147

148
class InferPythonProtobufDependencies(InferDependenciesRequest):
2✔
149
    infer_from = PythonProtobufDependenciesInferenceFieldSet
2✔
150

151

152
@rule
2✔
153
async def infer_dependencies(
2✔
154
    request: InferPythonProtobufDependencies,
155
    python_protobuf: PythonProtobufSubsystem,
156
    python_setup: PythonSetup,
157
    python_infer_subsystem: PythonInferSubsystem,
158
) -> InferredDependencies:
159
    if not python_protobuf.infer_runtime_dependency:
2✔
160
        return InferredDependencies([])
2✔
161

UNCOV
162
    resolve = request.field_set.python_resolve.normalized_value(python_setup)
×
163

UNCOV
164
    locality = None
×
UNCOV
165
    if python_infer_subsystem.ambiguity_resolution == AmbiguityResolution.by_source_root:
×
UNCOV
166
        source_root = await get_source_root(
×
167
            SourceRootRequest.for_address(request.field_set.address)
168
        )
UNCOV
169
        locality = source_root.path
×
170

UNCOV
171
    result = []
×
UNCOV
172
    addresses_for_protobuf = await map_module_to_address(
×
173
        PythonModuleOwnersRequest(
174
            "google.protobuf",
175
            resolve=resolve,
176
            locality=locality,
177
        ),
178
        **implicitly(),
179
    )
180

UNCOV
181
    result.append(
×
182
        find_python_runtime_library_or_raise_error(
183
            addresses_for_protobuf,
184
            request.field_set.address,
185
            "google.protobuf",
186
            resolve=resolve,
187
            resolves_enabled=python_setup.enable_resolves,
188
            recommended_requirement_name="protobuf",
189
            recommended_requirement_url="https://pypi.org/project/protobuf/",
190
            disable_inference_option=f"[{python_protobuf.options_scope}].infer_runtime_dependency",
191
        )
192
    )
193

UNCOV
194
    if request.field_set.grpc_toggle.value:
×
UNCOV
195
        if python_protobuf.grpcio_plugin:
×
UNCOV
196
            addresses_for_grpc = await map_module_to_address(
×
197
                PythonModuleOwnersRequest(
198
                    "grpc",
199
                    resolve=resolve,
200
                    locality=locality,
201
                ),
202
                **implicitly(),
203
            )
204

UNCOV
205
            result.append(
×
206
                find_python_runtime_library_or_raise_error(
207
                    addresses_for_grpc,
208
                    request.field_set.address,
209
                    # Note that the library is called `grpcio`, but the module is `grpc`.
210
                    "grpc",
211
                    resolve=resolve,
212
                    resolves_enabled=python_setup.enable_resolves,
213
                    recommended_requirement_name="grpcio",
214
                    recommended_requirement_url="https://pypi.org/project/grpcio/",
215
                    disable_inference_option=f"[{python_protobuf.options_scope}].infer_runtime_dependency",
216
                )
217
            )
218

UNCOV
219
        if python_protobuf.grpclib_plugin:
×
UNCOV
220
            addresses_for_grpclib = await map_module_to_address(
×
221
                PythonModuleOwnersRequest(
222
                    "grpclib",
223
                    resolve=resolve,
224
                    locality=locality,
225
                ),
226
                **implicitly(),
227
            )
228

UNCOV
229
            result.append(
×
230
                find_python_runtime_library_or_raise_error(
231
                    addresses_for_grpclib,
232
                    request.field_set.address,
233
                    "grpclib",
234
                    resolve=resolve,
235
                    resolves_enabled=python_setup.enable_resolves,
236
                    recommended_requirement_name="grpclib[protobuf]",
237
                    recommended_requirement_url="https://pypi.org/project/grpclib/",
238
                    disable_inference_option=f"[{python_protobuf.options_scope}].infer_runtime_dependency",
239
                )
240
            )
241

UNCOV
242
    return InferredDependencies(result)
×
243

244

245
def rules():
2✔
246
    return [
2✔
247
        *collect_rules(),
248
        UnionRule(InferDependenciesRequest, InferPythonProtobufDependencies),
249
    ]
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