@ajksunkang-aios/kgraph-linux-x64 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/bin/kgraph-launcher +15 -3
  2. package/lib/kgraph/scripts/build-bundle.sh +17 -4
  3. package/lib/site-packages/outcome/__init__.py +20 -0
  4. package/lib/site-packages/outcome/_impl.py +239 -0
  5. package/lib/site-packages/outcome/_util.py +33 -0
  6. package/lib/site-packages/outcome/_version.py +7 -0
  7. package/lib/site-packages/outcome/py.typed +0 -0
  8. package/lib/site-packages/outcome-1.3.0.post0.dist-info/INSTALLER +1 -0
  9. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE +3 -0
  10. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.APACHE2 +202 -0
  11. package/lib/site-packages/outcome-1.3.0.post0.dist-info/LICENSE.MIT +20 -0
  12. package/lib/site-packages/outcome-1.3.0.post0.dist-info/METADATA +63 -0
  13. package/lib/site-packages/outcome-1.3.0.post0.dist-info/RECORD +13 -0
  14. package/lib/site-packages/outcome-1.3.0.post0.dist-info/WHEEL +6 -0
  15. package/lib/site-packages/outcome-1.3.0.post0.dist-info/top_level.txt +1 -0
  16. package/lib/site-packages/sniffio/__init__.py +17 -0
  17. package/lib/site-packages/sniffio/_impl.py +95 -0
  18. package/lib/site-packages/sniffio/_tests/__init__.py +0 -0
  19. package/lib/site-packages/sniffio/_tests/test_sniffio.py +84 -0
  20. package/lib/site-packages/sniffio/_version.py +3 -0
  21. package/lib/site-packages/sniffio/py.typed +0 -0
  22. package/lib/site-packages/sniffio-1.3.1.dist-info/INSTALLER +1 -0
  23. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE +3 -0
  24. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.APACHE2 +202 -0
  25. package/lib/site-packages/sniffio-1.3.1.dist-info/LICENSE.MIT +20 -0
  26. package/lib/site-packages/sniffio-1.3.1.dist-info/METADATA +104 -0
  27. package/lib/site-packages/sniffio-1.3.1.dist-info/RECORD +14 -0
  28. package/lib/site-packages/sniffio-1.3.1.dist-info/WHEEL +5 -0
  29. package/lib/site-packages/sniffio-1.3.1.dist-info/top_level.txt +1 -0
  30. package/lib/site-packages/sortedcontainers/__init__.py +74 -0
  31. package/lib/site-packages/sortedcontainers/sorteddict.py +812 -0
  32. package/lib/site-packages/sortedcontainers/sortedlist.py +2646 -0
  33. package/lib/site-packages/sortedcontainers/sortedset.py +733 -0
  34. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/INSTALLER +1 -0
  35. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/LICENSE +13 -0
  36. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/METADATA +264 -0
  37. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/RECORD +10 -0
  38. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/WHEEL +6 -0
  39. package/lib/site-packages/sortedcontainers-2.4.0.dist-info/top_level.txt +1 -0
  40. package/lib/site-packages/trio/__init__.py +133 -0
  41. package/lib/site-packages/trio/__main__.py +3 -0
  42. package/lib/site-packages/trio/_abc.py +714 -0
  43. package/lib/site-packages/trio/_channel.py +610 -0
  44. package/lib/site-packages/trio/_core/__init__.py +94 -0
  45. package/lib/site-packages/trio/_core/_asyncgens.py +243 -0
  46. package/lib/site-packages/trio/_core/_concat_tb.py +26 -0
  47. package/lib/site-packages/trio/_core/_entry_queue.py +223 -0
  48. package/lib/site-packages/trio/_core/_exceptions.py +169 -0
  49. package/lib/site-packages/trio/_core/_generated_instrumentation.py +50 -0
  50. package/lib/site-packages/trio/_core/_generated_io_epoll.py +98 -0
  51. package/lib/site-packages/trio/_core/_generated_io_kqueue.py +153 -0
  52. package/lib/site-packages/trio/_core/_generated_io_windows.py +204 -0
  53. package/lib/site-packages/trio/_core/_generated_run.py +269 -0
  54. package/lib/site-packages/trio/_core/_generated_windows_ffi.py +10 -0
  55. package/lib/site-packages/trio/_core/_instrumentation.py +117 -0
  56. package/lib/site-packages/trio/_core/_io_common.py +31 -0
  57. package/lib/site-packages/trio/_core/_io_epoll.py +385 -0
  58. package/lib/site-packages/trio/_core/_io_kqueue.py +292 -0
  59. package/lib/site-packages/trio/_core/_io_windows.py +1036 -0
  60. package/lib/site-packages/trio/_core/_ki.py +271 -0
  61. package/lib/site-packages/trio/_core/_local.py +104 -0
  62. package/lib/site-packages/trio/_core/_mock_clock.py +165 -0
  63. package/lib/site-packages/trio/_core/_parking_lot.py +317 -0
  64. package/lib/site-packages/trio/_core/_run.py +3148 -0
  65. package/lib/site-packages/trio/_core/_run_context.py +15 -0
  66. package/lib/site-packages/trio/_core/_tests/__init__.py +0 -0
  67. package/lib/site-packages/trio/_core/_tests/test_asyncgen.py +339 -0
  68. package/lib/site-packages/trio/_core/_tests/test_cancelled.py +222 -0
  69. package/lib/site-packages/trio/_core/_tests/test_exceptiongroup_gc.py +103 -0
  70. package/lib/site-packages/trio/_core/_tests/test_guest_mode.py +755 -0
  71. package/lib/site-packages/trio/_core/_tests/test_instrumentation.py +315 -0
  72. package/lib/site-packages/trio/_core/_tests/test_io.py +522 -0
  73. package/lib/site-packages/trio/_core/_tests/test_ki.py +703 -0
  74. package/lib/site-packages/trio/_core/_tests/test_local.py +118 -0
  75. package/lib/site-packages/trio/_core/_tests/test_mock_clock.py +193 -0
  76. package/lib/site-packages/trio/_core/_tests/test_parking_lot.py +389 -0
  77. package/lib/site-packages/trio/_core/_tests/test_run.py +3024 -0
  78. package/lib/site-packages/trio/_core/_tests/test_thread_cache.py +227 -0
  79. package/lib/site-packages/trio/_core/_tests/test_tutil.py +13 -0
  80. package/lib/site-packages/trio/_core/_tests/test_unbounded_queue.py +154 -0
  81. package/lib/site-packages/trio/_core/_tests/test_windows.py +305 -0
  82. package/lib/site-packages/trio/_core/_tests/tutil.py +117 -0
  83. package/lib/site-packages/trio/_core/_tests/type_tests/nursery_start.py +79 -0
  84. package/lib/site-packages/trio/_core/_tests/type_tests/run.py +51 -0
  85. package/lib/site-packages/trio/_core/_thread_cache.py +317 -0
  86. package/lib/site-packages/trio/_core/_traps.py +318 -0
  87. package/lib/site-packages/trio/_core/_unbounded_queue.py +163 -0
  88. package/lib/site-packages/trio/_core/_wakeup_socketpair.py +75 -0
  89. package/lib/site-packages/trio/_core/_windows_cffi.py +313 -0
  90. package/lib/site-packages/trio/_deprecate.py +171 -0
  91. package/lib/site-packages/trio/_dtls.py +1380 -0
  92. package/lib/site-packages/trio/_file_io.py +513 -0
  93. package/lib/site-packages/trio/_highlevel_generic.py +125 -0
  94. package/lib/site-packages/trio/_highlevel_open_tcp_listeners.py +251 -0
  95. package/lib/site-packages/trio/_highlevel_open_tcp_stream.py +397 -0
  96. package/lib/site-packages/trio/_highlevel_open_unix_stream.py +65 -0
  97. package/lib/site-packages/trio/_highlevel_serve_listeners.py +148 -0
  98. package/lib/site-packages/trio/_highlevel_socket.py +423 -0
  99. package/lib/site-packages/trio/_highlevel_ssl_helpers.py +180 -0
  100. package/lib/site-packages/trio/_path.py +289 -0
  101. package/lib/site-packages/trio/_repl.py +159 -0
  102. package/lib/site-packages/trio/_signals.py +185 -0
  103. package/lib/site-packages/trio/_socket.py +1326 -0
  104. package/lib/site-packages/trio/_ssl.py +964 -0
  105. package/lib/site-packages/trio/_subprocess.py +1178 -0
  106. package/lib/site-packages/trio/_subprocess_platform/__init__.py +123 -0
  107. package/lib/site-packages/trio/_subprocess_platform/kqueue.py +48 -0
  108. package/lib/site-packages/trio/_subprocess_platform/waitid.py +113 -0
  109. package/lib/site-packages/trio/_subprocess_platform/windows.py +11 -0
  110. package/lib/site-packages/trio/_sync.py +908 -0
  111. package/lib/site-packages/trio/_tests/__init__.py +0 -0
  112. package/lib/site-packages/trio/_tests/astrill-codesigning-cert.cer +0 -0
  113. package/lib/site-packages/trio/_tests/check_type_completeness.py +247 -0
  114. package/lib/site-packages/trio/_tests/module_with_deprecations.py +22 -0
  115. package/lib/site-packages/trio/_tests/pytest_plugin.py +54 -0
  116. package/lib/site-packages/trio/_tests/test_abc.py +72 -0
  117. package/lib/site-packages/trio/_tests/test_channel.py +750 -0
  118. package/lib/site-packages/trio/_tests/test_contextvars.py +56 -0
  119. package/lib/site-packages/trio/_tests/test_deprecate.py +277 -0
  120. package/lib/site-packages/trio/_tests/test_deprecate_strict_exception_groups_false.py +64 -0
  121. package/lib/site-packages/trio/_tests/test_dtls.py +950 -0
  122. package/lib/site-packages/trio/_tests/test_exports.py +626 -0
  123. package/lib/site-packages/trio/_tests/test_fakenet.py +317 -0
  124. package/lib/site-packages/trio/_tests/test_file_io.py +269 -0
  125. package/lib/site-packages/trio/_tests/test_highlevel_generic.py +98 -0
  126. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_listeners.py +419 -0
  127. package/lib/site-packages/trio/_tests/test_highlevel_open_tcp_stream.py +693 -0
  128. package/lib/site-packages/trio/_tests/test_highlevel_open_unix_stream.py +86 -0
  129. package/lib/site-packages/trio/_tests/test_highlevel_serve_listeners.py +186 -0
  130. package/lib/site-packages/trio/_tests/test_highlevel_socket.py +336 -0
  131. package/lib/site-packages/trio/_tests/test_highlevel_ssl_helpers.py +169 -0
  132. package/lib/site-packages/trio/_tests/test_path.py +279 -0
  133. package/lib/site-packages/trio/_tests/test_repl.py +428 -0
  134. package/lib/site-packages/trio/_tests/test_scheduler_determinism.py +47 -0
  135. package/lib/site-packages/trio/_tests/test_signals.py +186 -0
  136. package/lib/site-packages/trio/_tests/test_socket.py +1253 -0
  137. package/lib/site-packages/trio/_tests/test_ssl.py +1371 -0
  138. package/lib/site-packages/trio/_tests/test_subprocess.py +767 -0
  139. package/lib/site-packages/trio/_tests/test_sync.py +735 -0
  140. package/lib/site-packages/trio/_tests/test_testing.py +682 -0
  141. package/lib/site-packages/trio/_tests/test_testing_raisesgroup.py +1128 -0
  142. package/lib/site-packages/trio/_tests/test_threads.py +1173 -0
  143. package/lib/site-packages/trio/_tests/test_timeouts.py +281 -0
  144. package/lib/site-packages/trio/_tests/test_tracing.py +88 -0
  145. package/lib/site-packages/trio/_tests/test_trio.py +8 -0
  146. package/lib/site-packages/trio/_tests/test_unix_pipes.py +288 -0
  147. package/lib/site-packages/trio/_tests/test_util.py +349 -0
  148. package/lib/site-packages/trio/_tests/test_wait_for_object.py +225 -0
  149. package/lib/site-packages/trio/_tests/test_windows_pipes.py +112 -0
  150. package/lib/site-packages/trio/_tests/tools/__init__.py +0 -0
  151. package/lib/site-packages/trio/_tests/tools/test_gen_exports.py +179 -0
  152. package/lib/site-packages/trio/_tests/tools/test_mypy_annotate.py +140 -0
  153. package/lib/site-packages/trio/_tests/tools/test_sync_requirements.py +80 -0
  154. package/lib/site-packages/trio/_tests/type_tests/check_wraps.py +9 -0
  155. package/lib/site-packages/trio/_tests/type_tests/open_memory_channel.py +4 -0
  156. package/lib/site-packages/trio/_tests/type_tests/path.py +140 -0
  157. package/lib/site-packages/trio/_tests/type_tests/subprocesses.py +23 -0
  158. package/lib/site-packages/trio/_tests/type_tests/task_status.py +29 -0
  159. package/lib/site-packages/trio/_threads.py +610 -0
  160. package/lib/site-packages/trio/_timeouts.py +197 -0
  161. package/lib/site-packages/trio/_tools/__init__.py +0 -0
  162. package/lib/site-packages/trio/_tools/gen_exports.py +401 -0
  163. package/lib/site-packages/trio/_tools/mypy_annotate.py +126 -0
  164. package/lib/site-packages/trio/_tools/sync_requirements.py +98 -0
  165. package/lib/site-packages/trio/_tools/windows_ffi_build.py +220 -0
  166. package/lib/site-packages/trio/_unix_pipes.py +197 -0
  167. package/lib/site-packages/trio/_util.py +385 -0
  168. package/lib/site-packages/trio/_version.py +3 -0
  169. package/lib/site-packages/trio/_wait_for_object.py +67 -0
  170. package/lib/site-packages/trio/_windows_pipes.py +144 -0
  171. package/lib/site-packages/trio/abc.py +23 -0
  172. package/lib/site-packages/trio/from_thread.py +13 -0
  173. package/lib/site-packages/trio/lowlevel.py +95 -0
  174. package/lib/site-packages/trio/py.typed +0 -0
  175. package/lib/site-packages/trio/socket.py +602 -0
  176. package/lib/site-packages/trio/testing/__init__.py +58 -0
  177. package/lib/site-packages/trio/testing/_check_streams.py +570 -0
  178. package/lib/site-packages/trio/testing/_checkpoints.py +69 -0
  179. package/lib/site-packages/trio/testing/_fake_net.py +584 -0
  180. package/lib/site-packages/trio/testing/_memory_streams.py +633 -0
  181. package/lib/site-packages/trio/testing/_network.py +36 -0
  182. package/lib/site-packages/trio/testing/_raises_group.py +1015 -0
  183. package/lib/site-packages/trio/testing/_sequencer.py +87 -0
  184. package/lib/site-packages/trio/testing/_trio_test.py +50 -0
  185. package/lib/site-packages/trio/to_thread.py +4 -0
  186. package/lib/site-packages/trio-0.33.0.dist-info/INSTALLER +1 -0
  187. package/lib/site-packages/trio-0.33.0.dist-info/METADATA +186 -0
  188. package/lib/site-packages/trio-0.33.0.dist-info/RECORD +156 -0
  189. package/lib/site-packages/trio-0.33.0.dist-info/REQUESTED +0 -0
  190. package/lib/site-packages/trio-0.33.0.dist-info/WHEEL +5 -0
  191. package/lib/site-packages/trio-0.33.0.dist-info/entry_points.txt +2 -0
  192. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE +3 -0
  193. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.APACHE2 +202 -0
  194. package/lib/site-packages/trio-0.33.0.dist-info/licenses/LICENSE.MIT +22 -0
  195. package/lib/site-packages/trio-0.33.0.dist-info/top_level.txt +1 -0
  196. package/package.json +1 -1
@@ -0,0 +1,2646 @@
1
+ """Sorted List
2
+ ==============
3
+
4
+ :doc:`Sorted Containers<index>` is an Apache2 licensed Python sorted
5
+ collections library, written in pure-Python, and fast as C-extensions. The
6
+ :doc:`introduction<introduction>` is the best way to get started.
7
+
8
+ Sorted list implementations:
9
+
10
+ .. currentmodule:: sortedcontainers
11
+
12
+ * :class:`SortedList`
13
+ * :class:`SortedKeyList`
14
+
15
+ """
16
+ # pylint: disable=too-many-lines
17
+ from __future__ import print_function
18
+
19
+ import sys
20
+ import traceback
21
+
22
+ from bisect import bisect_left, bisect_right, insort
23
+ from itertools import chain, repeat, starmap
24
+ from math import log
25
+ from operator import add, eq, ne, gt, ge, lt, le, iadd
26
+ from textwrap import dedent
27
+
28
+ ###############################################################################
29
+ # BEGIN Python 2/3 Shims
30
+ ###############################################################################
31
+
32
+ try:
33
+ from collections.abc import Sequence, MutableSequence
34
+ except ImportError:
35
+ from collections import Sequence, MutableSequence
36
+
37
+ from functools import wraps
38
+ from sys import hexversion
39
+
40
+ if hexversion < 0x03000000:
41
+ from itertools import imap as map # pylint: disable=redefined-builtin
42
+ from itertools import izip as zip # pylint: disable=redefined-builtin
43
+ try:
44
+ from thread import get_ident
45
+ except ImportError:
46
+ from dummy_thread import get_ident
47
+ else:
48
+ from functools import reduce
49
+ try:
50
+ from _thread import get_ident
51
+ except ImportError:
52
+ from _dummy_thread import get_ident
53
+
54
+
55
+ def recursive_repr(fillvalue='...'):
56
+ "Decorator to make a repr function return fillvalue for a recursive call."
57
+ # pylint: disable=missing-docstring
58
+ # Copied from reprlib in Python 3
59
+ # https://hg.python.org/cpython/file/3.6/Lib/reprlib.py
60
+
61
+ def decorating_function(user_function):
62
+ repr_running = set()
63
+
64
+ @wraps(user_function)
65
+ def wrapper(self):
66
+ key = id(self), get_ident()
67
+ if key in repr_running:
68
+ return fillvalue
69
+ repr_running.add(key)
70
+ try:
71
+ result = user_function(self)
72
+ finally:
73
+ repr_running.discard(key)
74
+ return result
75
+
76
+ return wrapper
77
+
78
+ return decorating_function
79
+
80
+ ###############################################################################
81
+ # END Python 2/3 Shims
82
+ ###############################################################################
83
+
84
+
85
+ class SortedList(MutableSequence):
86
+ """Sorted list is a sorted mutable sequence.
87
+
88
+ Sorted list values are maintained in sorted order.
89
+
90
+ Sorted list values must be comparable. The total ordering of values must
91
+ not change while they are stored in the sorted list.
92
+
93
+ Methods for adding values:
94
+
95
+ * :func:`SortedList.add`
96
+ * :func:`SortedList.update`
97
+ * :func:`SortedList.__add__`
98
+ * :func:`SortedList.__iadd__`
99
+ * :func:`SortedList.__mul__`
100
+ * :func:`SortedList.__imul__`
101
+
102
+ Methods for removing values:
103
+
104
+ * :func:`SortedList.clear`
105
+ * :func:`SortedList.discard`
106
+ * :func:`SortedList.remove`
107
+ * :func:`SortedList.pop`
108
+ * :func:`SortedList.__delitem__`
109
+
110
+ Methods for looking up values:
111
+
112
+ * :func:`SortedList.bisect_left`
113
+ * :func:`SortedList.bisect_right`
114
+ * :func:`SortedList.count`
115
+ * :func:`SortedList.index`
116
+ * :func:`SortedList.__contains__`
117
+ * :func:`SortedList.__getitem__`
118
+
119
+ Methods for iterating values:
120
+
121
+ * :func:`SortedList.irange`
122
+ * :func:`SortedList.islice`
123
+ * :func:`SortedList.__iter__`
124
+ * :func:`SortedList.__reversed__`
125
+
126
+ Methods for miscellany:
127
+
128
+ * :func:`SortedList.copy`
129
+ * :func:`SortedList.__len__`
130
+ * :func:`SortedList.__repr__`
131
+ * :func:`SortedList._check`
132
+ * :func:`SortedList._reset`
133
+
134
+ Sorted lists use lexicographical ordering semantics when compared to other
135
+ sequences.
136
+
137
+ Some methods of mutable sequences are not supported and will raise
138
+ not-implemented error.
139
+
140
+ """
141
+ DEFAULT_LOAD_FACTOR = 1000
142
+
143
+
144
+ def __init__(self, iterable=None, key=None):
145
+ """Initialize sorted list instance.
146
+
147
+ Optional `iterable` argument provides an initial iterable of values to
148
+ initialize the sorted list.
149
+
150
+ Runtime complexity: `O(n*log(n))`
151
+
152
+ >>> sl = SortedList()
153
+ >>> sl
154
+ SortedList([])
155
+ >>> sl = SortedList([3, 1, 2, 5, 4])
156
+ >>> sl
157
+ SortedList([1, 2, 3, 4, 5])
158
+
159
+ :param iterable: initial values (optional)
160
+
161
+ """
162
+ assert key is None
163
+ self._len = 0
164
+ self._load = self.DEFAULT_LOAD_FACTOR
165
+ self._lists = []
166
+ self._maxes = []
167
+ self._index = []
168
+ self._offset = 0
169
+
170
+ if iterable is not None:
171
+ self._update(iterable)
172
+
173
+
174
+ def __new__(cls, iterable=None, key=None):
175
+ """Create new sorted list or sorted-key list instance.
176
+
177
+ Optional `key`-function argument will return an instance of subtype
178
+ :class:`SortedKeyList`.
179
+
180
+ >>> sl = SortedList()
181
+ >>> isinstance(sl, SortedList)
182
+ True
183
+ >>> sl = SortedList(key=lambda x: -x)
184
+ >>> isinstance(sl, SortedList)
185
+ True
186
+ >>> isinstance(sl, SortedKeyList)
187
+ True
188
+
189
+ :param iterable: initial values (optional)
190
+ :param key: function used to extract comparison key (optional)
191
+ :return: sorted list or sorted-key list instance
192
+
193
+ """
194
+ # pylint: disable=unused-argument
195
+ if key is None:
196
+ return object.__new__(cls)
197
+ else:
198
+ if cls is SortedList:
199
+ return object.__new__(SortedKeyList)
200
+ else:
201
+ raise TypeError('inherit SortedKeyList for key argument')
202
+
203
+
204
+ @property
205
+ def key(self): # pylint: disable=useless-return
206
+ """Function used to extract comparison key from values.
207
+
208
+ Sorted list compares values directly so the key function is none.
209
+
210
+ """
211
+ return None
212
+
213
+
214
+ def _reset(self, load):
215
+ """Reset sorted list load factor.
216
+
217
+ The `load` specifies the load-factor of the list. The default load
218
+ factor of 1000 works well for lists from tens to tens-of-millions of
219
+ values. Good practice is to use a value that is the cube root of the
220
+ list size. With billions of elements, the best load factor depends on
221
+ your usage. It's best to leave the load factor at the default until you
222
+ start benchmarking.
223
+
224
+ See :doc:`implementation` and :doc:`performance-scale` for more
225
+ information.
226
+
227
+ Runtime complexity: `O(n)`
228
+
229
+ :param int load: load-factor for sorted list sublists
230
+
231
+ """
232
+ values = reduce(iadd, self._lists, [])
233
+ self._clear()
234
+ self._load = load
235
+ self._update(values)
236
+
237
+
238
+ def clear(self):
239
+ """Remove all values from sorted list.
240
+
241
+ Runtime complexity: `O(n)`
242
+
243
+ """
244
+ self._len = 0
245
+ del self._lists[:]
246
+ del self._maxes[:]
247
+ del self._index[:]
248
+ self._offset = 0
249
+
250
+ _clear = clear
251
+
252
+
253
+ def add(self, value):
254
+ """Add `value` to sorted list.
255
+
256
+ Runtime complexity: `O(log(n))` -- approximate.
257
+
258
+ >>> sl = SortedList()
259
+ >>> sl.add(3)
260
+ >>> sl.add(1)
261
+ >>> sl.add(2)
262
+ >>> sl
263
+ SortedList([1, 2, 3])
264
+
265
+ :param value: value to add to sorted list
266
+
267
+ """
268
+ _lists = self._lists
269
+ _maxes = self._maxes
270
+
271
+ if _maxes:
272
+ pos = bisect_right(_maxes, value)
273
+
274
+ if pos == len(_maxes):
275
+ pos -= 1
276
+ _lists[pos].append(value)
277
+ _maxes[pos] = value
278
+ else:
279
+ insort(_lists[pos], value)
280
+
281
+ self._expand(pos)
282
+ else:
283
+ _lists.append([value])
284
+ _maxes.append(value)
285
+
286
+ self._len += 1
287
+
288
+
289
+ def _expand(self, pos):
290
+ """Split sublists with length greater than double the load-factor.
291
+
292
+ Updates the index when the sublist length is less than double the load
293
+ level. This requires incrementing the nodes in a traversal from the
294
+ leaf node to the root. For an example traversal see
295
+ ``SortedList._loc``.
296
+
297
+ """
298
+ _load = self._load
299
+ _lists = self._lists
300
+ _index = self._index
301
+
302
+ if len(_lists[pos]) > (_load << 1):
303
+ _maxes = self._maxes
304
+
305
+ _lists_pos = _lists[pos]
306
+ half = _lists_pos[_load:]
307
+ del _lists_pos[_load:]
308
+ _maxes[pos] = _lists_pos[-1]
309
+
310
+ _lists.insert(pos + 1, half)
311
+ _maxes.insert(pos + 1, half[-1])
312
+
313
+ del _index[:]
314
+ else:
315
+ if _index:
316
+ child = self._offset + pos
317
+ while child:
318
+ _index[child] += 1
319
+ child = (child - 1) >> 1
320
+ _index[0] += 1
321
+
322
+
323
+ def update(self, iterable):
324
+ """Update sorted list by adding all values from `iterable`.
325
+
326
+ Runtime complexity: `O(k*log(n))` -- approximate.
327
+
328
+ >>> sl = SortedList()
329
+ >>> sl.update([3, 1, 2])
330
+ >>> sl
331
+ SortedList([1, 2, 3])
332
+
333
+ :param iterable: iterable of values to add
334
+
335
+ """
336
+ _lists = self._lists
337
+ _maxes = self._maxes
338
+ values = sorted(iterable)
339
+
340
+ if _maxes:
341
+ if len(values) * 4 >= self._len:
342
+ _lists.append(values)
343
+ values = reduce(iadd, _lists, [])
344
+ values.sort()
345
+ self._clear()
346
+ else:
347
+ _add = self.add
348
+ for val in values:
349
+ _add(val)
350
+ return
351
+
352
+ _load = self._load
353
+ _lists.extend(values[pos:(pos + _load)]
354
+ for pos in range(0, len(values), _load))
355
+ _maxes.extend(sublist[-1] for sublist in _lists)
356
+ self._len = len(values)
357
+ del self._index[:]
358
+
359
+ _update = update
360
+
361
+
362
+ def __contains__(self, value):
363
+ """Return true if `value` is an element of the sorted list.
364
+
365
+ ``sl.__contains__(value)`` <==> ``value in sl``
366
+
367
+ Runtime complexity: `O(log(n))`
368
+
369
+ >>> sl = SortedList([1, 2, 3, 4, 5])
370
+ >>> 3 in sl
371
+ True
372
+
373
+ :param value: search for value in sorted list
374
+ :return: true if `value` in sorted list
375
+
376
+ """
377
+ _maxes = self._maxes
378
+
379
+ if not _maxes:
380
+ return False
381
+
382
+ pos = bisect_left(_maxes, value)
383
+
384
+ if pos == len(_maxes):
385
+ return False
386
+
387
+ _lists = self._lists
388
+ idx = bisect_left(_lists[pos], value)
389
+
390
+ return _lists[pos][idx] == value
391
+
392
+
393
+ def discard(self, value):
394
+ """Remove `value` from sorted list if it is a member.
395
+
396
+ If `value` is not a member, do nothing.
397
+
398
+ Runtime complexity: `O(log(n))` -- approximate.
399
+
400
+ >>> sl = SortedList([1, 2, 3, 4, 5])
401
+ >>> sl.discard(5)
402
+ >>> sl.discard(0)
403
+ >>> sl == [1, 2, 3, 4]
404
+ True
405
+
406
+ :param value: `value` to discard from sorted list
407
+
408
+ """
409
+ _maxes = self._maxes
410
+
411
+ if not _maxes:
412
+ return
413
+
414
+ pos = bisect_left(_maxes, value)
415
+
416
+ if pos == len(_maxes):
417
+ return
418
+
419
+ _lists = self._lists
420
+ idx = bisect_left(_lists[pos], value)
421
+
422
+ if _lists[pos][idx] == value:
423
+ self._delete(pos, idx)
424
+
425
+
426
+ def remove(self, value):
427
+ """Remove `value` from sorted list; `value` must be a member.
428
+
429
+ If `value` is not a member, raise ValueError.
430
+
431
+ Runtime complexity: `O(log(n))` -- approximate.
432
+
433
+ >>> sl = SortedList([1, 2, 3, 4, 5])
434
+ >>> sl.remove(5)
435
+ >>> sl == [1, 2, 3, 4]
436
+ True
437
+ >>> sl.remove(0)
438
+ Traceback (most recent call last):
439
+ ...
440
+ ValueError: 0 not in list
441
+
442
+ :param value: `value` to remove from sorted list
443
+ :raises ValueError: if `value` is not in sorted list
444
+
445
+ """
446
+ _maxes = self._maxes
447
+
448
+ if not _maxes:
449
+ raise ValueError('{0!r} not in list'.format(value))
450
+
451
+ pos = bisect_left(_maxes, value)
452
+
453
+ if pos == len(_maxes):
454
+ raise ValueError('{0!r} not in list'.format(value))
455
+
456
+ _lists = self._lists
457
+ idx = bisect_left(_lists[pos], value)
458
+
459
+ if _lists[pos][idx] == value:
460
+ self._delete(pos, idx)
461
+ else:
462
+ raise ValueError('{0!r} not in list'.format(value))
463
+
464
+
465
+ def _delete(self, pos, idx):
466
+ """Delete value at the given `(pos, idx)`.
467
+
468
+ Combines lists that are less than half the load level.
469
+
470
+ Updates the index when the sublist length is more than half the load
471
+ level. This requires decrementing the nodes in a traversal from the
472
+ leaf node to the root. For an example traversal see
473
+ ``SortedList._loc``.
474
+
475
+ :param int pos: lists index
476
+ :param int idx: sublist index
477
+
478
+ """
479
+ _lists = self._lists
480
+ _maxes = self._maxes
481
+ _index = self._index
482
+
483
+ _lists_pos = _lists[pos]
484
+
485
+ del _lists_pos[idx]
486
+ self._len -= 1
487
+
488
+ len_lists_pos = len(_lists_pos)
489
+
490
+ if len_lists_pos > (self._load >> 1):
491
+ _maxes[pos] = _lists_pos[-1]
492
+
493
+ if _index:
494
+ child = self._offset + pos
495
+ while child > 0:
496
+ _index[child] -= 1
497
+ child = (child - 1) >> 1
498
+ _index[0] -= 1
499
+ elif len(_lists) > 1:
500
+ if not pos:
501
+ pos += 1
502
+
503
+ prev = pos - 1
504
+ _lists[prev].extend(_lists[pos])
505
+ _maxes[prev] = _lists[prev][-1]
506
+
507
+ del _lists[pos]
508
+ del _maxes[pos]
509
+ del _index[:]
510
+
511
+ self._expand(prev)
512
+ elif len_lists_pos:
513
+ _maxes[pos] = _lists_pos[-1]
514
+ else:
515
+ del _lists[pos]
516
+ del _maxes[pos]
517
+ del _index[:]
518
+
519
+
520
+ def _loc(self, pos, idx):
521
+ """Convert an index pair (lists index, sublist index) into a single
522
+ index number that corresponds to the position of the value in the
523
+ sorted list.
524
+
525
+ Many queries require the index be built. Details of the index are
526
+ described in ``SortedList._build_index``.
527
+
528
+ Indexing requires traversing the tree from a leaf node to the root. The
529
+ parent of each node is easily computable at ``(pos - 1) // 2``.
530
+
531
+ Left-child nodes are always at odd indices and right-child nodes are
532
+ always at even indices.
533
+
534
+ When traversing up from a right-child node, increment the total by the
535
+ left-child node.
536
+
537
+ The final index is the sum from traversal and the index in the sublist.
538
+
539
+ For example, using the index from ``SortedList._build_index``::
540
+
541
+ _index = 14 5 9 3 2 4 5
542
+ _offset = 3
543
+
544
+ Tree::
545
+
546
+ 14
547
+ 5 9
548
+ 3 2 4 5
549
+
550
+ Converting an index pair (2, 3) into a single index involves iterating
551
+ like so:
552
+
553
+ 1. Starting at the leaf node: offset + alpha = 3 + 2 = 5. We identify
554
+ the node as a left-child node. At such nodes, we simply traverse to
555
+ the parent.
556
+
557
+ 2. At node 9, position 2, we recognize the node as a right-child node
558
+ and accumulate the left-child in our total. Total is now 5 and we
559
+ traverse to the parent at position 0.
560
+
561
+ 3. Iteration ends at the root.
562
+
563
+ The index is then the sum of the total and sublist index: 5 + 3 = 8.
564
+
565
+ :param int pos: lists index
566
+ :param int idx: sublist index
567
+ :return: index in sorted list
568
+
569
+ """
570
+ if not pos:
571
+ return idx
572
+
573
+ _index = self._index
574
+
575
+ if not _index:
576
+ self._build_index()
577
+
578
+ total = 0
579
+
580
+ # Increment pos to point in the index to len(self._lists[pos]).
581
+
582
+ pos += self._offset
583
+
584
+ # Iterate until reaching the root of the index tree at pos = 0.
585
+
586
+ while pos:
587
+
588
+ # Right-child nodes are at odd indices. At such indices
589
+ # account the total below the left child node.
590
+
591
+ if not pos & 1:
592
+ total += _index[pos - 1]
593
+
594
+ # Advance pos to the parent node.
595
+
596
+ pos = (pos - 1) >> 1
597
+
598
+ return total + idx
599
+
600
+
601
+ def _pos(self, idx):
602
+ """Convert an index into an index pair (lists index, sublist index)
603
+ that can be used to access the corresponding lists position.
604
+
605
+ Many queries require the index be built. Details of the index are
606
+ described in ``SortedList._build_index``.
607
+
608
+ Indexing requires traversing the tree to a leaf node. Each node has two
609
+ children which are easily computable. Given an index, pos, the
610
+ left-child is at ``pos * 2 + 1`` and the right-child is at ``pos * 2 +
611
+ 2``.
612
+
613
+ When the index is less than the left-child, traversal moves to the
614
+ left sub-tree. Otherwise, the index is decremented by the left-child
615
+ and traversal moves to the right sub-tree.
616
+
617
+ At a child node, the indexing pair is computed from the relative
618
+ position of the child node as compared with the offset and the remaining
619
+ index.
620
+
621
+ For example, using the index from ``SortedList._build_index``::
622
+
623
+ _index = 14 5 9 3 2 4 5
624
+ _offset = 3
625
+
626
+ Tree::
627
+
628
+ 14
629
+ 5 9
630
+ 3 2 4 5
631
+
632
+ Indexing position 8 involves iterating like so:
633
+
634
+ 1. Starting at the root, position 0, 8 is compared with the left-child
635
+ node (5) which it is greater than. When greater the index is
636
+ decremented and the position is updated to the right child node.
637
+
638
+ 2. At node 9 with index 3, we again compare the index to the left-child
639
+ node with value 4. Because the index is the less than the left-child
640
+ node, we simply traverse to the left.
641
+
642
+ 3. At node 4 with index 3, we recognize that we are at a leaf node and
643
+ stop iterating.
644
+
645
+ 4. To compute the sublist index, we subtract the offset from the index
646
+ of the leaf node: 5 - 3 = 2. To compute the index in the sublist, we
647
+ simply use the index remaining from iteration. In this case, 3.
648
+
649
+ The final index pair from our example is (2, 3) which corresponds to
650
+ index 8 in the sorted list.
651
+
652
+ :param int idx: index in sorted list
653
+ :return: (lists index, sublist index) pair
654
+
655
+ """
656
+ if idx < 0:
657
+ last_len = len(self._lists[-1])
658
+
659
+ if (-idx) <= last_len:
660
+ return len(self._lists) - 1, last_len + idx
661
+
662
+ idx += self._len
663
+
664
+ if idx < 0:
665
+ raise IndexError('list index out of range')
666
+ elif idx >= self._len:
667
+ raise IndexError('list index out of range')
668
+
669
+ if idx < len(self._lists[0]):
670
+ return 0, idx
671
+
672
+ _index = self._index
673
+
674
+ if not _index:
675
+ self._build_index()
676
+
677
+ pos = 0
678
+ child = 1
679
+ len_index = len(_index)
680
+
681
+ while child < len_index:
682
+ index_child = _index[child]
683
+
684
+ if idx < index_child:
685
+ pos = child
686
+ else:
687
+ idx -= index_child
688
+ pos = child + 1
689
+
690
+ child = (pos << 1) + 1
691
+
692
+ return (pos - self._offset, idx)
693
+
694
+
695
+ def _build_index(self):
696
+ """Build a positional index for indexing the sorted list.
697
+
698
+ Indexes are represented as binary trees in a dense array notation
699
+ similar to a binary heap.
700
+
701
+ For example, given a lists representation storing integers::
702
+
703
+ 0: [1, 2, 3]
704
+ 1: [4, 5]
705
+ 2: [6, 7, 8, 9]
706
+ 3: [10, 11, 12, 13, 14]
707
+
708
+ The first transformation maps the sub-lists by their length. The
709
+ first row of the index is the length of the sub-lists::
710
+
711
+ 0: [3, 2, 4, 5]
712
+
713
+ Each row after that is the sum of consecutive pairs of the previous
714
+ row::
715
+
716
+ 1: [5, 9]
717
+ 2: [14]
718
+
719
+ Finally, the index is built by concatenating these lists together::
720
+
721
+ _index = [14, 5, 9, 3, 2, 4, 5]
722
+
723
+ An offset storing the start of the first row is also stored::
724
+
725
+ _offset = 3
726
+
727
+ When built, the index can be used for efficient indexing into the list.
728
+ See the comment and notes on ``SortedList._pos`` for details.
729
+
730
+ """
731
+ row0 = list(map(len, self._lists))
732
+
733
+ if len(row0) == 1:
734
+ self._index[:] = row0
735
+ self._offset = 0
736
+ return
737
+
738
+ head = iter(row0)
739
+ tail = iter(head)
740
+ row1 = list(starmap(add, zip(head, tail)))
741
+
742
+ if len(row0) & 1:
743
+ row1.append(row0[-1])
744
+
745
+ if len(row1) == 1:
746
+ self._index[:] = row1 + row0
747
+ self._offset = 1
748
+ return
749
+
750
+ size = 2 ** (int(log(len(row1) - 1, 2)) + 1)
751
+ row1.extend(repeat(0, size - len(row1)))
752
+ tree = [row0, row1]
753
+
754
+ while len(tree[-1]) > 1:
755
+ head = iter(tree[-1])
756
+ tail = iter(head)
757
+ row = list(starmap(add, zip(head, tail)))
758
+ tree.append(row)
759
+
760
+ reduce(iadd, reversed(tree), self._index)
761
+ self._offset = size * 2 - 1
762
+
763
+
764
+ def __delitem__(self, index):
765
+ """Remove value at `index` from sorted list.
766
+
767
+ ``sl.__delitem__(index)`` <==> ``del sl[index]``
768
+
769
+ Supports slicing.
770
+
771
+ Runtime complexity: `O(log(n))` -- approximate.
772
+
773
+ >>> sl = SortedList('abcde')
774
+ >>> del sl[2]
775
+ >>> sl
776
+ SortedList(['a', 'b', 'd', 'e'])
777
+ >>> del sl[:2]
778
+ >>> sl
779
+ SortedList(['d', 'e'])
780
+
781
+ :param index: integer or slice for indexing
782
+ :raises IndexError: if index out of range
783
+
784
+ """
785
+ if isinstance(index, slice):
786
+ start, stop, step = index.indices(self._len)
787
+
788
+ if step == 1 and start < stop:
789
+ if start == 0 and stop == self._len:
790
+ return self._clear()
791
+ elif self._len <= 8 * (stop - start):
792
+ values = self._getitem(slice(None, start))
793
+ if stop < self._len:
794
+ values += self._getitem(slice(stop, None))
795
+ self._clear()
796
+ return self._update(values)
797
+
798
+ indices = range(start, stop, step)
799
+
800
+ # Delete items from greatest index to least so
801
+ # that the indices remain valid throughout iteration.
802
+
803
+ if step > 0:
804
+ indices = reversed(indices)
805
+
806
+ _pos, _delete = self._pos, self._delete
807
+
808
+ for index in indices:
809
+ pos, idx = _pos(index)
810
+ _delete(pos, idx)
811
+ else:
812
+ pos, idx = self._pos(index)
813
+ self._delete(pos, idx)
814
+
815
+
816
+ def __getitem__(self, index):
817
+ """Lookup value at `index` in sorted list.
818
+
819
+ ``sl.__getitem__(index)`` <==> ``sl[index]``
820
+
821
+ Supports slicing.
822
+
823
+ Runtime complexity: `O(log(n))` -- approximate.
824
+
825
+ >>> sl = SortedList('abcde')
826
+ >>> sl[1]
827
+ 'b'
828
+ >>> sl[-1]
829
+ 'e'
830
+ >>> sl[2:5]
831
+ ['c', 'd', 'e']
832
+
833
+ :param index: integer or slice for indexing
834
+ :return: value or list of values
835
+ :raises IndexError: if index out of range
836
+
837
+ """
838
+ _lists = self._lists
839
+
840
+ if isinstance(index, slice):
841
+ start, stop, step = index.indices(self._len)
842
+
843
+ if step == 1 and start < stop:
844
+ # Whole slice optimization: start to stop slices the whole
845
+ # sorted list.
846
+
847
+ if start == 0 and stop == self._len:
848
+ return reduce(iadd, self._lists, [])
849
+
850
+ start_pos, start_idx = self._pos(start)
851
+ start_list = _lists[start_pos]
852
+ stop_idx = start_idx + stop - start
853
+
854
+ # Small slice optimization: start index and stop index are
855
+ # within the start list.
856
+
857
+ if len(start_list) >= stop_idx:
858
+ return start_list[start_idx:stop_idx]
859
+
860
+ if stop == self._len:
861
+ stop_pos = len(_lists) - 1
862
+ stop_idx = len(_lists[stop_pos])
863
+ else:
864
+ stop_pos, stop_idx = self._pos(stop)
865
+
866
+ prefix = _lists[start_pos][start_idx:]
867
+ middle = _lists[(start_pos + 1):stop_pos]
868
+ result = reduce(iadd, middle, prefix)
869
+ result += _lists[stop_pos][:stop_idx]
870
+
871
+ return result
872
+
873
+ if step == -1 and start > stop:
874
+ result = self._getitem(slice(stop + 1, start + 1))
875
+ result.reverse()
876
+ return result
877
+
878
+ # Return a list because a negative step could
879
+ # reverse the order of the items and this could
880
+ # be the desired behavior.
881
+
882
+ indices = range(start, stop, step)
883
+ return list(self._getitem(index) for index in indices)
884
+ else:
885
+ if self._len:
886
+ if index == 0:
887
+ return _lists[0][0]
888
+ elif index == -1:
889
+ return _lists[-1][-1]
890
+ else:
891
+ raise IndexError('list index out of range')
892
+
893
+ if 0 <= index < len(_lists[0]):
894
+ return _lists[0][index]
895
+
896
+ len_last = len(_lists[-1])
897
+
898
+ if -len_last < index < 0:
899
+ return _lists[-1][len_last + index]
900
+
901
+ pos, idx = self._pos(index)
902
+ return _lists[pos][idx]
903
+
904
+ _getitem = __getitem__
905
+
906
+
907
+ def __setitem__(self, index, value):
908
+ """Raise not-implemented error.
909
+
910
+ ``sl.__setitem__(index, value)`` <==> ``sl[index] = value``
911
+
912
+ :raises NotImplementedError: use ``del sl[index]`` and
913
+ ``sl.add(value)`` instead
914
+
915
+ """
916
+ message = 'use ``del sl[index]`` and ``sl.add(value)`` instead'
917
+ raise NotImplementedError(message)
918
+
919
+
920
+ def __iter__(self):
921
+ """Return an iterator over the sorted list.
922
+
923
+ ``sl.__iter__()`` <==> ``iter(sl)``
924
+
925
+ Iterating the sorted list while adding or deleting values may raise a
926
+ :exc:`RuntimeError` or fail to iterate over all values.
927
+
928
+ """
929
+ return chain.from_iterable(self._lists)
930
+
931
+
932
+ def __reversed__(self):
933
+ """Return a reverse iterator over the sorted list.
934
+
935
+ ``sl.__reversed__()`` <==> ``reversed(sl)``
936
+
937
+ Iterating the sorted list while adding or deleting values may raise a
938
+ :exc:`RuntimeError` or fail to iterate over all values.
939
+
940
+ """
941
+ return chain.from_iterable(map(reversed, reversed(self._lists)))
942
+
943
+
944
+ def reverse(self):
945
+ """Raise not-implemented error.
946
+
947
+ Sorted list maintains values in ascending sort order. Values may not be
948
+ reversed in-place.
949
+
950
+ Use ``reversed(sl)`` for an iterator over values in descending sort
951
+ order.
952
+
953
+ Implemented to override `MutableSequence.reverse` which provides an
954
+ erroneous default implementation.
955
+
956
+ :raises NotImplementedError: use ``reversed(sl)`` instead
957
+
958
+ """
959
+ raise NotImplementedError('use ``reversed(sl)`` instead')
960
+
961
+
962
+ def islice(self, start=None, stop=None, reverse=False):
963
+ """Return an iterator that slices sorted list from `start` to `stop`.
964
+
965
+ The `start` and `stop` index are treated inclusive and exclusive,
966
+ respectively.
967
+
968
+ Both `start` and `stop` default to `None` which is automatically
969
+ inclusive of the beginning and end of the sorted list.
970
+
971
+ When `reverse` is `True` the values are yielded from the iterator in
972
+ reverse order; `reverse` defaults to `False`.
973
+
974
+ >>> sl = SortedList('abcdefghij')
975
+ >>> it = sl.islice(2, 6)
976
+ >>> list(it)
977
+ ['c', 'd', 'e', 'f']
978
+
979
+ :param int start: start index (inclusive)
980
+ :param int stop: stop index (exclusive)
981
+ :param bool reverse: yield values in reverse order
982
+ :return: iterator
983
+
984
+ """
985
+ _len = self._len
986
+
987
+ if not _len:
988
+ return iter(())
989
+
990
+ start, stop, _ = slice(start, stop).indices(self._len)
991
+
992
+ if start >= stop:
993
+ return iter(())
994
+
995
+ _pos = self._pos
996
+
997
+ min_pos, min_idx = _pos(start)
998
+
999
+ if stop == _len:
1000
+ max_pos = len(self._lists) - 1
1001
+ max_idx = len(self._lists[-1])
1002
+ else:
1003
+ max_pos, max_idx = _pos(stop)
1004
+
1005
+ return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
1006
+
1007
+
1008
+ def _islice(self, min_pos, min_idx, max_pos, max_idx, reverse):
1009
+ """Return an iterator that slices sorted list using two index pairs.
1010
+
1011
+ The index pairs are (min_pos, min_idx) and (max_pos, max_idx), the
1012
+ first inclusive and the latter exclusive. See `_pos` for details on how
1013
+ an index is converted to an index pair.
1014
+
1015
+ When `reverse` is `True`, values are yielded from the iterator in
1016
+ reverse order.
1017
+
1018
+ """
1019
+ _lists = self._lists
1020
+
1021
+ if min_pos > max_pos:
1022
+ return iter(())
1023
+
1024
+ if min_pos == max_pos:
1025
+ if reverse:
1026
+ indices = reversed(range(min_idx, max_idx))
1027
+ return map(_lists[min_pos].__getitem__, indices)
1028
+
1029
+ indices = range(min_idx, max_idx)
1030
+ return map(_lists[min_pos].__getitem__, indices)
1031
+
1032
+ next_pos = min_pos + 1
1033
+
1034
+ if next_pos == max_pos:
1035
+ if reverse:
1036
+ min_indices = range(min_idx, len(_lists[min_pos]))
1037
+ max_indices = range(max_idx)
1038
+ return chain(
1039
+ map(_lists[max_pos].__getitem__, reversed(max_indices)),
1040
+ map(_lists[min_pos].__getitem__, reversed(min_indices)),
1041
+ )
1042
+
1043
+ min_indices = range(min_idx, len(_lists[min_pos]))
1044
+ max_indices = range(max_idx)
1045
+ return chain(
1046
+ map(_lists[min_pos].__getitem__, min_indices),
1047
+ map(_lists[max_pos].__getitem__, max_indices),
1048
+ )
1049
+
1050
+ if reverse:
1051
+ min_indices = range(min_idx, len(_lists[min_pos]))
1052
+ sublist_indices = range(next_pos, max_pos)
1053
+ sublists = map(_lists.__getitem__, reversed(sublist_indices))
1054
+ max_indices = range(max_idx)
1055
+ return chain(
1056
+ map(_lists[max_pos].__getitem__, reversed(max_indices)),
1057
+ chain.from_iterable(map(reversed, sublists)),
1058
+ map(_lists[min_pos].__getitem__, reversed(min_indices)),
1059
+ )
1060
+
1061
+ min_indices = range(min_idx, len(_lists[min_pos]))
1062
+ sublist_indices = range(next_pos, max_pos)
1063
+ sublists = map(_lists.__getitem__, sublist_indices)
1064
+ max_indices = range(max_idx)
1065
+ return chain(
1066
+ map(_lists[min_pos].__getitem__, min_indices),
1067
+ chain.from_iterable(sublists),
1068
+ map(_lists[max_pos].__getitem__, max_indices),
1069
+ )
1070
+
1071
+
1072
+ def irange(self, minimum=None, maximum=None, inclusive=(True, True),
1073
+ reverse=False):
1074
+ """Create an iterator of values between `minimum` and `maximum`.
1075
+
1076
+ Both `minimum` and `maximum` default to `None` which is automatically
1077
+ inclusive of the beginning and end of the sorted list.
1078
+
1079
+ The argument `inclusive` is a pair of booleans that indicates whether
1080
+ the minimum and maximum ought to be included in the range,
1081
+ respectively. The default is ``(True, True)`` such that the range is
1082
+ inclusive of both minimum and maximum.
1083
+
1084
+ When `reverse` is `True` the values are yielded from the iterator in
1085
+ reverse order; `reverse` defaults to `False`.
1086
+
1087
+ >>> sl = SortedList('abcdefghij')
1088
+ >>> it = sl.irange('c', 'f')
1089
+ >>> list(it)
1090
+ ['c', 'd', 'e', 'f']
1091
+
1092
+ :param minimum: minimum value to start iterating
1093
+ :param maximum: maximum value to stop iterating
1094
+ :param inclusive: pair of booleans
1095
+ :param bool reverse: yield values in reverse order
1096
+ :return: iterator
1097
+
1098
+ """
1099
+ _maxes = self._maxes
1100
+
1101
+ if not _maxes:
1102
+ return iter(())
1103
+
1104
+ _lists = self._lists
1105
+
1106
+ # Calculate the minimum (pos, idx) pair. By default this location
1107
+ # will be inclusive in our calculation.
1108
+
1109
+ if minimum is None:
1110
+ min_pos = 0
1111
+ min_idx = 0
1112
+ else:
1113
+ if inclusive[0]:
1114
+ min_pos = bisect_left(_maxes, minimum)
1115
+
1116
+ if min_pos == len(_maxes):
1117
+ return iter(())
1118
+
1119
+ min_idx = bisect_left(_lists[min_pos], minimum)
1120
+ else:
1121
+ min_pos = bisect_right(_maxes, minimum)
1122
+
1123
+ if min_pos == len(_maxes):
1124
+ return iter(())
1125
+
1126
+ min_idx = bisect_right(_lists[min_pos], minimum)
1127
+
1128
+ # Calculate the maximum (pos, idx) pair. By default this location
1129
+ # will be exclusive in our calculation.
1130
+
1131
+ if maximum is None:
1132
+ max_pos = len(_maxes) - 1
1133
+ max_idx = len(_lists[max_pos])
1134
+ else:
1135
+ if inclusive[1]:
1136
+ max_pos = bisect_right(_maxes, maximum)
1137
+
1138
+ if max_pos == len(_maxes):
1139
+ max_pos -= 1
1140
+ max_idx = len(_lists[max_pos])
1141
+ else:
1142
+ max_idx = bisect_right(_lists[max_pos], maximum)
1143
+ else:
1144
+ max_pos = bisect_left(_maxes, maximum)
1145
+
1146
+ if max_pos == len(_maxes):
1147
+ max_pos -= 1
1148
+ max_idx = len(_lists[max_pos])
1149
+ else:
1150
+ max_idx = bisect_left(_lists[max_pos], maximum)
1151
+
1152
+ return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
1153
+
1154
+
1155
+ def __len__(self):
1156
+ """Return the size of the sorted list.
1157
+
1158
+ ``sl.__len__()`` <==> ``len(sl)``
1159
+
1160
+ :return: size of sorted list
1161
+
1162
+ """
1163
+ return self._len
1164
+
1165
+
1166
+ def bisect_left(self, value):
1167
+ """Return an index to insert `value` in the sorted list.
1168
+
1169
+ If the `value` is already present, the insertion point will be before
1170
+ (to the left of) any existing values.
1171
+
1172
+ Similar to the `bisect` module in the standard library.
1173
+
1174
+ Runtime complexity: `O(log(n))` -- approximate.
1175
+
1176
+ >>> sl = SortedList([10, 11, 12, 13, 14])
1177
+ >>> sl.bisect_left(12)
1178
+ 2
1179
+
1180
+ :param value: insertion index of value in sorted list
1181
+ :return: index
1182
+
1183
+ """
1184
+ _maxes = self._maxes
1185
+
1186
+ if not _maxes:
1187
+ return 0
1188
+
1189
+ pos = bisect_left(_maxes, value)
1190
+
1191
+ if pos == len(_maxes):
1192
+ return self._len
1193
+
1194
+ idx = bisect_left(self._lists[pos], value)
1195
+ return self._loc(pos, idx)
1196
+
1197
+
1198
+ def bisect_right(self, value):
1199
+ """Return an index to insert `value` in the sorted list.
1200
+
1201
+ Similar to `bisect_left`, but if `value` is already present, the
1202
+ insertion point will be after (to the right of) any existing values.
1203
+
1204
+ Similar to the `bisect` module in the standard library.
1205
+
1206
+ Runtime complexity: `O(log(n))` -- approximate.
1207
+
1208
+ >>> sl = SortedList([10, 11, 12, 13, 14])
1209
+ >>> sl.bisect_right(12)
1210
+ 3
1211
+
1212
+ :param value: insertion index of value in sorted list
1213
+ :return: index
1214
+
1215
+ """
1216
+ _maxes = self._maxes
1217
+
1218
+ if not _maxes:
1219
+ return 0
1220
+
1221
+ pos = bisect_right(_maxes, value)
1222
+
1223
+ if pos == len(_maxes):
1224
+ return self._len
1225
+
1226
+ idx = bisect_right(self._lists[pos], value)
1227
+ return self._loc(pos, idx)
1228
+
1229
+ bisect = bisect_right
1230
+ _bisect_right = bisect_right
1231
+
1232
+
1233
+ def count(self, value):
1234
+ """Return number of occurrences of `value` in the sorted list.
1235
+
1236
+ Runtime complexity: `O(log(n))` -- approximate.
1237
+
1238
+ >>> sl = SortedList([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])
1239
+ >>> sl.count(3)
1240
+ 3
1241
+
1242
+ :param value: value to count in sorted list
1243
+ :return: count
1244
+
1245
+ """
1246
+ _maxes = self._maxes
1247
+
1248
+ if not _maxes:
1249
+ return 0
1250
+
1251
+ pos_left = bisect_left(_maxes, value)
1252
+
1253
+ if pos_left == len(_maxes):
1254
+ return 0
1255
+
1256
+ _lists = self._lists
1257
+ idx_left = bisect_left(_lists[pos_left], value)
1258
+ pos_right = bisect_right(_maxes, value)
1259
+
1260
+ if pos_right == len(_maxes):
1261
+ return self._len - self._loc(pos_left, idx_left)
1262
+
1263
+ idx_right = bisect_right(_lists[pos_right], value)
1264
+
1265
+ if pos_left == pos_right:
1266
+ return idx_right - idx_left
1267
+
1268
+ right = self._loc(pos_right, idx_right)
1269
+ left = self._loc(pos_left, idx_left)
1270
+ return right - left
1271
+
1272
+
1273
+ def copy(self):
1274
+ """Return a shallow copy of the sorted list.
1275
+
1276
+ Runtime complexity: `O(n)`
1277
+
1278
+ :return: new sorted list
1279
+
1280
+ """
1281
+ return self.__class__(self)
1282
+
1283
+ __copy__ = copy
1284
+
1285
+
1286
+ def append(self, value):
1287
+ """Raise not-implemented error.
1288
+
1289
+ Implemented to override `MutableSequence.append` which provides an
1290
+ erroneous default implementation.
1291
+
1292
+ :raises NotImplementedError: use ``sl.add(value)`` instead
1293
+
1294
+ """
1295
+ raise NotImplementedError('use ``sl.add(value)`` instead')
1296
+
1297
+
1298
+ def extend(self, values):
1299
+ """Raise not-implemented error.
1300
+
1301
+ Implemented to override `MutableSequence.extend` which provides an
1302
+ erroneous default implementation.
1303
+
1304
+ :raises NotImplementedError: use ``sl.update(values)`` instead
1305
+
1306
+ """
1307
+ raise NotImplementedError('use ``sl.update(values)`` instead')
1308
+
1309
+
1310
+ def insert(self, index, value):
1311
+ """Raise not-implemented error.
1312
+
1313
+ :raises NotImplementedError: use ``sl.add(value)`` instead
1314
+
1315
+ """
1316
+ raise NotImplementedError('use ``sl.add(value)`` instead')
1317
+
1318
+
1319
+ def pop(self, index=-1):
1320
+ """Remove and return value at `index` in sorted list.
1321
+
1322
+ Raise :exc:`IndexError` if the sorted list is empty or index is out of
1323
+ range.
1324
+
1325
+ Negative indices are supported.
1326
+
1327
+ Runtime complexity: `O(log(n))` -- approximate.
1328
+
1329
+ >>> sl = SortedList('abcde')
1330
+ >>> sl.pop()
1331
+ 'e'
1332
+ >>> sl.pop(2)
1333
+ 'c'
1334
+ >>> sl
1335
+ SortedList(['a', 'b', 'd'])
1336
+
1337
+ :param int index: index of value (default -1)
1338
+ :return: value
1339
+ :raises IndexError: if index is out of range
1340
+
1341
+ """
1342
+ if not self._len:
1343
+ raise IndexError('pop index out of range')
1344
+
1345
+ _lists = self._lists
1346
+
1347
+ if index == 0:
1348
+ val = _lists[0][0]
1349
+ self._delete(0, 0)
1350
+ return val
1351
+
1352
+ if index == -1:
1353
+ pos = len(_lists) - 1
1354
+ loc = len(_lists[pos]) - 1
1355
+ val = _lists[pos][loc]
1356
+ self._delete(pos, loc)
1357
+ return val
1358
+
1359
+ if 0 <= index < len(_lists[0]):
1360
+ val = _lists[0][index]
1361
+ self._delete(0, index)
1362
+ return val
1363
+
1364
+ len_last = len(_lists[-1])
1365
+
1366
+ if -len_last < index < 0:
1367
+ pos = len(_lists) - 1
1368
+ loc = len_last + index
1369
+ val = _lists[pos][loc]
1370
+ self._delete(pos, loc)
1371
+ return val
1372
+
1373
+ pos, idx = self._pos(index)
1374
+ val = _lists[pos][idx]
1375
+ self._delete(pos, idx)
1376
+ return val
1377
+
1378
+
1379
+ def index(self, value, start=None, stop=None):
1380
+ """Return first index of value in sorted list.
1381
+
1382
+ Raise ValueError if `value` is not present.
1383
+
1384
+ Index must be between `start` and `stop` for the `value` to be
1385
+ considered present. The default value, None, for `start` and `stop`
1386
+ indicate the beginning and end of the sorted list.
1387
+
1388
+ Negative indices are supported.
1389
+
1390
+ Runtime complexity: `O(log(n))` -- approximate.
1391
+
1392
+ >>> sl = SortedList('abcde')
1393
+ >>> sl.index('d')
1394
+ 3
1395
+ >>> sl.index('z')
1396
+ Traceback (most recent call last):
1397
+ ...
1398
+ ValueError: 'z' is not in list
1399
+
1400
+ :param value: value in sorted list
1401
+ :param int start: start index (default None, start of sorted list)
1402
+ :param int stop: stop index (default None, end of sorted list)
1403
+ :return: index of value
1404
+ :raises ValueError: if value is not present
1405
+
1406
+ """
1407
+ _len = self._len
1408
+
1409
+ if not _len:
1410
+ raise ValueError('{0!r} is not in list'.format(value))
1411
+
1412
+ if start is None:
1413
+ start = 0
1414
+ if start < 0:
1415
+ start += _len
1416
+ if start < 0:
1417
+ start = 0
1418
+
1419
+ if stop is None:
1420
+ stop = _len
1421
+ if stop < 0:
1422
+ stop += _len
1423
+ if stop > _len:
1424
+ stop = _len
1425
+
1426
+ if stop <= start:
1427
+ raise ValueError('{0!r} is not in list'.format(value))
1428
+
1429
+ _maxes = self._maxes
1430
+ pos_left = bisect_left(_maxes, value)
1431
+
1432
+ if pos_left == len(_maxes):
1433
+ raise ValueError('{0!r} is not in list'.format(value))
1434
+
1435
+ _lists = self._lists
1436
+ idx_left = bisect_left(_lists[pos_left], value)
1437
+
1438
+ if _lists[pos_left][idx_left] != value:
1439
+ raise ValueError('{0!r} is not in list'.format(value))
1440
+
1441
+ stop -= 1
1442
+ left = self._loc(pos_left, idx_left)
1443
+
1444
+ if start <= left:
1445
+ if left <= stop:
1446
+ return left
1447
+ else:
1448
+ right = self._bisect_right(value) - 1
1449
+
1450
+ if start <= right:
1451
+ return start
1452
+
1453
+ raise ValueError('{0!r} is not in list'.format(value))
1454
+
1455
+
1456
+ def __add__(self, other):
1457
+ """Return new sorted list containing all values in both sequences.
1458
+
1459
+ ``sl.__add__(other)`` <==> ``sl + other``
1460
+
1461
+ Values in `other` do not need to be in sorted order.
1462
+
1463
+ Runtime complexity: `O(n*log(n))`
1464
+
1465
+ >>> sl1 = SortedList('bat')
1466
+ >>> sl2 = SortedList('cat')
1467
+ >>> sl1 + sl2
1468
+ SortedList(['a', 'a', 'b', 'c', 't', 't'])
1469
+
1470
+ :param other: other iterable
1471
+ :return: new sorted list
1472
+
1473
+ """
1474
+ values = reduce(iadd, self._lists, [])
1475
+ values.extend(other)
1476
+ return self.__class__(values)
1477
+
1478
+ __radd__ = __add__
1479
+
1480
+
1481
+ def __iadd__(self, other):
1482
+ """Update sorted list with values from `other`.
1483
+
1484
+ ``sl.__iadd__(other)`` <==> ``sl += other``
1485
+
1486
+ Values in `other` do not need to be in sorted order.
1487
+
1488
+ Runtime complexity: `O(k*log(n))` -- approximate.
1489
+
1490
+ >>> sl = SortedList('bat')
1491
+ >>> sl += 'cat'
1492
+ >>> sl
1493
+ SortedList(['a', 'a', 'b', 'c', 't', 't'])
1494
+
1495
+ :param other: other iterable
1496
+ :return: existing sorted list
1497
+
1498
+ """
1499
+ self._update(other)
1500
+ return self
1501
+
1502
+
1503
+ def __mul__(self, num):
1504
+ """Return new sorted list with `num` shallow copies of values.
1505
+
1506
+ ``sl.__mul__(num)`` <==> ``sl * num``
1507
+
1508
+ Runtime complexity: `O(n*log(n))`
1509
+
1510
+ >>> sl = SortedList('abc')
1511
+ >>> sl * 3
1512
+ SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
1513
+
1514
+ :param int num: count of shallow copies
1515
+ :return: new sorted list
1516
+
1517
+ """
1518
+ values = reduce(iadd, self._lists, []) * num
1519
+ return self.__class__(values)
1520
+
1521
+ __rmul__ = __mul__
1522
+
1523
+
1524
+ def __imul__(self, num):
1525
+ """Update the sorted list with `num` shallow copies of values.
1526
+
1527
+ ``sl.__imul__(num)`` <==> ``sl *= num``
1528
+
1529
+ Runtime complexity: `O(n*log(n))`
1530
+
1531
+ >>> sl = SortedList('abc')
1532
+ >>> sl *= 3
1533
+ >>> sl
1534
+ SortedList(['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c'])
1535
+
1536
+ :param int num: count of shallow copies
1537
+ :return: existing sorted list
1538
+
1539
+ """
1540
+ values = reduce(iadd, self._lists, []) * num
1541
+ self._clear()
1542
+ self._update(values)
1543
+ return self
1544
+
1545
+
1546
+ def __make_cmp(seq_op, symbol, doc):
1547
+ "Make comparator method."
1548
+ def comparer(self, other):
1549
+ "Compare method for sorted list and sequence."
1550
+ if not isinstance(other, Sequence):
1551
+ return NotImplemented
1552
+
1553
+ self_len = self._len
1554
+ len_other = len(other)
1555
+
1556
+ if self_len != len_other:
1557
+ if seq_op is eq:
1558
+ return False
1559
+ if seq_op is ne:
1560
+ return True
1561
+
1562
+ for alpha, beta in zip(self, other):
1563
+ if alpha != beta:
1564
+ return seq_op(alpha, beta)
1565
+
1566
+ return seq_op(self_len, len_other)
1567
+
1568
+ seq_op_name = seq_op.__name__
1569
+ comparer.__name__ = '__{0}__'.format(seq_op_name)
1570
+ doc_str = """Return true if and only if sorted list is {0} `other`.
1571
+
1572
+ ``sl.__{1}__(other)`` <==> ``sl {2} other``
1573
+
1574
+ Comparisons use lexicographical order as with sequences.
1575
+
1576
+ Runtime complexity: `O(n)`
1577
+
1578
+ :param other: `other` sequence
1579
+ :return: true if sorted list is {0} `other`
1580
+
1581
+ """
1582
+ comparer.__doc__ = dedent(doc_str.format(doc, seq_op_name, symbol))
1583
+ return comparer
1584
+
1585
+
1586
+ __eq__ = __make_cmp(eq, '==', 'equal to')
1587
+ __ne__ = __make_cmp(ne, '!=', 'not equal to')
1588
+ __lt__ = __make_cmp(lt, '<', 'less than')
1589
+ __gt__ = __make_cmp(gt, '>', 'greater than')
1590
+ __le__ = __make_cmp(le, '<=', 'less than or equal to')
1591
+ __ge__ = __make_cmp(ge, '>=', 'greater than or equal to')
1592
+ __make_cmp = staticmethod(__make_cmp)
1593
+
1594
+
1595
+ def __reduce__(self):
1596
+ values = reduce(iadd, self._lists, [])
1597
+ return (type(self), (values,))
1598
+
1599
+
1600
+ @recursive_repr()
1601
+ def __repr__(self):
1602
+ """Return string representation of sorted list.
1603
+
1604
+ ``sl.__repr__()`` <==> ``repr(sl)``
1605
+
1606
+ :return: string representation
1607
+
1608
+ """
1609
+ return '{0}({1!r})'.format(type(self).__name__, list(self))
1610
+
1611
+
1612
+ def _check(self):
1613
+ """Check invariants of sorted list.
1614
+
1615
+ Runtime complexity: `O(n)`
1616
+
1617
+ """
1618
+ try:
1619
+ assert self._load >= 4
1620
+ assert len(self._maxes) == len(self._lists)
1621
+ assert self._len == sum(len(sublist) for sublist in self._lists)
1622
+
1623
+ # Check all sublists are sorted.
1624
+
1625
+ for sublist in self._lists:
1626
+ for pos in range(1, len(sublist)):
1627
+ assert sublist[pos - 1] <= sublist[pos]
1628
+
1629
+ # Check beginning/end of sublists are sorted.
1630
+
1631
+ for pos in range(1, len(self._lists)):
1632
+ assert self._lists[pos - 1][-1] <= self._lists[pos][0]
1633
+
1634
+ # Check _maxes index is the last value of each sublist.
1635
+
1636
+ for pos in range(len(self._maxes)):
1637
+ assert self._maxes[pos] == self._lists[pos][-1]
1638
+
1639
+ # Check sublist lengths are less than double load-factor.
1640
+
1641
+ double = self._load << 1
1642
+ assert all(len(sublist) <= double for sublist in self._lists)
1643
+
1644
+ # Check sublist lengths are greater than half load-factor for all
1645
+ # but the last sublist.
1646
+
1647
+ half = self._load >> 1
1648
+ for pos in range(0, len(self._lists) - 1):
1649
+ assert len(self._lists[pos]) >= half
1650
+
1651
+ if self._index:
1652
+ assert self._len == self._index[0]
1653
+ assert len(self._index) == self._offset + len(self._lists)
1654
+
1655
+ # Check index leaf nodes equal length of sublists.
1656
+
1657
+ for pos in range(len(self._lists)):
1658
+ leaf = self._index[self._offset + pos]
1659
+ assert leaf == len(self._lists[pos])
1660
+
1661
+ # Check index branch nodes are the sum of their children.
1662
+
1663
+ for pos in range(self._offset):
1664
+ child = (pos << 1) + 1
1665
+ if child >= len(self._index):
1666
+ assert self._index[pos] == 0
1667
+ elif child + 1 == len(self._index):
1668
+ assert self._index[pos] == self._index[child]
1669
+ else:
1670
+ child_sum = self._index[child] + self._index[child + 1]
1671
+ assert child_sum == self._index[pos]
1672
+ except:
1673
+ traceback.print_exc(file=sys.stdout)
1674
+ print('len', self._len)
1675
+ print('load', self._load)
1676
+ print('offset', self._offset)
1677
+ print('len_index', len(self._index))
1678
+ print('index', self._index)
1679
+ print('len_maxes', len(self._maxes))
1680
+ print('maxes', self._maxes)
1681
+ print('len_lists', len(self._lists))
1682
+ print('lists', self._lists)
1683
+ raise
1684
+
1685
+
1686
+ def identity(value):
1687
+ "Identity function."
1688
+ return value
1689
+
1690
+
1691
+ class SortedKeyList(SortedList):
1692
+ """Sorted-key list is a subtype of sorted list.
1693
+
1694
+ The sorted-key list maintains values in comparison order based on the
1695
+ result of a key function applied to every value.
1696
+
1697
+ All the same methods that are available in :class:`SortedList` are also
1698
+ available in :class:`SortedKeyList`.
1699
+
1700
+ Additional methods provided:
1701
+
1702
+ * :attr:`SortedKeyList.key`
1703
+ * :func:`SortedKeyList.bisect_key_left`
1704
+ * :func:`SortedKeyList.bisect_key_right`
1705
+ * :func:`SortedKeyList.irange_key`
1706
+
1707
+ Some examples below use:
1708
+
1709
+ >>> from operator import neg
1710
+ >>> neg
1711
+ <built-in function neg>
1712
+ >>> neg(1)
1713
+ -1
1714
+
1715
+ """
1716
+ def __init__(self, iterable=None, key=identity):
1717
+ """Initialize sorted-key list instance.
1718
+
1719
+ Optional `iterable` argument provides an initial iterable of values to
1720
+ initialize the sorted-key list.
1721
+
1722
+ Optional `key` argument defines a callable that, like the `key`
1723
+ argument to Python's `sorted` function, extracts a comparison key from
1724
+ each value. The default is the identity function.
1725
+
1726
+ Runtime complexity: `O(n*log(n))`
1727
+
1728
+ >>> from operator import neg
1729
+ >>> skl = SortedKeyList(key=neg)
1730
+ >>> skl
1731
+ SortedKeyList([], key=<built-in function neg>)
1732
+ >>> skl = SortedKeyList([3, 1, 2], key=neg)
1733
+ >>> skl
1734
+ SortedKeyList([3, 2, 1], key=<built-in function neg>)
1735
+
1736
+ :param iterable: initial values (optional)
1737
+ :param key: function used to extract comparison key (optional)
1738
+
1739
+ """
1740
+ self._key = key
1741
+ self._len = 0
1742
+ self._load = self.DEFAULT_LOAD_FACTOR
1743
+ self._lists = []
1744
+ self._keys = []
1745
+ self._maxes = []
1746
+ self._index = []
1747
+ self._offset = 0
1748
+
1749
+ if iterable is not None:
1750
+ self._update(iterable)
1751
+
1752
+
1753
+ def __new__(cls, iterable=None, key=identity):
1754
+ return object.__new__(cls)
1755
+
1756
+
1757
+ @property
1758
+ def key(self):
1759
+ "Function used to extract comparison key from values."
1760
+ return self._key
1761
+
1762
+
1763
+ def clear(self):
1764
+ """Remove all values from sorted-key list.
1765
+
1766
+ Runtime complexity: `O(n)`
1767
+
1768
+ """
1769
+ self._len = 0
1770
+ del self._lists[:]
1771
+ del self._keys[:]
1772
+ del self._maxes[:]
1773
+ del self._index[:]
1774
+
1775
+ _clear = clear
1776
+
1777
+
1778
+ def add(self, value):
1779
+ """Add `value` to sorted-key list.
1780
+
1781
+ Runtime complexity: `O(log(n))` -- approximate.
1782
+
1783
+ >>> from operator import neg
1784
+ >>> skl = SortedKeyList(key=neg)
1785
+ >>> skl.add(3)
1786
+ >>> skl.add(1)
1787
+ >>> skl.add(2)
1788
+ >>> skl
1789
+ SortedKeyList([3, 2, 1], key=<built-in function neg>)
1790
+
1791
+ :param value: value to add to sorted-key list
1792
+
1793
+ """
1794
+ _lists = self._lists
1795
+ _keys = self._keys
1796
+ _maxes = self._maxes
1797
+
1798
+ key = self._key(value)
1799
+
1800
+ if _maxes:
1801
+ pos = bisect_right(_maxes, key)
1802
+
1803
+ if pos == len(_maxes):
1804
+ pos -= 1
1805
+ _lists[pos].append(value)
1806
+ _keys[pos].append(key)
1807
+ _maxes[pos] = key
1808
+ else:
1809
+ idx = bisect_right(_keys[pos], key)
1810
+ _lists[pos].insert(idx, value)
1811
+ _keys[pos].insert(idx, key)
1812
+
1813
+ self._expand(pos)
1814
+ else:
1815
+ _lists.append([value])
1816
+ _keys.append([key])
1817
+ _maxes.append(key)
1818
+
1819
+ self._len += 1
1820
+
1821
+
1822
+ def _expand(self, pos):
1823
+ """Split sublists with length greater than double the load-factor.
1824
+
1825
+ Updates the index when the sublist length is less than double the load
1826
+ level. This requires incrementing the nodes in a traversal from the
1827
+ leaf node to the root. For an example traversal see
1828
+ ``SortedList._loc``.
1829
+
1830
+ """
1831
+ _lists = self._lists
1832
+ _keys = self._keys
1833
+ _index = self._index
1834
+
1835
+ if len(_keys[pos]) > (self._load << 1):
1836
+ _maxes = self._maxes
1837
+ _load = self._load
1838
+
1839
+ _lists_pos = _lists[pos]
1840
+ _keys_pos = _keys[pos]
1841
+ half = _lists_pos[_load:]
1842
+ half_keys = _keys_pos[_load:]
1843
+ del _lists_pos[_load:]
1844
+ del _keys_pos[_load:]
1845
+ _maxes[pos] = _keys_pos[-1]
1846
+
1847
+ _lists.insert(pos + 1, half)
1848
+ _keys.insert(pos + 1, half_keys)
1849
+ _maxes.insert(pos + 1, half_keys[-1])
1850
+
1851
+ del _index[:]
1852
+ else:
1853
+ if _index:
1854
+ child = self._offset + pos
1855
+ while child:
1856
+ _index[child] += 1
1857
+ child = (child - 1) >> 1
1858
+ _index[0] += 1
1859
+
1860
+
1861
+ def update(self, iterable):
1862
+ """Update sorted-key list by adding all values from `iterable`.
1863
+
1864
+ Runtime complexity: `O(k*log(n))` -- approximate.
1865
+
1866
+ >>> from operator import neg
1867
+ >>> skl = SortedKeyList(key=neg)
1868
+ >>> skl.update([3, 1, 2])
1869
+ >>> skl
1870
+ SortedKeyList([3, 2, 1], key=<built-in function neg>)
1871
+
1872
+ :param iterable: iterable of values to add
1873
+
1874
+ """
1875
+ _lists = self._lists
1876
+ _keys = self._keys
1877
+ _maxes = self._maxes
1878
+ values = sorted(iterable, key=self._key)
1879
+
1880
+ if _maxes:
1881
+ if len(values) * 4 >= self._len:
1882
+ _lists.append(values)
1883
+ values = reduce(iadd, _lists, [])
1884
+ values.sort(key=self._key)
1885
+ self._clear()
1886
+ else:
1887
+ _add = self.add
1888
+ for val in values:
1889
+ _add(val)
1890
+ return
1891
+
1892
+ _load = self._load
1893
+ _lists.extend(values[pos:(pos + _load)]
1894
+ for pos in range(0, len(values), _load))
1895
+ _keys.extend(list(map(self._key, _list)) for _list in _lists)
1896
+ _maxes.extend(sublist[-1] for sublist in _keys)
1897
+ self._len = len(values)
1898
+ del self._index[:]
1899
+
1900
+ _update = update
1901
+
1902
+
1903
+ def __contains__(self, value):
1904
+ """Return true if `value` is an element of the sorted-key list.
1905
+
1906
+ ``skl.__contains__(value)`` <==> ``value in skl``
1907
+
1908
+ Runtime complexity: `O(log(n))`
1909
+
1910
+ >>> from operator import neg
1911
+ >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
1912
+ >>> 3 in skl
1913
+ True
1914
+
1915
+ :param value: search for value in sorted-key list
1916
+ :return: true if `value` in sorted-key list
1917
+
1918
+ """
1919
+ _maxes = self._maxes
1920
+
1921
+ if not _maxes:
1922
+ return False
1923
+
1924
+ key = self._key(value)
1925
+ pos = bisect_left(_maxes, key)
1926
+
1927
+ if pos == len(_maxes):
1928
+ return False
1929
+
1930
+ _lists = self._lists
1931
+ _keys = self._keys
1932
+
1933
+ idx = bisect_left(_keys[pos], key)
1934
+
1935
+ len_keys = len(_keys)
1936
+ len_sublist = len(_keys[pos])
1937
+
1938
+ while True:
1939
+ if _keys[pos][idx] != key:
1940
+ return False
1941
+ if _lists[pos][idx] == value:
1942
+ return True
1943
+ idx += 1
1944
+ if idx == len_sublist:
1945
+ pos += 1
1946
+ if pos == len_keys:
1947
+ return False
1948
+ len_sublist = len(_keys[pos])
1949
+ idx = 0
1950
+
1951
+
1952
+ def discard(self, value):
1953
+ """Remove `value` from sorted-key list if it is a member.
1954
+
1955
+ If `value` is not a member, do nothing.
1956
+
1957
+ Runtime complexity: `O(log(n))` -- approximate.
1958
+
1959
+ >>> from operator import neg
1960
+ >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
1961
+ >>> skl.discard(1)
1962
+ >>> skl.discard(0)
1963
+ >>> skl == [5, 4, 3, 2]
1964
+ True
1965
+
1966
+ :param value: `value` to discard from sorted-key list
1967
+
1968
+ """
1969
+ _maxes = self._maxes
1970
+
1971
+ if not _maxes:
1972
+ return
1973
+
1974
+ key = self._key(value)
1975
+ pos = bisect_left(_maxes, key)
1976
+
1977
+ if pos == len(_maxes):
1978
+ return
1979
+
1980
+ _lists = self._lists
1981
+ _keys = self._keys
1982
+ idx = bisect_left(_keys[pos], key)
1983
+ len_keys = len(_keys)
1984
+ len_sublist = len(_keys[pos])
1985
+
1986
+ while True:
1987
+ if _keys[pos][idx] != key:
1988
+ return
1989
+ if _lists[pos][idx] == value:
1990
+ self._delete(pos, idx)
1991
+ return
1992
+ idx += 1
1993
+ if idx == len_sublist:
1994
+ pos += 1
1995
+ if pos == len_keys:
1996
+ return
1997
+ len_sublist = len(_keys[pos])
1998
+ idx = 0
1999
+
2000
+
2001
+ def remove(self, value):
2002
+ """Remove `value` from sorted-key list; `value` must be a member.
2003
+
2004
+ If `value` is not a member, raise ValueError.
2005
+
2006
+ Runtime complexity: `O(log(n))` -- approximate.
2007
+
2008
+ >>> from operator import neg
2009
+ >>> skl = SortedKeyList([1, 2, 3, 4, 5], key=neg)
2010
+ >>> skl.remove(5)
2011
+ >>> skl == [4, 3, 2, 1]
2012
+ True
2013
+ >>> skl.remove(0)
2014
+ Traceback (most recent call last):
2015
+ ...
2016
+ ValueError: 0 not in list
2017
+
2018
+ :param value: `value` to remove from sorted-key list
2019
+ :raises ValueError: if `value` is not in sorted-key list
2020
+
2021
+ """
2022
+ _maxes = self._maxes
2023
+
2024
+ if not _maxes:
2025
+ raise ValueError('{0!r} not in list'.format(value))
2026
+
2027
+ key = self._key(value)
2028
+ pos = bisect_left(_maxes, key)
2029
+
2030
+ if pos == len(_maxes):
2031
+ raise ValueError('{0!r} not in list'.format(value))
2032
+
2033
+ _lists = self._lists
2034
+ _keys = self._keys
2035
+ idx = bisect_left(_keys[pos], key)
2036
+ len_keys = len(_keys)
2037
+ len_sublist = len(_keys[pos])
2038
+
2039
+ while True:
2040
+ if _keys[pos][idx] != key:
2041
+ raise ValueError('{0!r} not in list'.format(value))
2042
+ if _lists[pos][idx] == value:
2043
+ self._delete(pos, idx)
2044
+ return
2045
+ idx += 1
2046
+ if idx == len_sublist:
2047
+ pos += 1
2048
+ if pos == len_keys:
2049
+ raise ValueError('{0!r} not in list'.format(value))
2050
+ len_sublist = len(_keys[pos])
2051
+ idx = 0
2052
+
2053
+
2054
+ def _delete(self, pos, idx):
2055
+ """Delete value at the given `(pos, idx)`.
2056
+
2057
+ Combines lists that are less than half the load level.
2058
+
2059
+ Updates the index when the sublist length is more than half the load
2060
+ level. This requires decrementing the nodes in a traversal from the
2061
+ leaf node to the root. For an example traversal see
2062
+ ``SortedList._loc``.
2063
+
2064
+ :param int pos: lists index
2065
+ :param int idx: sublist index
2066
+
2067
+ """
2068
+ _lists = self._lists
2069
+ _keys = self._keys
2070
+ _maxes = self._maxes
2071
+ _index = self._index
2072
+ keys_pos = _keys[pos]
2073
+ lists_pos = _lists[pos]
2074
+
2075
+ del keys_pos[idx]
2076
+ del lists_pos[idx]
2077
+ self._len -= 1
2078
+
2079
+ len_keys_pos = len(keys_pos)
2080
+
2081
+ if len_keys_pos > (self._load >> 1):
2082
+ _maxes[pos] = keys_pos[-1]
2083
+
2084
+ if _index:
2085
+ child = self._offset + pos
2086
+ while child > 0:
2087
+ _index[child] -= 1
2088
+ child = (child - 1) >> 1
2089
+ _index[0] -= 1
2090
+ elif len(_keys) > 1:
2091
+ if not pos:
2092
+ pos += 1
2093
+
2094
+ prev = pos - 1
2095
+ _keys[prev].extend(_keys[pos])
2096
+ _lists[prev].extend(_lists[pos])
2097
+ _maxes[prev] = _keys[prev][-1]
2098
+
2099
+ del _lists[pos]
2100
+ del _keys[pos]
2101
+ del _maxes[pos]
2102
+ del _index[:]
2103
+
2104
+ self._expand(prev)
2105
+ elif len_keys_pos:
2106
+ _maxes[pos] = keys_pos[-1]
2107
+ else:
2108
+ del _lists[pos]
2109
+ del _keys[pos]
2110
+ del _maxes[pos]
2111
+ del _index[:]
2112
+
2113
+
2114
+ def irange(self, minimum=None, maximum=None, inclusive=(True, True),
2115
+ reverse=False):
2116
+ """Create an iterator of values between `minimum` and `maximum`.
2117
+
2118
+ Both `minimum` and `maximum` default to `None` which is automatically
2119
+ inclusive of the beginning and end of the sorted-key list.
2120
+
2121
+ The argument `inclusive` is a pair of booleans that indicates whether
2122
+ the minimum and maximum ought to be included in the range,
2123
+ respectively. The default is ``(True, True)`` such that the range is
2124
+ inclusive of both minimum and maximum.
2125
+
2126
+ When `reverse` is `True` the values are yielded from the iterator in
2127
+ reverse order; `reverse` defaults to `False`.
2128
+
2129
+ >>> from operator import neg
2130
+ >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
2131
+ >>> it = skl.irange(14.5, 11.5)
2132
+ >>> list(it)
2133
+ [14, 13, 12]
2134
+
2135
+ :param minimum: minimum value to start iterating
2136
+ :param maximum: maximum value to stop iterating
2137
+ :param inclusive: pair of booleans
2138
+ :param bool reverse: yield values in reverse order
2139
+ :return: iterator
2140
+
2141
+ """
2142
+ min_key = self._key(minimum) if minimum is not None else None
2143
+ max_key = self._key(maximum) if maximum is not None else None
2144
+ return self._irange_key(
2145
+ min_key=min_key, max_key=max_key,
2146
+ inclusive=inclusive, reverse=reverse,
2147
+ )
2148
+
2149
+
2150
+ def irange_key(self, min_key=None, max_key=None, inclusive=(True, True),
2151
+ reverse=False):
2152
+ """Create an iterator of values between `min_key` and `max_key`.
2153
+
2154
+ Both `min_key` and `max_key` default to `None` which is automatically
2155
+ inclusive of the beginning and end of the sorted-key list.
2156
+
2157
+ The argument `inclusive` is a pair of booleans that indicates whether
2158
+ the minimum and maximum ought to be included in the range,
2159
+ respectively. The default is ``(True, True)`` such that the range is
2160
+ inclusive of both minimum and maximum.
2161
+
2162
+ When `reverse` is `True` the values are yielded from the iterator in
2163
+ reverse order; `reverse` defaults to `False`.
2164
+
2165
+ >>> from operator import neg
2166
+ >>> skl = SortedKeyList([11, 12, 13, 14, 15], key=neg)
2167
+ >>> it = skl.irange_key(-14, -12)
2168
+ >>> list(it)
2169
+ [14, 13, 12]
2170
+
2171
+ :param min_key: minimum key to start iterating
2172
+ :param max_key: maximum key to stop iterating
2173
+ :param inclusive: pair of booleans
2174
+ :param bool reverse: yield values in reverse order
2175
+ :return: iterator
2176
+
2177
+ """
2178
+ _maxes = self._maxes
2179
+
2180
+ if not _maxes:
2181
+ return iter(())
2182
+
2183
+ _keys = self._keys
2184
+
2185
+ # Calculate the minimum (pos, idx) pair. By default this location
2186
+ # will be inclusive in our calculation.
2187
+
2188
+ if min_key is None:
2189
+ min_pos = 0
2190
+ min_idx = 0
2191
+ else:
2192
+ if inclusive[0]:
2193
+ min_pos = bisect_left(_maxes, min_key)
2194
+
2195
+ if min_pos == len(_maxes):
2196
+ return iter(())
2197
+
2198
+ min_idx = bisect_left(_keys[min_pos], min_key)
2199
+ else:
2200
+ min_pos = bisect_right(_maxes, min_key)
2201
+
2202
+ if min_pos == len(_maxes):
2203
+ return iter(())
2204
+
2205
+ min_idx = bisect_right(_keys[min_pos], min_key)
2206
+
2207
+ # Calculate the maximum (pos, idx) pair. By default this location
2208
+ # will be exclusive in our calculation.
2209
+
2210
+ if max_key is None:
2211
+ max_pos = len(_maxes) - 1
2212
+ max_idx = len(_keys[max_pos])
2213
+ else:
2214
+ if inclusive[1]:
2215
+ max_pos = bisect_right(_maxes, max_key)
2216
+
2217
+ if max_pos == len(_maxes):
2218
+ max_pos -= 1
2219
+ max_idx = len(_keys[max_pos])
2220
+ else:
2221
+ max_idx = bisect_right(_keys[max_pos], max_key)
2222
+ else:
2223
+ max_pos = bisect_left(_maxes, max_key)
2224
+
2225
+ if max_pos == len(_maxes):
2226
+ max_pos -= 1
2227
+ max_idx = len(_keys[max_pos])
2228
+ else:
2229
+ max_idx = bisect_left(_keys[max_pos], max_key)
2230
+
2231
+ return self._islice(min_pos, min_idx, max_pos, max_idx, reverse)
2232
+
2233
+ _irange_key = irange_key
2234
+
2235
+
2236
+ def bisect_left(self, value):
2237
+ """Return an index to insert `value` in the sorted-key list.
2238
+
2239
+ If the `value` is already present, the insertion point will be before
2240
+ (to the left of) any existing values.
2241
+
2242
+ Similar to the `bisect` module in the standard library.
2243
+
2244
+ Runtime complexity: `O(log(n))` -- approximate.
2245
+
2246
+ >>> from operator import neg
2247
+ >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2248
+ >>> skl.bisect_left(1)
2249
+ 4
2250
+
2251
+ :param value: insertion index of value in sorted-key list
2252
+ :return: index
2253
+
2254
+ """
2255
+ return self._bisect_key_left(self._key(value))
2256
+
2257
+
2258
+ def bisect_right(self, value):
2259
+ """Return an index to insert `value` in the sorted-key list.
2260
+
2261
+ Similar to `bisect_left`, but if `value` is already present, the
2262
+ insertion point will be after (to the right of) any existing values.
2263
+
2264
+ Similar to the `bisect` module in the standard library.
2265
+
2266
+ Runtime complexity: `O(log(n))` -- approximate.
2267
+
2268
+ >>> from operator import neg
2269
+ >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
2270
+ >>> skl.bisect_right(1)
2271
+ 5
2272
+
2273
+ :param value: insertion index of value in sorted-key list
2274
+ :return: index
2275
+
2276
+ """
2277
+ return self._bisect_key_right(self._key(value))
2278
+
2279
+ bisect = bisect_right
2280
+
2281
+
2282
+ def bisect_key_left(self, key):
2283
+ """Return an index to insert `key` in the sorted-key list.
2284
+
2285
+ If the `key` is already present, the insertion point will be before (to
2286
+ the left of) any existing keys.
2287
+
2288
+ Similar to the `bisect` module in the standard library.
2289
+
2290
+ Runtime complexity: `O(log(n))` -- approximate.
2291
+
2292
+ >>> from operator import neg
2293
+ >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2294
+ >>> skl.bisect_key_left(-1)
2295
+ 4
2296
+
2297
+ :param key: insertion index of key in sorted-key list
2298
+ :return: index
2299
+
2300
+ """
2301
+ _maxes = self._maxes
2302
+
2303
+ if not _maxes:
2304
+ return 0
2305
+
2306
+ pos = bisect_left(_maxes, key)
2307
+
2308
+ if pos == len(_maxes):
2309
+ return self._len
2310
+
2311
+ idx = bisect_left(self._keys[pos], key)
2312
+
2313
+ return self._loc(pos, idx)
2314
+
2315
+ _bisect_key_left = bisect_key_left
2316
+
2317
+
2318
+ def bisect_key_right(self, key):
2319
+ """Return an index to insert `key` in the sorted-key list.
2320
+
2321
+ Similar to `bisect_key_left`, but if `key` is already present, the
2322
+ insertion point will be after (to the right of) any existing keys.
2323
+
2324
+ Similar to the `bisect` module in the standard library.
2325
+
2326
+ Runtime complexity: `O(log(n))` -- approximate.
2327
+
2328
+ >>> from operator import neg
2329
+ >>> skl = SortedList([5, 4, 3, 2, 1], key=neg)
2330
+ >>> skl.bisect_key_right(-1)
2331
+ 5
2332
+
2333
+ :param key: insertion index of key in sorted-key list
2334
+ :return: index
2335
+
2336
+ """
2337
+ _maxes = self._maxes
2338
+
2339
+ if not _maxes:
2340
+ return 0
2341
+
2342
+ pos = bisect_right(_maxes, key)
2343
+
2344
+ if pos == len(_maxes):
2345
+ return self._len
2346
+
2347
+ idx = bisect_right(self._keys[pos], key)
2348
+
2349
+ return self._loc(pos, idx)
2350
+
2351
+ bisect_key = bisect_key_right
2352
+ _bisect_key_right = bisect_key_right
2353
+
2354
+
2355
+ def count(self, value):
2356
+ """Return number of occurrences of `value` in the sorted-key list.
2357
+
2358
+ Runtime complexity: `O(log(n))` -- approximate.
2359
+
2360
+ >>> from operator import neg
2361
+ >>> skl = SortedKeyList([4, 4, 4, 4, 3, 3, 3, 2, 2, 1], key=neg)
2362
+ >>> skl.count(2)
2363
+ 2
2364
+
2365
+ :param value: value to count in sorted-key list
2366
+ :return: count
2367
+
2368
+ """
2369
+ _maxes = self._maxes
2370
+
2371
+ if not _maxes:
2372
+ return 0
2373
+
2374
+ key = self._key(value)
2375
+ pos = bisect_left(_maxes, key)
2376
+
2377
+ if pos == len(_maxes):
2378
+ return 0
2379
+
2380
+ _lists = self._lists
2381
+ _keys = self._keys
2382
+ idx = bisect_left(_keys[pos], key)
2383
+ total = 0
2384
+ len_keys = len(_keys)
2385
+ len_sublist = len(_keys[pos])
2386
+
2387
+ while True:
2388
+ if _keys[pos][idx] != key:
2389
+ return total
2390
+ if _lists[pos][idx] == value:
2391
+ total += 1
2392
+ idx += 1
2393
+ if idx == len_sublist:
2394
+ pos += 1
2395
+ if pos == len_keys:
2396
+ return total
2397
+ len_sublist = len(_keys[pos])
2398
+ idx = 0
2399
+
2400
+
2401
+ def copy(self):
2402
+ """Return a shallow copy of the sorted-key list.
2403
+
2404
+ Runtime complexity: `O(n)`
2405
+
2406
+ :return: new sorted-key list
2407
+
2408
+ """
2409
+ return self.__class__(self, key=self._key)
2410
+
2411
+ __copy__ = copy
2412
+
2413
+
2414
+ def index(self, value, start=None, stop=None):
2415
+ """Return first index of value in sorted-key list.
2416
+
2417
+ Raise ValueError if `value` is not present.
2418
+
2419
+ Index must be between `start` and `stop` for the `value` to be
2420
+ considered present. The default value, None, for `start` and `stop`
2421
+ indicate the beginning and end of the sorted-key list.
2422
+
2423
+ Negative indices are supported.
2424
+
2425
+ Runtime complexity: `O(log(n))` -- approximate.
2426
+
2427
+ >>> from operator import neg
2428
+ >>> skl = SortedKeyList([5, 4, 3, 2, 1], key=neg)
2429
+ >>> skl.index(2)
2430
+ 3
2431
+ >>> skl.index(0)
2432
+ Traceback (most recent call last):
2433
+ ...
2434
+ ValueError: 0 is not in list
2435
+
2436
+ :param value: value in sorted-key list
2437
+ :param int start: start index (default None, start of sorted-key list)
2438
+ :param int stop: stop index (default None, end of sorted-key list)
2439
+ :return: index of value
2440
+ :raises ValueError: if value is not present
2441
+
2442
+ """
2443
+ _len = self._len
2444
+
2445
+ if not _len:
2446
+ raise ValueError('{0!r} is not in list'.format(value))
2447
+
2448
+ if start is None:
2449
+ start = 0
2450
+ if start < 0:
2451
+ start += _len
2452
+ if start < 0:
2453
+ start = 0
2454
+
2455
+ if stop is None:
2456
+ stop = _len
2457
+ if stop < 0:
2458
+ stop += _len
2459
+ if stop > _len:
2460
+ stop = _len
2461
+
2462
+ if stop <= start:
2463
+ raise ValueError('{0!r} is not in list'.format(value))
2464
+
2465
+ _maxes = self._maxes
2466
+ key = self._key(value)
2467
+ pos = bisect_left(_maxes, key)
2468
+
2469
+ if pos == len(_maxes):
2470
+ raise ValueError('{0!r} is not in list'.format(value))
2471
+
2472
+ stop -= 1
2473
+ _lists = self._lists
2474
+ _keys = self._keys
2475
+ idx = bisect_left(_keys[pos], key)
2476
+ len_keys = len(_keys)
2477
+ len_sublist = len(_keys[pos])
2478
+
2479
+ while True:
2480
+ if _keys[pos][idx] != key:
2481
+ raise ValueError('{0!r} is not in list'.format(value))
2482
+ if _lists[pos][idx] == value:
2483
+ loc = self._loc(pos, idx)
2484
+ if start <= loc <= stop:
2485
+ return loc
2486
+ elif loc > stop:
2487
+ break
2488
+ idx += 1
2489
+ if idx == len_sublist:
2490
+ pos += 1
2491
+ if pos == len_keys:
2492
+ raise ValueError('{0!r} is not in list'.format(value))
2493
+ len_sublist = len(_keys[pos])
2494
+ idx = 0
2495
+
2496
+ raise ValueError('{0!r} is not in list'.format(value))
2497
+
2498
+
2499
+ def __add__(self, other):
2500
+ """Return new sorted-key list containing all values in both sequences.
2501
+
2502
+ ``skl.__add__(other)`` <==> ``skl + other``
2503
+
2504
+ Values in `other` do not need to be in sorted-key order.
2505
+
2506
+ Runtime complexity: `O(n*log(n))`
2507
+
2508
+ >>> from operator import neg
2509
+ >>> skl1 = SortedKeyList([5, 4, 3], key=neg)
2510
+ >>> skl2 = SortedKeyList([2, 1, 0], key=neg)
2511
+ >>> skl1 + skl2
2512
+ SortedKeyList([5, 4, 3, 2, 1, 0], key=<built-in function neg>)
2513
+
2514
+ :param other: other iterable
2515
+ :return: new sorted-key list
2516
+
2517
+ """
2518
+ values = reduce(iadd, self._lists, [])
2519
+ values.extend(other)
2520
+ return self.__class__(values, key=self._key)
2521
+
2522
+ __radd__ = __add__
2523
+
2524
+
2525
+ def __mul__(self, num):
2526
+ """Return new sorted-key list with `num` shallow copies of values.
2527
+
2528
+ ``skl.__mul__(num)`` <==> ``skl * num``
2529
+
2530
+ Runtime complexity: `O(n*log(n))`
2531
+
2532
+ >>> from operator import neg
2533
+ >>> skl = SortedKeyList([3, 2, 1], key=neg)
2534
+ >>> skl * 2
2535
+ SortedKeyList([3, 3, 2, 2, 1, 1], key=<built-in function neg>)
2536
+
2537
+ :param int num: count of shallow copies
2538
+ :return: new sorted-key list
2539
+
2540
+ """
2541
+ values = reduce(iadd, self._lists, []) * num
2542
+ return self.__class__(values, key=self._key)
2543
+
2544
+
2545
+ def __reduce__(self):
2546
+ values = reduce(iadd, self._lists, [])
2547
+ return (type(self), (values, self.key))
2548
+
2549
+
2550
+ @recursive_repr()
2551
+ def __repr__(self):
2552
+ """Return string representation of sorted-key list.
2553
+
2554
+ ``skl.__repr__()`` <==> ``repr(skl)``
2555
+
2556
+ :return: string representation
2557
+
2558
+ """
2559
+ type_name = type(self).__name__
2560
+ return '{0}({1!r}, key={2!r})'.format(type_name, list(self), self._key)
2561
+
2562
+
2563
+ def _check(self):
2564
+ """Check invariants of sorted-key list.
2565
+
2566
+ Runtime complexity: `O(n)`
2567
+
2568
+ """
2569
+ try:
2570
+ assert self._load >= 4
2571
+ assert len(self._maxes) == len(self._lists) == len(self._keys)
2572
+ assert self._len == sum(len(sublist) for sublist in self._lists)
2573
+
2574
+ # Check all sublists are sorted.
2575
+
2576
+ for sublist in self._keys:
2577
+ for pos in range(1, len(sublist)):
2578
+ assert sublist[pos - 1] <= sublist[pos]
2579
+
2580
+ # Check beginning/end of sublists are sorted.
2581
+
2582
+ for pos in range(1, len(self._keys)):
2583
+ assert self._keys[pos - 1][-1] <= self._keys[pos][0]
2584
+
2585
+ # Check _keys matches _key mapped to _lists.
2586
+
2587
+ for val_sublist, key_sublist in zip(self._lists, self._keys):
2588
+ assert len(val_sublist) == len(key_sublist)
2589
+ for val, key in zip(val_sublist, key_sublist):
2590
+ assert self._key(val) == key
2591
+
2592
+ # Check _maxes index is the last value of each sublist.
2593
+
2594
+ for pos in range(len(self._maxes)):
2595
+ assert self._maxes[pos] == self._keys[pos][-1]
2596
+
2597
+ # Check sublist lengths are less than double load-factor.
2598
+
2599
+ double = self._load << 1
2600
+ assert all(len(sublist) <= double for sublist in self._lists)
2601
+
2602
+ # Check sublist lengths are greater than half load-factor for all
2603
+ # but the last sublist.
2604
+
2605
+ half = self._load >> 1
2606
+ for pos in range(0, len(self._lists) - 1):
2607
+ assert len(self._lists[pos]) >= half
2608
+
2609
+ if self._index:
2610
+ assert self._len == self._index[0]
2611
+ assert len(self._index) == self._offset + len(self._lists)
2612
+
2613
+ # Check index leaf nodes equal length of sublists.
2614
+
2615
+ for pos in range(len(self._lists)):
2616
+ leaf = self._index[self._offset + pos]
2617
+ assert leaf == len(self._lists[pos])
2618
+
2619
+ # Check index branch nodes are the sum of their children.
2620
+
2621
+ for pos in range(self._offset):
2622
+ child = (pos << 1) + 1
2623
+ if child >= len(self._index):
2624
+ assert self._index[pos] == 0
2625
+ elif child + 1 == len(self._index):
2626
+ assert self._index[pos] == self._index[child]
2627
+ else:
2628
+ child_sum = self._index[child] + self._index[child + 1]
2629
+ assert child_sum == self._index[pos]
2630
+ except:
2631
+ traceback.print_exc(file=sys.stdout)
2632
+ print('len', self._len)
2633
+ print('load', self._load)
2634
+ print('offset', self._offset)
2635
+ print('len_index', len(self._index))
2636
+ print('index', self._index)
2637
+ print('len_maxes', len(self._maxes))
2638
+ print('maxes', self._maxes)
2639
+ print('len_keys', len(self._keys))
2640
+ print('keys', self._keys)
2641
+ print('len_lists', len(self._lists))
2642
+ print('lists', self._lists)
2643
+ raise
2644
+
2645
+
2646
+ SortedListWithKey = SortedKeyList