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

pantsbuild / pants / 20147226056

11 Dec 2025 08:58PM UTC coverage: 78.827% (-1.5%) from 80.293%
20147226056

push

github

web-flow
Forwarded the `style` and `complete-platform` args from pants.toml to PEX (#22910)

## Context

After Apple switched to the `arm64` architecture, some package
publishers stopped releasing `x86_64` variants of their packages for
`darwin`. As a result, generating a universal lockfile now fails because
no single package version is compatible with both `x86_64` and `arm64`
on `darwin`.

The solution is to use the `--style` and `--complete-platform` flags
with PEX. For example:
```
pex3 lock create \
    --style strict \
    --complete-platform 3rdparty/platforms/manylinux_2_28_aarch64.json \
    --complete-platform 3rdparty/platforms/macosx_26_0_arm64.json \
    -r 3rdparty/python/requirements_pyarrow.txt \
    -o python-pyarrow.lock
```

See the Slack discussion here:
https://pantsbuild.slack.com/archives/C046T6T9U/p1760098582461759

## Reproduction

* `BUILD`
```
python_requirement(
    name="awswrangler",
    requirements=["awswrangler==3.12.1"],
    resolve="awswrangler",
)
```
* Run `pants generate-lockfiles --resolve=awswrangler` on macOS with an
`arm64` CPU
```
pip: ERROR: Cannot install awswrangler==3.12.1 because these package versions have conflicting dependencies.
pip: ERROR: ResolutionImpossible: for help visit https://pip.pypa.io/en/latest/topics/dependency-resolution/#dealing-with-dependency-conflicts
pip:  
pip:  The conflict is caused by:
pip:      awswrangler 3.12.1 depends on pyarrow<18.0.0 and >=8.0.0; sys_platform == "darwin" and platform_machine == "x86_64"
pip:      awswrangler 3.12.1 depends on pyarrow<21.0.0 and >=18.0.0; sys_platform != "darwin" or platform_machine != "x86_64"
pip:  
pip:  Additionally, some packages in these conflicts have no matching distributions available for your environment:
pip:      pyarrow
pip:  
pip:  To fix this you could try to:
pip:  1. loosen the range of package versions you've specified
pip:  2. remove package versions to allow pip to attempt to solve the dependency conflict
```

## Implementation
... (continued)

77 of 100 new or added lines in 6 files covered. (77.0%)

868 existing lines in 42 files now uncovered.

74471 of 94474 relevant lines covered (78.83%)

3.18 hits per line

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

62.5
/src/python/pants/util/ordered_set.py
1
# Copyright 2020 Pants project contributors (see CONTRIBUTORS.md).
2
# Licensed under the Apache License, Version 2.0 (see LICENSE).
3

4
"""An OrderedSet is a set that remembers its insertion order, and a FrozenOrderedSet is one that is
5
also immutable.
6

7
Based on the library `ordered-set` developed by Robyn Speer and released under the MIT license:
8
https://github.com/LuminosoInsight/ordered-set.
9

10
The library `ordered-set` is itself originally based on a recipe originally posted to ActivateState
11
Recipes by Raymond Hettiger and released under the MIT license:
12
http://code.activestate.com/recipes/576694/.
13
"""
14

15
from __future__ import annotations
11✔
16

17
import itertools
11✔
18
from collections.abc import Hashable, Iterable, Iterator, MutableSet
11✔
19
from typing import AbstractSet, Any, TypeVar, cast
11✔
20

21
T = TypeVar("T")
11✔
22
T_co = TypeVar("T_co", covariant=True)
11✔
23
_TAbstractOrderedSet = TypeVar("_TAbstractOrderedSet", bound="_AbstractOrderedSet")
11✔
24

25

26
class _AbstractOrderedSet(AbstractSet[T]):
11✔
27
    """Common functionality shared between OrderedSet and FrozenOrderedSet."""
28

29
    def __init__(self, iterable: Iterable[T] | None = None) -> None:
11✔
30
        # Using a dictionary, rather than using the recipe's original `self |= iterable`, results
31
        # in a ~20% performance increase for the constructor.
32
        #
33
        # NB: Dictionaries are ordered in Python 3.7+.
34
        self._items: dict[T, None] = dict.fromkeys(iterable) if iterable else {}
11✔
35

36
    def __len__(self) -> int:
11✔
37
        """Returns the number of unique elements in the set."""
38
        return len(self._items)
11✔
39

40
    def __copy__(self: _TAbstractOrderedSet) -> _TAbstractOrderedSet:
11✔
41
        """Return a shallow copy of this object."""
UNCOV
42
        return self.__class__(self)
×
43

44
    def __contains__(self, key: Any) -> bool:
11✔
45
        """Test if the item is in this ordered set."""
46
        return key in self._items
6✔
47

48
    def __iter__(self) -> Iterator[T]:
11✔
49
        return iter(self._items)
11✔
50

51
    def __reversed__(self) -> Iterator[T]:
11✔
UNCOV
52
        return reversed(tuple(self._items.keys()))
×
53

54
    def __repr__(self) -> str:
11✔
55
        name = self.__class__.__name__
11✔
56
        if not self:
11✔
57
            return f"{name}()"
11✔
58
        return f"{name}({list(self)!r})"
1✔
59

60
    def __eq__(self, other: Any) -> bool:
11✔
61
        """Returns True if other is the same type with the same elements and same order."""
62
        if not isinstance(other, self.__class__):
9✔
63
            return NotImplemented
1✔
64
        return len(self._items) == len(other._items) and all(
9✔
65
            x == y for x, y in zip(self._items, other._items)
66
        )
67

68
    def __or__(self: _TAbstractOrderedSet, other: Iterable[T]) -> _TAbstractOrderedSet:  # type: ignore[override]
11✔
UNCOV
69
        return self.union(other)
×
70

71
    def union(self: _TAbstractOrderedSet, *others: Iterable[T]) -> _TAbstractOrderedSet:
11✔
72
        """Combines all unique items.
73

74
        Each item's order is defined by its first appearance.
75
        """
76
        # Differences with AbstractSet: our set union forces "other" to have the same type. That
77
        # is, while AbstractSet allows {1, 2, 3} | {(True, False)} resulting in
78
        # set[int | tuple[bool, bool]], the analogous for descendants  of _TAbstractOrderedSet is
79
        # not allowed.
80
        #
81
        # GOTCHA: given _TAbstractOrderedSet[S]:
82
        #   if T is a subclass of S => _TAbstractOrderedSet[S] => *appears* to perform
83
        #     unification but it doesn't
84
        #   if S is a subclass of T => type error (while AbstractSet would resolve to
85
        #     AbstractSet[T])
UNCOV
86
        merged_iterables = itertools.chain([cast(Iterable[T], self)], others)
×
UNCOV
87
        return self.__class__(itertools.chain.from_iterable(merged_iterables))
×
88

89
    def __and__(self: _TAbstractOrderedSet, other: Iterable[T]) -> _TAbstractOrderedSet:
11✔
90
        # The parent class's implementation of this is backwards.
UNCOV
91
        return self.intersection(other)
×
92

93
    def intersection(self: _TAbstractOrderedSet, *others: Iterable[T]) -> _TAbstractOrderedSet:
11✔
94
        """Returns elements in common between all sets.
95

96
        Order is defined only by the first set.
97
        """
UNCOV
98
        cls = self.__class__
×
UNCOV
99
        if not others:
×
100
            return cls(self)
×
UNCOV
101
        common = set.intersection(*(set(other) for other in others))
×
UNCOV
102
        return cls(item for item in self if item in common)
×
103

104
    def difference(self: _TAbstractOrderedSet, *others: Iterable[T]) -> _TAbstractOrderedSet:
11✔
105
        """Returns all elements that are in this set but not the others."""
UNCOV
106
        cls = self.__class__
×
UNCOV
107
        if not others:
×
108
            return cls(self)
×
UNCOV
109
        other = set.union(*(set(other) for other in others))
×
UNCOV
110
        return cls(item for item in self if item not in other)
×
111

112
    def issubset(self, other: Iterable[T]) -> bool:
11✔
113
        """Report whether another set contains this set."""
114
        try:
1✔
115
            # Fast check for obvious cases
116
            if len(self) > len(other):  # type: ignore[arg-type]
1✔
UNCOV
117
                return False
×
118
        except TypeError:
×
119
            pass
×
120
        return all(item in other for item in self)
1✔
121

122
    def issuperset(self, other: Iterable[T]) -> bool:
11✔
123
        """Report whether this set contains another set."""
124
        try:
2✔
125
            # Fast check for obvious cases
126
            if len(self) < len(other):  # type: ignore[arg-type]
2✔
127
                return False
1✔
128
        except TypeError:
×
129
            pass
×
130
        return all(item in self for item in other)
2✔
131

132
    def __xor__(self: _TAbstractOrderedSet, other: Iterable[T]) -> _TAbstractOrderedSet:  # type: ignore[override]
11✔
UNCOV
133
        return self.symmetric_difference(other)
×
134

135
    def symmetric_difference(
11✔
136
        self: _TAbstractOrderedSet, other: Iterable[T]
137
    ) -> _TAbstractOrderedSet:
138
        """Return the symmetric difference of this OrderedSet and another set as a new OrderedSet.
139
        That is, the new set will contain all elements that are in exactly one of the sets.
140

141
        Their order will be preserved, with elements from `self` preceding elements from `other`.
142
        """
UNCOV
143
        cls = self.__class__
×
UNCOV
144
        diff1 = cls(self).difference(other)
×
UNCOV
145
        diff2 = cls(other).difference(self)
×
UNCOV
146
        return diff1.union(diff2)
×
147

148

149
class OrderedSet(_AbstractOrderedSet[T], MutableSet[T]):
11✔
150
    """A mutable set that retains its order.
151

152
    This is not safe to use with the V2 engine.
153
    """
154

155
    def add(self, key: T) -> None:
11✔
156
        """Add `key` as an item to this OrderedSet."""
157
        self._items[key] = None
11✔
158

159
    def update(self, iterable: Iterable[T]) -> None:
11✔
160
        """Update the set with the given iterable sequence."""
161
        for item in iterable:
2✔
162
            self.add(item)
2✔
163

164
    def discard(self, key: T) -> None:
11✔
165
        """Remove an element. Do not raise an exception if absent.
166

167
        The MutableSet mixin uses this to implement the .remove() method, which
168
        *does* raise an error when asked to remove a non-existent item.
169
        """
170
        self._items.pop(key, None)
1✔
171

172
    def clear(self) -> None:
11✔
173
        """Remove all items from this OrderedSet."""
UNCOV
174
        self._items.clear()
×
175

176
    def difference_update(self, *others: Iterable[T]) -> None:
11✔
177
        """Update this OrderedSet to remove items from one or more other sets."""
UNCOV
178
        items_to_remove: set[T] = set()
×
UNCOV
179
        for other in others:
×
UNCOV
180
            items_as_set = set(other)
×
UNCOV
181
            items_to_remove |= items_as_set
×
UNCOV
182
        self._items = {item: None for item in self._items.keys() if item not in items_to_remove}
×
183

184
    def intersection_update(self, other: Iterable[T]) -> None:
11✔
185
        """Update this OrderedSet to keep only items in another set, preserving their order in this
186
        set."""
UNCOV
187
        other = set(other)
×
UNCOV
188
        self._items = {item: None for item in self._items.keys() if item in other}
×
189

190
    def symmetric_difference_update(self, other: Iterable[T]) -> None:
11✔
191
        """Update this OrderedSet to remove items from another set, then add items from the other
192
        set that were not present in this set."""
UNCOV
193
        items_to_add = [item for item in other if item not in self]
×
UNCOV
194
        items_to_remove = cast(set[T], set(other))
×
UNCOV
195
        self._items = {item: None for item in self._items.keys() if item not in items_to_remove}
×
UNCOV
196
        for item in items_to_add:
×
UNCOV
197
            self._items[item] = None
×
198

199

200
class FrozenOrderedSet(_AbstractOrderedSet[T_co], Hashable):  # type: ignore[type-var]
11✔
201
    """A frozen (i.e. immutable) set that retains its order.
202

203
    This is safe to use with the V2 engine.
204
    """
205

206
    def __init__(self, iterable: Iterable[T_co] | None = None) -> None:
11✔
207
        super().__init__(iterable)
11✔
208
        self.__hash: int | None = None
11✔
209

210
    def __hash__(self) -> int:
11✔
211
        if self.__hash is None:
11✔
212
            self.__hash = 0
11✔
213
            for item in self._items.keys():
11✔
214
                self.__hash ^= hash(item)
11✔
215
        return self.__hash
11✔
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