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

pantsbuild / pants / 18791134616

24 Oct 2025 08:18PM UTC coverage: 75.519% (-4.8%) from 80.282%
18791134616

Pull #22794

github

web-flow
Merge 098c595a0 into 7971a20bf
Pull Request #22794: Use self-hosted MacOS Intel runner

65803 of 87134 relevant lines covered (75.52%)

3.07 hits per line

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

76.47
/src/python/pants/build_graph/build_file_aliases.py
1
# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
from __future__ import annotations
10✔
5

6
from collections.abc import Callable, Mapping
10✔
7
from dataclasses import dataclass
10✔
8
from typing import Any
10✔
9

10
from pants.base.parse_context import ParseContext
10✔
11
from pants.util.frozendict import FrozenDict
10✔
12

13
ContextAwareObjectFactory = Callable[[ParseContext], Callable[..., None]]
10✔
14

15

16
@dataclass(frozen=True)
10✔
17
class BuildFileAliases:
10✔
18
    """A structure containing sets of symbols to be exposed in BUILD files.
19

20
    There are three types of symbols that can be directly exposed:
21

22
    :API: public
23

24
    - targets: These are Target subclasses or TargetMacro.Factory instances.
25
    - objects: These are any python object, from constants to types.
26
    - context_aware_object_factories: These are object factories that are passed a ParseContext and
27
      produce one or more objects that use data from the context to enable some feature or utility;
28
      you might call them a BUILD file "macro" since they expand parameters to some final, "real"
29
      BUILD file object.  Common uses include creating objects that must be aware of the current
30
      BUILD file path or functions that need to be able to create targets or objects from within the
31
      BUILD file parse.
32
    """
33

34
    _objects: FrozenDict[str, Any]
10✔
35
    _context_aware_object_factories: FrozenDict[str, ContextAwareObjectFactory]
10✔
36

37
    @classmethod
10✔
38
    def _validate_alias(cls, category: str, alias: str, obj: Any) -> None:
10✔
39
        if not isinstance(alias, str):
10✔
40
            raise TypeError(
×
41
                "Aliases must be strings, given {category} entry {alias!r} of type {typ} as "
42
                "the alias of {obj}".format(
43
                    category=category, alias=alias, typ=type(alias).__name__, obj=obj
44
                )
45
            )
46

47
    @classmethod
10✔
48
    def _validate_objects(cls, objects: dict[str, Any] | None) -> FrozenDict[str, Any]:
10✔
49
        if not objects:
10✔
50
            return FrozenDict()
10✔
51

52
        for alias, obj in objects.items():
10✔
53
            cls._validate_alias("objects", alias, obj)
10✔
54
        return FrozenDict(objects)
10✔
55

56
    @classmethod
10✔
57
    def _validate_context_aware_object_factories(
10✔
58
        cls, context_aware_object_factories: dict[str, ContextAwareObjectFactory] | None
59
    ) -> FrozenDict[str, ContextAwareObjectFactory]:
60
        if not context_aware_object_factories:
10✔
61
            return FrozenDict()
10✔
62

63
        for alias, obj in context_aware_object_factories.items():
2✔
64
            cls._validate_alias("context_aware_object_factories", alias, obj)
2✔
65
            if not callable(obj):
2✔
66
                raise TypeError(
×
67
                    "The given context aware object factory {alias!r} must be a callable.".format(
68
                        alias=alias
69
                    )
70
                )
71

72
        return FrozenDict(context_aware_object_factories)
2✔
73

74
    def __init__(
10✔
75
        self,
76
        objects: dict[str, Any] | None = None,
77
        context_aware_object_factories: dict[str, ContextAwareObjectFactory] | None = None,
78
    ) -> None:
79
        """
80
        :API: public
81
        """
82
        object.__setattr__(self, "_objects", self._validate_objects(objects))
10✔
83
        object.__setattr__(
10✔
84
            self,
85
            "_context_aware_object_factories",
86
            self._validate_context_aware_object_factories(context_aware_object_factories),
87
        )
88

89
    @property
10✔
90
    def objects(self) -> FrozenDict[str, Any]:
10✔
91
        """
92
        :API: public
93
        """
94
        return self._objects
10✔
95

96
    @property
10✔
97
    def context_aware_object_factories(self) -> FrozenDict[str, ContextAwareObjectFactory]:
10✔
98
        """
99
        :API: public
100
        """
101
        return self._context_aware_object_factories
10✔
102

103
    def merge(self, other: BuildFileAliases) -> BuildFileAliases:
10✔
104
        """Merges a set of build file aliases and returns a new set of aliases containing both.
105

106
        Any duplicate aliases from `other` will trump.
107

108
        :API: public
109
        """
110
        if not isinstance(other, BuildFileAliases):
×
111
            raise TypeError(f"Can only merge other BuildFileAliases, given {other}")
×
112

113
        def _merge(item1: Mapping[str, Any], item2: Mapping[str, Any]) -> dict[str, Any]:
×
114
            merged: dict[str, Any] = {}
×
115
            merged.update(item1)
×
116
            merged.update(item2)
×
117
            return merged
×
118

119
        objects = _merge(self.objects, other.objects)
×
120
        context_aware_object_factories = _merge(
×
121
            self.context_aware_object_factories, other.context_aware_object_factories
122
        )
123
        return BuildFileAliases(
×
124
            objects=objects,
125
            context_aware_object_factories=context_aware_object_factories,
126
        )
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