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

pantsbuild / pants / 18252174847

05 Oct 2025 01:36AM UTC coverage: 43.382% (-36.9%) from 80.261%
18252174847

push

github

web-flow
run tests on mac arm (#22717)

Just doing the minimal to pull forward the x86_64 pattern.

ref #20993

25776 of 59416 relevant lines covered (43.38%)

1.3 hits per line

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

0.0
/src/python/pants/backend/codegen/thrift/dependency_inference.py
1
# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
×
5

6
from collections import defaultdict
×
7
from dataclasses import dataclass
×
8
from typing import DefaultDict
×
9

10
from pants.backend.codegen.thrift import thrift_parser
×
11
from pants.backend.codegen.thrift.subsystem import ThriftSubsystem
×
12
from pants.backend.codegen.thrift.target_types import (
×
13
    AllThriftTargets,
14
    ThriftDependenciesField,
15
    ThriftSourceField,
16
)
17
from pants.backend.codegen.thrift.thrift_parser import ParsedThriftRequest, parse_thrift_file
×
18
from pants.core.util_rules.stripped_source_files import StrippedFileNameRequest, strip_file_name
×
19
from pants.engine.addresses import Address
×
20
from pants.engine.internals.graph import determine_explicitly_provided_dependencies
×
21
from pants.engine.rules import collect_rules, concurrently, implicitly, rule
×
22
from pants.engine.target import (
×
23
    DependenciesRequest,
24
    FieldSet,
25
    InferDependenciesRequest,
26
    InferredDependencies,
27
)
28
from pants.engine.unions import UnionRule
×
29
from pants.util.frozendict import FrozenDict
×
30
from pants.util.logging import LogLevel
×
31
from pants.util.ordered_set import OrderedSet
×
32
from pants.util.strutil import softwrap
×
33

34

35
@dataclass(frozen=True)
×
36
class ThriftMapping:
×
37
    """A mapping of stripped .thrift file names to their owning file address."""
38

39
    mapping: FrozenDict[str, Address]
×
40
    ambiguous_modules: FrozenDict[str, tuple[Address, ...]]
×
41

42

43
@rule(desc="Creating map of Thrift file names to Thrift targets", level=LogLevel.DEBUG)
×
44
async def map_thrift_files(thrift_targets: AllThriftTargets) -> ThriftMapping:
×
45
    stripped_file_per_target = await concurrently(
×
46
        strip_file_name(StrippedFileNameRequest(tgt[ThriftSourceField].file_path))
47
        for tgt in thrift_targets
48
    )
49

50
    stripped_files_to_addresses: dict[str, Address] = {}
×
51
    stripped_files_with_multiple_owners: DefaultDict[str, set[Address]] = defaultdict(set)
×
52
    for tgt, stripped_file in zip(thrift_targets, stripped_file_per_target):
×
53
        if stripped_file.value in stripped_files_to_addresses:
×
54
            stripped_files_with_multiple_owners[stripped_file.value].update(
×
55
                {stripped_files_to_addresses[stripped_file.value], tgt.address}
56
            )
57
        else:
58
            stripped_files_to_addresses[stripped_file.value] = tgt.address
×
59

60
    # Remove files with ambiguous owners.
61
    for ambiguous_stripped_f in stripped_files_with_multiple_owners:
×
62
        stripped_files_to_addresses.pop(ambiguous_stripped_f)
×
63

64
    return ThriftMapping(
×
65
        mapping=FrozenDict(sorted(stripped_files_to_addresses.items())),
66
        ambiguous_modules=FrozenDict(
67
            (k, tuple(sorted(v))) for k, v in sorted(stripped_files_with_multiple_owners.items())
68
        ),
69
    )
70

71

72
@dataclass(frozen=True)
×
73
class ThriftDependenciesInferenceFieldSet(FieldSet):
×
74
    required_fields = (ThriftSourceField, ThriftDependenciesField)
×
75

76
    source: ThriftSourceField
×
77
    dependencies: ThriftDependenciesField
×
78

79

80
class InferThriftDependencies(InferDependenciesRequest):
×
81
    infer_from = ThriftDependenciesInferenceFieldSet
×
82

83

84
@rule(desc="Inferring Thrift dependencies by analyzing imports")
×
85
async def infer_thrift_dependencies(
×
86
    request: InferThriftDependencies, thrift_mapping: ThriftMapping, thrift: ThriftSubsystem
87
) -> InferredDependencies:
88
    if not thrift.dependency_inference:
×
89
        return InferredDependencies([])
×
90

91
    address = request.field_set.address
×
92
    explicitly_provided_deps, parsed_thrift = await concurrently(
×
93
        determine_explicitly_provided_dependencies(
94
            **implicitly(DependenciesRequest(request.field_set.dependencies))
95
        ),
96
        parse_thrift_file(ParsedThriftRequest(request.field_set.source)),
97
    )
98

99
    result: OrderedSet[Address] = OrderedSet()
×
100
    for import_path in parsed_thrift.imports:
×
101
        unambiguous = thrift_mapping.mapping.get(import_path)
×
102
        ambiguous = thrift_mapping.ambiguous_modules.get(import_path)
×
103
        if unambiguous:
×
104
            result.add(unambiguous)
×
105
        elif ambiguous:
×
106
            explicitly_provided_deps.maybe_warn_of_ambiguous_dependency_inference(
×
107
                ambiguous,
108
                address,
109
                import_reference="file",
110
                context=softwrap(
111
                    f"""
112
                    The target {address} imports `{import_path}` in the file
113
                    {request.field_set.source.file_path}
114
                    """
115
                ),
116
            )
117
            maybe_disambiguated = explicitly_provided_deps.disambiguated(ambiguous)
×
118
            if maybe_disambiguated:
×
119
                result.add(maybe_disambiguated)
×
120
    return InferredDependencies(sorted(result))
×
121

122

123
def rules():
×
124
    return (
×
125
        *collect_rules(),
126
        *thrift_parser.rules(),
127
        UnionRule(InferDependenciesRequest, InferThriftDependencies),
128
    )
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