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

pantsbuild / pants / 19015773527

02 Nov 2025 05:33PM UTC coverage: 17.872% (-62.4%) from 80.3%
19015773527

Pull #22816

github

web-flow
Merge a12d75757 into 6c024e162
Pull Request #22816: Update Pants internal Python to 3.14

4 of 5 new or added lines in 3 files covered. (80.0%)

28452 existing lines in 683 files now uncovered.

9831 of 55007 relevant lines covered (17.87%)

0.18 hits per line

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

0.0
/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

UNCOV
4
from dataclasses import dataclass
×
5

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

31

UNCOV
32
class PythonProtobufSubsystem(Subsystem):
×
UNCOV
33
    options_scope = "python-protobuf"
×
UNCOV
34
    help = help_text(
×
35
        f"""
36
        Options related to the Protobuf Python backend.
37

38
        See {doc_url("docs/python/integrations/protobuf-and-grpc")}.
39
        """
40
    )
41

UNCOV
42
    grpcio_plugin = BoolOption(
×
43
        default=True,
44
        help=softwrap(
45
            """
46
            Use the official `grpcio` plugin (https://pypi.org/project/grpcio/) to generate grpc
47
            service stubs.
48
            """
49
        ),
50
    )
51

UNCOV
52
    grpclib_plugin = BoolOption(
×
53
        default=False,
54
        help=softwrap(
55
            """
56
            Use the alternative `grpclib` plugin (https://github.com/vmagamedov/grpclib) to
57
            generate grpc service stubs.
58
            """
59
        ),
60
    )
61

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

UNCOV
74
    mypy_plugin = BoolOption(
×
75
        default=False,
76
        mutually_exclusive_group="typestubs",
77
        help=softwrap(
78
            """
79
            Use the `mypy-protobuf` plugin (https://github.com/dropbox/mypy-protobuf) to also
80
            generate `.pyi` type stubs.
81

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

UNCOV
88
    infer_runtime_dependency = BoolOption(
×
89
        default=True,
90
        help=softwrap(
91
            """
92
            If True, will add a dependency on a `python_requirement` target exposing the
93
            `protobuf` module (usually from the `protobuf` requirement). If the `protobuf_source`
94
            target sets `grpc=True`, will also add a dependency on the `python_requirement`
95
            target exposing the `grpcio` module.
96

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

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

109

UNCOV
110
class PythonProtobufMypyPlugin(PythonToolRequirementsBase):
×
UNCOV
111
    options_scope = "mypy-protobuf"
×
UNCOV
112
    help_short = "Configuration of the mypy-protobuf type stub generation plugin."
×
113

UNCOV
114
    default_requirements = ["mypy-protobuf>=3.4.0,<4"]
×
115

UNCOV
116
    register_interpreter_constraints = True
×
117

UNCOV
118
    default_lockfile_resource = ("pants.backend.codegen.protobuf.python", "mypy_protobuf.lock")
×
119

120

UNCOV
121
class PythonProtobufGrpclibPlugin(PythonToolRequirementsBase):
×
UNCOV
122
    options_scope = "python-grpclib-protobuf"
×
UNCOV
123
    help_short = "Configuration of the grpclib plugin."
×
124

UNCOV
125
    default_requirements = ["grpclib[protobuf]>=0.4,<1"]
×
126

UNCOV
127
    register_interpreter_constraints = True
×
128

UNCOV
129
    default_lockfile_resource = ("pants.backend.codegen.protobuf.python", "grpclib.lock")
×
130

131

UNCOV
132
@dataclass(frozen=True)
×
UNCOV
133
class PythonProtobufDependenciesInferenceFieldSet(FieldSet):
×
UNCOV
134
    required_fields = (
×
135
        ProtobufDependenciesField,
136
        ProtobufPythonResolveField,
137
        ProtobufGrpcToggleField,
138
    )
139

140
    dependencies: ProtobufDependenciesField
141
    python_resolve: ProtobufPythonResolveField
142
    grpc_toggle: ProtobufGrpcToggleField
143

144

UNCOV
145
class InferPythonProtobufDependencies(InferDependenciesRequest):
×
UNCOV
146
    infer_from = PythonProtobufDependenciesInferenceFieldSet
×
147

148

UNCOV
149
@rule
×
UNCOV
150
async def infer_dependencies(
×
151
    request: InferPythonProtobufDependencies,
152
    python_protobuf: PythonProtobufSubsystem,
153
    python_setup: PythonSetup,
154
    python_infer_subsystem: PythonInferSubsystem,
155
) -> InferredDependencies:
156
    if not python_protobuf.infer_runtime_dependency:
×
157
        return InferredDependencies([])
×
158

159
    resolve = request.field_set.python_resolve.normalized_value(python_setup)
×
160

161
    locality = None
×
162
    if python_infer_subsystem.ambiguity_resolution == AmbiguityResolution.by_source_root:
×
163
        source_root = await get_source_root(
×
164
            SourceRootRequest.for_address(request.field_set.address)
165
        )
166
        locality = source_root.path
×
167

168
    result = []
×
169
    addresses_for_protobuf = await map_module_to_address(
×
170
        PythonModuleOwnersRequest(
171
            "google.protobuf",
172
            resolve=resolve,
173
            locality=locality,
174
        ),
175
        **implicitly(),
176
    )
177

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

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

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

216
        if python_protobuf.grpclib_plugin:
×
217
            addresses_for_grpclib = await map_module_to_address(
×
218
                PythonModuleOwnersRequest(
219
                    "grpclib",
220
                    resolve=resolve,
221
                    locality=locality,
222
                ),
223
                **implicitly(),
224
            )
225

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

239
    return InferredDependencies(result)
×
240

241

UNCOV
242
def rules():
×
UNCOV
243
    return [
×
244
        *collect_rules(),
245
        UnionRule(InferDependenciesRequest, InferPythonProtobufDependencies),
246
    ]
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

© 2025 Coveralls, Inc