python-utils 3.8.2__py2.py3-none-any.whl → 3.9.1__py2.py3-none-any.whl
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.
- python_utils/__about__.py +13 -1
- python_utils/__init__.py +81 -32
- python_utils/aio.py +72 -9
- python_utils/containers.py +283 -33
- python_utils/converters.py +143 -63
- python_utils/decorators.py +47 -24
- python_utils/exceptions.py +20 -2
- python_utils/formatters.py +36 -15
- python_utils/generators.py +38 -6
- python_utils/import_.py +34 -14
- python_utils/logger.py +134 -17
- python_utils/loguru.py +36 -1
- python_utils/terminal.py +46 -20
- python_utils/time.py +98 -51
- python_utils/types.py +109 -92
- {python_utils-3.8.2.dist-info → python_utils-3.9.1.dist-info}/METADATA +20 -16
- python_utils-3.9.1.dist-info/RECORD +21 -0
- {python_utils-3.8.2.dist-info → python_utils-3.9.1.dist-info}/WHEEL +1 -1
- python_utils/compat.py +0 -0
- python_utils-3.8.2.dist-info/RECORD +0 -22
- {python_utils-3.8.2.dist-info → python_utils-3.9.1.dist-info}/LICENSE +0 -0
- {python_utils-3.8.2.dist-info → python_utils-3.9.1.dist-info}/top_level.txt +0 -0
python_utils/containers.py
CHANGED
|
@@ -1,3 +1,59 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module provides custom container classes with enhanced functionality.
|
|
3
|
+
|
|
4
|
+
Classes:
|
|
5
|
+
CastedDictBase: Abstract base class for dictionaries that cast keys and
|
|
6
|
+
values.
|
|
7
|
+
CastedDict: Dictionary that casts keys and values to specified types.
|
|
8
|
+
LazyCastedDict: Dictionary that lazily casts values to specified types upon
|
|
9
|
+
access.
|
|
10
|
+
UniqueList: List that only allows unique values, with configurable behavior
|
|
11
|
+
on duplicates.
|
|
12
|
+
SliceableDeque: Deque that supports slicing and enhanced equality checks.
|
|
13
|
+
|
|
14
|
+
Type Aliases:
|
|
15
|
+
KT: Type variable for dictionary keys.
|
|
16
|
+
VT: Type variable for dictionary values.
|
|
17
|
+
DT: Type alias for a dictionary with keys of type KT and values of type VT.
|
|
18
|
+
KT_cast: Type alias for a callable that casts dictionary keys.
|
|
19
|
+
VT_cast: Type alias for a callable that casts dictionary values.
|
|
20
|
+
HT: Type variable for hashable values in UniqueList.
|
|
21
|
+
T: Type variable for generic types.
|
|
22
|
+
DictUpdateArgs: Union type for arguments that can be used to update a
|
|
23
|
+
dictionary.
|
|
24
|
+
OnDuplicate: Literal type for handling duplicate values in UniqueList.
|
|
25
|
+
|
|
26
|
+
Usage:
|
|
27
|
+
- CastedDict and LazyCastedDict can be used to create dictionaries with
|
|
28
|
+
automatic type casting.
|
|
29
|
+
- UniqueList ensures all elements are unique and can raise an error on
|
|
30
|
+
duplicates.
|
|
31
|
+
- SliceableDeque extends deque with slicing support and enhanced equality
|
|
32
|
+
checks.
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
>>> d = CastedDict(int, int)
|
|
36
|
+
>>> d[1] = 2
|
|
37
|
+
>>> d['3'] = '4'
|
|
38
|
+
>>> d.update({'5': '6'})
|
|
39
|
+
>>> d.update([('7', '8')])
|
|
40
|
+
>>> d
|
|
41
|
+
{1: 2, 3: 4, 5: 6, 7: 8}
|
|
42
|
+
|
|
43
|
+
>>> l = UniqueList(1, 2, 3)
|
|
44
|
+
>>> l.append(4)
|
|
45
|
+
>>> l.append(4)
|
|
46
|
+
>>> l.insert(0, 4)
|
|
47
|
+
>>> l.insert(0, 5)
|
|
48
|
+
>>> l[1] = 10
|
|
49
|
+
>>> l
|
|
50
|
+
[5, 10, 2, 3, 4]
|
|
51
|
+
|
|
52
|
+
>>> d = SliceableDeque([1, 2, 3, 4, 5])
|
|
53
|
+
>>> d[1:4]
|
|
54
|
+
SliceableDeque([2, 3, 4])
|
|
55
|
+
"""
|
|
56
|
+
|
|
1
57
|
# pyright: reportIncompatibleMethodOverride=false
|
|
2
58
|
import abc
|
|
3
59
|
import collections
|
|
@@ -35,6 +91,26 @@ OnDuplicate = types.Literal['ignore', 'raise']
|
|
|
35
91
|
|
|
36
92
|
|
|
37
93
|
class CastedDictBase(types.Dict[KT, VT], abc.ABC):
|
|
94
|
+
"""
|
|
95
|
+
Abstract base class for dictionaries that cast keys and values.
|
|
96
|
+
|
|
97
|
+
Attributes:
|
|
98
|
+
_key_cast (KT_cast[KT]): Callable to cast dictionary keys.
|
|
99
|
+
_value_cast (VT_cast[VT]): Callable to cast dictionary values.
|
|
100
|
+
|
|
101
|
+
Methods:
|
|
102
|
+
__init__(key_cast: KT_cast[KT] = None, value_cast: VT_cast[VT] = None,
|
|
103
|
+
*args: DictUpdateArgs[KT, VT], **kwargs: VT) -> None:
|
|
104
|
+
Initializes the dictionary with optional key and value casting
|
|
105
|
+
callables.
|
|
106
|
+
update(*args: DictUpdateArgs[types.Any, types.Any],
|
|
107
|
+
**kwargs: types.Any) -> None:
|
|
108
|
+
Updates the dictionary with the given arguments.
|
|
109
|
+
__setitem__(key: types.Any, value: types.Any) -> None:
|
|
110
|
+
Sets the item in the dictionary, casting the key if a key cast
|
|
111
|
+
callable is provided.
|
|
112
|
+
"""
|
|
113
|
+
|
|
38
114
|
_key_cast: KT_cast[KT]
|
|
39
115
|
_value_cast: VT_cast[VT]
|
|
40
116
|
|
|
@@ -45,6 +121,20 @@ class CastedDictBase(types.Dict[KT, VT], abc.ABC):
|
|
|
45
121
|
*args: DictUpdateArgs[KT, VT],
|
|
46
122
|
**kwargs: VT,
|
|
47
123
|
) -> None:
|
|
124
|
+
"""
|
|
125
|
+
Initializes the CastedDictBase with optional key and value
|
|
126
|
+
casting callables.
|
|
127
|
+
|
|
128
|
+
Args:
|
|
129
|
+
key_cast (KT_cast[KT], optional): Callable to cast
|
|
130
|
+
dictionary keys. Defaults to None.
|
|
131
|
+
value_cast (VT_cast[VT], optional): Callable to cast
|
|
132
|
+
dictionary values. Defaults to None.
|
|
133
|
+
*args (DictUpdateArgs[KT, VT]): Arguments to initialize
|
|
134
|
+
the dictionary.
|
|
135
|
+
**kwargs (VT): Keyword arguments to initialize the
|
|
136
|
+
dictionary.
|
|
137
|
+
"""
|
|
48
138
|
self._value_cast = value_cast
|
|
49
139
|
self._key_cast = key_cast
|
|
50
140
|
self.update(*args, **kwargs)
|
|
@@ -52,6 +142,14 @@ class CastedDictBase(types.Dict[KT, VT], abc.ABC):
|
|
|
52
142
|
def update(
|
|
53
143
|
self, *args: DictUpdateArgs[types.Any, types.Any], **kwargs: types.Any
|
|
54
144
|
) -> None:
|
|
145
|
+
"""
|
|
146
|
+
Updates the dictionary with the given arguments.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
*args (DictUpdateArgs[types.Any, types.Any]): Arguments to update
|
|
150
|
+
the dictionary.
|
|
151
|
+
**kwargs (types.Any): Keyword arguments to update the dictionary.
|
|
152
|
+
"""
|
|
55
153
|
if args:
|
|
56
154
|
kwargs.update(*args)
|
|
57
155
|
|
|
@@ -60,6 +158,14 @@ class CastedDictBase(types.Dict[KT, VT], abc.ABC):
|
|
|
60
158
|
self[key] = value
|
|
61
159
|
|
|
62
160
|
def __setitem__(self, key: types.Any, value: types.Any) -> None:
|
|
161
|
+
"""
|
|
162
|
+
Sets the item in the dictionary, casting the key if a key cast
|
|
163
|
+
callable is provided.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
key (types.Any): The key to set in the dictionary.
|
|
167
|
+
value (types.Any): The value to set in the dictionary.
|
|
168
|
+
"""
|
|
63
169
|
if self._key_cast is not None:
|
|
64
170
|
key = self._key_cast(key)
|
|
65
171
|
|
|
@@ -67,7 +173,7 @@ class CastedDictBase(types.Dict[KT, VT], abc.ABC):
|
|
|
67
173
|
|
|
68
174
|
|
|
69
175
|
class CastedDict(CastedDictBase[KT, VT]):
|
|
70
|
-
|
|
176
|
+
"""
|
|
71
177
|
Custom dictionary that casts keys and values to the specified typing.
|
|
72
178
|
|
|
73
179
|
Note that you can specify the types for mypy and type hinting with:
|
|
@@ -99,9 +205,10 @@ class CastedDict(CastedDictBase[KT, VT]):
|
|
|
99
205
|
>>> d.update([('7', '8')])
|
|
100
206
|
>>> d
|
|
101
207
|
{1: 2, '3': '4', '5': '6', '7': '8'}
|
|
102
|
-
|
|
208
|
+
"""
|
|
103
209
|
|
|
104
210
|
def __setitem__(self, key: typing.Any, value: typing.Any) -> None:
|
|
211
|
+
"""Sets `key` to `cast(value)` in the dictionary."""
|
|
105
212
|
if self._value_cast is not None:
|
|
106
213
|
value = self._value_cast(value)
|
|
107
214
|
|
|
@@ -109,7 +216,7 @@ class CastedDict(CastedDictBase[KT, VT]):
|
|
|
109
216
|
|
|
110
217
|
|
|
111
218
|
class LazyCastedDict(CastedDictBase[KT, VT]):
|
|
112
|
-
|
|
219
|
+
"""
|
|
113
220
|
Custom dictionary that casts keys and lazily casts values to the specified
|
|
114
221
|
typing. Note that the values are cast only when they are accessed and
|
|
115
222
|
are not cached between executions.
|
|
@@ -152,15 +259,33 @@ class LazyCastedDict(CastedDictBase[KT, VT]):
|
|
|
152
259
|
[(1, 2), ('3', '4'), ('5', '6'), ('7', '8')]
|
|
153
260
|
>>> d['3']
|
|
154
261
|
'4'
|
|
155
|
-
|
|
262
|
+
"""
|
|
156
263
|
|
|
157
|
-
def __setitem__(self, key: types.Any, value: types.Any):
|
|
264
|
+
def __setitem__(self, key: types.Any, value: types.Any) -> None:
|
|
265
|
+
"""
|
|
266
|
+
Sets the item in the dictionary, casting the key if a key cast
|
|
267
|
+
callable is provided.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
key (types.Any): The key to set in the dictionary.
|
|
271
|
+
value (types.Any): The value to set in the dictionary.
|
|
272
|
+
"""
|
|
158
273
|
if self._key_cast is not None:
|
|
159
274
|
key = self._key_cast(key)
|
|
160
275
|
|
|
161
276
|
super().__setitem__(key, value)
|
|
162
277
|
|
|
163
278
|
def __getitem__(self, key: types.Any) -> VT:
|
|
279
|
+
"""
|
|
280
|
+
Gets the item from the dictionary, casting the value if a value cast
|
|
281
|
+
callable is provided.
|
|
282
|
+
|
|
283
|
+
Args:
|
|
284
|
+
key (types.Any): The key to get from the dictionary.
|
|
285
|
+
|
|
286
|
+
Returns:
|
|
287
|
+
VT: The value from the dictionary.
|
|
288
|
+
"""
|
|
164
289
|
if self._key_cast is not None:
|
|
165
290
|
key = self._key_cast(key)
|
|
166
291
|
|
|
@@ -171,16 +296,32 @@ class LazyCastedDict(CastedDictBase[KT, VT]):
|
|
|
171
296
|
|
|
172
297
|
return value
|
|
173
298
|
|
|
174
|
-
def items( # type: ignore
|
|
299
|
+
def items( # type: ignore[override]
|
|
175
300
|
self,
|
|
176
301
|
) -> types.Generator[types.Tuple[KT, VT], None, None]:
|
|
302
|
+
"""
|
|
303
|
+
Returns a generator of the dictionary's items, casting the values if a
|
|
304
|
+
value cast callable is provided.
|
|
305
|
+
|
|
306
|
+
Yields:
|
|
307
|
+
types.Generator[types.Tuple[KT, VT], None, None]: A generator of
|
|
308
|
+
the dictionary's items.
|
|
309
|
+
"""
|
|
177
310
|
if self._value_cast is None:
|
|
178
311
|
yield from super().items()
|
|
179
312
|
else:
|
|
180
313
|
for key, value in super().items():
|
|
181
314
|
yield key, self._value_cast(value)
|
|
182
315
|
|
|
183
|
-
def values(self) -> types.Generator[VT, None, None]: # type: ignore
|
|
316
|
+
def values(self) -> types.Generator[VT, None, None]: # type: ignore[override]
|
|
317
|
+
"""
|
|
318
|
+
Returns a generator of the dictionary's values, casting the values if a
|
|
319
|
+
value cast callable is provided.
|
|
320
|
+
|
|
321
|
+
Yields:
|
|
322
|
+
types.Generator[VT, None, None]: A generator of the dictionary's
|
|
323
|
+
values.
|
|
324
|
+
"""
|
|
184
325
|
if self._value_cast is None:
|
|
185
326
|
yield from super().values()
|
|
186
327
|
else:
|
|
@@ -189,7 +330,7 @@ class LazyCastedDict(CastedDictBase[KT, VT]):
|
|
|
189
330
|
|
|
190
331
|
|
|
191
332
|
class UniqueList(types.List[HT]):
|
|
192
|
-
|
|
333
|
+
"""
|
|
193
334
|
A list that only allows unique values. Duplicate values are ignored by
|
|
194
335
|
default, but can be configured to raise an exception instead.
|
|
195
336
|
|
|
@@ -220,7 +361,7 @@ class UniqueList(types.List[HT]):
|
|
|
220
361
|
Traceback (most recent call last):
|
|
221
362
|
...
|
|
222
363
|
ValueError: Duplicate value: 4
|
|
223
|
-
|
|
364
|
+
"""
|
|
224
365
|
|
|
225
366
|
_set: types.Set[HT]
|
|
226
367
|
|
|
@@ -229,6 +370,14 @@ class UniqueList(types.List[HT]):
|
|
|
229
370
|
*args: HT,
|
|
230
371
|
on_duplicate: OnDuplicate = 'ignore',
|
|
231
372
|
):
|
|
373
|
+
"""
|
|
374
|
+
Initializes the UniqueList with optional duplicate handling behavior.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
*args (HT): Initial values for the list.
|
|
378
|
+
on_duplicate (OnDuplicate, optional): Behavior on duplicates.
|
|
379
|
+
Defaults to 'ignore'.
|
|
380
|
+
"""
|
|
232
381
|
self.on_duplicate = on_duplicate
|
|
233
382
|
self._set = set()
|
|
234
383
|
super().__init__()
|
|
@@ -236,6 +385,17 @@ class UniqueList(types.List[HT]):
|
|
|
236
385
|
self.append(arg)
|
|
237
386
|
|
|
238
387
|
def insert(self, index: types.SupportsIndex, value: HT) -> None:
|
|
388
|
+
"""
|
|
389
|
+
Inserts a value at the specified index, ensuring uniqueness.
|
|
390
|
+
|
|
391
|
+
Args:
|
|
392
|
+
index (types.SupportsIndex): The index to insert the value at.
|
|
393
|
+
value (HT): The value to insert.
|
|
394
|
+
|
|
395
|
+
Raises:
|
|
396
|
+
ValueError: If the value is a duplicate and `on_duplicate` is set
|
|
397
|
+
to 'raise'.
|
|
398
|
+
"""
|
|
239
399
|
if value in self._set:
|
|
240
400
|
if self.on_duplicate == 'raise':
|
|
241
401
|
raise ValueError(f'Duplicate value: {value}')
|
|
@@ -246,6 +406,16 @@ class UniqueList(types.List[HT]):
|
|
|
246
406
|
super().insert(index, value)
|
|
247
407
|
|
|
248
408
|
def append(self, value: HT) -> None:
|
|
409
|
+
"""
|
|
410
|
+
Appends a value to the list, ensuring uniqueness.
|
|
411
|
+
|
|
412
|
+
Args:
|
|
413
|
+
value (HT): The value to append.
|
|
414
|
+
|
|
415
|
+
Raises:
|
|
416
|
+
ValueError: If the value is a duplicate and `on_duplicate` is set
|
|
417
|
+
to 'raise'.
|
|
418
|
+
"""
|
|
249
419
|
if value in self._set:
|
|
250
420
|
if self.on_duplicate == 'raise':
|
|
251
421
|
raise ValueError(f'Duplicate value: {value}')
|
|
@@ -255,22 +425,46 @@ class UniqueList(types.List[HT]):
|
|
|
255
425
|
self._set.add(value)
|
|
256
426
|
super().append(value)
|
|
257
427
|
|
|
258
|
-
def __contains__(self, item: HT) -> bool: # type: ignore
|
|
428
|
+
def __contains__(self, item: HT) -> bool: # type: ignore[override]
|
|
429
|
+
"""
|
|
430
|
+
Checks if the list contains the specified item.
|
|
431
|
+
|
|
432
|
+
Args:
|
|
433
|
+
item (HT): The item to check for.
|
|
434
|
+
|
|
435
|
+
Returns:
|
|
436
|
+
bool: True if the item is in the list, False otherwise.
|
|
437
|
+
"""
|
|
259
438
|
return item in self._set
|
|
260
439
|
|
|
261
440
|
@typing.overload
|
|
262
|
-
def __setitem__(
|
|
263
|
-
|
|
441
|
+
def __setitem__(
|
|
442
|
+
self, indices: types.SupportsIndex, values: HT
|
|
443
|
+
) -> None: ...
|
|
264
444
|
|
|
265
445
|
@typing.overload
|
|
266
|
-
def __setitem__(
|
|
267
|
-
|
|
446
|
+
def __setitem__(
|
|
447
|
+
self, indices: slice, values: types.Iterable[HT]
|
|
448
|
+
) -> None: ...
|
|
268
449
|
|
|
269
450
|
def __setitem__(
|
|
270
451
|
self,
|
|
271
452
|
indices: types.Union[slice, types.SupportsIndex],
|
|
272
453
|
values: types.Union[types.Iterable[HT], HT],
|
|
273
454
|
) -> None:
|
|
455
|
+
"""
|
|
456
|
+
Sets the item(s) at the specified index/indices, ensuring uniqueness.
|
|
457
|
+
|
|
458
|
+
Args:
|
|
459
|
+
indices (types.Union[slice, types.SupportsIndex]): The index or
|
|
460
|
+
slice to set the value(s) at.
|
|
461
|
+
values (types.Union[types.Iterable[HT], HT]): The value(s) to set.
|
|
462
|
+
|
|
463
|
+
Raises:
|
|
464
|
+
RuntimeError: If `on_duplicate` is 'ignore' and setting slices.
|
|
465
|
+
ValueError: If the value(s) are duplicates and `on_duplicate` is
|
|
466
|
+
set to 'raise'.
|
|
467
|
+
"""
|
|
274
468
|
if isinstance(indices, slice):
|
|
275
469
|
values = types.cast(types.Iterable[HT], values)
|
|
276
470
|
if self.on_duplicate == 'ignore':
|
|
@@ -301,6 +495,13 @@ class UniqueList(types.List[HT]):
|
|
|
301
495
|
def __delitem__(
|
|
302
496
|
self, index: types.Union[types.SupportsIndex, slice]
|
|
303
497
|
) -> None:
|
|
498
|
+
"""
|
|
499
|
+
Deletes the item(s) at the specified index/indices.
|
|
500
|
+
|
|
501
|
+
Args:
|
|
502
|
+
index (types.Union[types.SupportsIndex, slice]): The index or slice
|
|
503
|
+
to delete the item(s) at.
|
|
504
|
+
"""
|
|
304
505
|
if isinstance(index, slice):
|
|
305
506
|
for value in self[index]:
|
|
306
507
|
self._set.remove(value)
|
|
@@ -312,38 +513,68 @@ class UniqueList(types.List[HT]):
|
|
|
312
513
|
|
|
313
514
|
# Type hinting `collections.deque` does not work consistently between Python
|
|
314
515
|
# runtime, mypy and pyright currently so we have to ignore the errors
|
|
315
|
-
class SliceableDeque(types.Generic[T], collections.deque):
|
|
516
|
+
class SliceableDeque(types.Generic[T], collections.deque[T]):
|
|
517
|
+
"""
|
|
518
|
+
A deque that supports slicing and enhanced equality checks.
|
|
519
|
+
|
|
520
|
+
Methods:
|
|
521
|
+
__getitem__(index: types.Union[types.SupportsIndex, slice]) ->
|
|
522
|
+
types.Union[T, 'SliceableDeque[T]']:
|
|
523
|
+
Returns the item or slice at the given index.
|
|
524
|
+
__eq__(other: types.Any) -> bool:
|
|
525
|
+
Checks equality with another object, allowing for comparison with
|
|
526
|
+
lists, tuples, and sets.
|
|
527
|
+
pop(index: int = -1) -> T:
|
|
528
|
+
Removes and returns the item at the given index. Only supports
|
|
529
|
+
index 0 and the last index.
|
|
530
|
+
"""
|
|
531
|
+
|
|
316
532
|
@typing.overload
|
|
317
|
-
def __getitem__(self, index: types.SupportsIndex) -> T:
|
|
318
|
-
...
|
|
533
|
+
def __getitem__(self, index: types.SupportsIndex) -> T: ...
|
|
319
534
|
|
|
320
535
|
@typing.overload
|
|
321
|
-
def __getitem__(self, index: slice) -> 'SliceableDeque[T]':
|
|
322
|
-
...
|
|
536
|
+
def __getitem__(self, index: slice) -> 'SliceableDeque[T]': ...
|
|
323
537
|
|
|
324
538
|
def __getitem__(
|
|
325
539
|
self, index: types.Union[types.SupportsIndex, slice]
|
|
326
540
|
) -> types.Union[T, 'SliceableDeque[T]']:
|
|
327
|
-
|
|
541
|
+
"""
|
|
328
542
|
Return the item or slice at the given index.
|
|
329
543
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
544
|
+
Args:
|
|
545
|
+
index (types.Union[types.SupportsIndex, slice]): The index or
|
|
546
|
+
slice to retrieve.
|
|
547
|
+
|
|
548
|
+
Returns:
|
|
549
|
+
types.Union[T, 'SliceableDeque[T]']: The item or slice at the
|
|
550
|
+
given index.
|
|
333
551
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
552
|
+
Examples:
|
|
553
|
+
>>> d = SliceableDeque[int]([1, 2, 3, 4, 5])
|
|
554
|
+
>>> d[1:4]
|
|
555
|
+
SliceableDeque([2, 3, 4])
|
|
337
556
|
|
|
338
|
-
|
|
557
|
+
>>> d = SliceableDeque[str](['a', 'b', 'c'])
|
|
558
|
+
>>> d[-2:]
|
|
559
|
+
SliceableDeque(['b', 'c'])
|
|
560
|
+
"""
|
|
339
561
|
if isinstance(index, slice):
|
|
340
562
|
start, stop, step = index.indices(len(self))
|
|
341
563
|
return self.__class__(self[i] for i in range(start, stop, step))
|
|
342
564
|
else:
|
|
343
|
-
return
|
|
565
|
+
return super().__getitem__(index)
|
|
344
566
|
|
|
345
567
|
def __eq__(self, other: types.Any) -> bool:
|
|
346
|
-
|
|
568
|
+
"""
|
|
569
|
+
Checks equality with another object, allowing for comparison with
|
|
570
|
+
lists, tuples, and sets.
|
|
571
|
+
|
|
572
|
+
Args:
|
|
573
|
+
other (types.Any): The object to compare with.
|
|
574
|
+
|
|
575
|
+
Returns:
|
|
576
|
+
bool: True if the objects are equal, False otherwise.
|
|
577
|
+
"""
|
|
347
578
|
if isinstance(other, list):
|
|
348
579
|
return list(self) == other
|
|
349
580
|
elif isinstance(other, tuple):
|
|
@@ -354,12 +585,31 @@ class SliceableDeque(types.Generic[T], collections.deque): # type: ignore
|
|
|
354
585
|
return super().__eq__(other)
|
|
355
586
|
|
|
356
587
|
def pop(self, index: int = -1) -> T:
|
|
357
|
-
|
|
358
|
-
|
|
588
|
+
"""
|
|
589
|
+
Removes and returns the item at the given index. Only supports index 0
|
|
590
|
+
and the last index.
|
|
591
|
+
|
|
592
|
+
Args:
|
|
593
|
+
index (int, optional): The index of the item to remove. Defaults to
|
|
594
|
+
-1.
|
|
595
|
+
|
|
596
|
+
Returns:
|
|
597
|
+
T: The removed item.
|
|
598
|
+
|
|
599
|
+
Raises:
|
|
600
|
+
IndexError: If the index is not 0 or the last index.
|
|
601
|
+
|
|
602
|
+
Examples:
|
|
603
|
+
>>> d = SliceableDeque([1, 2, 3])
|
|
604
|
+
>>> d.pop(0)
|
|
605
|
+
1
|
|
606
|
+
>>> d.pop()
|
|
607
|
+
3
|
|
608
|
+
"""
|
|
359
609
|
if index == 0:
|
|
360
|
-
return
|
|
610
|
+
return super().popleft()
|
|
361
611
|
elif index in {-1, len(self) - 1}:
|
|
362
|
-
return
|
|
612
|
+
return super().pop()
|
|
363
613
|
else:
|
|
364
614
|
raise IndexError(
|
|
365
615
|
'Only index 0 and the last index (`N-1` or `-1`) '
|