orionis 0.712.0__py3-none-any.whl → 0.714.0__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.
- orionis/metadata/framework.py +6 -1
- orionis/support/collections/__init__.py +0 -0
- orionis/support/collections/collection.py +1381 -0
- orionis/support/collections/contracts/__init__.py +0 -0
- orionis/support/collections/contracts/collection.py +766 -0
- {orionis-0.712.0.dist-info → orionis-0.714.0.dist-info}/METADATA +6 -1
- {orionis-0.712.0.dist-info → orionis-0.714.0.dist-info}/RECORD +10 -6
- {orionis-0.712.0.dist-info → orionis-0.714.0.dist-info}/WHEEL +0 -0
- {orionis-0.712.0.dist-info → orionis-0.714.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.712.0.dist-info → orionis-0.714.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,1381 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import operator
|
|
3
|
+
import random
|
|
4
|
+
from functools import reduce
|
|
5
|
+
from typing import Any, Callable, Dict, List, Optional, Union
|
|
6
|
+
from dotty_dict import Dotty, dotty
|
|
7
|
+
from orionis.support.collections.contracts.collection import ICollection
|
|
8
|
+
|
|
9
|
+
class Collection(ICollection):
|
|
10
|
+
|
|
11
|
+
def __init__(self, items: Optional[List[Any]] = None) -> None:
|
|
12
|
+
"""Initialize a new collection instance.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
items : list, optional
|
|
17
|
+
Initial items for the collection, by default None
|
|
18
|
+
"""
|
|
19
|
+
self._items = items or []
|
|
20
|
+
self.__appends__ = []
|
|
21
|
+
|
|
22
|
+
def take(self, number: int) -> 'Collection':
|
|
23
|
+
"""Take a specific number of results from the items.
|
|
24
|
+
|
|
25
|
+
Parameters
|
|
26
|
+
----------
|
|
27
|
+
number : int
|
|
28
|
+
The number of results to take. If negative, takes from the end.
|
|
29
|
+
|
|
30
|
+
Returns
|
|
31
|
+
-------
|
|
32
|
+
Collection
|
|
33
|
+
A new collection with the specified number of items.
|
|
34
|
+
"""
|
|
35
|
+
if number < 0:
|
|
36
|
+
return self[number:]
|
|
37
|
+
|
|
38
|
+
return self[:number]
|
|
39
|
+
|
|
40
|
+
def first(self, callback: Optional[Callable] = None) -> Any:
|
|
41
|
+
"""Get the first result in the items.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
callback : callable, optional
|
|
46
|
+
Filter function to apply before returning the first item, by default None
|
|
47
|
+
|
|
48
|
+
Returns
|
|
49
|
+
-------
|
|
50
|
+
mixed
|
|
51
|
+
The first item in the collection, or None if empty.
|
|
52
|
+
"""
|
|
53
|
+
filtered = self
|
|
54
|
+
if callback:
|
|
55
|
+
filtered = self.filter(callback)
|
|
56
|
+
response = None
|
|
57
|
+
if filtered:
|
|
58
|
+
response = filtered[0]
|
|
59
|
+
return response
|
|
60
|
+
|
|
61
|
+
def last(self, callback: Optional[Callable] = None) -> Any:
|
|
62
|
+
"""Get the last result in the items.
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
callback : callable, optional
|
|
67
|
+
Filter function to apply before returning the last item, by default None
|
|
68
|
+
|
|
69
|
+
Returns
|
|
70
|
+
-------
|
|
71
|
+
mixed
|
|
72
|
+
The last item in the collection.
|
|
73
|
+
"""
|
|
74
|
+
filtered = self
|
|
75
|
+
if callback:
|
|
76
|
+
filtered = self.filter(callback)
|
|
77
|
+
return filtered[-1]
|
|
78
|
+
|
|
79
|
+
def all(self) -> List[Any]:
|
|
80
|
+
"""Get all items in the collection.
|
|
81
|
+
|
|
82
|
+
Returns
|
|
83
|
+
-------
|
|
84
|
+
list
|
|
85
|
+
All items in the collection.
|
|
86
|
+
"""
|
|
87
|
+
return self._items
|
|
88
|
+
|
|
89
|
+
def avg(self, key: Optional[str] = None) -> float:
|
|
90
|
+
"""Calculate the average of the items.
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
key : str, optional
|
|
95
|
+
The key to use for calculating the average of values, by default None
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
float
|
|
100
|
+
The average value.
|
|
101
|
+
"""
|
|
102
|
+
result = 0
|
|
103
|
+
items = self.__getValue(key) or self._items
|
|
104
|
+
try:
|
|
105
|
+
result = sum(items) / len(items)
|
|
106
|
+
except TypeError:
|
|
107
|
+
pass
|
|
108
|
+
return result
|
|
109
|
+
|
|
110
|
+
def max(self, key: Optional[str] = None) -> Any:
|
|
111
|
+
"""Get the maximum value from the items.
|
|
112
|
+
|
|
113
|
+
Parameters
|
|
114
|
+
----------
|
|
115
|
+
key : str, optional
|
|
116
|
+
The key to use for finding the maximum value, by default None
|
|
117
|
+
|
|
118
|
+
Returns
|
|
119
|
+
-------
|
|
120
|
+
mixed
|
|
121
|
+
The maximum value.
|
|
122
|
+
"""
|
|
123
|
+
result = 0
|
|
124
|
+
items = self.__getValue(key) or self._items
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
return max(items)
|
|
128
|
+
except (TypeError, ValueError):
|
|
129
|
+
pass
|
|
130
|
+
return result
|
|
131
|
+
|
|
132
|
+
def min(self, key: Optional[str] = None) -> Any:
|
|
133
|
+
"""Get the minimum value from the items.
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
key : str, optional
|
|
138
|
+
The key to use for finding the minimum value, by default None
|
|
139
|
+
|
|
140
|
+
Returns
|
|
141
|
+
-------
|
|
142
|
+
mixed
|
|
143
|
+
The minimum value.
|
|
144
|
+
"""
|
|
145
|
+
result = 0
|
|
146
|
+
items = self.__getValue(key) or self._items
|
|
147
|
+
|
|
148
|
+
try:
|
|
149
|
+
return min(items)
|
|
150
|
+
except (TypeError, ValueError):
|
|
151
|
+
pass
|
|
152
|
+
return result
|
|
153
|
+
|
|
154
|
+
def chunk(self, size: int) -> 'Collection':
|
|
155
|
+
"""Break the collection into multiple smaller collections of a given size.
|
|
156
|
+
|
|
157
|
+
Parameters
|
|
158
|
+
----------
|
|
159
|
+
size : int
|
|
160
|
+
The number of values in each chunk.
|
|
161
|
+
|
|
162
|
+
Returns
|
|
163
|
+
-------
|
|
164
|
+
Collection
|
|
165
|
+
A new collection containing the chunks.
|
|
166
|
+
"""
|
|
167
|
+
items = []
|
|
168
|
+
for i in range(0, self.count(), size):
|
|
169
|
+
items.append(self[i : i + size])
|
|
170
|
+
return self.__class__(items)
|
|
171
|
+
|
|
172
|
+
def collapse(self) -> 'Collection':
|
|
173
|
+
"""Collapse the collection of arrays into a single, flat collection.
|
|
174
|
+
|
|
175
|
+
Returns
|
|
176
|
+
-------
|
|
177
|
+
Collection
|
|
178
|
+
A new flattened collection.
|
|
179
|
+
"""
|
|
180
|
+
items = []
|
|
181
|
+
for item in self:
|
|
182
|
+
items += self.__getItems(item)
|
|
183
|
+
return self.__class__(items)
|
|
184
|
+
|
|
185
|
+
def contains(self, key: Union[str, Callable], value: Any = None) -> bool:
|
|
186
|
+
"""Determine if the collection contains a given item.
|
|
187
|
+
|
|
188
|
+
Parameters
|
|
189
|
+
----------
|
|
190
|
+
key : mixed
|
|
191
|
+
The key or callback function to check for
|
|
192
|
+
value : mixed, optional
|
|
193
|
+
The value to match when key is a string, by default None
|
|
194
|
+
|
|
195
|
+
Returns
|
|
196
|
+
-------
|
|
197
|
+
bool
|
|
198
|
+
True if the item is found, False otherwise.
|
|
199
|
+
"""
|
|
200
|
+
if value:
|
|
201
|
+
return self.contains(lambda x: self.__dataGet(x, key) == value)
|
|
202
|
+
|
|
203
|
+
if self.__checkIsCallable(key, raise_exception=False):
|
|
204
|
+
return self.first(key) is not None
|
|
205
|
+
|
|
206
|
+
return key in self
|
|
207
|
+
|
|
208
|
+
def count(self) -> int:
|
|
209
|
+
"""Get the number of items in the collection.
|
|
210
|
+
|
|
211
|
+
Returns
|
|
212
|
+
-------
|
|
213
|
+
int
|
|
214
|
+
The number of items.
|
|
215
|
+
"""
|
|
216
|
+
return len(self._items)
|
|
217
|
+
|
|
218
|
+
def diff(self, items: Union[List[Any], 'Collection']) -> 'Collection':
|
|
219
|
+
"""Get the items that are not present in the given collection.
|
|
220
|
+
|
|
221
|
+
Parameters
|
|
222
|
+
----------
|
|
223
|
+
items : mixed
|
|
224
|
+
The items to diff against
|
|
225
|
+
|
|
226
|
+
Returns
|
|
227
|
+
-------
|
|
228
|
+
Collection
|
|
229
|
+
A new collection with the difference.
|
|
230
|
+
"""
|
|
231
|
+
items = self.__getItems(items)
|
|
232
|
+
return self.__class__([x for x in self if x not in items])
|
|
233
|
+
|
|
234
|
+
def each(self, callback: Callable) -> 'Collection':
|
|
235
|
+
"""Iterate over the items in the collection and pass each item to the given callback.
|
|
236
|
+
|
|
237
|
+
Parameters
|
|
238
|
+
----------
|
|
239
|
+
callback : callable
|
|
240
|
+
The callback function to apply to each item
|
|
241
|
+
|
|
242
|
+
Returns
|
|
243
|
+
-------
|
|
244
|
+
Collection
|
|
245
|
+
The current collection instance.
|
|
246
|
+
"""
|
|
247
|
+
self.__checkIsCallable(callback)
|
|
248
|
+
|
|
249
|
+
for k, v in enumerate(self):
|
|
250
|
+
result = callback(v)
|
|
251
|
+
if not result:
|
|
252
|
+
break
|
|
253
|
+
self[k] = result
|
|
254
|
+
|
|
255
|
+
return self
|
|
256
|
+
|
|
257
|
+
def every(self, callback: Callable) -> bool:
|
|
258
|
+
"""Determine if all items pass the given callback test.
|
|
259
|
+
|
|
260
|
+
Parameters
|
|
261
|
+
----------
|
|
262
|
+
callback : callable
|
|
263
|
+
The callback function to test each item
|
|
264
|
+
|
|
265
|
+
Returns
|
|
266
|
+
-------
|
|
267
|
+
bool
|
|
268
|
+
True if all items pass the test, False otherwise.
|
|
269
|
+
"""
|
|
270
|
+
self.__checkIsCallable(callback)
|
|
271
|
+
return all(callback(x) for x in self)
|
|
272
|
+
|
|
273
|
+
def filter(self, callback: Callable) -> 'Collection':
|
|
274
|
+
"""Filter the collection using the given callback.
|
|
275
|
+
|
|
276
|
+
Parameters
|
|
277
|
+
----------
|
|
278
|
+
callback : callable
|
|
279
|
+
The callback function to filter items
|
|
280
|
+
|
|
281
|
+
Returns
|
|
282
|
+
-------
|
|
283
|
+
Collection
|
|
284
|
+
A new filtered collection.
|
|
285
|
+
"""
|
|
286
|
+
self.__checkIsCallable(callback)
|
|
287
|
+
return self.__class__(list(filter(callback, self)))
|
|
288
|
+
|
|
289
|
+
def flatten(self) -> 'Collection': # NOSONAR
|
|
290
|
+
"""Flatten a multi-dimensional collection into a single dimension.
|
|
291
|
+
|
|
292
|
+
Returns
|
|
293
|
+
-------
|
|
294
|
+
Collection
|
|
295
|
+
A new flattened collection.
|
|
296
|
+
"""
|
|
297
|
+
def _flatten(items):
|
|
298
|
+
if isinstance(items, dict):
|
|
299
|
+
for v in items.values():
|
|
300
|
+
for x in _flatten(v):
|
|
301
|
+
yield x
|
|
302
|
+
elif isinstance(items, list):
|
|
303
|
+
for i in items:
|
|
304
|
+
for j in _flatten(i):
|
|
305
|
+
yield j
|
|
306
|
+
else:
|
|
307
|
+
yield items
|
|
308
|
+
|
|
309
|
+
return self.__class__(list(_flatten(self._items)))
|
|
310
|
+
|
|
311
|
+
def forget(self, *keys: Any) -> 'Collection':
|
|
312
|
+
"""Remove an item from the collection by key.
|
|
313
|
+
|
|
314
|
+
Parameters
|
|
315
|
+
----------
|
|
316
|
+
*keys : mixed
|
|
317
|
+
The keys to remove from the collection
|
|
318
|
+
|
|
319
|
+
Returns
|
|
320
|
+
-------
|
|
321
|
+
Collection
|
|
322
|
+
The current collection instance.
|
|
323
|
+
"""
|
|
324
|
+
keys = sorted(keys, reverse=True)
|
|
325
|
+
|
|
326
|
+
for key in keys:
|
|
327
|
+
del self[key]
|
|
328
|
+
|
|
329
|
+
return self
|
|
330
|
+
|
|
331
|
+
def forPage(self, page: int, number: int) -> 'Collection':
|
|
332
|
+
"""Slice the underlying collection array for pagination.
|
|
333
|
+
|
|
334
|
+
Parameters
|
|
335
|
+
----------
|
|
336
|
+
page : int
|
|
337
|
+
The page number
|
|
338
|
+
number : int
|
|
339
|
+
Number of items per page
|
|
340
|
+
|
|
341
|
+
Returns
|
|
342
|
+
-------
|
|
343
|
+
Collection
|
|
344
|
+
A new collection with the paginated items.
|
|
345
|
+
"""
|
|
346
|
+
return self.__class__(self[page:number])
|
|
347
|
+
|
|
348
|
+
def get(self, key: Any, default: Any = None) -> Any:
|
|
349
|
+
"""Get an item from the collection by key.
|
|
350
|
+
|
|
351
|
+
Parameters
|
|
352
|
+
----------
|
|
353
|
+
key : mixed
|
|
354
|
+
The key to retrieve
|
|
355
|
+
default : mixed, optional
|
|
356
|
+
The default value to return if key not found, by default None
|
|
357
|
+
|
|
358
|
+
Returns
|
|
359
|
+
-------
|
|
360
|
+
mixed
|
|
361
|
+
The item at the specified key or default value.
|
|
362
|
+
"""
|
|
363
|
+
try:
|
|
364
|
+
return self[key]
|
|
365
|
+
except IndexError:
|
|
366
|
+
pass
|
|
367
|
+
|
|
368
|
+
return self.__value(default)
|
|
369
|
+
|
|
370
|
+
def implode(self, glue: str = ",", key: Optional[str] = None) -> str:
|
|
371
|
+
"""Join all items from the collection using a string.
|
|
372
|
+
|
|
373
|
+
Parameters
|
|
374
|
+
----------
|
|
375
|
+
glue : str, optional
|
|
376
|
+
The string to use for joining, by default ","
|
|
377
|
+
key : str, optional
|
|
378
|
+
The key to pluck from items before joining, by default None
|
|
379
|
+
|
|
380
|
+
Returns
|
|
381
|
+
-------
|
|
382
|
+
str
|
|
383
|
+
The joined string.
|
|
384
|
+
"""
|
|
385
|
+
first = self.first()
|
|
386
|
+
if not isinstance(first, str) and key:
|
|
387
|
+
return glue.join(self.pluck(key))
|
|
388
|
+
return glue.join([str(x) for x in self])
|
|
389
|
+
|
|
390
|
+
def isEmpty(self) -> bool:
|
|
391
|
+
"""Determine if the collection is empty.
|
|
392
|
+
|
|
393
|
+
Returns
|
|
394
|
+
-------
|
|
395
|
+
bool
|
|
396
|
+
True if the collection is empty, False otherwise.
|
|
397
|
+
"""
|
|
398
|
+
return not self
|
|
399
|
+
|
|
400
|
+
def map(self, callback: Callable) -> 'Collection':
|
|
401
|
+
"""Run a map over each of the items.
|
|
402
|
+
|
|
403
|
+
Parameters
|
|
404
|
+
----------
|
|
405
|
+
callback : callable
|
|
406
|
+
The callback function to apply to each item
|
|
407
|
+
|
|
408
|
+
Returns
|
|
409
|
+
-------
|
|
410
|
+
Collection
|
|
411
|
+
A new collection with the mapped items.
|
|
412
|
+
"""
|
|
413
|
+
self.__checkIsCallable(callback)
|
|
414
|
+
items = [callback(x) for x in self]
|
|
415
|
+
return self.__class__(items)
|
|
416
|
+
|
|
417
|
+
def mapInto(self, cls: type, method: Optional[str] = None, **kwargs: Any) -> 'Collection':
|
|
418
|
+
"""Map items into instances of the given class.
|
|
419
|
+
|
|
420
|
+
Parameters
|
|
421
|
+
----------
|
|
422
|
+
cls : class
|
|
423
|
+
The class to map items into
|
|
424
|
+
method : str, optional
|
|
425
|
+
The method to call on the class, by default None
|
|
426
|
+
**kwargs : dict
|
|
427
|
+
Additional keyword arguments to pass to the constructor or method
|
|
428
|
+
|
|
429
|
+
Returns
|
|
430
|
+
-------
|
|
431
|
+
Collection
|
|
432
|
+
A new collection with the mapped instances.
|
|
433
|
+
"""
|
|
434
|
+
results = []
|
|
435
|
+
for item in self:
|
|
436
|
+
if method:
|
|
437
|
+
results.append(getattr(cls, method)(item, **kwargs))
|
|
438
|
+
else:
|
|
439
|
+
results.append(cls(item))
|
|
440
|
+
|
|
441
|
+
return self.__class__(results)
|
|
442
|
+
|
|
443
|
+
def merge(self, items: Union[List[Any], 'Collection']) -> 'Collection':
|
|
444
|
+
"""Merge the collection with the given items.
|
|
445
|
+
|
|
446
|
+
Parameters
|
|
447
|
+
----------
|
|
448
|
+
items : list or Collection
|
|
449
|
+
The items to merge into the collection
|
|
450
|
+
|
|
451
|
+
Returns
|
|
452
|
+
-------
|
|
453
|
+
Collection
|
|
454
|
+
The current collection instance.
|
|
455
|
+
|
|
456
|
+
Raises
|
|
457
|
+
------
|
|
458
|
+
ValueError
|
|
459
|
+
If items cannot be merged due to incompatible types.
|
|
460
|
+
"""
|
|
461
|
+
if not isinstance(items, list):
|
|
462
|
+
raise ValueError("Unable to merge uncompatible types")
|
|
463
|
+
|
|
464
|
+
items = self.__getItems(items)
|
|
465
|
+
|
|
466
|
+
self._items += items
|
|
467
|
+
return self
|
|
468
|
+
|
|
469
|
+
def pluck(self, value: str, key: Optional[str] = None) -> 'Collection': # NOSONAR
|
|
470
|
+
"""Get the values of a given key from all items.
|
|
471
|
+
|
|
472
|
+
Parameters
|
|
473
|
+
----------
|
|
474
|
+
value : str
|
|
475
|
+
The key to pluck from each item
|
|
476
|
+
key : str, optional
|
|
477
|
+
The key to use as the result key, by default None
|
|
478
|
+
|
|
479
|
+
Returns
|
|
480
|
+
-------
|
|
481
|
+
Collection
|
|
482
|
+
A new collection with the plucked values.
|
|
483
|
+
"""
|
|
484
|
+
if key:
|
|
485
|
+
attributes = {}
|
|
486
|
+
else:
|
|
487
|
+
attributes = []
|
|
488
|
+
|
|
489
|
+
if isinstance(self._items, dict):
|
|
490
|
+
return Collection([self._items.get(value)])
|
|
491
|
+
|
|
492
|
+
for item in self:
|
|
493
|
+
if isinstance(item, dict):
|
|
494
|
+
iterable = item.items()
|
|
495
|
+
elif hasattr(item, "serialize"):
|
|
496
|
+
iterable = item.serialize().items()
|
|
497
|
+
else:
|
|
498
|
+
iterable = self.all().items()
|
|
499
|
+
|
|
500
|
+
for k, v in iterable:
|
|
501
|
+
if k == value:
|
|
502
|
+
if key:
|
|
503
|
+
attributes[self.__dataGet(item, key)] = self.__dataGet(
|
|
504
|
+
item, value
|
|
505
|
+
)
|
|
506
|
+
else:
|
|
507
|
+
attributes.append(v)
|
|
508
|
+
|
|
509
|
+
return Collection(attributes)
|
|
510
|
+
|
|
511
|
+
def pop(self) -> Any:
|
|
512
|
+
"""Remove and return the last item from the collection.
|
|
513
|
+
|
|
514
|
+
Returns
|
|
515
|
+
-------
|
|
516
|
+
mixed
|
|
517
|
+
The last item from the collection.
|
|
518
|
+
"""
|
|
519
|
+
last = self._items.pop()
|
|
520
|
+
return last
|
|
521
|
+
|
|
522
|
+
def prepend(self, value: Any) -> 'Collection':
|
|
523
|
+
"""Add an item to the beginning of the collection.
|
|
524
|
+
|
|
525
|
+
Parameters
|
|
526
|
+
----------
|
|
527
|
+
value : mixed
|
|
528
|
+
The value to prepend
|
|
529
|
+
|
|
530
|
+
Returns
|
|
531
|
+
-------
|
|
532
|
+
Collection
|
|
533
|
+
The current collection instance.
|
|
534
|
+
"""
|
|
535
|
+
self._items.insert(0, value)
|
|
536
|
+
return self
|
|
537
|
+
|
|
538
|
+
def pull(self, key: Any) -> Any:
|
|
539
|
+
"""Remove an item from the collection and return it.
|
|
540
|
+
|
|
541
|
+
Parameters
|
|
542
|
+
----------
|
|
543
|
+
key : mixed
|
|
544
|
+
The key of the item to remove
|
|
545
|
+
|
|
546
|
+
Returns
|
|
547
|
+
-------
|
|
548
|
+
mixed
|
|
549
|
+
The removed item.
|
|
550
|
+
"""
|
|
551
|
+
value = self.get(key)
|
|
552
|
+
self.forget(key)
|
|
553
|
+
return value
|
|
554
|
+
|
|
555
|
+
def push(self, value: Any) -> 'Collection':
|
|
556
|
+
"""Add an item to the end of the collection.
|
|
557
|
+
|
|
558
|
+
Parameters
|
|
559
|
+
----------
|
|
560
|
+
value : mixed
|
|
561
|
+
The value to add
|
|
562
|
+
|
|
563
|
+
Returns
|
|
564
|
+
-------
|
|
565
|
+
Collection
|
|
566
|
+
The current collection instance.
|
|
567
|
+
"""
|
|
568
|
+
self._items.append(value)
|
|
569
|
+
return self
|
|
570
|
+
|
|
571
|
+
def put(self, key: Any, value: Any) -> 'Collection':
|
|
572
|
+
"""Put an item in the collection by key.
|
|
573
|
+
|
|
574
|
+
Parameters
|
|
575
|
+
----------
|
|
576
|
+
key : mixed
|
|
577
|
+
The key to set
|
|
578
|
+
value : mixed
|
|
579
|
+
The value to set
|
|
580
|
+
|
|
581
|
+
Returns
|
|
582
|
+
-------
|
|
583
|
+
Collection
|
|
584
|
+
The current collection instance.
|
|
585
|
+
"""
|
|
586
|
+
self[key] = value
|
|
587
|
+
return self
|
|
588
|
+
|
|
589
|
+
def random(self, count: Optional[int] = None) -> Union[Any, 'Collection', None]:
|
|
590
|
+
"""Get one or more random items from the collection.
|
|
591
|
+
|
|
592
|
+
Parameters
|
|
593
|
+
----------
|
|
594
|
+
count : int, optional
|
|
595
|
+
The number of items to return, by default None
|
|
596
|
+
|
|
597
|
+
Returns
|
|
598
|
+
-------
|
|
599
|
+
mixed or Collection
|
|
600
|
+
A single random item if count is None, otherwise a Collection.
|
|
601
|
+
|
|
602
|
+
Raises
|
|
603
|
+
------
|
|
604
|
+
ValueError
|
|
605
|
+
If count is greater than collection length.
|
|
606
|
+
"""
|
|
607
|
+
collection_count = self.count()
|
|
608
|
+
if collection_count == 0:
|
|
609
|
+
return None
|
|
610
|
+
elif count and count > collection_count:
|
|
611
|
+
raise ValueError("count argument must be inferior to collection length.")
|
|
612
|
+
elif count:
|
|
613
|
+
self._items = random.sample(self._items, k=count)
|
|
614
|
+
return self
|
|
615
|
+
else:
|
|
616
|
+
return random.choice(self._items)
|
|
617
|
+
|
|
618
|
+
def reduce(self, callback: Callable, initial: Any = 0) -> Any:
|
|
619
|
+
"""Reduce the collection to a single value.
|
|
620
|
+
|
|
621
|
+
Parameters
|
|
622
|
+
----------
|
|
623
|
+
callback : callable
|
|
624
|
+
The callback function for reduction
|
|
625
|
+
initial : mixed, optional
|
|
626
|
+
The initial value, by default 0
|
|
627
|
+
|
|
628
|
+
Returns
|
|
629
|
+
-------
|
|
630
|
+
mixed
|
|
631
|
+
The reduced value.
|
|
632
|
+
"""
|
|
633
|
+
return reduce(callback, self, initial)
|
|
634
|
+
|
|
635
|
+
def reject(self, callback: Callable) -> 'Collection':
|
|
636
|
+
"""Filter items that do not pass a given truth test.
|
|
637
|
+
|
|
638
|
+
Parameters
|
|
639
|
+
----------
|
|
640
|
+
callback : callable
|
|
641
|
+
The callback function to test items
|
|
642
|
+
|
|
643
|
+
Returns
|
|
644
|
+
-------
|
|
645
|
+
Collection
|
|
646
|
+
The current collection instance.
|
|
647
|
+
"""
|
|
648
|
+
self.__checkIsCallable(callback)
|
|
649
|
+
|
|
650
|
+
items = self.__getValue(callback) or self._items
|
|
651
|
+
self._items = items
|
|
652
|
+
return self
|
|
653
|
+
|
|
654
|
+
def reverse(self) -> 'Collection':
|
|
655
|
+
"""Reverse items order in the collection.
|
|
656
|
+
|
|
657
|
+
Returns
|
|
658
|
+
-------
|
|
659
|
+
Collection
|
|
660
|
+
The current collection instance.
|
|
661
|
+
"""
|
|
662
|
+
self._items = self[::-1]
|
|
663
|
+
return self
|
|
664
|
+
|
|
665
|
+
def serialize(self) -> List[Any]:
|
|
666
|
+
"""Get the collection items as a serialized array.
|
|
667
|
+
|
|
668
|
+
Returns
|
|
669
|
+
-------
|
|
670
|
+
list
|
|
671
|
+
The serialized items.
|
|
672
|
+
"""
|
|
673
|
+
def _serialize(item):
|
|
674
|
+
if self.__appends__:
|
|
675
|
+
item.set_appends(self.__appends__)
|
|
676
|
+
|
|
677
|
+
if hasattr(item, "serialize"):
|
|
678
|
+
return item.serialize()
|
|
679
|
+
elif hasattr(item, "to_dict"):
|
|
680
|
+
return item.to_dict()
|
|
681
|
+
return item
|
|
682
|
+
|
|
683
|
+
return list(map(_serialize, self))
|
|
684
|
+
|
|
685
|
+
def addRelation(self, result: Optional[Dict[str, Any]] = None) -> 'Collection':
|
|
686
|
+
"""Add relation data to all models in the collection.
|
|
687
|
+
|
|
688
|
+
Parameters
|
|
689
|
+
----------
|
|
690
|
+
result : dict, optional
|
|
691
|
+
The relation data to add, by default None
|
|
692
|
+
|
|
693
|
+
Returns
|
|
694
|
+
-------
|
|
695
|
+
Collection
|
|
696
|
+
The current collection instance.
|
|
697
|
+
"""
|
|
698
|
+
for model in self._items:
|
|
699
|
+
model.add_relations(result or {})
|
|
700
|
+
|
|
701
|
+
return self
|
|
702
|
+
|
|
703
|
+
def shift(self) -> Any:
|
|
704
|
+
"""Remove and return the first item from the collection.
|
|
705
|
+
|
|
706
|
+
Returns
|
|
707
|
+
-------
|
|
708
|
+
mixed
|
|
709
|
+
The first item from the collection.
|
|
710
|
+
"""
|
|
711
|
+
return self.pull(0)
|
|
712
|
+
|
|
713
|
+
def sort(self, key: Optional[str] = None) -> 'Collection':
|
|
714
|
+
"""Sort through each item with a callback.
|
|
715
|
+
|
|
716
|
+
Parameters
|
|
717
|
+
----------
|
|
718
|
+
key : str, optional
|
|
719
|
+
The key to sort by, by default None
|
|
720
|
+
|
|
721
|
+
Returns
|
|
722
|
+
-------
|
|
723
|
+
Collection
|
|
724
|
+
The current collection instance.
|
|
725
|
+
"""
|
|
726
|
+
if key:
|
|
727
|
+
self._items.sort(key=lambda x: x[key], reverse=False)
|
|
728
|
+
return self
|
|
729
|
+
|
|
730
|
+
self._items = sorted(self)
|
|
731
|
+
return self
|
|
732
|
+
|
|
733
|
+
def sum(self, key: Optional[str] = None) -> float:
|
|
734
|
+
"""Get the sum of the given values.
|
|
735
|
+
|
|
736
|
+
Parameters
|
|
737
|
+
----------
|
|
738
|
+
key : str, optional
|
|
739
|
+
The key to sum by, by default None
|
|
740
|
+
|
|
741
|
+
Returns
|
|
742
|
+
-------
|
|
743
|
+
float
|
|
744
|
+
The sum of the values.
|
|
745
|
+
"""
|
|
746
|
+
result = 0
|
|
747
|
+
items = self.__getValue(key) or self._items
|
|
748
|
+
try:
|
|
749
|
+
result = sum(items)
|
|
750
|
+
except TypeError:
|
|
751
|
+
pass
|
|
752
|
+
return result
|
|
753
|
+
|
|
754
|
+
def toJson(self, **kwargs: Any) -> str:
|
|
755
|
+
"""Get the collection items as JSON.
|
|
756
|
+
|
|
757
|
+
Parameters
|
|
758
|
+
----------
|
|
759
|
+
**kwargs : dict
|
|
760
|
+
Additional arguments to pass to json.dumps
|
|
761
|
+
|
|
762
|
+
Returns
|
|
763
|
+
-------
|
|
764
|
+
str
|
|
765
|
+
The JSON representation of the collection.
|
|
766
|
+
"""
|
|
767
|
+
return json.dumps(self.serialize(), **kwargs)
|
|
768
|
+
|
|
769
|
+
def groupBy(self, key: str) -> 'Collection':
|
|
770
|
+
"""Group the collection items by a given key.
|
|
771
|
+
|
|
772
|
+
Parameters
|
|
773
|
+
----------
|
|
774
|
+
key : str
|
|
775
|
+
The key to group by
|
|
776
|
+
|
|
777
|
+
Returns
|
|
778
|
+
-------
|
|
779
|
+
Collection
|
|
780
|
+
A new collection with grouped items.
|
|
781
|
+
"""
|
|
782
|
+
from itertools import groupby
|
|
783
|
+
|
|
784
|
+
self.sort(key)
|
|
785
|
+
|
|
786
|
+
new_dict = {}
|
|
787
|
+
|
|
788
|
+
for k, v in groupby(self._items, key=lambda x: x[key]):
|
|
789
|
+
new_dict.update({k: list(v)})
|
|
790
|
+
|
|
791
|
+
return Collection(new_dict)
|
|
792
|
+
|
|
793
|
+
def transform(self, callback: Callable) -> 'Collection':
|
|
794
|
+
"""Transform each item in the collection using a callback.
|
|
795
|
+
|
|
796
|
+
Parameters
|
|
797
|
+
----------
|
|
798
|
+
callback : callable
|
|
799
|
+
The callback function to transform items
|
|
800
|
+
|
|
801
|
+
Returns
|
|
802
|
+
-------
|
|
803
|
+
Collection
|
|
804
|
+
The current collection instance.
|
|
805
|
+
"""
|
|
806
|
+
self.__checkIsCallable(callback)
|
|
807
|
+
self._items = self.__getValue(callback)
|
|
808
|
+
return self
|
|
809
|
+
|
|
810
|
+
def unique(self, key: Optional[str] = None) -> 'Collection':
|
|
811
|
+
"""Return only unique items from the collection array.
|
|
812
|
+
|
|
813
|
+
Parameters
|
|
814
|
+
----------
|
|
815
|
+
key : str, optional
|
|
816
|
+
The key to use for uniqueness comparison, by default None
|
|
817
|
+
|
|
818
|
+
Returns
|
|
819
|
+
-------
|
|
820
|
+
Collection
|
|
821
|
+
A new collection with unique items.
|
|
822
|
+
"""
|
|
823
|
+
if not key:
|
|
824
|
+
items = list(set(self._items))
|
|
825
|
+
return self.__class__(items)
|
|
826
|
+
|
|
827
|
+
keys = set()
|
|
828
|
+
items = []
|
|
829
|
+
if isinstance(self.all(), dict):
|
|
830
|
+
return self
|
|
831
|
+
|
|
832
|
+
for item in self:
|
|
833
|
+
if isinstance(item, dict):
|
|
834
|
+
comparison = item.get(key)
|
|
835
|
+
elif isinstance(item, str):
|
|
836
|
+
comparison = item
|
|
837
|
+
else:
|
|
838
|
+
comparison = getattr(item, key)
|
|
839
|
+
if comparison not in keys:
|
|
840
|
+
items.append(item)
|
|
841
|
+
keys.add(comparison)
|
|
842
|
+
|
|
843
|
+
return self.__class__(items)
|
|
844
|
+
|
|
845
|
+
def where(self, key: str, *args: Any) -> 'Collection':
|
|
846
|
+
"""Filter items by a given key value pair.
|
|
847
|
+
|
|
848
|
+
Parameters
|
|
849
|
+
----------
|
|
850
|
+
key : str
|
|
851
|
+
The key to filter by
|
|
852
|
+
*args : mixed
|
|
853
|
+
The operator and value, or just the value
|
|
854
|
+
|
|
855
|
+
Returns
|
|
856
|
+
-------
|
|
857
|
+
Collection
|
|
858
|
+
A new collection with filtered items.
|
|
859
|
+
"""
|
|
860
|
+
op = "=="
|
|
861
|
+
value = args[0]
|
|
862
|
+
|
|
863
|
+
if len(args) >= 2:
|
|
864
|
+
op = args[0]
|
|
865
|
+
value = args[1]
|
|
866
|
+
|
|
867
|
+
attributes = []
|
|
868
|
+
|
|
869
|
+
for item in self._items:
|
|
870
|
+
if isinstance(item, dict):
|
|
871
|
+
comparison = item.get(key)
|
|
872
|
+
else:
|
|
873
|
+
comparison = getattr(item, key)
|
|
874
|
+
if self.__makeComparison(comparison, value, op):
|
|
875
|
+
attributes.append(item)
|
|
876
|
+
|
|
877
|
+
return self.__class__(attributes)
|
|
878
|
+
|
|
879
|
+
def whereIn(self, key: str, values: Union[List[Any], 'Collection']) -> 'Collection':
|
|
880
|
+
"""Filter items where a given key's value is in a list of values.
|
|
881
|
+
|
|
882
|
+
Parameters
|
|
883
|
+
----------
|
|
884
|
+
key : str
|
|
885
|
+
The key to filter by
|
|
886
|
+
values : list or Collection
|
|
887
|
+
The list of values to check against
|
|
888
|
+
|
|
889
|
+
Returns
|
|
890
|
+
-------
|
|
891
|
+
Collection
|
|
892
|
+
A new collection with filtered items.
|
|
893
|
+
"""
|
|
894
|
+
values = self.__getItems(values)
|
|
895
|
+
attributes = []
|
|
896
|
+
|
|
897
|
+
for item in self._items:
|
|
898
|
+
if isinstance(item, dict):
|
|
899
|
+
comparison = item.get(key)
|
|
900
|
+
else:
|
|
901
|
+
comparison = getattr(item, key, None)
|
|
902
|
+
|
|
903
|
+
# Handle string comparison for numeric values
|
|
904
|
+
if comparison in values or str(comparison) in [str(v) for v in values]:
|
|
905
|
+
attributes.append(item)
|
|
906
|
+
|
|
907
|
+
return self.__class__(attributes)
|
|
908
|
+
|
|
909
|
+
def whereNotIn(self, key: str, values: Union[List[Any], 'Collection']) -> 'Collection':
|
|
910
|
+
"""Filter items where a given key's value is not in a list of values.
|
|
911
|
+
|
|
912
|
+
Parameters
|
|
913
|
+
----------
|
|
914
|
+
key : str
|
|
915
|
+
The key to filter by
|
|
916
|
+
values : list or Collection
|
|
917
|
+
The list of values to check against
|
|
918
|
+
|
|
919
|
+
Returns
|
|
920
|
+
-------
|
|
921
|
+
Collection
|
|
922
|
+
A new collection with filtered items.
|
|
923
|
+
"""
|
|
924
|
+
values = self.__getItems(values)
|
|
925
|
+
attributes = []
|
|
926
|
+
|
|
927
|
+
for item in self._items:
|
|
928
|
+
if isinstance(item, dict):
|
|
929
|
+
comparison = item.get(key)
|
|
930
|
+
else:
|
|
931
|
+
comparison = getattr(item, key, None)
|
|
932
|
+
|
|
933
|
+
# Handle string comparison for numeric values
|
|
934
|
+
if comparison not in values and str(comparison) not in [str(v) for v in values]:
|
|
935
|
+
attributes.append(item)
|
|
936
|
+
|
|
937
|
+
return self.__class__(attributes)
|
|
938
|
+
|
|
939
|
+
def zip(self, items: Union[List[Any], 'Collection']) -> 'Collection':
|
|
940
|
+
"""Merge the collection with the given items by index.
|
|
941
|
+
|
|
942
|
+
Parameters
|
|
943
|
+
----------
|
|
944
|
+
items : list or Collection
|
|
945
|
+
The items to zip with
|
|
946
|
+
|
|
947
|
+
Returns
|
|
948
|
+
-------
|
|
949
|
+
Collection
|
|
950
|
+
A new collection with zipped items.
|
|
951
|
+
|
|
952
|
+
Raises
|
|
953
|
+
------
|
|
954
|
+
ValueError
|
|
955
|
+
If items parameter is not a list or Collection.
|
|
956
|
+
"""
|
|
957
|
+
items = self.__getItems(items)
|
|
958
|
+
if not isinstance(items, list):
|
|
959
|
+
raise ValueError("The 'items' parameter must be a list or a Collection")
|
|
960
|
+
|
|
961
|
+
_items = []
|
|
962
|
+
for x, y in zip(self, items):
|
|
963
|
+
_items.append([x, y])
|
|
964
|
+
return self.__class__(_items)
|
|
965
|
+
|
|
966
|
+
def setAppends(self, appends: List[str]) -> 'Collection':
|
|
967
|
+
"""Set the attributes that should be appended to the Collection.
|
|
968
|
+
|
|
969
|
+
Parameters
|
|
970
|
+
----------
|
|
971
|
+
appends : list
|
|
972
|
+
The attributes to append
|
|
973
|
+
|
|
974
|
+
Returns
|
|
975
|
+
-------
|
|
976
|
+
Collection
|
|
977
|
+
The current collection instance.
|
|
978
|
+
"""
|
|
979
|
+
self.__appends__ += appends
|
|
980
|
+
return self
|
|
981
|
+
|
|
982
|
+
def __getValue(self, key: Union[str, Callable, None]) -> Optional[List[Any]]:
|
|
983
|
+
"""Get values from items using a key or callback.
|
|
984
|
+
|
|
985
|
+
Parameters
|
|
986
|
+
----------
|
|
987
|
+
key : str or callable
|
|
988
|
+
The key to extract or callback to apply
|
|
989
|
+
|
|
990
|
+
Returns
|
|
991
|
+
-------
|
|
992
|
+
list
|
|
993
|
+
List of extracted values.
|
|
994
|
+
"""
|
|
995
|
+
if not key:
|
|
996
|
+
return None
|
|
997
|
+
|
|
998
|
+
items = []
|
|
999
|
+
for item in self:
|
|
1000
|
+
if isinstance(key, str):
|
|
1001
|
+
if hasattr(item, key) or (key in item):
|
|
1002
|
+
items.append(getattr(item, key, item[key]))
|
|
1003
|
+
elif callable(key):
|
|
1004
|
+
result = key(item)
|
|
1005
|
+
if result:
|
|
1006
|
+
items.append(result)
|
|
1007
|
+
return items
|
|
1008
|
+
|
|
1009
|
+
def __dataGet(self, item: Any, key: str, default: Any = None) -> Any:
|
|
1010
|
+
"""Read dictionary value from key using nested notation.
|
|
1011
|
+
|
|
1012
|
+
Parameters
|
|
1013
|
+
----------
|
|
1014
|
+
item : mixed
|
|
1015
|
+
The item to extract data from
|
|
1016
|
+
key : str
|
|
1017
|
+
The key to look for
|
|
1018
|
+
default : mixed, optional
|
|
1019
|
+
Default value if key not found, by default None
|
|
1020
|
+
|
|
1021
|
+
Returns
|
|
1022
|
+
-------
|
|
1023
|
+
mixed
|
|
1024
|
+
The extracted value or default.
|
|
1025
|
+
"""
|
|
1026
|
+
try:
|
|
1027
|
+
if isinstance(item, (list, tuple)):
|
|
1028
|
+
item = item[key]
|
|
1029
|
+
elif isinstance(item, (dict, Dotty)):
|
|
1030
|
+
# Use dotty for nested key access
|
|
1031
|
+
dotty_key = key.replace("*", ":")
|
|
1032
|
+
dotty_item = dotty(item)
|
|
1033
|
+
item = dotty_item.get(dotty_key, default)
|
|
1034
|
+
elif isinstance(item, object):
|
|
1035
|
+
item = getattr(item, key)
|
|
1036
|
+
except (IndexError, AttributeError, KeyError, TypeError):
|
|
1037
|
+
return self.__value(default)
|
|
1038
|
+
|
|
1039
|
+
return item
|
|
1040
|
+
|
|
1041
|
+
def __value(self, value: Any) -> Any:
|
|
1042
|
+
"""Get the value from a callable or return the value itself.
|
|
1043
|
+
|
|
1044
|
+
Parameters
|
|
1045
|
+
----------
|
|
1046
|
+
value : mixed
|
|
1047
|
+
The value or callable to evaluate
|
|
1048
|
+
|
|
1049
|
+
Returns
|
|
1050
|
+
-------
|
|
1051
|
+
mixed
|
|
1052
|
+
The evaluated value.
|
|
1053
|
+
"""
|
|
1054
|
+
if callable(value):
|
|
1055
|
+
return value()
|
|
1056
|
+
return value
|
|
1057
|
+
|
|
1058
|
+
def __checkIsCallable(self, callback: Any, raise_exception: bool = True) -> bool:
|
|
1059
|
+
"""Check if the given callback is callable.
|
|
1060
|
+
|
|
1061
|
+
Parameters
|
|
1062
|
+
----------
|
|
1063
|
+
callback : mixed
|
|
1064
|
+
The callback to check
|
|
1065
|
+
raise_exception : bool, optional
|
|
1066
|
+
Whether to raise exception if not callable, by default True
|
|
1067
|
+
|
|
1068
|
+
Returns
|
|
1069
|
+
-------
|
|
1070
|
+
bool
|
|
1071
|
+
True if callable, False otherwise.
|
|
1072
|
+
|
|
1073
|
+
Raises
|
|
1074
|
+
------
|
|
1075
|
+
ValueError
|
|
1076
|
+
If callback is not callable and raise_exception is True.
|
|
1077
|
+
"""
|
|
1078
|
+
if not callable(callback):
|
|
1079
|
+
if not raise_exception:
|
|
1080
|
+
return False
|
|
1081
|
+
raise ValueError("The 'callback' should be a function")
|
|
1082
|
+
return True
|
|
1083
|
+
|
|
1084
|
+
def __makeComparison(self, a: Any, b: Any, op: str) -> bool:
|
|
1085
|
+
"""Make a comparison between two values using an operator.
|
|
1086
|
+
|
|
1087
|
+
Parameters
|
|
1088
|
+
----------
|
|
1089
|
+
a : mixed
|
|
1090
|
+
First value
|
|
1091
|
+
b : mixed
|
|
1092
|
+
Second value
|
|
1093
|
+
op : str
|
|
1094
|
+
Comparison operator
|
|
1095
|
+
|
|
1096
|
+
Returns
|
|
1097
|
+
-------
|
|
1098
|
+
bool
|
|
1099
|
+
Result of the comparison.
|
|
1100
|
+
"""
|
|
1101
|
+
operators = {
|
|
1102
|
+
"<": operator.lt,
|
|
1103
|
+
"<=": operator.le,
|
|
1104
|
+
"==": operator.eq,
|
|
1105
|
+
"!=": operator.ne,
|
|
1106
|
+
">": operator.gt,
|
|
1107
|
+
">=": operator.ge,
|
|
1108
|
+
}
|
|
1109
|
+
return operators[op](a, b)
|
|
1110
|
+
|
|
1111
|
+
def __iter__(self) -> Any:
|
|
1112
|
+
"""
|
|
1113
|
+
Iterate over the items in the collection.
|
|
1114
|
+
|
|
1115
|
+
Returns
|
|
1116
|
+
-------
|
|
1117
|
+
generator
|
|
1118
|
+
A generator yielding each item in the collection.
|
|
1119
|
+
"""
|
|
1120
|
+
|
|
1121
|
+
# Yield each item in the internal _items list
|
|
1122
|
+
for item in self._items:
|
|
1123
|
+
yield item
|
|
1124
|
+
|
|
1125
|
+
def __eq__(self, other: Any) -> bool:
|
|
1126
|
+
"""
|
|
1127
|
+
Compare the current collection with another object for equality.
|
|
1128
|
+
|
|
1129
|
+
Parameters
|
|
1130
|
+
----------
|
|
1131
|
+
other : Any
|
|
1132
|
+
The object to compare with the current collection.
|
|
1133
|
+
|
|
1134
|
+
Returns
|
|
1135
|
+
-------
|
|
1136
|
+
bool
|
|
1137
|
+
True if the collections are equal, False otherwise.
|
|
1138
|
+
"""
|
|
1139
|
+
|
|
1140
|
+
# If the other object is a Collection, compare its items with self._items
|
|
1141
|
+
if isinstance(other, Collection):
|
|
1142
|
+
return other.all() == self._items
|
|
1143
|
+
|
|
1144
|
+
# Otherwise, compare the other object directly with self._items
|
|
1145
|
+
return other == self._items
|
|
1146
|
+
|
|
1147
|
+
def __getitem__(self, item: Union[int, slice]) -> Union[Any, 'Collection']:
|
|
1148
|
+
"""
|
|
1149
|
+
Retrieve an item or a slice of items from the collection.
|
|
1150
|
+
|
|
1151
|
+
Parameters
|
|
1152
|
+
----------
|
|
1153
|
+
item : int or slice
|
|
1154
|
+
The index or slice to retrieve from the collection.
|
|
1155
|
+
|
|
1156
|
+
Returns
|
|
1157
|
+
-------
|
|
1158
|
+
Any or Collection
|
|
1159
|
+
The item at the specified index, or a new Collection containing the sliced items.
|
|
1160
|
+
|
|
1161
|
+
Notes
|
|
1162
|
+
-----
|
|
1163
|
+
If a slice is provided, a new Collection instance is returned containing the sliced items.
|
|
1164
|
+
If an integer index is provided, the corresponding item is returned.
|
|
1165
|
+
"""
|
|
1166
|
+
|
|
1167
|
+
# If the item is a slice, return a new Collection with the sliced items
|
|
1168
|
+
if isinstance(item, slice):
|
|
1169
|
+
return self.__class__(self._items[item])
|
|
1170
|
+
|
|
1171
|
+
# Otherwise, return the item at the specified index
|
|
1172
|
+
return self._items[item]
|
|
1173
|
+
|
|
1174
|
+
def __setitem__(self, key: Any, value: Any) -> None:
|
|
1175
|
+
"""
|
|
1176
|
+
Set the value of an item in the collection at the specified key.
|
|
1177
|
+
|
|
1178
|
+
Parameters
|
|
1179
|
+
----------
|
|
1180
|
+
key : Any
|
|
1181
|
+
The index or key at which to set the value.
|
|
1182
|
+
value : Any
|
|
1183
|
+
The value to assign at the specified key.
|
|
1184
|
+
|
|
1185
|
+
Returns
|
|
1186
|
+
-------
|
|
1187
|
+
None
|
|
1188
|
+
This method does not return a value.
|
|
1189
|
+
|
|
1190
|
+
Notes
|
|
1191
|
+
-----
|
|
1192
|
+
Updates the internal _items list at the given key with the provided value.
|
|
1193
|
+
"""
|
|
1194
|
+
|
|
1195
|
+
# Assign the value to the specified key in the internal _items list
|
|
1196
|
+
self._items[key] = value
|
|
1197
|
+
|
|
1198
|
+
def __delitem__(self, key: Any) -> None:
|
|
1199
|
+
"""
|
|
1200
|
+
Remove an item from the collection at the specified key.
|
|
1201
|
+
|
|
1202
|
+
Parameters
|
|
1203
|
+
----------
|
|
1204
|
+
key : Any
|
|
1205
|
+
The index or key of the item to remove from the collection.
|
|
1206
|
+
|
|
1207
|
+
Returns
|
|
1208
|
+
-------
|
|
1209
|
+
None
|
|
1210
|
+
This method does not return a value.
|
|
1211
|
+
|
|
1212
|
+
Notes
|
|
1213
|
+
-----
|
|
1214
|
+
Deletes the item at the given key from the internal _items list.
|
|
1215
|
+
"""
|
|
1216
|
+
|
|
1217
|
+
# Delete the item at the specified key from the internal _items list
|
|
1218
|
+
del self._items[key]
|
|
1219
|
+
|
|
1220
|
+
def __ne__(self, other: Any) -> bool:
|
|
1221
|
+
"""
|
|
1222
|
+
Determine if the current collection is not equal to another object.
|
|
1223
|
+
|
|
1224
|
+
Parameters
|
|
1225
|
+
----------
|
|
1226
|
+
other : Any
|
|
1227
|
+
The object to compare with the current collection.
|
|
1228
|
+
|
|
1229
|
+
Returns
|
|
1230
|
+
-------
|
|
1231
|
+
bool
|
|
1232
|
+
True if the collections are not equal, False otherwise.
|
|
1233
|
+
|
|
1234
|
+
Notes
|
|
1235
|
+
-----
|
|
1236
|
+
Uses the internal items for comparison. If `other` is a Collection, compares its items.
|
|
1237
|
+
"""
|
|
1238
|
+
|
|
1239
|
+
# Extract items from the other object if it is a Collection
|
|
1240
|
+
other = self.__getItems(other)
|
|
1241
|
+
|
|
1242
|
+
# Return True if the items are not equal, False otherwise
|
|
1243
|
+
return other != self._items
|
|
1244
|
+
|
|
1245
|
+
def __len__(self) -> int:
|
|
1246
|
+
"""
|
|
1247
|
+
Return the number of items in the collection.
|
|
1248
|
+
|
|
1249
|
+
Returns
|
|
1250
|
+
-------
|
|
1251
|
+
int
|
|
1252
|
+
The total number of items contained in the collection.
|
|
1253
|
+
"""
|
|
1254
|
+
|
|
1255
|
+
# Return the length of the internal _items list
|
|
1256
|
+
return len(self._items)
|
|
1257
|
+
|
|
1258
|
+
def __le__(self, other: Any) -> bool:
|
|
1259
|
+
"""
|
|
1260
|
+
Determine if the current collection is less than or equal to another object.
|
|
1261
|
+
|
|
1262
|
+
Parameters
|
|
1263
|
+
----------
|
|
1264
|
+
other : Any
|
|
1265
|
+
The object to compare with the current collection.
|
|
1266
|
+
|
|
1267
|
+
Returns
|
|
1268
|
+
-------
|
|
1269
|
+
bool
|
|
1270
|
+
True if the current collection is less than or equal to the other object, False otherwise.
|
|
1271
|
+
|
|
1272
|
+
Notes
|
|
1273
|
+
-----
|
|
1274
|
+
Uses the internal items for comparison. If `other` is a Collection, compares its items.
|
|
1275
|
+
"""
|
|
1276
|
+
|
|
1277
|
+
# Extract items from the other object if it is a Collection
|
|
1278
|
+
other = self.__getItems(other)
|
|
1279
|
+
|
|
1280
|
+
# Return True if the items are less than or equal, False otherwise
|
|
1281
|
+
return self._items <= other
|
|
1282
|
+
|
|
1283
|
+
def __lt__(self, other: Any) -> bool:
|
|
1284
|
+
"""
|
|
1285
|
+
Determine if the current collection is less than another object.
|
|
1286
|
+
|
|
1287
|
+
Parameters
|
|
1288
|
+
----------
|
|
1289
|
+
other : Any
|
|
1290
|
+
The object to compare with the current collection.
|
|
1291
|
+
|
|
1292
|
+
Returns
|
|
1293
|
+
-------
|
|
1294
|
+
bool
|
|
1295
|
+
True if the current collection is less than the other object, False otherwise.
|
|
1296
|
+
|
|
1297
|
+
Notes
|
|
1298
|
+
-----
|
|
1299
|
+
Uses the internal items for comparison. If `other` is a Collection, compares its items.
|
|
1300
|
+
"""
|
|
1301
|
+
|
|
1302
|
+
# Extract items from the other object if it is a Collection
|
|
1303
|
+
other = self.__getItems(other)
|
|
1304
|
+
|
|
1305
|
+
# Return True if the items are less than, False otherwise
|
|
1306
|
+
return self._items < other
|
|
1307
|
+
|
|
1308
|
+
def __ge__(self, other: Any) -> bool:
|
|
1309
|
+
"""
|
|
1310
|
+
Determine if the current collection is greater than or equal to another object.
|
|
1311
|
+
|
|
1312
|
+
Parameters
|
|
1313
|
+
----------
|
|
1314
|
+
other : Any
|
|
1315
|
+
The object to compare with the current collection.
|
|
1316
|
+
|
|
1317
|
+
Returns
|
|
1318
|
+
-------
|
|
1319
|
+
bool
|
|
1320
|
+
True if the current collection is greater than or equal to the other object, False otherwise.
|
|
1321
|
+
|
|
1322
|
+
Notes
|
|
1323
|
+
-----
|
|
1324
|
+
Uses the internal items for comparison. If `other` is a Collection, compares its items.
|
|
1325
|
+
"""
|
|
1326
|
+
|
|
1327
|
+
# Extract items from the other object if it is a Collection
|
|
1328
|
+
other = self.__getItems(other)
|
|
1329
|
+
|
|
1330
|
+
# Return True if the items are greater than or equal, False otherwise
|
|
1331
|
+
return self._items >= other
|
|
1332
|
+
|
|
1333
|
+
def __gt__(self, other: Any) -> bool:
|
|
1334
|
+
"""
|
|
1335
|
+
Determine if the current collection is greater than another object.
|
|
1336
|
+
|
|
1337
|
+
Parameters
|
|
1338
|
+
----------
|
|
1339
|
+
other : Any
|
|
1340
|
+
The object to compare with the current collection.
|
|
1341
|
+
|
|
1342
|
+
Returns
|
|
1343
|
+
-------
|
|
1344
|
+
bool
|
|
1345
|
+
True if the current collection is greater than the other object, False otherwise.
|
|
1346
|
+
|
|
1347
|
+
Notes
|
|
1348
|
+
-----
|
|
1349
|
+
Uses the internal items for comparison. If `other` is a Collection, compares its items.
|
|
1350
|
+
"""
|
|
1351
|
+
|
|
1352
|
+
# Extract items from the other object if it is a Collection
|
|
1353
|
+
other = self.__getItems(other)
|
|
1354
|
+
|
|
1355
|
+
# Return True if the items are greater than, False otherwise
|
|
1356
|
+
return self._items > other
|
|
1357
|
+
|
|
1358
|
+
@classmethod
|
|
1359
|
+
def __getItems(cls, items: Any) -> Any:
|
|
1360
|
+
"""
|
|
1361
|
+
Extracts the underlying items from a Collection instance or returns the input as-is.
|
|
1362
|
+
|
|
1363
|
+
Parameters
|
|
1364
|
+
----------
|
|
1365
|
+
items : Collection or Any
|
|
1366
|
+
The input to extract items from. If a Collection, its items are returned; otherwise, the input is returned unchanged.
|
|
1367
|
+
|
|
1368
|
+
Returns
|
|
1369
|
+
-------
|
|
1370
|
+
Any
|
|
1371
|
+
The extracted items if `items` is a Collection, otherwise the original input.
|
|
1372
|
+
"""
|
|
1373
|
+
|
|
1374
|
+
# If the input is a Collection, extract its items using the all() method
|
|
1375
|
+
if isinstance(items, Collection):
|
|
1376
|
+
items = items.all()
|
|
1377
|
+
|
|
1378
|
+
# Return the extracted items or the original input
|
|
1379
|
+
return items
|
|
1380
|
+
|
|
1381
|
+
|