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

pantsbuild / pants / 21572405674

01 Feb 2026 11:36PM UTC coverage: 80.273% (-0.05%) from 80.324%
21572405674

push

github

web-flow
Remove support for Get (#23062)

Delete the bulk of the code needed to
support `Get` (and `Effect`).

Follow up changes will further trim code
that is no longer needed, but this
is already a big enough step for now.

23 of 27 new or added lines in 5 files covered. (85.19%)

49 existing lines in 3 files now uncovered.

78274 of 97510 relevant lines covered (80.27%)

3.1 hits per line

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

66.25
/src/python/pants/engine/internals/selectors.py
1
# Copyright 2015 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
11✔
5

6
import itertools
11✔
7
from collections.abc import Coroutine, Generator, Iterable
11✔
8
from dataclasses import dataclass
11✔
9
from typing import Any, TypeVar, cast, overload
11✔
10

11
from pants.engine.internals.native_engine import PyGeneratorResponseCall
11✔
12
from pants.util.strutil import softwrap
11✔
13

14
_Output = TypeVar("_Output")
11✔
15

16

17
@dataclass(frozen=True)
11✔
18
class AwaitableConstraints:
11✔
19
    rule_id: str
11✔
20
    output_type: type
11✔
21
    # The number of explicit positional arguments passed to a call-by-name awaitable.
22
    explicit_args_arity: int
11✔
23
    input_types: tuple[type, ...]
11✔
24
    is_effect: bool
11✔
25

26
    def __repr__(self) -> str:
11✔
27
        inputs = ", ".join(f"{t.__name__}" for t in self.input_types)
2✔
28
        return f"{self.rule_id}({inputs}) -> {self.output_type.__name__}"
2✔
29

30
    def __str__(self) -> str:
11✔
31
        return repr(self)
2✔
32

33

34
class Call(PyGeneratorResponseCall):
11✔
35
    def __await__(
11✔
36
        self,
37
    ) -> Generator[Any, None, Any]:
38
        result = yield self
11✔
39
        return result
11✔
40

41
    def __repr__(self) -> str:
11✔
42
        return f"Call({self.rule_id}(...) -> {self.output_type.__name__})"
×
43

44

45
@dataclass(frozen=True)
11✔
46
class _Concurrently:
11✔
47
    calls: tuple[Coroutine, ...]
11✔
48

49
    def __await__(self) -> Generator[tuple[Coroutine, ...], None, tuple]:
11✔
50
        result = yield self.calls
6✔
51
        return cast(tuple, result)
6✔
52

53

54
# These type variables are used to parametrize from 1 to 10 args when used in a tuple-style
55
# concurrently() call.
56

57
_Out0 = TypeVar("_Out0")
11✔
58
_Out1 = TypeVar("_Out1")
11✔
59
_Out2 = TypeVar("_Out2")
11✔
60
_Out3 = TypeVar("_Out3")
11✔
61
_Out4 = TypeVar("_Out4")
11✔
62
_Out5 = TypeVar("_Out5")
11✔
63
_Out6 = TypeVar("_Out6")
11✔
64
_Out7 = TypeVar("_Out7")
11✔
65
_Out8 = TypeVar("_Out8")
11✔
66
_Out9 = TypeVar("_Out9")
11✔
67

68

69
@overload
70
async def Concurrently(
71
    __gets: Iterable[Coroutine[Any, Any, _Output]],
72
) -> tuple[_Output, ...]: ...
73

74

75
@overload
76
async def Concurrently(
77
    __get0: Coroutine[Any, Any, _Output],
78
    __get1: Coroutine[Any, Any, _Output],
79
    __get2: Coroutine[Any, Any, _Output],
80
    __get3: Coroutine[Any, Any, _Output],
81
    __get4: Coroutine[Any, Any, _Output],
82
    __get5: Coroutine[Any, Any, _Output],
83
    __get6: Coroutine[Any, Any, _Output],
84
    __get7: Coroutine[Any, Any, _Output],
85
    __get8: Coroutine[Any, Any, _Output],
86
    __get9: Coroutine[Any, Any, _Output],
87
    __get10: Coroutine[Any, Any, _Output],
88
    *__gets: Coroutine[Any, Any, _Output],
89
) -> tuple[_Output, ...]: ...
90

91

92
@overload
93
async def Concurrently(
94
    __get0: Coroutine[Any, Any, _Out0],
95
    __get1: Coroutine[Any, Any, _Out1],
96
    __get2: Coroutine[Any, Any, _Out2],
97
    __get3: Coroutine[Any, Any, _Out3],
98
    __get4: Coroutine[Any, Any, _Out4],
99
    __get5: Coroutine[Any, Any, _Out5],
100
    __get6: Coroutine[Any, Any, _Out6],
101
    __get7: Coroutine[Any, Any, _Out7],
102
    __get8: Coroutine[Any, Any, _Out8],
103
    __get9: Coroutine[Any, Any, _Out9],
104
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7, _Out8, _Out9]: ...
105

106

107
@overload
108
async def Concurrently(
109
    __get0: Coroutine[Any, Any, _Out0],
110
    __get1: Coroutine[Any, Any, _Out1],
111
    __get2: Coroutine[Any, Any, _Out2],
112
    __get3: Coroutine[Any, Any, _Out3],
113
    __get4: Coroutine[Any, Any, _Out4],
114
    __get5: Coroutine[Any, Any, _Out5],
115
    __get6: Coroutine[Any, Any, _Out6],
116
    __get7: Coroutine[Any, Any, _Out7],
117
    __get8: Coroutine[Any, Any, _Out8],
118
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7, _Out8]: ...
119

120

121
@overload
122
async def Concurrently(
123
    __get0: Coroutine[Any, Any, _Out0],
124
    __get1: Coroutine[Any, Any, _Out1],
125
    __get2: Coroutine[Any, Any, _Out2],
126
    __get3: Coroutine[Any, Any, _Out3],
127
    __get4: Coroutine[Any, Any, _Out4],
128
    __get5: Coroutine[Any, Any, _Out5],
129
    __get6: Coroutine[Any, Any, _Out6],
130
    __get7: Coroutine[Any, Any, _Out7],
131
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7]: ...
132

133

134
@overload
135
async def Concurrently(
136
    __get0: Coroutine[Any, Any, _Out0],
137
    __get1: Coroutine[Any, Any, _Out1],
138
    __get2: Coroutine[Any, Any, _Out2],
139
    __get3: Coroutine[Any, Any, _Out3],
140
    __get4: Coroutine[Any, Any, _Out4],
141
    __get5: Coroutine[Any, Any, _Out5],
142
    __get6: Coroutine[Any, Any, _Out6],
143
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6]: ...
144

145

146
@overload
147
async def Concurrently(
148
    __get0: Coroutine[Any, Any, _Out0],
149
    __get1: Coroutine[Any, Any, _Out1],
150
    __get2: Coroutine[Any, Any, _Out2],
151
    __get3: Coroutine[Any, Any, _Out3],
152
    __get4: Coroutine[Any, Any, _Out4],
153
    __get5: Coroutine[Any, Any, _Out5],
154
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5]: ...
155

156

157
@overload
158
async def Concurrently(
159
    __get0: Coroutine[Any, Any, _Out0],
160
    __get1: Coroutine[Any, Any, _Out1],
161
    __get2: Coroutine[Any, Any, _Out2],
162
    __get3: Coroutine[Any, Any, _Out3],
163
    __get4: Coroutine[Any, Any, _Out4],
164
) -> tuple[_Out0, _Out1, _Out2, _Out3, _Out4]: ...
165

166

167
@overload
168
async def Concurrently(
169
    __get0: Coroutine[Any, Any, _Out0],
170
    __get1: Coroutine[Any, Any, _Out1],
171
    __get2: Coroutine[Any, Any, _Out2],
172
    __get3: Coroutine[Any, Any, _Out3],
173
) -> tuple[_Out0, _Out1, _Out2, _Out3]: ...
174

175

176
@overload
177
async def Concurrently(
178
    __get0: Coroutine[Any, Any, _Out0],
179
    __get1: Coroutine[Any, Any, _Out1],
180
    __get2: Coroutine[Any, Any, _Out2],
181
) -> tuple[_Out0, _Out1, _Out2]: ...
182

183

184
@overload
185
async def Concurrently(
186
    __get0: Coroutine[Any, Any, _Out0],
187
    __get1: Coroutine[Any, Any, _Out1],
188
) -> tuple[_Out0, _Out1]: ...
189

190

191
async def Concurrently(
11✔
192
    __arg0: (Iterable[Coroutine[Any, Any, _Output]] | Coroutine[Any, Any, _Out0]),
193
    __arg1: Coroutine[Any, Any, _Out1] | None = None,
194
    __arg2: Coroutine[Any, Any, _Out2] | None = None,
195
    __arg3: Coroutine[Any, Any, _Out3] | None = None,
196
    __arg4: Coroutine[Any, Any, _Out4] | None = None,
197
    __arg5: Coroutine[Any, Any, _Out5] | None = None,
198
    __arg6: Coroutine[Any, Any, _Out6] | None = None,
199
    __arg7: Coroutine[Any, Any, _Out7] | None = None,
200
    __arg8: Coroutine[Any, Any, _Out8] | None = None,
201
    __arg9: Coroutine[Any, Any, _Out9] | None = None,
202
    *__args: Coroutine[Any, Any, _Output],
203
) -> (
204
    tuple[_Output, ...]
205
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7, _Out8, _Out9]
206
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7, _Out8]
207
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6, _Out7]
208
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5, _Out6]
209
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4, _Out5]
210
    | tuple[_Out0, _Out1, _Out2, _Out3, _Out4]
211
    | tuple[_Out0, _Out1, _Out2, _Out3]
212
    | tuple[_Out0, _Out1, _Out2]
213
    | tuple[_Out0, _Out1]
214
    | tuple[_Out0]
215
):
216
    """Yield a tuple of Coroutine instances all at once.
217

218
    The `yield`ed value `self.calls` is interpreted by the engine within
219
    `generator_send()`. This class will yield a tuple of Coroutine instances,
220
    which is converted into `PyGeneratorResponse::GetMulti`.
221

222
    The engine will fulfill these coroutines in parallel, and return a tuple of _Output
223
    instances to this method, which then returns this tuple to the `@rule` which called
224
    `await concurrently(...) for ... in ...)`.
225
    """
226
    if (
6✔
227
        isinstance(__arg0, Iterable)
228
        and __arg1 is None
229
        and __arg2 is None
230
        and __arg3 is None
231
        and __arg4 is None
232
        and __arg5 is None
233
        and __arg6 is None
234
        and __arg7 is None
235
        and __arg8 is None
236
        and __arg9 is None
237
        and not __args
238
    ):
239
        return await _Concurrently(tuple(__arg0))
6✔
240

241
    if (
4✔
242
        isinstance(__arg0, Coroutine)
243
        and __arg1 is None
244
        and __arg2 is None
245
        and __arg3 is None
246
        and __arg4 is None
247
        and __arg5 is None
248
        and __arg6 is None
249
        and __arg7 is None
250
        and __arg8 is None
251
        and __arg9 is None
252
        and not __args
253
    ):
UNCOV
254
        return await _Concurrently((__arg0,))
×
255

256
    if (
4✔
257
        isinstance(__arg0, Coroutine)
258
        and isinstance(__arg1, Coroutine)
259
        and __arg2 is None
260
        and __arg3 is None
261
        and __arg4 is None
262
        and __arg5 is None
263
        and __arg6 is None
264
        and __arg7 is None
265
        and __arg8 is None
266
        and __arg9 is None
267
        and not __args
268
    ):
269
        return await _Concurrently((__arg0, __arg1))
4✔
270

UNCOV
271
    if (
×
272
        isinstance(__arg0, Coroutine)
273
        and isinstance(__arg1, Coroutine)
274
        and isinstance(__arg2, Coroutine)
275
        and __arg3 is None
276
        and __arg4 is None
277
        and __arg5 is None
278
        and __arg6 is None
279
        and __arg7 is None
280
        and __arg8 is None
281
        and __arg9 is None
282
        and not __args
283
    ):
UNCOV
284
        return await _Concurrently((__arg0, __arg1, __arg2))
×
285

UNCOV
286
    if (
×
287
        isinstance(__arg0, Coroutine)
288
        and isinstance(__arg1, Coroutine)
289
        and isinstance(__arg2, Coroutine)
290
        and isinstance(__arg3, Coroutine)
291
        and __arg4 is None
292
        and __arg5 is None
293
        and __arg6 is None
294
        and __arg7 is None
295
        and __arg8 is None
296
        and __arg9 is None
297
        and not __args
298
    ):
UNCOV
299
        return await _Concurrently((__arg0, __arg1, __arg2, __arg3))
×
300

UNCOV
301
    if (
×
302
        isinstance(__arg0, Coroutine)
303
        and isinstance(__arg1, Coroutine)
304
        and isinstance(__arg2, Coroutine)
305
        and isinstance(__arg3, Coroutine)
306
        and isinstance(__arg4, Coroutine)
307
        and __arg5 is None
308
        and __arg6 is None
309
        and __arg7 is None
310
        and __arg8 is None
311
        and __arg9 is None
312
        and not __args
313
    ):
UNCOV
314
        return await _Concurrently((__arg0, __arg1, __arg2, __arg3, __arg4))
×
315

UNCOV
316
    if (
×
317
        isinstance(__arg0, Coroutine)
318
        and isinstance(__arg1, Coroutine)
319
        and isinstance(__arg2, Coroutine)
320
        and isinstance(__arg3, Coroutine)
321
        and isinstance(__arg4, Coroutine)
322
        and isinstance(__arg5, Coroutine)
323
        and __arg6 is None
324
        and __arg7 is None
325
        and __arg8 is None
326
        and __arg9 is None
327
        and not __args
328
    ):
UNCOV
329
        return await _Concurrently((__arg0, __arg1, __arg2, __arg3, __arg4, __arg5))
×
330

UNCOV
331
    if (
×
332
        isinstance(__arg0, Coroutine)
333
        and isinstance(__arg1, Coroutine)
334
        and isinstance(__arg2, Coroutine)
335
        and isinstance(__arg3, Coroutine)
336
        and isinstance(__arg4, Coroutine)
337
        and isinstance(__arg5, Coroutine)
338
        and isinstance(__arg6, Coroutine)
339
        and __arg7 is None
340
        and __arg8 is None
341
        and __arg9 is None
342
        and not __args
343
    ):
UNCOV
344
        return await _Concurrently((__arg0, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6))
×
345

UNCOV
346
    if (
×
347
        isinstance(__arg0, Coroutine)
348
        and isinstance(__arg1, Coroutine)
349
        and isinstance(__arg2, Coroutine)
350
        and isinstance(__arg3, Coroutine)
351
        and isinstance(__arg4, Coroutine)
352
        and isinstance(__arg5, Coroutine)
353
        and isinstance(__arg6, Coroutine)
354
        and isinstance(__arg7, Coroutine)
355
        and __arg8 is None
356
        and __arg9 is None
357
        and not __args
358
    ):
UNCOV
359
        return await _Concurrently((__arg0, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7))
×
360

UNCOV
361
    if (
×
362
        isinstance(__arg0, Coroutine)
363
        and isinstance(__arg1, Coroutine)
364
        and isinstance(__arg2, Coroutine)
365
        and isinstance(__arg3, Coroutine)
366
        and isinstance(__arg4, Coroutine)
367
        and isinstance(__arg5, Coroutine)
368
        and isinstance(__arg6, Coroutine)
369
        and isinstance(__arg7, Coroutine)
370
        and isinstance(__arg8, Coroutine)
371
        and __arg9 is None
372
        and not __args
373
    ):
UNCOV
374
        return await _Concurrently(
×
375
            (__arg0, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8)
376
        )
377

UNCOV
378
    if (
×
379
        isinstance(__arg0, Coroutine)
380
        and isinstance(__arg1, Coroutine)
381
        and isinstance(__arg2, Coroutine)
382
        and isinstance(__arg3, Coroutine)
383
        and isinstance(__arg4, Coroutine)
384
        and isinstance(__arg5, Coroutine)
385
        and isinstance(__arg6, Coroutine)
386
        and isinstance(__arg7, Coroutine)
387
        and isinstance(__arg8, Coroutine)
388
        and isinstance(__arg9, Coroutine)
389
        and all(isinstance(arg, Coroutine) for arg in __args)
390
    ):
UNCOV
391
        return await _Concurrently(
×
392
            (
393
                __arg0,
394
                __arg1,
395
                __arg2,
396
                __arg3,
397
                __arg4,
398
                __arg5,
399
                __arg6,
400
                __arg7,
401
                __arg8,
402
                __arg9,
403
                *__args,
404
            )
405
        )
406

UNCOV
407
    args = __arg0, __arg1, __arg2, __arg3, __arg4, __arg5, __arg6, __arg7, __arg8, __arg9, *__args
×
408

UNCOV
409
    def render_arg(arg: Any) -> str | None:
×
UNCOV
410
        if arg is None:
×
UNCOV
411
            return None
×
UNCOV
412
        return repr(arg)
×
413

UNCOV
414
    likely_args_explicitly_passed = tuple(
×
415
        reversed(
416
            [
417
                render_arg(arg)
418
                for arg in itertools.dropwhile(lambda arg: arg is None, reversed(args))
419
            ]
420
        )
421
    )
UNCOV
422
    if any(arg is None for arg in likely_args_explicitly_passed):
×
UNCOV
423
        raise ValueError(
×
424
            softwrap(
425
                f"""
426
                Unexpected concurrently() None arguments: {
427
                    ", ".join(map(str, likely_args_explicitly_passed))
428
                }
429

430
                When calling concurrently() on individual rule calls, all leading arguments must be
431
                awaitables.
432
                """
433
            )
434
        )
435

UNCOV
436
    raise TypeError(
×
437
        softwrap(
438
            f"""
439
            Unexpected concurrently() argument types: {", ".join(map(str, likely_args_explicitly_passed))}
440

441
            `concurrently` can be used in two ways:
442
              1. concurrently(Iterable[awaitable[T]]) -> Tuple[T]
443
              2. concurrently(awaitable[T1]], ...) -> Tuple[T1, T2, ...]
444

445
            The 1st form is intended for homogenous collections of rule calls and emulates an
446
            async `for ...` comprehension used to iterate over the collection in parallel and
447
            collect the results in a homogenous tuple when all are complete.
448

449
            The 2nd form supports executing heterogeneous rule calls in parallel and collecting
450
            them in a heterogeneous tuple when all are complete. Currently up to 10 heterogeneous
451
            rule calls can be passed while still tracking their output types for type-checking by
452
            MyPy and similar type checkers. If more than 10 rule calls are passed, type checking
453
            will enforce that they are homogeneous.
454
            """
455
        )
456
    )
457

458

459
concurrently = Concurrently
11✔
460

461

462
@dataclass(frozen=True)
11✔
463
class Params:
11✔
464
    """A set of values with distinct types.
465

466
    Distinct types are enforced at consumption time by the rust type of the same name.
467
    """
468

469
    params: tuple[Any, ...]
11✔
470

471
    def __init__(self, *args: Any) -> None:
11✔
472
        object.__setattr__(self, "params", tuple(args))
11✔
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