datahold 4.0.0.dev21__tar.gz → 4.0.0.dev23__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.
Files changed (38) hide show
  1. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/PKG-INFO +2 -1
  2. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/pyproject.toml +3 -2
  3. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold/__init__.py +285 -48
  4. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold.egg-info/PKG-INFO +2 -1
  5. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold.egg-info/SOURCES.txt +2 -2
  6. datahold-4.0.0.dev23/src/datahold.egg-info/requires.txt +2 -0
  7. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_abstractmethods.py +5 -9
  8. datahold-4.0.0.dev23/tests/test_name.py +81 -0
  9. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/testdata.toml +40 -35
  10. datahold-4.0.0.dev21/src/datahold.egg-info/requires.txt +0 -1
  11. datahold-4.0.0.dev21/tests/test_prefix.py +0 -41
  12. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/LICENSE.txt +0 -0
  13. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/MANIFEST.in +0 -0
  14. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/README.rst +0 -0
  15. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v1.1.rst +0 -0
  16. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v1.2.rst +0 -0
  17. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v2.0.rst +0 -0
  18. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v2.1.rst +0 -0
  19. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v2.2.rst +0 -0
  20. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v2.3.rst +0 -0
  21. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v3.0.rst +0 -0
  22. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/docs/v4.0.rst +0 -0
  23. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/run_tests.py +0 -0
  24. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/setup.cfg +0 -0
  25. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold/py.typed +0 -0
  26. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold.egg-info/dependency_links.txt +0 -0
  27. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/src/datahold.egg-info/top_level.txt +0 -0
  28. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_FrozenListSlot.py +0 -0
  29. /datahold-4.0.0.dev21/tests/test_MutableListHold.py → /datahold-4.0.0.dev23/tests/test_MutableListSlot.py +0 -0
  30. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_all.py +0 -0
  31. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_attributes.py +0 -0
  32. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_docs.py +0 -0
  33. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_generic.py +0 -0
  34. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_internal_comparison.py +0 -0
  35. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_issubclass.py +0 -0
  36. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_nested.py +0 -0
  37. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_sorted.py +0 -0
  38. {datahold-4.0.0.dev21 → datahold-4.0.0.dev23}/tests/test_variance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datahold
3
- Version: 4.0.0.dev21
3
+ Version: 4.0.0.dev23
4
4
  Summary: This project wraps common mutable datastructures for inheritance with modification.
5
5
  Author-email: Johannes <johannes.programming@gmail.com>
6
6
  License-Expression: MIT
@@ -19,6 +19,7 @@ Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE.txt
22
+ Requires-Dist: frozendict<3,>=2.4.7
22
23
  Requires-Dist: setdoc<2,>=1.3.24
23
24
  Dynamic: license-file
24
25
 
@@ -19,6 +19,7 @@ classifiers = [
19
19
  "Typing :: Typed",
20
20
  ]
21
21
  dependencies = [
22
+ "frozendict>=2.4.7,<3",
22
23
  "setdoc>=1.3.24,<2",
23
24
  ]
24
25
  description = "This project wraps common mutable datastructures for inheritance with modification."
@@ -30,7 +31,7 @@ license-files = [
30
31
  name = "datahold"
31
32
  readme = "README.rst"
32
33
  requires-python = ">=3.11"
33
- version = "4.0.0.dev21"
34
+ version = "4.0.0.dev23"
34
35
 
35
36
  [project.urls]
36
37
  Download = "https://pypi.org/project/datahold/#files"
@@ -42,5 +43,5 @@ Website = "http://datahold.johannes-programming.online/"
42
43
  files = [
43
44
  ".",
44
45
  ]
45
- python_version = "3.11"
46
+ python_version = "3.12"
46
47
  strict = true
@@ -4,14 +4,22 @@ from __future__ import annotations
4
4
 
5
5
  __all__: list[str] = [
6
6
  "Collection",
7
+ "DictLike",
8
+ "DictSlot",
9
+ "FrozenDictLike",
10
+ "FrozenDictSlot",
7
11
  "FrozenListLike",
8
12
  "FrozenListSlot",
9
13
  "FrozenSetLike",
10
14
  "FrozenSetSlot",
11
15
  "ListLike",
12
16
  "ListSlot",
17
+ "Mapping",
18
+ "MutableDictLike",
19
+ "MutableDictSlot",
13
20
  "MutableListLike",
14
21
  "MutableListSlot",
22
+ "MutableMapping",
15
23
  "MutableSequence",
16
24
  "MutableSet",
17
25
  "MutableSetLike",
@@ -37,6 +45,7 @@ from typing import (
37
45
  )
38
46
 
39
47
  import setdoc
48
+ from frozendict import frozendict
40
49
 
41
50
  ### UTILS ###
42
51
 
@@ -57,6 +66,20 @@ class ContextManager[Enter](Protocol):
57
66
  ) -> object: ...
58
67
 
59
68
 
69
+ class SupportsKeysAndGetitem[Key, Value](Protocol):
70
+ """Provide protocol supporting keys and __getitem__."""
71
+
72
+ @setdoc.basic
73
+ def __getitem__(self: Self, key: Key, /) -> Value: ...
74
+ @setdoc.basic
75
+ def keys(self: Self, /) -> abc.Iterable[Key]: ...
76
+
77
+
78
+ type DictInit[Key, Value] = (
79
+ SupportsKeysAndGetitem[Key | str, Optional[Value]]
80
+ | abc.Iterable[tuple[Key | str, Optional[Value]]]
81
+ )
82
+
60
83
  type Slice[Index] = slice[Optional[Index], Optional[Index], Optional[Index]]
61
84
 
62
85
 
@@ -68,12 +91,12 @@ class Collection[Item](
68
91
  abc.Iterable[Item],
69
92
  abc.Container[object],
70
93
  ):
71
- """Provide abc for custom collections."""
94
+ """Provide abc for custom collection."""
72
95
 
73
96
  @setdoc.basic
74
- class __Frozen__[FrozenItem](
97
+ class __Frozen__[Item_](
75
98
  abc.Sized,
76
- abc.Iterable[FrozenItem],
99
+ abc.Iterable[Item_],
77
100
  Protocol,
78
101
  ):
79
102
  @setdoc.basic
@@ -114,9 +137,9 @@ class MutableSet[Item: abc.Hashable](Set[Item], abc.MutableSet[Item]):
114
137
  __slots__ = ()
115
138
 
116
139
  @setdoc.basic
117
- class __Mutable__[MutableItem: abc.Hashable](Protocol):
140
+ class __Mutable__[Item_: abc.Hashable](Protocol):
118
141
  @setdoc.basic
119
- def add(self: Self, item: MutableItem, /) -> object: ...
142
+ def add(self: Self, item: Item_, /) -> object: ...
120
143
  @setdoc.basic
121
144
  def discard(self: Self, item: abc.Hashable, /) -> object: ...
122
145
  @abstractmethod
@@ -140,15 +163,14 @@ class SetLike[Item: abc.Hashable](Set[Item]):
140
163
  """Provide abc for custom set-like."""
141
164
 
142
165
  __slots__ = ()
143
- type __Frozen__[FrozenItem] = frozenset[FrozenItem]
144
- type Init[FrozenItem] = abc.Iterable[FrozenItem]
166
+ type __Frozen__[Item_] = frozenset[Item_]
145
167
 
146
168
  @abstractmethod
147
169
  @setdoc.basic
148
170
  def __frozen__(self: Self, /) -> __Frozen__[Item]: ...
149
171
  @abstractmethod
150
172
  @setdoc.basic
151
- def __init__(self: Self, data: Init[Item] = (), /) -> None: ...
173
+ def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None: ...
152
174
  @setdoc.basic
153
175
  def difference(self: Self, /, *others: abc.Iterable[abc.Hashable]) -> Self:
154
176
  return type(self)(self.__frozen__().difference(*others))
@@ -190,17 +212,15 @@ class MutableSetLike[Item: abc.Hashable](SetLike[Item], MutableSet[Item]):
190
212
  """Provide abc for custom mutable set-like."""
191
213
 
192
214
  __slots__ = ()
193
-
194
- type __Mutable__[MutableItem] = set[MutableItem]
215
+ type __Mutable__[Item_] = set[Item_]
195
216
 
196
217
  @setdoc.basic
197
218
  def __frozen__(self: Self, /) -> MutableSetLike.__Frozen__[Item]:
198
219
  with self.__mutate__() as mutable:
199
220
  return frozenset(mutable)
200
221
 
201
- @abstractmethod
202
222
  @setdoc.basic
203
- def __init__(self: Self, data: MutableSetLike.Init[Item] = (), /) -> None:
223
+ def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None:
204
224
  with self.__mutate__() as mutable:
205
225
  mutable.update(data)
206
226
 
@@ -255,7 +275,7 @@ class FrozenSetSlot[Item](SetSlot[Item], FrozenSetLike[Item]):
255
275
  __slots__ = ()
256
276
 
257
277
  @setdoc.basic
258
- def __init__(self: Self, data: FrozenSetSlot.Init[Item] = (), /) -> None:
278
+ def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None:
259
279
  self._slot = frozenset(data)
260
280
 
261
281
 
@@ -266,44 +286,270 @@ class MutableSetSlot[Item](SetSlot[Item], MutableSetLike[Item]):
266
286
 
267
287
  @contextmanager
268
288
  @setdoc.basic
269
- def __mutate__(self: Self, /) -> abc.Generator[set[Item], None, None]:
289
+ def __mutate__(
290
+ self: Self,
291
+ /,
292
+ ) -> abc.Generator[MutableSetSlot.__Mutable__[Item], None, None]:
293
+ slot: MutableSetSlot.__Mutable__[Item]
270
294
  slot = set(getattr(self, "_slot", ()))
271
295
  yield slot
272
296
  self._slot = frozenset(slot)
273
297
 
274
298
 
299
+ ### MAPPING ###
300
+
301
+
302
+ class Mapping[Key: abc.Hashable, Value](
303
+ Collection[Key],
304
+ abc.Mapping[Key, Value],
305
+ ):
306
+ """Provide abc for custom mapping."""
307
+
308
+ __slots__ = ()
309
+
310
+ @setdoc.basic
311
+ class __Frozen__[FrozenKey, FrozenValue](
312
+ Collection.__Frozen__[FrozenKey], Protocol
313
+ ):
314
+ @setdoc.basic
315
+ def __getitem__(self: Self, key: abc.Hashable, /) -> FrozenValue: ...
316
+ @abstractmethod
317
+ @setdoc.basic
318
+ def __frozen__(self: Self, /) -> __Frozen__[Key, Value]: ...
319
+ @setdoc.basic
320
+ def __getitem__(self: Self, key: abc.Hashable, /) -> Value:
321
+ return self.__frozen__()[key]
322
+
323
+
324
+ class MutableMapping[Key: abc.Hashable, Value](
325
+ Mapping[Key, Value],
326
+ abc.MutableMapping[Key | str, Optional[Value]],
327
+ ):
328
+ """Provide abc for custom mutable mapping."""
329
+
330
+ __slots__ = ()
331
+
332
+ @setdoc.basic
333
+ class __Mutable__[Key_, Value_](
334
+ Protocol,
335
+ ):
336
+ @setdoc.basic
337
+ def __delitem__(self: Self, key: Key_ | str, /) -> object: ...
338
+ @setdoc.basic
339
+ def __setitem__(
340
+ self: Self, key: Key_ | str, value: Optional[Value_], /
341
+ ) -> object: ...
342
+
343
+ @setdoc.basic
344
+ def __delitem__(self: Self, key: Key | str, /) -> None:
345
+ with self.__mutate__() as mutable:
346
+ del mutable[key]
347
+
348
+ @abstractmethod
349
+ @setdoc.basic
350
+ def __mutate__(self: Self) -> ContextManager[__Mutable__[Key, Value]]: ...
351
+ @setdoc.basic
352
+ def __setitem__(
353
+ self: Self, key: Key | str, value: Optional[Value], /
354
+ ) -> None:
355
+ self[key] = value
356
+
357
+
358
+ ### DICT-LIKE ###
359
+
360
+
361
+ class DictLike[Key: abc.Hashable, Value](
362
+ Mapping[Key | str, Optional[Value]],
363
+ ):
364
+ """Provide abc for custom dict-like."""
365
+
366
+ __slots__ = ()
367
+ type __Frozen__[FrozenKey, FrozenValue] = frozendict[
368
+ FrozenKey | str, Optional[FrozenValue]
369
+ ]
370
+
371
+ @abstractmethod
372
+ @setdoc.basic
373
+ def __frozen__(self: Self, /) -> __Frozen__[Key, Value]: ... # type: ignore[override]
374
+ @abstractmethod
375
+ @setdoc.basic
376
+ def __init__(
377
+ self: Self,
378
+ data: DictInit[Key, Value] = (),
379
+ /,
380
+ **kwargs: Value,
381
+ ): ...
382
+ @setdoc.basic
383
+ def __or__[Key_, Value_](
384
+ self: Self,
385
+ other: DictInit[Key_, Value_],
386
+ /,
387
+ ) -> DictLike[Key | Key_, Value | Value_]:
388
+ data: DictLike.__Frozen__[Key_, Value_]
389
+ try:
390
+ data = frozendict(other) # type: ignore[arg-type]
391
+ except TypeError:
392
+ return NotImplemented
393
+ return type(self)( # type: ignore[return-value]
394
+ self.__frozen__() | data # type: ignore[operator]
395
+ )
396
+
397
+ @classmethod
398
+ @setdoc.basic
399
+ def fromkeys(
400
+ cls: type[Self],
401
+ iterable: abc.Iterable[Key | str],
402
+ value: Optional[Value],
403
+ /,
404
+ ) -> Self:
405
+ return cls(dict.fromkeys(iterable, value))
406
+
407
+
408
+ class FrozenDictLike[Key: abc.Hashable, Value](
409
+ DictLike[Key, Value],
410
+ abc.Hashable,
411
+ ):
412
+ """Provide abc for custom frozen dict-like."""
413
+
414
+ __slots__ = ()
415
+
416
+ @setdoc.basic
417
+ def __hash__(self: Self, /) -> int:
418
+ return hash(self.__frozen__())
419
+
420
+
421
+ class MutableDictLike[Key: abc.Hashable, Value](
422
+ DictLike[Key, Value],
423
+ MutableMapping[Key, Value],
424
+ ):
425
+ """Provide abc for custom mutable dict-like."""
426
+
427
+ __slots__ = ()
428
+ type __Mutable__[Key_: abc.Hashable, Value_] = dict[
429
+ Key_ | str, Optional[Value_]
430
+ ]
431
+
432
+ @setdoc.basic
433
+ def __frozen__( # type: ignore[override]
434
+ self: Self,
435
+ /,
436
+ ) -> MutableDictLike.__Frozen__[Key, Value]:
437
+ with self.__mutate__() as mutable:
438
+ return frozendict(mutable)
439
+
440
+ @setdoc.basic
441
+ def __init__(
442
+ self: Self,
443
+ data: DictInit[Key, Value] = (),
444
+ /,
445
+ **kwargs: Optional[Value],
446
+ ):
447
+ self.update(data, **kwargs)
448
+
449
+ @setdoc.basic
450
+ def __ior__( # type: ignore[override]
451
+ self: Self,
452
+ other: DictInit[Key, Value],
453
+ /,
454
+ ) -> Self:
455
+ with self.__mutate__() as mutable:
456
+ mutable |= other
457
+ return self
458
+
459
+ @abstractmethod
460
+ @setdoc.basic
461
+ def __mutate__(
462
+ self: Self, /
463
+ ) -> ContextManager[__Mutable__[Key, Value]]: ...
464
+ @setdoc.basic
465
+ def copy(self: Self, /) -> Self:
466
+ return type(self)(self)
467
+
468
+
469
+ ### DICT-SLOT ###
470
+
471
+
472
+ class DictSlot[Key: abc.Hashable, Value](DictLike[Key, Value]):
473
+ """Provide slotted dict-like."""
474
+
475
+ __slots__ = ("_slot",)
476
+ _slot: DictSlot.__Frozen__[Key, Value]
477
+
478
+ @setdoc.basic
479
+ def __frozen__( # type: ignore[override]
480
+ self: Self,
481
+ ) -> DictSlot.__Frozen__[Key, Value]:
482
+ return self._slot
483
+
484
+
485
+ class FrozenDictSlot[Key: abc.Hashable, Value](
486
+ DictSlot[Key, Value],
487
+ FrozenDictLike[Key, Value],
488
+ ):
489
+ """Provide slotted frozen dict-like."""
490
+
491
+ __slots__ = ()
492
+
493
+ @setdoc.basic
494
+ def __init__(
495
+ self: Self,
496
+ data: DictInit[Key, Value] = (),
497
+ /,
498
+ **kwargs: Optional[Value],
499
+ ) -> None:
500
+ self._slot = frozendict(data) # type: ignore[arg-type]
501
+
502
+
503
+ class MutableDictSlot[Key: abc.Hashable, Value](
504
+ DictSlot[Key, Value],
505
+ MutableDictLike[Key, Value],
506
+ ):
507
+ """Provide slotted mutable dict-like."""
508
+
509
+ __slots__ = ()
510
+
511
+ @contextmanager
512
+ @setdoc.basic
513
+ def __mutate__(
514
+ self: Self,
515
+ /,
516
+ ) -> abc.Generator[MutableDictSlot.__Mutable__[Key, Value], None, None]:
517
+ slot: MutableDictSlot.__Mutable__[Key, Value]
518
+ slot = dict(getattr(self, "_slot", ()))
519
+ yield slot
520
+ self._slot = frozendict(slot)
521
+
522
+
275
523
  ### SEQUENCE ###
276
524
 
277
525
 
278
526
  class Sequence[Item](Collection[Item], abc.Sequence[Item]):
279
- """Provide a base class for customized sequence."""
527
+ """Provide abc for customized sequence."""
280
528
 
281
529
  __slots__ = ()
282
530
 
283
531
  @setdoc.basic
284
- class __Frozen__[FrozenItem](
285
- Collection.__Frozen__[FrozenItem],
532
+ class __Frozen__[Item_](
533
+ Collection.__Frozen__[Item_],
286
534
  Protocol,
287
535
  ):
288
536
  @overload
289
537
  @setdoc.basic
290
- def __getitem__(self: Self, key: int, /) -> FrozenItem: ...
538
+ def __getitem__(self: Self, key: int, /) -> Item_: ...
291
539
  @overload
292
540
  @setdoc.basic
293
541
  def __getitem__(
294
542
  self: Self, key: Slice[int], /
295
- ) -> abc.Sequence[FrozenItem]: ...
543
+ ) -> abc.Sequence[Item_]: ...
296
544
  @setdoc.basic
297
545
  def __getitem__(
298
546
  self: Self,
299
547
  key: int | Slice[int],
300
548
  /,
301
- ) -> FrozenItem | abc.Sequence[FrozenItem]: ...
302
-
549
+ ) -> Item_ | abc.Sequence[Item_]: ...
303
550
  @abstractmethod
304
551
  @setdoc.basic
305
552
  def __frozen__(self: Self, /) -> __Frozen__[Item]: ...
306
-
307
553
  @overload
308
554
  @setdoc.basic
309
555
  def __getitem__(self: Self, key: int, /) -> Item: ...
@@ -318,13 +564,12 @@ class Sequence[Item](Collection[Item], abc.Sequence[Item]):
318
564
 
319
565
 
320
566
  class MutableSequence[Item](Sequence[Item], abc.MutableSequence[Item]):
321
- """Provide a base class for customized mutable list-likes."""
567
+ """Provide abc for custom mutable sequence."""
322
568
 
323
569
  __slots__ = ()
324
570
 
325
571
  @setdoc.basic
326
- class __Mutable__[MutableItem](Protocol):
327
-
572
+ class __Mutable__[Item_](Protocol):
328
573
  @overload
329
574
  @setdoc.basic
330
575
  def __delitem__(self: Self, key: SupportsIndex, /) -> None: ...
@@ -335,42 +580,37 @@ class MutableSequence[Item](Sequence[Item], abc.MutableSequence[Item]):
335
580
  def __delitem__(
336
581
  self: Self, key: SupportsIndex | Slice[SupportsIndex], /
337
582
  ) -> None: ...
338
-
339
583
  @overload
340
584
  @setdoc.basic
341
- def __getitem__(self: Self, key: int, /) -> MutableItem: ...
585
+ def __getitem__(self: Self, key: int, /) -> Item_: ...
342
586
  @overload
343
587
  @setdoc.basic
344
588
  def __getitem__(
345
589
  self: Self, key: Slice[int], /
346
- ) -> abc.MutableSequence[MutableItem]: ...
590
+ ) -> abc.MutableSequence[Item_]: ...
347
591
  @setdoc.basic
348
592
  def __getitem__(
349
593
  self: Self,
350
594
  key: int | Slice[int],
351
595
  /,
352
- ) -> MutableItem | abc.MutableSequence[MutableItem]: ...
353
-
596
+ ) -> Item_ | abc.MutableSequence[Item_]: ...
354
597
  @overload
355
598
  @setdoc.basic
356
- def __setitem__(
357
- self: Self, key: int, value: MutableItem, /
358
- ) -> None: ...
599
+ def __setitem__(self: Self, key: int, value: Item_, /) -> None: ...
359
600
  @overload
360
601
  @setdoc.basic
361
602
  def __setitem__(
362
- self: Self, key: Slice[int], value: abc.Iterable[MutableItem], /
603
+ self: Self, key: Slice[int], value: abc.Iterable[Item_], /
363
604
  ) -> None: ...
364
605
  @setdoc.basic
365
606
  def __setitem__(
366
607
  self: Self,
367
608
  key: int | Slice[int],
368
- value: MutableItem | abc.Iterable[MutableItem],
609
+ value: Item_ | abc.Iterable[Item_],
369
610
  /,
370
611
  ) -> None: ...
371
-
372
612
  @setdoc.basic
373
- def insert(self: Self, index: int, item: MutableItem, /) -> None: ...
613
+ def insert(self: Self, index: int, item: Item_, /) -> None: ...
374
614
 
375
615
  @overload
376
616
  @setdoc.basic
@@ -428,15 +668,13 @@ class MutableSequence[Item](Sequence[Item], abc.MutableSequence[Item]):
428
668
 
429
669
  ### LIST-LIKE ###
430
670
  class ListLike[Item](Sequence[Item]):
431
- """Provide a base class for customized list-likes."""
671
+ """Provide abc for custom list-like."""
432
672
 
433
673
  __slots__ = ()
434
674
 
435
- type __Frozen__[FrozenItem] = tuple[FrozenItem, ...]
675
+ type __Frozen__[Item_] = tuple[Item_, ...]
436
676
  # Frozen has to be tuple to allow covariance
437
677
 
438
- type Init[InitItem] = abc.Iterable[InitItem]
439
-
440
678
  @setdoc.basic
441
679
  def __add__[Item_](
442
680
  self: Self, other: ListLike[Item_], /
@@ -492,7 +730,7 @@ class ListLike[Item](Sequence[Item]):
492
730
 
493
731
  @abstractmethod
494
732
  @setdoc.basic
495
- def __init__(self: Self, data: Init[Item] = (), /) -> None: ...
733
+ def __init__(self: Self, data: abc.Iterable[Item] = (), /) -> None: ...
496
734
 
497
735
  @setdoc.basic
498
736
  def __le__(self: Self, other: ListLike[Any], /) -> bool:
@@ -523,7 +761,7 @@ class ListLike[Item](Sequence[Item]):
523
761
 
524
762
 
525
763
  class FrozenListLike[Item](ListLike[Item], abc.Hashable):
526
- """Provide a base class for customized frozen list-likes."""
764
+ """Provide abc for custom frozen list-like."""
527
765
 
528
766
  __slots__ = ()
529
767
 
@@ -533,11 +771,11 @@ class FrozenListLike[Item](ListLike[Item], abc.Hashable):
533
771
 
534
772
 
535
773
  class MutableListLike[Item](ListLike[Item], MutableSequence[Item]):
536
- """Provide a base class for customized mutable list-likes."""
774
+ """Provide abc for custom mutable list-like."""
537
775
 
538
776
  __slots__ = ()
539
777
 
540
- type __Mutable__[MutableItem] = list[MutableItem]
778
+ type __Mutable__[Item_] = list[Item_]
541
779
 
542
780
  @overload
543
781
  @setdoc.basic
@@ -618,7 +856,6 @@ class ListSlot[Item](ListLike[Item]):
618
856
  """Provide slotted list-like class."""
619
857
 
620
858
  __slots__ = ("_slot",)
621
-
622
859
  _slot: ListSlot.__Frozen__[Item]
623
860
 
624
861
  @setdoc.basic
@@ -627,7 +864,7 @@ class ListSlot[Item](ListLike[Item]):
627
864
 
628
865
 
629
866
  class FrozenListSlot[Item](ListSlot[Item], FrozenListLike[Item]):
630
- """Provide a base class for customized frozen data-holds."""
867
+ """Provide slotted frozen list-like."""
631
868
 
632
869
  __slots__ = ()
633
870
 
@@ -637,7 +874,7 @@ class FrozenListSlot[Item](ListSlot[Item], FrozenListLike[Item]):
637
874
 
638
875
 
639
876
  class MutableListSlot[Item](ListSlot[Item], MutableListLike[Item]):
640
- """Provide slotted mutable list-like class."""
877
+ """Provide slotted mutable list-like."""
641
878
 
642
879
  __slots__ = ()
643
880
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datahold
3
- Version: 4.0.0.dev21
3
+ Version: 4.0.0.dev23
4
4
  Summary: This project wraps common mutable datastructures for inheritance with modification.
5
5
  Author-email: Johannes <johannes.programming@gmail.com>
6
6
  License-Expression: MIT
@@ -19,6 +19,7 @@ Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.11
20
20
  Description-Content-Type: text/x-rst
21
21
  License-File: LICENSE.txt
22
+ Requires-Dist: frozendict<3,>=2.4.7
22
23
  Requires-Dist: setdoc<2,>=1.3.24
23
24
  Dynamic: license-file
24
25
 
@@ -20,7 +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_MutableListHold.py
23
+ tests/test_MutableListSlot.py
24
24
  tests/test_abstractmethods.py
25
25
  tests/test_all.py
26
26
  tests/test_attributes.py
@@ -28,8 +28,8 @@ tests/test_docs.py
28
28
  tests/test_generic.py
29
29
  tests/test_internal_comparison.py
30
30
  tests/test_issubclass.py
31
+ tests/test_name.py
31
32
  tests/test_nested.py
32
- tests/test_prefix.py
33
33
  tests/test_sorted.py
34
34
  tests/test_variance.py
35
35
  tests/testdata.toml
@@ -0,0 +1,2 @@
1
+ frozendict<3,>=2.4.7
2
+ setdoc<2,>=1.3.24
@@ -12,22 +12,18 @@ import datahold
12
12
 
13
13
 
14
14
  class TestAbstractmethods(unittest.TestCase):
15
- def _test(
16
- self: Self, name: str, abstractmethods: Optional[list[str]] = None, /
17
- ) -> None:
15
+ def _test(self: Self, name: str, abstractmethods: set[str], /) -> None:
18
16
  datatype: Any
19
- if abstractmethods is None:
20
- return
21
17
  datatype = getattr(datahold, name)
22
- self.assertSetEqual(datatype.__abstractmethods__, set(abstractmethods))
18
+ self.assertLessEqual(len(datatype.__abstractmethods__), 2)
19
+ self.assertSetEqual(datatype.__abstractmethods__, abstractmethods)
23
20
  self.assertEqual(ins.isabstract(datatype), bool(abstractmethods))
24
21
 
25
22
  def test_abstractmethods(self: Self, /) -> None:
26
- data: Any
27
23
  name: Any
28
- for name, data in Lazy.lazy.datatypes.items():
24
+ for name in Lazy.lazy.datatypes.keys():
29
25
  with self.subTest(datatype=name):
30
- self._test(name, data.get("abstractmethods"))
26
+ self._test(name, Lazy.get_abstractmethods(name))
31
27
 
32
28
 
33
29
  if __name__ == "__main__":
@@ -0,0 +1,81 @@
1
+ from __future__ import annotations
2
+
3
+ __all__: list[str] = ["TestName"]
4
+
5
+ import unittest
6
+ from collections import abc
7
+ from typing import Self
8
+
9
+ from Lazy import Lazy
10
+
11
+ import datahold
12
+
13
+
14
+ class TestName(unittest.TestCase):
15
+
16
+ def _test_name(self: Self, name: str, /) -> None:
17
+ prefix: str
18
+ suffix: str
19
+ if name.startswith("Frozen"):
20
+ prefix = "Frozen"
21
+ elif name.startswith("Mutable"):
22
+ prefix = "Mutable"
23
+ else:
24
+ prefix = ""
25
+ if name.endswith("Like"):
26
+ suffix = "Like"
27
+ elif name.endswith("Slot"):
28
+ suffix = "Slot"
29
+ else:
30
+ suffix = ""
31
+ # all
32
+ datatype = getattr(datahold, name)
33
+ self.assertEqual(datatype.__name__, name)
34
+ self.assertTrue(hasattr(datatype, "__Frozen__"))
35
+ self.assertTrue(hasattr(datatype, "__frozen__"))
36
+ self.assertTrue(issubclass(datatype, datahold.Collection))
37
+ # frozen
38
+ if prefix == "Frozen":
39
+ self.assertIsNot(datatype.__hash__, object.__hash__)
40
+ self.assertTrue(issubclass(datatype, abc.Hashable))
41
+ self.assertFalse(hasattr(datatype, "__Mutable__"))
42
+ self.assertFalse(hasattr(datatype, "__mutate__"))
43
+ self.assertTrue(
44
+ issubclass(datatype, Lazy.get_import("datahold." + name[6:]))
45
+ )
46
+ # mutable
47
+ if prefix == "Mutable":
48
+ self.assertIn(datatype.__hash__, [None, object.__hash__])
49
+ self.assertTrue(hasattr(datatype, "__Mutable__"))
50
+ self.assertTrue(hasattr(datatype, "__mutate__"))
51
+ self.assertTrue(
52
+ issubclass(datatype, Lazy.get_import("datahold." + name[7:]))
53
+ )
54
+ # no prefix
55
+ if prefix == "":
56
+ self.assertIn(datatype.__hash__, [None, object.__hash__])
57
+ self.assertFalse(hasattr(datatype, "__Mutable__"))
58
+ self.assertFalse(hasattr(datatype, "__mutate__"))
59
+ # like
60
+ if suffix == "Like":
61
+ self.assertTrue(hasattr(datatype, "__init__"))
62
+ # slot
63
+ if suffix == "Slot":
64
+ self.assertTrue(hasattr(datatype, "__init__"))
65
+ self.assertTrue(
66
+ issubclass(
67
+ datatype, Lazy.get_import("datahold." + name[:-4] + "Like")
68
+ )
69
+ )
70
+ # no suffix
71
+ if suffix == "":
72
+ self.assertIs(datatype.__init__, object.__init__)
73
+
74
+ def test_name(self: Self, /) -> None:
75
+ for name in Lazy.lazy.datatypes.keys():
76
+ with self.subTest(datatype=name):
77
+ self._test_name(name)
78
+
79
+
80
+ if __name__ == "__main__":
81
+ unittest.main(verbosity=2)
@@ -1,10 +1,23 @@
1
1
  [datatypes.Collection]
2
2
 
3
- [datatypes.FrozenListLike]
4
- abstractmethods = [
5
- "__frozen__",
6
- "__init__",
7
- ]
3
+ [datatypes.DictLike.attributes]
4
+ __or__ = "datahold.DictLike"
5
+
6
+ [datatypes.DictLike.issubclass]
7
+ "collections.abc.Mapping" = true
8
+ "datahold.Mapping" = true
9
+
10
+ [datatypes.DictSlot.issubclass]
11
+ "collections.abc.Mapping" = true
12
+ "datahold.DictLike" = true
13
+
14
+ [datatypes.FrozenDictLike.issubclass]
15
+ "collections.abc.Hashable" = true
16
+ "datahold.Mapping" = true
17
+
18
+ [datatypes.FrozenDictSlot.issubclass]
19
+ "collections.abc.Hashable" = true
20
+ "datahold.FrozenDictLike" = true
8
21
 
9
22
  [datatypes.FrozenListLike.attributes]
10
23
  __frozen__ = "datahold.ListLike"
@@ -18,16 +31,12 @@ __init__ = "datahold.ListLike"
18
31
  "collections.abc.Sequence" = true
19
32
 
20
33
  [datatypes.FrozenListLike.nested]
21
- Init = "collections.abc.Iterable"
22
34
  __Frozen__ = "builtins.tuple"
23
35
  __Mutable__ = ""
24
36
 
25
37
  [datatypes.FrozenListLike.varia]
26
38
  generic = 1
27
39
 
28
- [datatypes.FrozenListSlot]
29
- abstractmethods = []
30
-
31
40
  [datatypes.FrozenListSlot.TestInternalComparsion.ge.test_greater_value]
32
41
  a = "_1_3"
33
42
  b = "_1_2"
@@ -133,7 +142,6 @@ args = [
133
142
  ]
134
143
 
135
144
  [datatypes.FrozenListSlot.nested]
136
- Init = "collections.abc.Iterable"
137
145
  __Frozen__ = "builtins.tuple"
138
146
  __Mutable__ = ""
139
147
 
@@ -152,12 +160,6 @@ generic = 1
152
160
  "collections.abc.Set" = true
153
161
  "datahold.Collection" = true
154
162
 
155
- [datatypes.ListLike]
156
- abstractmethods = [
157
- "__frozen__",
158
- "__init__",
159
- ]
160
-
161
163
  [datatypes.ListLike.attributes]
162
164
  __frozen__ = "datahold.ListLike"
163
165
  __init__ = "datahold.ListLike"
@@ -174,30 +176,37 @@ index = "collections.abc.Sequence"
174
176
  "datahold.MutableSequence" = false
175
177
 
176
178
  [datatypes.ListLike.nested]
177
- Init = "collections.abc.Iterable"
178
179
  __Frozen__ = "builtins.tuple"
179
180
  __Mutable__ = ""
180
181
 
181
182
  [datatypes.ListLike.varia]
182
183
  generic = 1
183
184
 
184
- [datatypes.ListSlot]
185
- abstractmethods = [
186
- "__init__",
187
- ]
188
-
189
185
  [datatypes.ListSlot.nested]
190
- Init = "collections.abc.Iterable"
191
186
  __Frozen__ = "builtins.tuple"
192
187
  __Mutable__ = ""
193
188
 
194
189
  [datatypes.ListSlot.varia]
195
190
  generic = 1
196
191
 
197
- [datatypes.MutableListLike]
198
- abstractmethods = [
199
- "__mutate__",
200
- ]
192
+ [datatypes.Mapping.issubclass]
193
+ "collections.abc.Mapping" = true
194
+ "datahold.Collection" = true
195
+
196
+ [datatypes.MutableDictLike.attributes]
197
+ __ior__ = "datahold.MutableDictLike"
198
+ __or__ = "datahold.DictLike"
199
+
200
+ [datatypes.MutableDictLike.issubclass]
201
+ "collections.abc.Mapping" = true
202
+ "collections.abc.MutableMapping" = true
203
+ "datahold.MutableMapping" = true
204
+
205
+ [datatypes.MutableDictSlot.issubclass]
206
+ "collections.abc.Mapping" = true
207
+ "collections.abc.MutableMapping" = true
208
+ "datahold.MutableDictLike" = true
209
+ "datahold.MutableMapping" = true
201
210
 
202
211
  [datatypes.MutableListLike.attributes]
203
212
  __add__ = "datahold.MutableListLike"
@@ -226,16 +235,12 @@ reverse = "collections.abc.MutableSequence"
226
235
  "datahold.MutableSequence" = true
227
236
 
228
237
  [datatypes.MutableListLike.nested]
229
- Init = "collections.abc.Iterable"
230
238
  __Frozen__ = "builtins.tuple"
231
239
  __hash__ = ""
232
240
 
233
241
  [datatypes.MutableListLike.varia]
234
242
  generic = 1
235
243
 
236
- [datatypes.MutableListSlot]
237
- abstractmethods = []
238
-
239
244
  [datatypes.MutableListSlot.issubclass]
240
245
  "builtins.list" = false
241
246
  "datahold.ListLike" = true
@@ -243,13 +248,16 @@ abstractmethods = []
243
248
  "datahold.MutableListSlot" = true
244
249
 
245
250
  [datatypes.MutableListSlot.nested]
246
- Init = "collections.abc.Iterable"
247
251
  __Frozen__ = "builtins.tuple"
248
252
  __hash__ = ""
249
253
 
250
254
  [datatypes.MutableListSlot.varia]
251
255
  generic = 1
252
256
 
257
+ [datatypes.MutableMapping.issubclass]
258
+ "collections.abc.MutableMapping" = true
259
+ "datahold.Mapping" = true
260
+
253
261
  [datatypes.MutableSequence.attributes]
254
262
  __Frozen__ = "datahold.Sequence"
255
263
  __Mutable__ = "datahold.MutableSequence"
@@ -283,9 +291,6 @@ sort = ""
283
291
  "datahold.SetSlot" = true
284
292
 
285
293
  [datatypes.Sequence]
286
- abstractmethods = [
287
- "__frozen__",
288
- ]
289
294
 
290
295
  [datatypes.Set.issubclass]
291
296
  "collections.abc.Set" = true
@@ -1 +0,0 @@
1
- setdoc<2,>=1.3.24
@@ -1,41 +0,0 @@
1
- from __future__ import annotations
2
-
3
- __all__: list[str] = ["TestPrefix"]
4
-
5
- import unittest
6
- from collections import abc
7
- from typing import Self
8
-
9
- from Lazy import Lazy
10
-
11
- import datahold
12
-
13
-
14
- class TestPrefix(unittest.TestCase):
15
- def _test_prefix(self: Self, name: str, /) -> None:
16
- datatype = getattr(datahold, name)
17
- self.assertEqual(datatype.__name__, name)
18
- self.assertTrue(hasattr(datatype, "__Frozen__"))
19
- self.assertTrue(hasattr(datatype, "__frozen__"))
20
- if name.startswith("Frozen"):
21
- self.assertIsNot(datatype.__hash__, object.__hash__)
22
- self.assertTrue(issubclass(datatype, abc.Hashable))
23
- self.assertFalse(hasattr(datatype, "__Mutable__"))
24
- self.assertFalse(hasattr(datatype, "__mutate__"))
25
- return
26
- self.assertIn(datatype.__hash__, [None, object.__hash__])
27
- if name.startswith("Mutable"):
28
- self.assertTrue(hasattr(datatype, "__Mutable__"))
29
- self.assertTrue(hasattr(datatype, "__mutate__"))
30
- return
31
- self.assertFalse(hasattr(datatype, "__Mutable__"))
32
- self.assertFalse(hasattr(datatype, "__mutate__"))
33
-
34
- def test_prefix(self: Self, /) -> None:
35
- for name in Lazy.lazy.datatypes.keys():
36
- with self.subTest(datatype=name):
37
- self._test_prefix(name)
38
-
39
-
40
- if __name__ == "__main__":
41
- unittest.main(verbosity=2)
File without changes