• 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/jvm/bsp/compile.py
1
# Copyright 2022 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

UNCOV
4
import time
×
UNCOV
5
from dataclasses import dataclass
×
6

UNCOV
7
from pants.bsp.context import BSPContext
×
UNCOV
8
from pants.bsp.spec.base import BuildTargetIdentifier, StatusCode, TaskId
×
UNCOV
9
from pants.bsp.spec.log import LogMessageParams, MessageType
×
UNCOV
10
from pants.bsp.spec.task import TaskProgressParams
×
UNCOV
11
from pants.bsp.util_rules.targets import BSPCompileRequest, BSPCompileResult
×
UNCOV
12
from pants.engine.addresses import Addresses
×
UNCOV
13
from pants.engine.fs import AddPrefix, MergeDigests
×
UNCOV
14
from pants.engine.internals.graph import resolve_coarsened_targets
×
UNCOV
15
from pants.engine.internals.native_engine import EMPTY_DIGEST
×
UNCOV
16
from pants.engine.internals.selectors import concurrently
×
UNCOV
17
from pants.engine.intrinsics import add_prefix, merge_digests
×
UNCOV
18
from pants.engine.rules import collect_rules, implicitly, rule
×
UNCOV
19
from pants.jvm import classpath
×
UNCOV
20
from pants.jvm.compile import (
×
21
    ClasspathEntryRequest,
22
    ClasspathEntryRequestFactory,
23
    CompileResult,
24
    FallibleClasspathEntry,
25
    get_fallible_classpath_entry,
26
)
UNCOV
27
from pants.jvm.resolve.coursier_fetch import select_coursier_resolve_for_targets
×
UNCOV
28
from pants.jvm.target_types import JvmArtifactFieldSet
×
UNCOV
29
from pants.util.strutil import path_safe
×
30

31

UNCOV
32
def jvm_classes_directory(target_id: BuildTargetIdentifier) -> str:
×
33
    return f"jvm/classes/{path_safe(target_id.uri)}"
×
34

35

UNCOV
36
@dataclass(frozen=True)
×
UNCOV
37
class BSPClasspathEntryRequest:
×
38
    """A wrapper around a `ClasspathEntryRequest` which notifies the BSP client on completion.
39

40
    TODO: Because this struct contains a `task_id`, messages will re-render in every run, even
41
    though the underlying computation does not re-run. See #15426 for an alternative.
42
    """
43

44
    request: ClasspathEntryRequest
45
    task_id: TaskId
46

47

UNCOV
48
@rule
×
UNCOV
49
async def notify_for_classpath_entry(
×
50
    request: BSPClasspathEntryRequest,
51
    context: BSPContext,
52
) -> FallibleClasspathEntry:
53
    entry = await get_fallible_classpath_entry(
×
54
        **implicitly({request.request: ClasspathEntryRequest})
55
    )
56
    context.notify_client(
×
57
        TaskProgressParams(
58
            task_id=request.task_id,
59
            event_time=int(time.time() * 1000),
60
            message=entry.message(),
61
        )
62
    )
63
    if entry.result == CompileResult.FAILED:
×
64
        context.notify_client(
×
65
            LogMessageParams(
66
                type_=MessageType.ERROR,
67
                message=entry.message(),
68
                task=request.task_id,
69
            )
70
        )
71
    return entry
×
72

73

UNCOV
74
async def _jvm_bsp_compile(
×
75
    request: BSPCompileRequest, classpath_entry_request: ClasspathEntryRequestFactory
76
) -> BSPCompileResult:
77
    """Generically handles a BSPCompileRequest (subclass).
78

79
    This is a rule helper rather than a `@rule`, because BSP backends like `java` and `scala`
80
    independently declare their `BSPCompileRequest` union members. We can't register a single shared
81
    `BSPCompileRequest` @union member for all JVM because their FieldSets are also declared via
82
    @unions, and we can't forward the implementation of a @union to another the way we might with
83
    an abstract class.
84
    """
85
    coarsened_targets = await resolve_coarsened_targets(
×
86
        **implicitly(Addresses([fs.address for fs in request.field_sets]))
87
    )
88
    resolve = await select_coursier_resolve_for_targets(coarsened_targets, **implicitly())
×
89

90
    # TODO: We include the (non-3rdparty) transitive dependencies here, because each project
91
    # currently only has a single BuildTarget. This has the effect of including `resources` targets,
92
    # which are referenced by BuildTargets (via `buildTarget/resources`), rather than necessarily
93
    # being owned by any particular BuildTarget.
94
    #
95
    # To resolve #15051, this will no longer be transitive, and so `resources` will need to be
96
    # attached-to/referenced-by nearby BuildTarget(s) instead (most likely: direct dependent(s)).
97
    results = await concurrently(
×
98
        notify_for_classpath_entry(
99
            BSPClasspathEntryRequest(
100
                classpath_entry_request.for_targets(component=coarsened_target, resolve=resolve),
101
                task_id=request.task_id,
102
            ),
103
            **implicitly(),
104
        )
105
        for coarsened_target in coarsened_targets.coarsened_closure()
106
        if not any(JvmArtifactFieldSet.is_applicable(t) for t in coarsened_target.members)
107
    )
108

109
    entries = FallibleClasspathEntry.if_all_succeeded(results)
×
110
    if entries is None:
×
111
        return BSPCompileResult(
×
112
            status=StatusCode.ERROR,
113
            output_digest=EMPTY_DIGEST,
114
        )
115

116
    loose_clsfiles = await concurrently(
×
117
        classpath.loose_classfiles(entry, **implicitly()) for entry in entries
118
    )
119
    merged_loose_classfiles = await merge_digests(MergeDigests(lc.digest for lc in loose_clsfiles))
×
120
    output_digest = await add_prefix(
×
121
        AddPrefix(merged_loose_classfiles, jvm_classes_directory(request.bsp_target.bsp_target_id)),
122
    )
123

124
    return BSPCompileResult(
×
125
        status=StatusCode.OK,
126
        output_digest=output_digest,
127
    )
128

129

UNCOV
130
def rules():
×
UNCOV
131
    return [
×
132
        *collect_rules(),
133
        *classpath.rules(),
134
    ]
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