datahold 4.0.0.dev27__tar.gz → 4.0.0.dev28__tar.gz
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.
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/PKG-INFO +1 -1
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/pyproject.toml +1 -1
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold/__init__.py +140 -112
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold.egg-info/PKG-INFO +1 -1
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold.egg-info/SOURCES.txt +2 -1
- datahold-4.0.0.dev28/tests/test_FrozenSetSlot.py +233 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_abstractmethods.py +3 -1
- datahold-4.0.0.dev28/tests/test_metaclass.py +25 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_name.py +6 -5
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/testdata.toml +35 -11
- datahold-4.0.0.dev27/tests/test_internal_comparison.py +0 -50
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/LICENSE.txt +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/MANIFEST.in +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/README.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v1.1.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v1.2.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v2.0.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v2.1.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v2.2.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v2.3.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v3.0.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/docs/v4.0.rst +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/run_tests.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/setup.cfg +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold/py.typed +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold.egg-info/dependency_links.txt +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold.egg-info/requires.txt +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/src/datahold.egg-info/top_level.txt +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_FrozenListSlot.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_MutableDictSlot.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_MutableListSlot.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_MutableSetSlot.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_all.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_attributes.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_docs.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_generic.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_issubclass.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_nested.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_sorted.py +0 -0
- {datahold-4.0.0.dev27 → datahold-4.0.0.dev28}/tests/test_variance.py +0 -0
|
@@ -9,6 +9,7 @@ __all__: list[str] = [
|
|
|
9
9
|
"FrozenDictSlot",
|
|
10
10
|
"FrozenListLike",
|
|
11
11
|
"FrozenListSlot",
|
|
12
|
+
"FrozenObjectSlot",
|
|
12
13
|
"FrozenSetLike",
|
|
13
14
|
"FrozenSetSlot",
|
|
14
15
|
"ListLike",
|
|
@@ -18,16 +19,20 @@ __all__: list[str] = [
|
|
|
18
19
|
"MutableListLike",
|
|
19
20
|
"MutableListSlot",
|
|
20
21
|
"MutableMapping",
|
|
22
|
+
"MutableObject",
|
|
23
|
+
"MutableObjectLike",
|
|
21
24
|
"MutableSequence",
|
|
22
25
|
"MutableSet",
|
|
23
26
|
"MutableSetLike",
|
|
24
27
|
"MutableSetSlot",
|
|
28
|
+
"Object",
|
|
29
|
+
"ObjectSlot",
|
|
25
30
|
"Sequence",
|
|
26
31
|
"Set",
|
|
27
32
|
"SetLike",
|
|
28
33
|
]
|
|
29
34
|
|
|
30
|
-
from abc import abstractmethod
|
|
35
|
+
from abc import ABCMeta, abstractmethod
|
|
31
36
|
from collections import abc
|
|
32
37
|
from contextlib import contextmanager
|
|
33
38
|
from types import NotImplementedType, TracebackType
|
|
@@ -164,15 +169,82 @@ class MutableSequence_Mutable[Item](Protocol):
|
|
|
164
169
|
|
|
165
170
|
### TYPE ALIASES ###
|
|
166
171
|
|
|
172
|
+
type Dict[Key, Value] = dict[Key | str, Optional[Value]]
|
|
167
173
|
|
|
168
174
|
type DictInit[Key, Value] = (
|
|
169
175
|
SupportsKeysAndGetitem[Key | str, Optional[Value]]
|
|
170
176
|
| abc.Iterable[tuple[Key | str, Optional[Value]]]
|
|
171
177
|
)
|
|
172
178
|
|
|
179
|
+
type FrozenDict[Key, Value] = frozendict[Key | str, Optional[Value]]
|
|
180
|
+
|
|
173
181
|
type Slice[Index] = slice[Optional[Index], Optional[Index], Optional[Index]]
|
|
174
182
|
|
|
175
183
|
|
|
184
|
+
### OBJECT ###
|
|
185
|
+
class Object[Frozen](metaclass=ABCMeta):
|
|
186
|
+
"""Provide abc for custom object."""
|
|
187
|
+
|
|
188
|
+
__slots__ = ()
|
|
189
|
+
|
|
190
|
+
@abstractmethod
|
|
191
|
+
@setdoc.basic
|
|
192
|
+
def __frozen__(self: Self, /) -> Frozen: ...
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
class MutableObject[Frozen, Mutable](Object[Frozen]):
|
|
196
|
+
"""Provide abc for custom mutable object."""
|
|
197
|
+
|
|
198
|
+
__slots__ = ()
|
|
199
|
+
|
|
200
|
+
@abstractmethod
|
|
201
|
+
@setdoc.basic
|
|
202
|
+
def __mutate__(self: Self, /) -> ContextManager[Mutable]: ...
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
### OBJECT-LIKE ###
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
class MutableObjectLike[Frozen, Mutable](
|
|
209
|
+
MutableObject[Frozen, Mutable],
|
|
210
|
+
):
|
|
211
|
+
"""Provide abc for custom mutable object-like."""
|
|
212
|
+
|
|
213
|
+
__slots__ = ()
|
|
214
|
+
|
|
215
|
+
@abstractmethod
|
|
216
|
+
@setdoc.basic
|
|
217
|
+
def __init__(self: Self, other: Self, /) -> None: ...
|
|
218
|
+
@setdoc.basic
|
|
219
|
+
def copy(self: Self, /) -> Self:
|
|
220
|
+
return type(self)(self)
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
### OBJECT-HOLD ###
|
|
224
|
+
|
|
225
|
+
|
|
226
|
+
class ObjectSlot[Frozen](
|
|
227
|
+
Object[Frozen],
|
|
228
|
+
):
|
|
229
|
+
"""Provide slotted abc for custom object-like."""
|
|
230
|
+
|
|
231
|
+
__slots__ = ("_slot",)
|
|
232
|
+
_slot: Frozen
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class FrozenObjectSlot[Frozen](
|
|
236
|
+
ObjectSlot[Frozen],
|
|
237
|
+
):
|
|
238
|
+
"""Provide slotted abc for custom frozen object-like."""
|
|
239
|
+
|
|
240
|
+
__slots__ = ()
|
|
241
|
+
_slot: Frozen
|
|
242
|
+
|
|
243
|
+
@setdoc.basic
|
|
244
|
+
def __frozen__(self: Self, /) -> Frozen:
|
|
245
|
+
return self._slot
|
|
246
|
+
|
|
247
|
+
|
|
176
248
|
### COLLECTION ###
|
|
177
249
|
|
|
178
250
|
|
|
@@ -180,11 +252,10 @@ class Collection[Item](
|
|
|
180
252
|
abc.Sized,
|
|
181
253
|
abc.Iterable[Item],
|
|
182
254
|
abc.Container[object],
|
|
255
|
+
Object[Collection_Frozen[Item]],
|
|
183
256
|
):
|
|
184
257
|
"""Provide abc for custom collection."""
|
|
185
258
|
|
|
186
|
-
type __Frozen__[Item_] = Collection_Frozen[Item_]
|
|
187
|
-
|
|
188
259
|
@setdoc.basic
|
|
189
260
|
def __contains__(self: Self, other: object, /) -> bool:
|
|
190
261
|
try:
|
|
@@ -192,10 +263,6 @@ class Collection[Item](
|
|
|
192
263
|
except TypeError:
|
|
193
264
|
return other in (x for x in self) # type: ignore[operator]
|
|
194
265
|
|
|
195
|
-
@abstractmethod
|
|
196
|
-
@setdoc.basic
|
|
197
|
-
def __frozen__(self: Self, /) -> Collection_Frozen[Item]: ...
|
|
198
|
-
|
|
199
266
|
@setdoc.basic
|
|
200
267
|
def __iter__(self: Self, /) -> abc.Iterator[Item]:
|
|
201
268
|
return iter(self.__frozen__())
|
|
@@ -214,15 +281,15 @@ class Set[Item: abc.Hashable](Collection[Item], abc.Set[Item]):
|
|
|
214
281
|
__slots__ = ()
|
|
215
282
|
|
|
216
283
|
|
|
217
|
-
class MutableSet[Item: abc.Hashable](
|
|
284
|
+
class MutableSet[Item: abc.Hashable](
|
|
285
|
+
Set[Item],
|
|
286
|
+
abc.MutableSet[Item],
|
|
287
|
+
MutableObject[Collection_Frozen[Item], MutableSet_Mutable[Item]],
|
|
288
|
+
):
|
|
218
289
|
"""Provide abc for custom mutable set."""
|
|
219
290
|
|
|
220
291
|
__slots__ = ()
|
|
221
|
-
type __Mutable__[Item_] = MutableSet_Mutable[Item_]
|
|
222
292
|
|
|
223
|
-
@abstractmethod
|
|
224
|
-
@setdoc.basic
|
|
225
|
-
def __mutate__(self: Self) -> ContextManager[MutableSet_Mutable[Item]]: ...
|
|
226
293
|
@setdoc.basic
|
|
227
294
|
def add(self: Self, item: Item, /) -> None:
|
|
228
295
|
with self.__mutate__() as mutable:
|
|
@@ -241,11 +308,10 @@ class SetLike[Item: abc.Hashable](Set[Item]):
|
|
|
241
308
|
"""Provide abc for custom set-like."""
|
|
242
309
|
|
|
243
310
|
__slots__ = ()
|
|
244
|
-
type __Frozen__[Item_] = frozenset[Item_]
|
|
245
311
|
|
|
246
312
|
@abstractmethod
|
|
247
313
|
@setdoc.basic
|
|
248
|
-
def __frozen__(self: Self, /) ->
|
|
314
|
+
def __frozen__(self: Self, /) -> frozenset[Item]: ...
|
|
249
315
|
@abstractmethod
|
|
250
316
|
@setdoc.basic
|
|
251
317
|
def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None: ...
|
|
@@ -286,14 +352,17 @@ class FrozenSetLike[Item: abc.Hashable](SetLike[Item], abc.Hashable):
|
|
|
286
352
|
return hash(self.__frozen__())
|
|
287
353
|
|
|
288
354
|
|
|
289
|
-
class MutableSetLike[Item: abc.Hashable](
|
|
355
|
+
class MutableSetLike[Item: abc.Hashable](
|
|
356
|
+
SetLike[Item],
|
|
357
|
+
MutableObjectLike[frozenset[Item], set[Item]],
|
|
358
|
+
MutableSet[Item],
|
|
359
|
+
):
|
|
290
360
|
"""Provide abc for custom mutable set-like."""
|
|
291
361
|
|
|
292
362
|
__slots__ = ()
|
|
293
|
-
type __Mutable__[Item_] = set[Item_]
|
|
294
363
|
|
|
295
364
|
@setdoc.basic
|
|
296
|
-
def __frozen__(self: Self, /) ->
|
|
365
|
+
def __frozen__(self: Self, /) -> frozenset[Item]:
|
|
297
366
|
with self.__mutate__() as mutable:
|
|
298
367
|
return frozenset(mutable)
|
|
299
368
|
|
|
@@ -302,14 +371,6 @@ class MutableSetLike[Item: abc.Hashable](SetLike[Item], MutableSet[Item]):
|
|
|
302
371
|
with self.__mutate__() as mutable:
|
|
303
372
|
mutable.update(data)
|
|
304
373
|
|
|
305
|
-
@abstractmethod
|
|
306
|
-
@setdoc.basic
|
|
307
|
-
def __mutate__(self: Self) -> ContextManager[__Mutable__[Item]]: ...
|
|
308
|
-
|
|
309
|
-
@setdoc.basic
|
|
310
|
-
def copy(self: Self, /) -> Self:
|
|
311
|
-
return type(self)(self)
|
|
312
|
-
|
|
313
374
|
@setdoc.basic
|
|
314
375
|
def difference_update(
|
|
315
376
|
self: Self, /, *others: abc.Iterable[abc.Hashable]
|
|
@@ -340,36 +401,34 @@ class MutableSetLike[Item: abc.Hashable](SetLike[Item], MutableSet[Item]):
|
|
|
340
401
|
### SET-SLOT ###
|
|
341
402
|
|
|
342
403
|
|
|
343
|
-
class FrozenSetSlot[Item](
|
|
404
|
+
class FrozenSetSlot[Item](
|
|
405
|
+
FrozenObjectSlot[frozenset[Item]],
|
|
406
|
+
FrozenSetLike[Item],
|
|
407
|
+
):
|
|
344
408
|
"""Provide slotted frozen set-like."""
|
|
345
409
|
|
|
346
|
-
__slots__ = (
|
|
347
|
-
|
|
348
|
-
_slot: FrozenSetSlot.__Frozen__[Item]
|
|
349
|
-
|
|
350
|
-
@setdoc.basic
|
|
351
|
-
def __frozen__(self: Self, /) -> FrozenSetSlot.__Frozen__[Item]:
|
|
352
|
-
return self._slot
|
|
410
|
+
__slots__ = ()
|
|
353
411
|
|
|
354
412
|
@setdoc.basic
|
|
355
413
|
def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None:
|
|
356
414
|
self._slot = frozenset(data)
|
|
357
415
|
|
|
358
416
|
|
|
359
|
-
class MutableSetSlot[Item](
|
|
417
|
+
class MutableSetSlot[Item](
|
|
418
|
+
MutableSetLike[Item],
|
|
419
|
+
ObjectSlot[frozenset[Item]],
|
|
420
|
+
):
|
|
360
421
|
"""Provide slotted mutable set-like."""
|
|
361
422
|
|
|
362
|
-
__slots__ = (
|
|
363
|
-
|
|
364
|
-
_slot: FrozenSetSlot.__Frozen__[Item]
|
|
423
|
+
__slots__ = ()
|
|
365
424
|
|
|
366
425
|
@contextmanager
|
|
367
426
|
@setdoc.basic
|
|
368
427
|
def __mutate__(
|
|
369
428
|
self: Self,
|
|
370
429
|
/,
|
|
371
|
-
) -> abc.Generator[
|
|
372
|
-
slot:
|
|
430
|
+
) -> abc.Generator[set[Item], None, None]:
|
|
431
|
+
slot: set[Item]
|
|
373
432
|
slot = set(getattr(self, "_slot", ()))
|
|
374
433
|
yield slot
|
|
375
434
|
self._slot = frozenset(slot)
|
|
@@ -386,11 +445,9 @@ class Mapping[Key: abc.Hashable, Value](
|
|
|
386
445
|
|
|
387
446
|
__slots__ = ()
|
|
388
447
|
|
|
389
|
-
type __Frozen__[Key_, Value_] = Mapping_Frozen[Key_, Value_]
|
|
390
|
-
|
|
391
448
|
@abstractmethod
|
|
392
449
|
@setdoc.basic
|
|
393
|
-
def __frozen__(self: Self, /) ->
|
|
450
|
+
def __frozen__(self: Self, /) -> Mapping_Frozen[Key, Value]: ...
|
|
394
451
|
@setdoc.basic
|
|
395
452
|
def __getitem__(self: Self, key: abc.Hashable, /) -> Value:
|
|
396
453
|
return self.__frozen__()[key]
|
|
@@ -399,21 +456,17 @@ class Mapping[Key: abc.Hashable, Value](
|
|
|
399
456
|
class MutableMapping[Key: abc.Hashable, Value](
|
|
400
457
|
Mapping[Key, Value],
|
|
401
458
|
abc.MutableMapping[Key | str, Optional[Value]],
|
|
459
|
+
MutableObject[FrozenDict[Key, Value], Dict[Key, Value]],
|
|
402
460
|
):
|
|
403
461
|
"""Provide abc for custom mutable mapping."""
|
|
404
462
|
|
|
405
463
|
__slots__ = ()
|
|
406
464
|
|
|
407
|
-
type __Mutable__[Key_, Value_] = MutableMapping_Mutable[Key_, Value_]
|
|
408
|
-
|
|
409
465
|
@setdoc.basic
|
|
410
466
|
def __delitem__(self: Self, key: Key | str, /) -> None:
|
|
411
467
|
with self.__mutate__() as mutable:
|
|
412
468
|
del mutable[key]
|
|
413
469
|
|
|
414
|
-
@abstractmethod
|
|
415
|
-
@setdoc.basic
|
|
416
|
-
def __mutate__(self: Self) -> ContextManager[__Mutable__[Key, Value]]: ...
|
|
417
470
|
@setdoc.basic
|
|
418
471
|
def __setitem__(
|
|
419
472
|
self: Self, key: Key | str, value: Optional[Value], /
|
|
@@ -431,11 +484,12 @@ class DictLike[Key: abc.Hashable, Value](
|
|
|
431
484
|
"""Provide abc for custom dict-like."""
|
|
432
485
|
|
|
433
486
|
__slots__ = ()
|
|
434
|
-
type __Frozen__[Key_, Value_] = frozendict[Key_ | str, Optional[Value_]]
|
|
435
487
|
|
|
436
488
|
@abstractmethod
|
|
437
489
|
@setdoc.basic
|
|
438
|
-
def __frozen__(self: Self, /) ->
|
|
490
|
+
def __frozen__(self: Self, /) -> FrozenDict[Key, Value]: # type: ignore[override]
|
|
491
|
+
...
|
|
492
|
+
|
|
439
493
|
@abstractmethod
|
|
440
494
|
@setdoc.basic
|
|
441
495
|
def __init__(
|
|
@@ -450,13 +504,13 @@ class DictLike[Key: abc.Hashable, Value](
|
|
|
450
504
|
other: DictInit[Key_, Value_],
|
|
451
505
|
/,
|
|
452
506
|
) -> DictLike[Key | Key_, Value | Value_]:
|
|
453
|
-
data:
|
|
507
|
+
data: FrozenDict[Key, Value]
|
|
454
508
|
try:
|
|
455
509
|
data = frozendict(other) # type: ignore[arg-type]
|
|
456
510
|
except TypeError:
|
|
457
511
|
return NotImplemented
|
|
458
512
|
return type(self)( # type: ignore[return-value]
|
|
459
|
-
self.__frozen__() | data
|
|
513
|
+
self.__frozen__() | data
|
|
460
514
|
)
|
|
461
515
|
|
|
462
516
|
@classmethod
|
|
@@ -485,20 +539,18 @@ class FrozenDictLike[Key: abc.Hashable, Value](
|
|
|
485
539
|
|
|
486
540
|
class MutableDictLike[Key: abc.Hashable, Value](
|
|
487
541
|
DictLike[Key, Value],
|
|
542
|
+
MutableObjectLike[FrozenDict[Key, Value], Dict[Key, Value]],
|
|
488
543
|
MutableMapping[Key, Value],
|
|
489
544
|
):
|
|
490
545
|
"""Provide abc for custom mutable dict-like."""
|
|
491
546
|
|
|
492
547
|
__slots__ = ()
|
|
493
|
-
type __Mutable__[Key_: abc.Hashable, Value_] = dict[
|
|
494
|
-
Key_ | str, Optional[Value_]
|
|
495
|
-
]
|
|
496
548
|
|
|
497
549
|
@setdoc.basic
|
|
498
550
|
def __frozen__( # type: ignore[override]
|
|
499
551
|
self: Self,
|
|
500
552
|
/,
|
|
501
|
-
) ->
|
|
553
|
+
) -> FrozenDict[Key, Value]:
|
|
502
554
|
with self.__mutate__() as mutable:
|
|
503
555
|
return frozendict(mutable)
|
|
504
556
|
|
|
@@ -521,15 +573,6 @@ class MutableDictLike[Key: abc.Hashable, Value](
|
|
|
521
573
|
mutable |= other
|
|
522
574
|
return self
|
|
523
575
|
|
|
524
|
-
@abstractmethod
|
|
525
|
-
@setdoc.basic
|
|
526
|
-
def __mutate__(
|
|
527
|
-
self: Self, /
|
|
528
|
-
) -> ContextManager[__Mutable__[Key, Value]]: ...
|
|
529
|
-
@setdoc.basic
|
|
530
|
-
def copy(self: Self, /) -> Self:
|
|
531
|
-
return type(self)(self)
|
|
532
|
-
|
|
533
576
|
@setdoc.basic
|
|
534
577
|
def popitem(self: Self, /) -> tuple[Key | str, Optional[Value]]:
|
|
535
578
|
# for most dict d
|
|
@@ -542,19 +585,13 @@ class MutableDictLike[Key: abc.Hashable, Value](
|
|
|
542
585
|
### DICT-SLOT ###
|
|
543
586
|
|
|
544
587
|
|
|
545
|
-
class FrozenDictSlot[Key: abc.Hashable, Value](
|
|
588
|
+
class FrozenDictSlot[Key: abc.Hashable, Value]( # type: ignore[misc]
|
|
589
|
+
FrozenObjectSlot[FrozenDict[Key, Value]],
|
|
546
590
|
FrozenDictLike[Key, Value],
|
|
547
591
|
):
|
|
548
592
|
"""Provide slotted frozen dict-like."""
|
|
549
593
|
|
|
550
|
-
__slots__ = (
|
|
551
|
-
_slot: FrozenDictSlot.__Frozen__[Key, Value]
|
|
552
|
-
|
|
553
|
-
@setdoc.basic
|
|
554
|
-
def __frozen__( # type: ignore[override]
|
|
555
|
-
self: Self,
|
|
556
|
-
) -> FrozenDictSlot.__Frozen__[Key, Value]:
|
|
557
|
-
return self._slot
|
|
594
|
+
__slots__ = ()
|
|
558
595
|
|
|
559
596
|
@setdoc.basic
|
|
560
597
|
def __init__(
|
|
@@ -568,19 +605,19 @@ class FrozenDictSlot[Key: abc.Hashable, Value](
|
|
|
568
605
|
|
|
569
606
|
class MutableDictSlot[Key: abc.Hashable, Value](
|
|
570
607
|
MutableDictLike[Key, Value],
|
|
608
|
+
ObjectSlot[FrozenDict[Key, Value]],
|
|
571
609
|
):
|
|
572
610
|
"""Provide slotted mutable dict-like."""
|
|
573
611
|
|
|
574
|
-
__slots__ = (
|
|
575
|
-
_slot: FrozenDictSlot.__Frozen__[Key, Value]
|
|
612
|
+
__slots__ = ()
|
|
576
613
|
|
|
577
614
|
@contextmanager
|
|
578
615
|
@setdoc.basic
|
|
579
616
|
def __mutate__(
|
|
580
617
|
self: Self,
|
|
581
618
|
/,
|
|
582
|
-
) -> abc.Generator[
|
|
583
|
-
slot:
|
|
619
|
+
) -> abc.Generator[Dict[Key, Value], None, None]:
|
|
620
|
+
slot: Dict[Key, Value]
|
|
584
621
|
slot = dict(getattr(self, "_slot", ()))
|
|
585
622
|
yield slot
|
|
586
623
|
self._slot = frozendict(slot)
|
|
@@ -593,11 +630,10 @@ class Sequence[Item](Collection[Item], abc.Sequence[Item]):
|
|
|
593
630
|
"""Provide abc for customized sequence."""
|
|
594
631
|
|
|
595
632
|
__slots__ = ()
|
|
596
|
-
type __Frozen__[Item_] = Sequence_Frozen[Item_]
|
|
597
633
|
|
|
598
634
|
@abstractmethod
|
|
599
635
|
@setdoc.basic
|
|
600
|
-
def __frozen__(self: Self, /) ->
|
|
636
|
+
def __frozen__(self: Self, /) -> Sequence_Frozen[Item]: ...
|
|
601
637
|
@overload
|
|
602
638
|
@setdoc.basic
|
|
603
639
|
def __getitem__(self: Self, key: int, /) -> Item: ...
|
|
@@ -611,11 +647,14 @@ class Sequence[Item](Collection[Item], abc.Sequence[Item]):
|
|
|
611
647
|
return self.__frozen__()[key]
|
|
612
648
|
|
|
613
649
|
|
|
614
|
-
class MutableSequence[Item](
|
|
650
|
+
class MutableSequence[Item](
|
|
651
|
+
Sequence[Item],
|
|
652
|
+
abc.MutableSequence[Item],
|
|
653
|
+
MutableObject[Sequence_Frozen[Item], MutableSequence_Mutable[Item]],
|
|
654
|
+
):
|
|
615
655
|
"""Provide abc for custom mutable sequence."""
|
|
616
656
|
|
|
617
657
|
__slots__ = ()
|
|
618
|
-
type __Mutable__[Item_] = MutableSequence_Mutable[Item_]
|
|
619
658
|
|
|
620
659
|
@overload
|
|
621
660
|
@setdoc.basic
|
|
@@ -643,10 +682,6 @@ class MutableSequence[Item](Sequence[Item], abc.MutableSequence[Item]):
|
|
|
643
682
|
with self.__mutate__() as mutable:
|
|
644
683
|
return mutable[key]
|
|
645
684
|
|
|
646
|
-
@abstractmethod
|
|
647
|
-
@setdoc.basic
|
|
648
|
-
def __mutate__(self: Self, /) -> ContextManager[__Mutable__[Item]]: ...
|
|
649
|
-
|
|
650
685
|
@overload
|
|
651
686
|
@setdoc.basic
|
|
652
687
|
def __setitem__(self: Self, key: int, value: Item, /) -> None: ...
|
|
@@ -677,9 +712,6 @@ class ListLike[Item](Sequence[Item]):
|
|
|
677
712
|
|
|
678
713
|
__slots__ = ()
|
|
679
714
|
|
|
680
|
-
type __Frozen__[Item_] = tuple[Item_, ...]
|
|
681
|
-
# Frozen has to be tuple to allow covariance
|
|
682
|
-
|
|
683
715
|
@setdoc.basic
|
|
684
716
|
def __add__[Item_](
|
|
685
717
|
self: Self, other: ListLike[Item_], /
|
|
@@ -698,7 +730,9 @@ class ListLike[Item](Sequence[Item]):
|
|
|
698
730
|
|
|
699
731
|
@abstractmethod
|
|
700
732
|
@setdoc.basic
|
|
701
|
-
def __frozen__(self: Self, /) ->
|
|
733
|
+
def __frozen__(self: Self, /) -> tuple[Item, ...]:
|
|
734
|
+
# __frozen__ has to be tuple to allow covariance
|
|
735
|
+
...
|
|
702
736
|
|
|
703
737
|
@setdoc.basic
|
|
704
738
|
def __ge__(self: Self, other: ListLike[Any], /) -> bool:
|
|
@@ -771,17 +805,19 @@ class FrozenListLike[Item](ListLike[Item], abc.Hashable):
|
|
|
771
805
|
__slots__ = ()
|
|
772
806
|
|
|
773
807
|
@setdoc.basic
|
|
774
|
-
def __hash__(self: Self) -> int:
|
|
808
|
+
def __hash__(self: Self, /) -> int:
|
|
775
809
|
return hash(self.__frozen__())
|
|
776
810
|
|
|
777
811
|
|
|
778
|
-
class MutableListLike[Item](
|
|
812
|
+
class MutableListLike[Item](
|
|
813
|
+
ListLike[Item],
|
|
814
|
+
MutableObjectLike[tuple[Item, ...], list[Item]],
|
|
815
|
+
MutableSequence[Item],
|
|
816
|
+
):
|
|
779
817
|
"""Provide abc for custom mutable list-like."""
|
|
780
818
|
|
|
781
819
|
__slots__ = ()
|
|
782
820
|
|
|
783
|
-
type __Mutable__[Item_] = list[Item_]
|
|
784
|
-
|
|
785
821
|
@overload
|
|
786
822
|
@setdoc.basic
|
|
787
823
|
def __delitem__(self: Self, key: SupportsIndex, /) -> None: ...
|
|
@@ -796,7 +832,7 @@ class MutableListLike[Item](ListLike[Item], MutableSequence[Item]):
|
|
|
796
832
|
del mutable[key]
|
|
797
833
|
|
|
798
834
|
@setdoc.basic
|
|
799
|
-
def __frozen__(self: Self) ->
|
|
835
|
+
def __frozen__(self: Self) -> tuple[Item, ...]:
|
|
800
836
|
with self.__mutate__() as mutable:
|
|
801
837
|
return tuple(mutable)
|
|
802
838
|
|
|
@@ -811,10 +847,6 @@ class MutableListLike[Item](ListLike[Item], MutableSequence[Item]):
|
|
|
811
847
|
with self.__mutate__() as mutable:
|
|
812
848
|
mutable.extend(data)
|
|
813
849
|
|
|
814
|
-
@abstractmethod
|
|
815
|
-
@setdoc.basic
|
|
816
|
-
def __mutate__(self: Self, /) -> ContextManager[__Mutable__[Item]]: ...
|
|
817
|
-
|
|
818
850
|
@overload
|
|
819
851
|
@setdoc.basic
|
|
820
852
|
def __setitem__(
|
|
@@ -835,10 +867,6 @@ class MutableListLike[Item](ListLike[Item], MutableSequence[Item]):
|
|
|
835
867
|
with self.__mutate__() as mutable:
|
|
836
868
|
mutable[key] = value # type: ignore
|
|
837
869
|
|
|
838
|
-
@setdoc.basic
|
|
839
|
-
def copy(self: Self) -> Self:
|
|
840
|
-
return type(self)(self)
|
|
841
|
-
|
|
842
870
|
@setdoc.basic
|
|
843
871
|
def insert(self: Self, index: SupportsIndex, item: Item, /) -> None:
|
|
844
872
|
with self.__mutate__() as mutable:
|
|
@@ -857,26 +885,26 @@ class MutableListLike[Item](ListLike[Item], MutableSequence[Item]):
|
|
|
857
885
|
### LIST-SLOT ###
|
|
858
886
|
|
|
859
887
|
|
|
860
|
-
class FrozenListSlot[Item](
|
|
888
|
+
class FrozenListSlot[Item](
|
|
889
|
+
FrozenObjectSlot[tuple[Item, ...]],
|
|
890
|
+
FrozenListLike[Item],
|
|
891
|
+
):
|
|
861
892
|
"""Provide slotted frozen list-like."""
|
|
862
893
|
|
|
863
|
-
__slots__ = (
|
|
864
|
-
_slot: FrozenListSlot.__Frozen__[Item]
|
|
865
|
-
|
|
866
|
-
@setdoc.basic
|
|
867
|
-
def __frozen__(self: Self) -> FrozenListSlot.__Frozen__[Item]:
|
|
868
|
-
return self._slot
|
|
894
|
+
__slots__ = ()
|
|
869
895
|
|
|
870
896
|
@setdoc.basic
|
|
871
897
|
def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None:
|
|
872
898
|
self._slot = tuple(data)
|
|
873
899
|
|
|
874
900
|
|
|
875
|
-
class MutableListSlot[Item](
|
|
901
|
+
class MutableListSlot[Item](
|
|
902
|
+
MutableListLike[Item],
|
|
903
|
+
ObjectSlot[tuple[Item, ...]],
|
|
904
|
+
):
|
|
876
905
|
"""Provide slotted mutable list-like."""
|
|
877
906
|
|
|
878
|
-
__slots__ = (
|
|
879
|
-
_slot: MutableListSlot.__Frozen__[Item]
|
|
907
|
+
__slots__ = ()
|
|
880
908
|
|
|
881
909
|
@contextmanager
|
|
882
910
|
@setdoc.basic
|
|
@@ -20,6 +20,7 @@ src/datahold.egg-info/dependency_links.txt
|
|
|
20
20
|
src/datahold.egg-info/requires.txt
|
|
21
21
|
src/datahold.egg-info/top_level.txt
|
|
22
22
|
tests/test_FrozenListSlot.py
|
|
23
|
+
tests/test_FrozenSetSlot.py
|
|
23
24
|
tests/test_MutableDictSlot.py
|
|
24
25
|
tests/test_MutableListSlot.py
|
|
25
26
|
tests/test_MutableSetSlot.py
|
|
@@ -28,8 +29,8 @@ tests/test_all.py
|
|
|
28
29
|
tests/test_attributes.py
|
|
29
30
|
tests/test_docs.py
|
|
30
31
|
tests/test_generic.py
|
|
31
|
-
tests/test_internal_comparison.py
|
|
32
32
|
tests/test_issubclass.py
|
|
33
|
+
tests/test_metaclass.py
|
|
33
34
|
tests/test_name.py
|
|
34
35
|
tests/test_nested.py
|
|
35
36
|
tests/test_sorted.py
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Self
|
|
3
|
+
|
|
4
|
+
from datahold import FrozenSetSlot
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestUnionOperator(unittest.TestCase):
|
|
8
|
+
def test_union_with_overlap(self: Self) -> None:
|
|
9
|
+
self.assertEqual(
|
|
10
|
+
FrozenSetSlot({1, 2, 3}) | FrozenSetSlot({3, 4}),
|
|
11
|
+
frozenset({1, 2, 3, 4}),
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def test_union_with_disjoint_sets(self: Self) -> None:
|
|
15
|
+
self.assertEqual(
|
|
16
|
+
FrozenSetSlot({1, 2}) | FrozenSetSlot({3, 4}),
|
|
17
|
+
frozenset({1, 2, 3, 4}),
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
def test_union_with_empty_set(self: Self) -> None:
|
|
21
|
+
self.assertEqual(
|
|
22
|
+
FrozenSetSlot({1, 2}) | FrozenSetSlot(),
|
|
23
|
+
frozenset({1, 2}),
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
def test_union_with_builtin_frozenset(self: Self) -> None:
|
|
27
|
+
self.assertEqual(
|
|
28
|
+
FrozenSetSlot({1, 2}) | frozenset({2, 3}),
|
|
29
|
+
frozenset({1, 2, 3}),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestIntersectionOperator(unittest.TestCase):
|
|
34
|
+
def test_intersection_with_overlap(self: Self) -> None:
|
|
35
|
+
self.assertEqual(
|
|
36
|
+
FrozenSetSlot({1, 2, 3}) & FrozenSetSlot({2, 3, 4}),
|
|
37
|
+
frozenset({2, 3}),
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
def test_intersection_with_disjoint_sets(self: Self) -> None:
|
|
41
|
+
self.assertEqual(
|
|
42
|
+
FrozenSetSlot({1, 2}) & FrozenSetSlot({3, 4}),
|
|
43
|
+
frozenset(),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def test_intersection_with_empty_set(self: Self) -> None:
|
|
47
|
+
self.assertEqual(
|
|
48
|
+
FrozenSetSlot({1, 2}) & FrozenSetSlot(),
|
|
49
|
+
frozenset(),
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
def test_intersection_with_builtin_set(self: Self) -> None:
|
|
53
|
+
self.assertEqual(
|
|
54
|
+
FrozenSetSlot({1, 2, 3}) & {2, 3, 4},
|
|
55
|
+
frozenset({2, 3}),
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
class TestDifferenceOperator(unittest.TestCase):
|
|
60
|
+
def test_difference_with_overlap(self: Self) -> None:
|
|
61
|
+
self.assertEqual(
|
|
62
|
+
FrozenSetSlot({1, 2, 3}) - FrozenSetSlot({2, 3, 4}),
|
|
63
|
+
frozenset({1}),
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
def test_difference_with_disjoint_sets(self: Self) -> None:
|
|
67
|
+
self.assertEqual(
|
|
68
|
+
FrozenSetSlot({1, 2}) - FrozenSetSlot({3, 4}),
|
|
69
|
+
frozenset({1, 2}),
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
def test_difference_with_identical_sets(self: Self) -> None:
|
|
73
|
+
self.assertEqual(
|
|
74
|
+
FrozenSetSlot({1, 2}) - FrozenSetSlot({1, 2}),
|
|
75
|
+
frozenset(),
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
def test_difference_with_empty_set(self: Self) -> None:
|
|
79
|
+
self.assertEqual(
|
|
80
|
+
FrozenSetSlot({1, 2}) - FrozenSetSlot(),
|
|
81
|
+
frozenset({1, 2}),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class TestSymmetricDifferenceOperator(unittest.TestCase):
|
|
86
|
+
def test_symmetric_difference_with_overlap(self: Self) -> None:
|
|
87
|
+
self.assertEqual(
|
|
88
|
+
FrozenSetSlot({1, 2, 3}) ^ FrozenSetSlot({3, 4}),
|
|
89
|
+
frozenset({1, 2, 4}),
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
def test_symmetric_difference_with_disjoint_sets(self: Self) -> None:
|
|
93
|
+
self.assertEqual(
|
|
94
|
+
FrozenSetSlot({1, 2}) ^ FrozenSetSlot({3, 4}),
|
|
95
|
+
frozenset({1, 2, 3, 4}),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
def test_symmetric_difference_with_identical_sets(self: Self) -> None:
|
|
99
|
+
self.assertEqual(
|
|
100
|
+
FrozenSetSlot({1, 2}) ^ FrozenSetSlot({1, 2}),
|
|
101
|
+
frozenset(),
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
def test_symmetric_difference_with_empty_set(self: Self) -> None:
|
|
105
|
+
self.assertEqual(
|
|
106
|
+
FrozenSetSlot({1, 2}) ^ FrozenSetSlot(),
|
|
107
|
+
frozenset({1, 2}),
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class TestSubsetOperator(unittest.TestCase):
|
|
112
|
+
def test_equal_sets_are_subsets(self: Self) -> None:
|
|
113
|
+
self.assertTrue(FrozenSetSlot({1, 2}) <= FrozenSetSlot({1, 2}))
|
|
114
|
+
|
|
115
|
+
def test_proper_subset_is_subset(self: Self) -> None:
|
|
116
|
+
self.assertTrue(FrozenSetSlot({1, 2}) <= FrozenSetSlot({1, 2, 3}))
|
|
117
|
+
|
|
118
|
+
def test_larger_set_is_not_subset(self: Self) -> None:
|
|
119
|
+
self.assertFalse(FrozenSetSlot({1, 2, 3}) <= FrozenSetSlot({1, 2}))
|
|
120
|
+
|
|
121
|
+
def test_empty_set_is_subset(self: Self) -> None:
|
|
122
|
+
self.assertTrue(FrozenSetSlot() <= FrozenSetSlot({1}))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TestProperSubsetOperator(unittest.TestCase):
|
|
126
|
+
def test_proper_subset(self: Self) -> None:
|
|
127
|
+
self.assertTrue(FrozenSetSlot({1, 2}) < FrozenSetSlot({1, 2, 3}))
|
|
128
|
+
|
|
129
|
+
def test_equal_sets_are_not_proper_subsets(self: Self) -> None:
|
|
130
|
+
self.assertFalse(FrozenSetSlot({1, 2}) < FrozenSetSlot({1, 2}))
|
|
131
|
+
|
|
132
|
+
def test_larger_set_is_not_proper_subset(self: Self) -> None:
|
|
133
|
+
self.assertFalse(FrozenSetSlot({1, 2, 3}) < FrozenSetSlot({1, 2}))
|
|
134
|
+
|
|
135
|
+
def test_empty_set_is_proper_subset_of_nonempty_set(self: Self) -> None:
|
|
136
|
+
self.assertTrue(FrozenSetSlot() < FrozenSetSlot({1}))
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
class TestSupersetOperator(unittest.TestCase):
|
|
140
|
+
def test_equal_sets_are_supersets(self: Self) -> None:
|
|
141
|
+
self.assertTrue(FrozenSetSlot({1, 2}) >= FrozenSetSlot({1, 2}))
|
|
142
|
+
|
|
143
|
+
def test_larger_set_is_superset(self: Self) -> None:
|
|
144
|
+
self.assertTrue(FrozenSetSlot({1, 2, 3}) >= FrozenSetSlot({1, 2}))
|
|
145
|
+
|
|
146
|
+
def test_smaller_set_is_not_superset(self: Self) -> None:
|
|
147
|
+
self.assertFalse(FrozenSetSlot({1, 2}) >= FrozenSetSlot({1, 2, 3}))
|
|
148
|
+
|
|
149
|
+
def test_every_set_is_superset_of_empty_set(self: Self) -> None:
|
|
150
|
+
self.assertTrue(FrozenSetSlot({1}) >= FrozenSetSlot())
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
class TestProperSupersetOperator(unittest.TestCase):
|
|
154
|
+
def test_proper_superset(self: Self) -> None:
|
|
155
|
+
self.assertTrue(FrozenSetSlot({1, 2, 3}) > FrozenSetSlot({1, 2}))
|
|
156
|
+
|
|
157
|
+
def test_equal_sets_are_not_proper_supersets(self: Self) -> None:
|
|
158
|
+
self.assertFalse(FrozenSetSlot({1, 2}) > FrozenSetSlot({1, 2}))
|
|
159
|
+
|
|
160
|
+
def test_smaller_set_is_not_proper_superset(self: Self) -> None:
|
|
161
|
+
self.assertFalse(FrozenSetSlot({1, 2}) > FrozenSetSlot({1, 2, 3}))
|
|
162
|
+
|
|
163
|
+
def test_nonempty_set_is_proper_superset_of_empty_set(self: Self) -> None:
|
|
164
|
+
self.assertTrue(FrozenSetSlot({1}) > FrozenSetSlot())
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
class TestEqualityOperator(unittest.TestCase):
|
|
168
|
+
def test_equal_instances(self: Self) -> None:
|
|
169
|
+
self.assertTrue(FrozenSetSlot({1, 2, 3}) == FrozenSetSlot({3, 2, 1}))
|
|
170
|
+
|
|
171
|
+
def test_equal_to_builtin_frozenset(self: Self) -> None:
|
|
172
|
+
self.assertTrue(FrozenSetSlot({1, 2}) == frozenset({1, 2})) # type: ignore[comparison-overlap]
|
|
173
|
+
|
|
174
|
+
def test_equal_to_builtin_set(self: Self) -> None:
|
|
175
|
+
self.assertTrue(FrozenSetSlot({1, 2}) == {1, 2}) # type: ignore[comparison-overlap]
|
|
176
|
+
|
|
177
|
+
def test_unequal_values(self: Self) -> None:
|
|
178
|
+
self.assertFalse(FrozenSetSlot({1, 2}) == FrozenSetSlot({1, 3}))
|
|
179
|
+
|
|
180
|
+
def test_not_equal_to_non_set_object(self: Self) -> None:
|
|
181
|
+
self.assertFalse(FrozenSetSlot({1, 2}) == [1, 2]) # type: ignore[comparison-overlap]
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
class TestInequalityOperator(unittest.TestCase):
|
|
185
|
+
def test_different_instances_are_unequal(self: Self) -> None:
|
|
186
|
+
self.assertTrue(FrozenSetSlot({1, 2}) != FrozenSetSlot({1, 3}))
|
|
187
|
+
|
|
188
|
+
def test_equal_instances_are_not_unequal(self: Self) -> None:
|
|
189
|
+
self.assertFalse(FrozenSetSlot({1, 2}) != FrozenSetSlot({2, 1}))
|
|
190
|
+
|
|
191
|
+
def test_equal_builtin_frozenset_is_not_unequal(self: Self) -> None:
|
|
192
|
+
self.assertFalse(FrozenSetSlot({1, 2}) != frozenset({1, 2})) # type: ignore[comparison-overlap]
|
|
193
|
+
|
|
194
|
+
def test_different_builtin_set_is_unequal(self: Self) -> None:
|
|
195
|
+
self.assertTrue(FrozenSetSlot({1, 2}) != {1, 2, 3}) # type: ignore[comparison-overlap]
|
|
196
|
+
|
|
197
|
+
def test_non_set_object_is_unequal(self: Self) -> None:
|
|
198
|
+
self.assertTrue(FrozenSetSlot({1, 2}) != [1, 2]) # type: ignore[comparison-overlap]
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
class TestMembershipOperator(unittest.TestCase):
|
|
202
|
+
def test_existing_element_is_member(self: Self) -> None:
|
|
203
|
+
self.assertTrue(2 in FrozenSetSlot({1, 2, 3}))
|
|
204
|
+
|
|
205
|
+
def test_missing_element_is_not_member(self: Self) -> None:
|
|
206
|
+
self.assertFalse(4 in FrozenSetSlot({1, 2, 3}))
|
|
207
|
+
|
|
208
|
+
def test_nested_frozenset_is_member(self: Self) -> None:
|
|
209
|
+
nested = frozenset({1, 2})
|
|
210
|
+
self.assertTrue(nested in FrozenSetSlot({nested, frozenset({3})}))
|
|
211
|
+
|
|
212
|
+
def test_equivalent_set_matches_nested_frozenset(self: Self) -> None:
|
|
213
|
+
self.assertTrue({1, 2} in FrozenSetSlot({frozenset({1, 2})}))
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
class TestNonMembershipOperator(unittest.TestCase):
|
|
217
|
+
def test_missing_element_is_not_member(self: Self) -> None:
|
|
218
|
+
self.assertTrue(4 not in FrozenSetSlot({1, 2, 3}))
|
|
219
|
+
|
|
220
|
+
def test_existing_element_is_member(self: Self) -> None:
|
|
221
|
+
self.assertFalse(2 not in FrozenSetSlot({1, 2, 3}))
|
|
222
|
+
|
|
223
|
+
def test_missing_nested_frozenset_is_not_member(self: Self) -> None:
|
|
224
|
+
self.assertTrue(
|
|
225
|
+
frozenset({3, 4}) not in FrozenSetSlot({frozenset({1, 2})})
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
def test_equivalent_set_is_considered_a_member(self: Self) -> None:
|
|
229
|
+
self.assertFalse({1, 2} not in FrozenSetSlot({frozenset({1, 2})}))
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
if __name__ == "__main__":
|
|
233
|
+
unittest.main()
|
|
@@ -4,7 +4,7 @@ __all__: list[str] = ["TestAbstractmethods"]
|
|
|
4
4
|
|
|
5
5
|
import inspect as ins
|
|
6
6
|
import unittest
|
|
7
|
-
from typing import Any,
|
|
7
|
+
from typing import Any, Self
|
|
8
8
|
|
|
9
9
|
from Lazy import Lazy
|
|
10
10
|
|
|
@@ -22,6 +22,8 @@ class TestAbstractmethods(unittest.TestCase):
|
|
|
22
22
|
def test_abstractmethods(self: Self, /) -> None:
|
|
23
23
|
name: Any
|
|
24
24
|
for name in Lazy.lazy.datatypes.keys():
|
|
25
|
+
if "Object" in name:
|
|
26
|
+
continue
|
|
25
27
|
with self.subTest(datatype=name):
|
|
26
28
|
self._test(name, Lazy.get_abstractmethods(name))
|
|
27
29
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
__all__: list[str] = ["TestMetaclass"]
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
from abc import ABCMeta
|
|
7
|
+
from typing import Any, Self
|
|
8
|
+
|
|
9
|
+
from Lazy import Lazy
|
|
10
|
+
|
|
11
|
+
import datahold
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestMetaclass(unittest.TestCase):
|
|
15
|
+
|
|
16
|
+
def test_metaclass(self: Self, /) -> None:
|
|
17
|
+
datatype: type[Any]
|
|
18
|
+
for name in Lazy.lazy.datatypes.keys():
|
|
19
|
+
with self.subTest(datatype=name):
|
|
20
|
+
datatype = getattr(datahold, name)
|
|
21
|
+
self.assertIs(type(datatype), ABCMeta)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
unittest.main(verbosity=2)
|
|
@@ -31,28 +31,28 @@ class TestName(unittest.TestCase):
|
|
|
31
31
|
# all
|
|
32
32
|
datatype = getattr(datahold, name)
|
|
33
33
|
self.assertEqual(datatype.__name__, name)
|
|
34
|
-
self.assertTrue(
|
|
35
|
-
|
|
34
|
+
self.assertTrue(issubclass(datatype, datahold.Object))
|
|
35
|
+
if "Object" in name:
|
|
36
|
+
return
|
|
36
37
|
self.assertTrue(issubclass(datatype, datahold.Collection))
|
|
38
|
+
self.assertTrue(hasattr(datatype, "__frozen__"))
|
|
37
39
|
# frozen
|
|
38
40
|
if prefix == "Frozen":
|
|
39
41
|
self.assertIsNot(datatype.__hash__, object.__hash__)
|
|
40
42
|
self.assertTrue(issubclass(datatype, abc.Hashable))
|
|
41
|
-
self.assertFalse(hasattr(datatype, "__Mutable__"))
|
|
42
43
|
self.assertFalse(hasattr(datatype, "__mutate__"))
|
|
43
44
|
ancestor = getattr(datahold, name[6:], object)
|
|
44
45
|
self.assertTrue(issubclass(datatype, ancestor))
|
|
45
46
|
# mutable
|
|
46
47
|
if prefix == "Mutable":
|
|
47
48
|
self.assertIn(datatype.__hash__, [None, object.__hash__])
|
|
48
|
-
self.assertTrue(hasattr(datatype, "__Mutable__"))
|
|
49
49
|
self.assertTrue(hasattr(datatype, "__mutate__"))
|
|
50
|
+
self.assertTrue(issubclass(datatype, datahold.MutableObject))
|
|
50
51
|
ancestor = getattr(datahold, name[7:], object)
|
|
51
52
|
self.assertTrue(issubclass(datatype, ancestor))
|
|
52
53
|
# no prefix
|
|
53
54
|
if prefix == "":
|
|
54
55
|
self.assertIn(datatype.__hash__, [None, object.__hash__])
|
|
55
|
-
self.assertFalse(hasattr(datatype, "__Mutable__"))
|
|
56
56
|
self.assertFalse(hasattr(datatype, "__mutate__"))
|
|
57
57
|
# like
|
|
58
58
|
if suffix == "Like":
|
|
@@ -60,6 +60,7 @@ class TestName(unittest.TestCase):
|
|
|
60
60
|
# slot
|
|
61
61
|
if suffix == "Slot":
|
|
62
62
|
self.assertTrue(hasattr(datatype, "__init__"))
|
|
63
|
+
self.assertTrue(issubclass(datatype, datahold.ObjectSlot))
|
|
63
64
|
ancestor = getattr(datahold, name[:-4] + "Like")
|
|
64
65
|
self.assertTrue(issubclass(datatype, ancestor))
|
|
65
66
|
# no suffix
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
[datatypes.Collection]
|
|
1
|
+
[datatypes.Collection.issubclass]
|
|
2
|
+
"datahold.Object" = true
|
|
2
3
|
|
|
3
4
|
[datatypes.DictLike.attributes]
|
|
4
5
|
__or__ = "datahold.DictLike"
|
|
@@ -27,8 +28,6 @@ __init__ = "datahold.ListLike"
|
|
|
27
28
|
"collections.abc.Sequence" = true
|
|
28
29
|
|
|
29
30
|
[datatypes.FrozenListLike.nested]
|
|
30
|
-
__Frozen__ = "builtins.tuple"
|
|
31
|
-
__Mutable__ = ""
|
|
32
31
|
|
|
33
32
|
[datatypes.FrozenListLike.varia]
|
|
34
33
|
generic = 1
|
|
@@ -138,12 +137,16 @@ args = [
|
|
|
138
137
|
]
|
|
139
138
|
|
|
140
139
|
[datatypes.FrozenListSlot.nested]
|
|
141
|
-
__Frozen__ = "builtins.tuple"
|
|
142
|
-
__Mutable__ = ""
|
|
143
140
|
|
|
144
141
|
[datatypes.FrozenListSlot.varia]
|
|
145
142
|
generic = 1
|
|
146
143
|
|
|
144
|
+
[datatypes.FrozenObjectSlot.issubclass]
|
|
145
|
+
"datahold.ObjectSlot" = true
|
|
146
|
+
|
|
147
|
+
[datatypes.FrozenObjectSlot.varia]
|
|
148
|
+
generic = 1
|
|
149
|
+
|
|
147
150
|
[datatypes.FrozenSetLike.issubclass]
|
|
148
151
|
"collections.abc.Hashable" = true
|
|
149
152
|
"collections.abc.Set" = true
|
|
@@ -172,8 +175,6 @@ index = "collections.abc.Sequence"
|
|
|
172
175
|
"datahold.MutableSequence" = false
|
|
173
176
|
|
|
174
177
|
[datatypes.ListLike.nested]
|
|
175
|
-
__Frozen__ = "builtins.tuple"
|
|
176
|
-
__Mutable__ = ""
|
|
177
178
|
|
|
178
179
|
[datatypes.ListLike.varia]
|
|
179
180
|
generic = 1
|
|
@@ -185,11 +186,13 @@ generic = 1
|
|
|
185
186
|
[datatypes.MutableDictLike.attributes]
|
|
186
187
|
__ior__ = "datahold.MutableDictLike"
|
|
187
188
|
__or__ = "datahold.DictLike"
|
|
189
|
+
copy = "datahold.MutableObjectLike"
|
|
188
190
|
|
|
189
191
|
[datatypes.MutableDictLike.issubclass]
|
|
190
192
|
"collections.abc.Mapping" = true
|
|
191
193
|
"collections.abc.MutableMapping" = true
|
|
192
194
|
"datahold.MutableMapping" = true
|
|
195
|
+
"datahold.MutableObjectLike" = true
|
|
193
196
|
|
|
194
197
|
[datatypes.MutableDictSlot.issubclass]
|
|
195
198
|
"collections.abc.Mapping" = true
|
|
@@ -207,6 +210,7 @@ __mutate__ = "datahold.MutableListLike"
|
|
|
207
210
|
__reversed__ = "collections.abc.Sequence"
|
|
208
211
|
append = "collections.abc.MutableSequence"
|
|
209
212
|
clear = "collections.abc.MutableSequence"
|
|
213
|
+
copy = "datahold.MutableObjectLike"
|
|
210
214
|
count = "collections.abc.Sequence"
|
|
211
215
|
extend = "collections.abc.MutableSequence"
|
|
212
216
|
foo = ""
|
|
@@ -221,10 +225,10 @@ reverse = "collections.abc.MutableSequence"
|
|
|
221
225
|
"collections.abc.Hashable" = false
|
|
222
226
|
"collections.abc.MutableMapping" = false
|
|
223
227
|
"collections.abc.MutableSequence" = true
|
|
228
|
+
"datahold.MutableObjectLike" = true
|
|
224
229
|
"datahold.MutableSequence" = true
|
|
225
230
|
|
|
226
231
|
[datatypes.MutableListLike.nested]
|
|
227
|
-
__Frozen__ = "builtins.tuple"
|
|
228
232
|
__hash__ = ""
|
|
229
233
|
|
|
230
234
|
[datatypes.MutableListLike.varia]
|
|
@@ -237,7 +241,6 @@ generic = 1
|
|
|
237
241
|
"datahold.MutableListSlot" = true
|
|
238
242
|
|
|
239
243
|
[datatypes.MutableListSlot.nested]
|
|
240
|
-
__Frozen__ = "builtins.tuple"
|
|
241
244
|
__hash__ = ""
|
|
242
245
|
|
|
243
246
|
[datatypes.MutableListSlot.varia]
|
|
@@ -247,9 +250,17 @@ generic = 1
|
|
|
247
250
|
"collections.abc.MutableMapping" = true
|
|
248
251
|
"datahold.Mapping" = true
|
|
249
252
|
|
|
253
|
+
[datatypes.MutableObject.issubclass]
|
|
254
|
+
"datahold.Object" = true
|
|
255
|
+
|
|
256
|
+
[datatypes.MutableObjectLike.attributes]
|
|
257
|
+
__init__ = "datahold.MutableObjectLike"
|
|
258
|
+
copy = "datahold.MutableObjectLike"
|
|
259
|
+
|
|
260
|
+
[datatypes.MutableObjectLike.issubclass]
|
|
261
|
+
"datahold.Object" = true
|
|
262
|
+
|
|
250
263
|
[datatypes.MutableSequence.attributes]
|
|
251
|
-
__Frozen__ = "datahold.Sequence"
|
|
252
|
-
__Mutable__ = "datahold.MutableSequence"
|
|
253
264
|
__delitem__ = "datahold.MutableSequence"
|
|
254
265
|
__frozen__ = "datahold.Sequence"
|
|
255
266
|
__getitem__ = "datahold.MutableSequence"
|
|
@@ -263,11 +274,15 @@ sort = ""
|
|
|
263
274
|
"collections.abc.Set" = true
|
|
264
275
|
"datahold.Collection" = true
|
|
265
276
|
|
|
277
|
+
[datatypes.MutableSetLike.attributes]
|
|
278
|
+
copy = "datahold.MutableObjectLike"
|
|
279
|
+
|
|
266
280
|
[datatypes.MutableSetLike.issubclass]
|
|
267
281
|
"collections.abc.Hashable" = false
|
|
268
282
|
"collections.abc.MutableSet" = true
|
|
269
283
|
"collections.abc.Set" = true
|
|
270
284
|
"datahold.Collection" = true
|
|
285
|
+
"datahold.MutableObjectLike" = true
|
|
271
286
|
"datahold.MutableSet" = true
|
|
272
287
|
"datahold.SetLike" = true
|
|
273
288
|
|
|
@@ -278,6 +293,15 @@ sort = ""
|
|
|
278
293
|
"datahold.MutableSet" = true
|
|
279
294
|
"datahold.MutableSetLike" = true
|
|
280
295
|
|
|
296
|
+
[datatypes.Object.varia]
|
|
297
|
+
generic = 1
|
|
298
|
+
|
|
299
|
+
[datatypes.ObjectSlot.issubclass]
|
|
300
|
+
"datahold.Object" = true
|
|
301
|
+
|
|
302
|
+
[datatypes.ObjectSlot.varia]
|
|
303
|
+
generic = 1
|
|
304
|
+
|
|
281
305
|
[datatypes.Sequence]
|
|
282
306
|
|
|
283
307
|
[datatypes.Set.issubclass]
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import operator
|
|
2
|
-
import unittest
|
|
3
|
-
from typing import Any, Self
|
|
4
|
-
|
|
5
|
-
from Lazy import Lazy
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class TestInternalComparsion(unittest.TestCase):
|
|
9
|
-
def _test_typename(self: Self, typename: str, /, **kwargs: Any) -> None:
|
|
10
|
-
for opername, info in kwargs.items():
|
|
11
|
-
oper = getattr(operator, opername)
|
|
12
|
-
with self.subTest(operator=opername):
|
|
13
|
-
self._test_operator(typename, oper, **info)
|
|
14
|
-
|
|
15
|
-
def _test_operator(self: Self, *args: Any, **kwargs: Any) -> None:
|
|
16
|
-
for testname, testinfo in kwargs.items():
|
|
17
|
-
with self.subTest(testname=testname):
|
|
18
|
-
self._test_vars(*args, **testinfo)
|
|
19
|
-
|
|
20
|
-
def _test_vars(
|
|
21
|
-
self: Self,
|
|
22
|
-
typename: str,
|
|
23
|
-
oper: Any,
|
|
24
|
-
/,
|
|
25
|
-
*,
|
|
26
|
-
a: str,
|
|
27
|
-
b: str,
|
|
28
|
-
valid: bool = True,
|
|
29
|
-
) -> None:
|
|
30
|
-
example_a = Lazy.get_example(typename, a)
|
|
31
|
-
example_b = Lazy.get_example(typename, b)
|
|
32
|
-
builtin_a = Lazy.get_builtin_example(typename, a)
|
|
33
|
-
builtin_b = Lazy.get_builtin_example(typename, b)
|
|
34
|
-
if valid:
|
|
35
|
-
answer = oper(example_a, example_b)
|
|
36
|
-
solution = oper(builtin_a, builtin_b)
|
|
37
|
-
self.assertEqual(answer, solution)
|
|
38
|
-
return
|
|
39
|
-
with self.assertRaises(Exception):
|
|
40
|
-
answer = oper(example_a, example_b)
|
|
41
|
-
with self.assertRaises(Exception):
|
|
42
|
-
solution = oper(builtin_a, builtin_b)
|
|
43
|
-
|
|
44
|
-
def test_internal_comparison(self: Self) -> None:
|
|
45
|
-
for typename, info in Lazy.lazy.datatypes.items():
|
|
46
|
-
with self.subTest(typename=typename):
|
|
47
|
-
self._test_typename(
|
|
48
|
-
typename,
|
|
49
|
-
**info.get("TestInternalComparsion", {}),
|
|
50
|
-
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|