forked from pantsbuild/pants
-
Notifications
You must be signed in to change notification settings - Fork 0
/
addresses.py
74 lines (54 loc) · 2.84 KB
/
addresses.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from dataclasses import dataclass
from typing import Iterable, Optional, Sequence, Tuple
from pants.base.exceptions import ResolveError
from pants.base.specs import Spec
from pants.build_graph.address import Address as Address
from pants.build_graph.address import AddressInput as AddressInput # noqa: F401: rexport.
from pants.build_graph.address import BuildFileAddress as BuildFileAddress # noqa: F401: rexport.
from pants.engine.collection import Collection
from pants.util.meta import frozen_after_init
def assert_single_address(addresses: Sequence[Address]) -> None:
"""Assert that exactly one address must be contained in the collection."""
if len(addresses) == 0:
raise ResolveError("No targets were matched.")
if len(addresses) > 1:
output = "\n * ".join(address.spec for address in addresses)
raise ResolveError(
"Expected a single target, but was given multiple targets.\n\n"
f"Did you mean one of:\n * {output}"
)
class Addresses(Collection[Address]):
def expect_single(self) -> Address:
assert_single_address(self)
return self[0]
@dataclass(frozen=True)
class AddressWithOrigin:
"""An Address along with the cmd-line spec it was generated from."""
address: Address
origin: Spec
class AddressesWithOrigins(Collection[AddressWithOrigin]):
def expect_single(self) -> AddressWithOrigin:
assert_single_address([address_with_origin.address for address_with_origin in self])
return self[0]
@frozen_after_init
@dataclass(unsafe_hash=True)
class UnparsedAddressInputs:
"""Raw addresses that have not been parsed yet.
You can convert these into fully normalized `Addresses` and `Targets` like this:
await Get(Addresses, UnparsedAddressInputs(["//:tgt1", "//:tgt2"], owning_address=None)
await Get(Targets, UnparsedAddressInputs([...], owning_address=Address("original"))
This is intended for contexts where the user specifies addresses outside of the `dependencies`
field, such as through an option or a special field on a target that is not normal
`dependencies`. You should not use this to resolve the `dependencies` field; use
`await Get(Addresses, DependenciesRequest)` for that.
If the addresses are coming from a target's fields, set `owning_address` so that relative
references like `:sibling` work properly.
Unlike the `dependencies` field, this type does not work with `!` and `!!` ignores.
"""
values: Tuple[str, ...]
relative_to: Optional[str]
def __init__(self, values: Iterable[str], *, owning_address: Optional[Address]) -> None:
self.values = tuple(values)
self.relative_to = owning_address.spec_path if owning_address else None