]> jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/setuptools/_distutils/_collections.py
init: venv aand flask
[dlqueue.git] / venv / lib / python3.11 / site-packages / setuptools / _distutils / _collections.py
1 import collections
2 import functools
3 import itertools
4 import operator
5
6
7 # from jaraco.collections 3.5.1
8 class DictStack(list, collections.abc.Mapping):
9 """
10 A stack of dictionaries that behaves as a view on those dictionaries,
11 giving preference to the last.
12
13 >>> stack = DictStack([dict(a=1, c=2), dict(b=2, a=2)])
14 >>> stack['a']
15 2
16 >>> stack['b']
17 2
18 >>> stack['c']
19 2
20 >>> len(stack)
21 3
22 >>> stack.push(dict(a=3))
23 >>> stack['a']
24 3
25 >>> set(stack.keys()) == set(['a', 'b', 'c'])
26 True
27 >>> set(stack.items()) == set([('a', 3), ('b', 2), ('c', 2)])
28 True
29 >>> dict(**stack) == dict(stack) == dict(a=3, c=2, b=2)
30 True
31 >>> d = stack.pop()
32 >>> stack['a']
33 2
34 >>> d = stack.pop()
35 >>> stack['a']
36 1
37 >>> stack.get('b', None)
38 >>> 'c' in stack
39 True
40 """
41
42 def __iter__(self):
43 dicts = list.__iter__(self)
44 return iter(set(itertools.chain.from_iterable(c.keys() for c in dicts)))
45
46 def __getitem__(self, key):
47 for scope in reversed(tuple(list.__iter__(self))):
48 if key in scope:
49 return scope[key]
50 raise KeyError(key)
51
52 push = list.append
53
54 def __contains__(self, other):
55 return collections.abc.Mapping.__contains__(self, other)
56
57 def __len__(self):
58 return len(list(iter(self)))
59
60
61 # from jaraco.collections 3.7
62 class RangeMap(dict):
63 """
64 A dictionary-like object that uses the keys as bounds for a range.
65 Inclusion of the value for that range is determined by the
66 key_match_comparator, which defaults to less-than-or-equal.
67 A value is returned for a key if it is the first key that matches in
68 the sorted list of keys.
69
70 One may supply keyword parameters to be passed to the sort function used
71 to sort keys (i.e. key, reverse) as sort_params.
72
73 Let's create a map that maps 1-3 -> 'a', 4-6 -> 'b'
74
75 >>> r = RangeMap({3: 'a', 6: 'b'}) # boy, that was easy
76 >>> r[1], r[2], r[3], r[4], r[5], r[6]
77 ('a', 'a', 'a', 'b', 'b', 'b')
78
79 Even float values should work so long as the comparison operator
80 supports it.
81
82 >>> r[4.5]
83 'b'
84
85 But you'll notice that the way rangemap is defined, it must be open-ended
86 on one side.
87
88 >>> r[0]
89 'a'
90 >>> r[-1]
91 'a'
92
93 One can close the open-end of the RangeMap by using undefined_value
94
95 >>> r = RangeMap({0: RangeMap.undefined_value, 3: 'a', 6: 'b'})
96 >>> r[0]
97 Traceback (most recent call last):
98 ...
99 KeyError: 0
100
101 One can get the first or last elements in the range by using RangeMap.Item
102
103 >>> last_item = RangeMap.Item(-1)
104 >>> r[last_item]
105 'b'
106
107 .last_item is a shortcut for Item(-1)
108
109 >>> r[RangeMap.last_item]
110 'b'
111
112 Sometimes it's useful to find the bounds for a RangeMap
113
114 >>> r.bounds()
115 (0, 6)
116
117 RangeMap supports .get(key, default)
118
119 >>> r.get(0, 'not found')
120 'not found'
121
122 >>> r.get(7, 'not found')
123 'not found'
124
125 One often wishes to define the ranges by their left-most values,
126 which requires use of sort params and a key_match_comparator.
127
128 >>> r = RangeMap({1: 'a', 4: 'b'},
129 ... sort_params=dict(reverse=True),
130 ... key_match_comparator=operator.ge)
131 >>> r[1], r[2], r[3], r[4], r[5], r[6]
132 ('a', 'a', 'a', 'b', 'b', 'b')
133
134 That wasn't nearly as easy as before, so an alternate constructor
135 is provided:
136
137 >>> r = RangeMap.left({1: 'a', 4: 'b', 7: RangeMap.undefined_value})
138 >>> r[1], r[2], r[3], r[4], r[5], r[6]
139 ('a', 'a', 'a', 'b', 'b', 'b')
140
141 """
142
143 def __init__(self, source, sort_params={}, key_match_comparator=operator.le):
144 dict.__init__(self, source)
145 self.sort_params = sort_params
146 self.match = key_match_comparator
147
148 @classmethod
149 def left(cls, source):
150 return cls(
151 source, sort_params=dict(reverse=True), key_match_comparator=operator.ge
152 )
153
154 def __getitem__(self, item):
155 sorted_keys = sorted(self.keys(), **self.sort_params)
156 if isinstance(item, RangeMap.Item):
157 result = self.__getitem__(sorted_keys[item])
158 else:
159 key = self._find_first_match_(sorted_keys, item)
160 result = dict.__getitem__(self, key)
161 if result is RangeMap.undefined_value:
162 raise KeyError(key)
163 return result
164
165 def get(self, key, default=None):
166 """
167 Return the value for key if key is in the dictionary, else default.
168 If default is not given, it defaults to None, so that this method
169 never raises a KeyError.
170 """
171 try:
172 return self[key]
173 except KeyError:
174 return default
175
176 def _find_first_match_(self, keys, item):
177 is_match = functools.partial(self.match, item)
178 matches = list(filter(is_match, keys))
179 if matches:
180 return matches[0]
181 raise KeyError(item)
182
183 def bounds(self):
184 sorted_keys = sorted(self.keys(), **self.sort_params)
185 return (sorted_keys[RangeMap.first_item], sorted_keys[RangeMap.last_item])
186
187 # some special values for the RangeMap
188 undefined_value = type('RangeValueUndefined', (), {})()
189
190 class Item(int):
191 "RangeMap Item"
192
193 first_item = Item(0)
194 last_item = Item(-1)