comparison env/lib/python3.9/site-packages/pip/_vendor/resolvelib/structs.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 from .compat import collections_abc
2
3
4 class DirectedGraph(object):
5 """A graph structure with directed edges."""
6
7 def __init__(self):
8 self._vertices = set()
9 self._forwards = {} # <key> -> Set[<key>]
10 self._backwards = {} # <key> -> Set[<key>]
11
12 def __iter__(self):
13 return iter(self._vertices)
14
15 def __len__(self):
16 return len(self._vertices)
17
18 def __contains__(self, key):
19 return key in self._vertices
20
21 def copy(self):
22 """Return a shallow copy of this graph."""
23 other = DirectedGraph()
24 other._vertices = set(self._vertices)
25 other._forwards = {k: set(v) for k, v in self._forwards.items()}
26 other._backwards = {k: set(v) for k, v in self._backwards.items()}
27 return other
28
29 def add(self, key):
30 """Add a new vertex to the graph."""
31 if key in self._vertices:
32 raise ValueError("vertex exists")
33 self._vertices.add(key)
34 self._forwards[key] = set()
35 self._backwards[key] = set()
36
37 def remove(self, key):
38 """Remove a vertex from the graph, disconnecting all edges from/to it."""
39 self._vertices.remove(key)
40 for f in self._forwards.pop(key):
41 self._backwards[f].remove(key)
42 for t in self._backwards.pop(key):
43 self._forwards[t].remove(key)
44
45 def connected(self, f, t):
46 return f in self._backwards[t] and t in self._forwards[f]
47
48 def connect(self, f, t):
49 """Connect two existing vertices.
50
51 Nothing happens if the vertices are already connected.
52 """
53 if t not in self._vertices:
54 raise KeyError(t)
55 self._forwards[f].add(t)
56 self._backwards[t].add(f)
57
58 def iter_edges(self):
59 for f, children in self._forwards.items():
60 for t in children:
61 yield f, t
62
63 def iter_children(self, key):
64 return iter(self._forwards[key])
65
66 def iter_parents(self, key):
67 return iter(self._backwards[key])
68
69
70 class _FactoryIterableView(object):
71 """Wrap an iterator factory returned by `find_matches()`.
72
73 Calling `iter()` on this class would invoke the underlying iterator
74 factory, making it a "collection with ordering" that can be iterated
75 through multiple times, but lacks random access methods presented in
76 built-in Python sequence types.
77 """
78
79 def __init__(self, factory):
80 self._factory = factory
81
82 def __repr__(self):
83 return "{}({})".format(type(self).__name__, list(self._factory()))
84
85 def __bool__(self):
86 try:
87 next(self._factory())
88 except StopIteration:
89 return False
90 return True
91
92 __nonzero__ = __bool__ # XXX: Python 2.
93
94 def __iter__(self):
95 return self._factory()
96
97 def for_preference(self):
98 """Provide an candidate iterable for `get_preference()`"""
99 return self._factory()
100
101 def excluding(self, candidates):
102 """Create a new instance excluding specified candidates."""
103
104 def factory():
105 return (c for c in self._factory() if c not in candidates)
106
107 return type(self)(factory)
108
109
110 class _SequenceIterableView(object):
111 """Wrap an iterable returned by find_matches().
112
113 This is essentially just a proxy to the underlying sequence that provides
114 the same interface as `_FactoryIterableView`.
115 """
116
117 def __init__(self, sequence):
118 self._sequence = sequence
119
120 def __repr__(self):
121 return "{}({})".format(type(self).__name__, self._sequence)
122
123 def __bool__(self):
124 return bool(self._sequence)
125
126 __nonzero__ = __bool__ # XXX: Python 2.
127
128 def __iter__(self):
129 return iter(self._sequence)
130
131 def __len__(self):
132 return len(self._sequence)
133
134 def for_preference(self):
135 """Provide an candidate iterable for `get_preference()`"""
136 return self._sequence
137
138 def excluding(self, candidates):
139 """Create a new instance excluding specified candidates."""
140 return type(self)([c for c in self._sequence if c not in candidates])
141
142
143 def build_iter_view(matches):
144 """Build an iterable view from the value returned by `find_matches()`."""
145 if callable(matches):
146 return _FactoryIterableView(matches)
147 if not isinstance(matches, collections_abc.Sequence):
148 matches = list(matches)
149 return _SequenceIterableView(matches)