• 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/jvm_symbol_mapper.py
1
# Copyright 2023 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
UNCOV
3
from __future__ import annotations
×
4

UNCOV
5
import os
×
UNCOV
6
import re
×
UNCOV
7
from collections import defaultdict
×
UNCOV
8
from collections.abc import Mapping
×
UNCOV
9
from dataclasses import dataclass
×
UNCOV
10
from typing import DefaultDict
×
11

UNCOV
12
from pants.backend.codegen.protobuf.target_types import AllProtobufTargets, ProtobufSourceField
×
UNCOV
13
from pants.engine.addresses import Address
×
UNCOV
14
from pants.engine.fs import FileContent
×
UNCOV
15
from pants.engine.internals.graph import hydrate_sources
×
UNCOV
16
from pants.engine.intrinsics import get_digest_contents
×
UNCOV
17
from pants.engine.rules import collect_rules, concurrently, implicitly, rule
×
UNCOV
18
from pants.engine.target import HydrateSourcesRequest
×
UNCOV
19
from pants.jvm.dependency_inference.artifact_mapper import MutableTrieNode
×
UNCOV
20
from pants.jvm.dependency_inference.symbol_mapper import SymbolMap
×
UNCOV
21
from pants.jvm.subsystems import JvmSubsystem
×
UNCOV
22
from pants.jvm.target_types import JvmResolveField
×
UNCOV
23
from pants.util.ordered_set import OrderedSet
×
24

UNCOV
25
_ResolveName = str
×
26

27

UNCOV
28
@dataclass(frozen=True)
×
UNCOV
29
class FirstPartyProtobufJvmMappingRequest:
×
UNCOV
30
    capitalize_base_name: bool
×
31

32

UNCOV
33
@rule
×
UNCOV
34
async def map_first_party_protobuf_jvm_targets_to_symbols(
×
35
    request: FirstPartyProtobufJvmMappingRequest,
36
    all_protobuf_targets: AllProtobufTargets,
37
    jvm: JvmSubsystem,
38
) -> SymbolMap:
39
    sources = await concurrently(
×
40
        hydrate_sources(
41
            HydrateSourcesRequest(
42
                tgt[ProtobufSourceField],
43
                for_sources_types=(ProtobufSourceField,),
44
                enable_codegen=True,
45
            ),
46
            **implicitly(),
47
        )
48
        for tgt in all_protobuf_targets
49
    )
50

51
    all_contents = await concurrently(
×
52
        get_digest_contents(source.snapshot.digest) for source in sources
53
    )
54

55
    namespace_mapping: DefaultDict[tuple[_ResolveName, str], OrderedSet[Address]] = defaultdict(
×
56
        OrderedSet
57
    )
58
    for tgt, contents in zip(all_protobuf_targets, all_contents):
×
59
        if not contents:
×
60
            continue
×
61
        if len(contents) > 1:
×
62
            raise AssertionError(
×
63
                f"Protobuf target `{tgt.address}` mapped to more than one source file."
64
            )
65

66
        resolve = tgt[JvmResolveField].normalized_value(jvm)
×
67
        namespace = _determine_namespace(
×
68
            contents[0], capitalize_base_name=request.capitalize_base_name
69
        )
70
        namespace_mapping[(resolve, namespace)].add(tgt.address)
×
71

72
    mapping: Mapping[str, MutableTrieNode] = defaultdict(MutableTrieNode)
×
73
    for (resolve, namespace), addresses in namespace_mapping.items():
×
74
        mapping[resolve].insert(namespace, addresses, first_party=True, recursive=True)
×
75

76
    return SymbolMap((resolve, node.frozen()) for resolve, node in mapping.items())
×
77

78

79
# Determine generated Java/Scala package name
80
# * https://grpc.io/docs/languages/java/generated-code
81
# * https://scalapb.github.io/docs/generated-code
UNCOV
82
def _determine_namespace(file: FileContent, *, capitalize_base_name: bool) -> str:
×
83
    base_name, _, _ = os.path.basename(file.path).partition(".")
×
84
    base_name = base_name.capitalize() if capitalize_base_name else base_name
×
85
    package_definition = _parse_package_definition(file.content)
×
86
    return f"{package_definition}.{base_name}" if package_definition else base_name
×
87

88

UNCOV
89
_QUOTE_CHAR = r"(?:'|\")"
×
UNCOV
90
_JAVA_PACKAGE_OPTION_RE = re.compile(
×
91
    rf"^\s*option\s+java_package\s+=\s+{_QUOTE_CHAR}(.+){_QUOTE_CHAR};"
92
)
UNCOV
93
_PACKAGE_RE = re.compile(r"^\s*package\s+(.+);")
×
94

95

UNCOV
96
def _parse_package_definition(content_raw: bytes) -> str | None:
×
97
    content = content_raw.decode()
×
98
    for line in content.splitlines():
×
99
        m = _JAVA_PACKAGE_OPTION_RE.match(line)
×
100
        if m:
×
101
            return m.group(1)
×
102
        m = _PACKAGE_RE.match(line)
×
103
        if m:
×
104
            return m.group(1)
×
105
    return None
×
106

107

UNCOV
108
def rules():
×
UNCOV
109
    return collect_rules()
×
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