datahold 3.0.0.dev1__tar.gz → 3.0.0.dev3__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-3.0.0.dev1/src/datahold.egg-info → datahold-3.0.0.dev3}/PKG-INFO +1 -1
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/pyproject.toml +1 -1
- datahold-3.0.0.dev3/src/datahold/__init__.py +25 -0
- datahold-3.0.0.dev3/src/datahold/core/__init__.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/tests/test_0.py +20 -18
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestAbstractness.py +54 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestCopy.py +85 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestDataAttribute.py +55 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestFrozenMutability.py +38 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestInheritance.py +62 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestMutableBehavior.py +38 -0
- datahold-3.0.0.dev3/src/datahold/tests/test_datahold_TestProtocols.py +66 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/tests/test_generic.py +2 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3/src/datahold.egg-info}/PKG-INFO +1 -1
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold.egg-info/SOURCES.txt +7 -1
- datahold-3.0.0.dev1/src/datahold/__init__.py +0 -2
- datahold-3.0.0.dev1/src/datahold/core/__init__.py +0 -24
- datahold-3.0.0.dev1/src/datahold/tests/test_datahold.py +0 -298
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/LICENSE.txt +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/MANIFEST.in +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/README.rst +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/setup.cfg +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/_utils/__init__.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/_utils/wrapping.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseDataDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseDataList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseDataObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseDataSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseHoldDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseHoldList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseHoldObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/BaseHoldSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/DataDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/DataList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/DataObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/DataSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenDataDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenDataList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenDataObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenDataSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenHoldDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenHoldList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenHoldObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/FrozenHoldSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/HoldDict.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/HoldList.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/HoldObject.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/core/HoldSet.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold/tests/__init__.py +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold.egg-info/dependency_links.txt +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold.egg-info/requires.txt +0 -0
- {datahold-3.0.0.dev1 → datahold-3.0.0.dev3}/src/datahold.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datahold
|
|
3
|
-
Version: 3.0.0.
|
|
3
|
+
Version: 3.0.0.dev3
|
|
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: The MIT License (MIT)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
from datahold.core.BaseDataDict import BaseDataDict
|
|
2
|
+
from datahold.core.BaseDataList import BaseDataList
|
|
3
|
+
from datahold.core.BaseDataObject import BaseDataObject
|
|
4
|
+
from datahold.core.BaseDataSet import BaseDataSet
|
|
5
|
+
from datahold.core.BaseHoldDict import BaseHoldDict
|
|
6
|
+
from datahold.core.BaseHoldList import BaseHoldList
|
|
7
|
+
from datahold.core.BaseHoldObject import BaseHoldObject
|
|
8
|
+
from datahold.core.BaseHoldSet import BaseHoldSet
|
|
9
|
+
from datahold.core.DataDict import DataDict
|
|
10
|
+
from datahold.core.DataList import DataList
|
|
11
|
+
from datahold.core.DataObject import DataObject
|
|
12
|
+
from datahold.core.DataSet import DataSet
|
|
13
|
+
from datahold.core.FrozenDataDict import FrozenDataDict
|
|
14
|
+
from datahold.core.FrozenDataList import FrozenDataList
|
|
15
|
+
from datahold.core.FrozenDataObject import FrozenDataObject
|
|
16
|
+
from datahold.core.FrozenDataSet import FrozenDataSet
|
|
17
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
18
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
19
|
+
from datahold.core.FrozenHoldObject import FrozenHoldObject
|
|
20
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
21
|
+
from datahold.core.HoldDict import HoldDict
|
|
22
|
+
from datahold.core.HoldList import HoldList
|
|
23
|
+
from datahold.core.HoldObject import HoldObject
|
|
24
|
+
from datahold.core.HoldSet import HoldSet
|
|
25
|
+
from datahold.tests import test
|
|
File without changes
|
|
@@ -8,18 +8,18 @@ from datahold.core import *
|
|
|
8
8
|
class TestData(unittest.TestCase):
|
|
9
9
|
def test_constructor(self: Self) -> None:
|
|
10
10
|
with self.assertRaises(Exception):
|
|
11
|
-
DataDict()
|
|
11
|
+
core.DataDict.DataDict()
|
|
12
12
|
with self.assertRaises(Exception):
|
|
13
|
-
DataList()
|
|
13
|
+
core.DataList.DataList()
|
|
14
14
|
with self.assertRaises(Exception):
|
|
15
|
-
DataSet()
|
|
15
|
+
core.DataSet.DataSet()
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
class TestHold(unittest.TestCase):
|
|
19
19
|
def test_constructor(self: Self) -> None:
|
|
20
|
-
HoldDict()
|
|
21
|
-
HoldList()
|
|
22
|
-
HoldSet()
|
|
20
|
+
core.HoldDict.HoldDict()
|
|
21
|
+
core.HoldList.HoldList()
|
|
22
|
+
core.HoldSet.HoldSet()
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class TestDoc(unittest.TestCase):
|
|
@@ -34,26 +34,28 @@ class TestDoc(unittest.TestCase):
|
|
|
34
34
|
self.go(name=name)
|
|
35
35
|
|
|
36
36
|
def go(self: Self, name: str) -> None:
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
attrname: Any
|
|
38
|
+
cls: Any
|
|
39
39
|
doc: Any
|
|
40
40
|
error: Any
|
|
41
|
+
member: Any
|
|
42
|
+
module: Any
|
|
41
43
|
obj: Any
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
for
|
|
45
|
-
|
|
46
|
-
if not callable(
|
|
44
|
+
module = getattr(core, name)
|
|
45
|
+
cls = getattr(module, name)
|
|
46
|
+
for attrname in dir(cls):
|
|
47
|
+
member = getattr(cls, attrname)
|
|
48
|
+
if not callable(member) and not isinstance(member, property):
|
|
47
49
|
continue
|
|
48
|
-
if getattr(
|
|
50
|
+
if getattr(member, "__isabstractmethod__", False):
|
|
49
51
|
continue
|
|
50
|
-
if
|
|
52
|
+
if attrname == "__subclasshook__":
|
|
51
53
|
continue
|
|
52
|
-
doc = getattr(
|
|
53
|
-
error = "%r inside %r has no docstring" % (
|
|
54
|
+
doc = getattr(member, "__doc__", None)
|
|
55
|
+
error = "%r inside %r has no docstring" % (attrname, name)
|
|
54
56
|
self.assertNotEqual(doc, None, error)
|
|
55
57
|
try:
|
|
56
|
-
obj =
|
|
58
|
+
obj = cls()
|
|
57
59
|
except TypeError:
|
|
58
60
|
return
|
|
59
61
|
with self.assertRaises(AttributeError):
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from inspect import isabstract
|
|
3
|
+
from typing import Self
|
|
4
|
+
|
|
5
|
+
from frozendict import frozendict
|
|
6
|
+
|
|
7
|
+
from datahold.core.DataDict import DataDict
|
|
8
|
+
from datahold.core.DataList import DataList
|
|
9
|
+
from datahold.core.DataObject import DataObject
|
|
10
|
+
from datahold.core.DataSet import DataSet
|
|
11
|
+
from datahold.core.FrozenDataDict import FrozenDataDict
|
|
12
|
+
from datahold.core.FrozenDataList import FrozenDataList
|
|
13
|
+
from datahold.core.FrozenDataObject import FrozenDataObject
|
|
14
|
+
from datahold.core.FrozenDataSet import FrozenDataSet
|
|
15
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
16
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
17
|
+
from datahold.core.FrozenHoldObject import FrozenHoldObject
|
|
18
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
19
|
+
from datahold.core.HoldDict import HoldDict
|
|
20
|
+
from datahold.core.HoldList import HoldList
|
|
21
|
+
from datahold.core.HoldSet import HoldSet
|
|
22
|
+
|
|
23
|
+
__all__ = ["TestAbstractness"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class TestAbstractness(unittest.TestCase):
|
|
27
|
+
def test_abstract_classes(self: Self) -> None:
|
|
28
|
+
# data
|
|
29
|
+
self.assertTrue(isabstract(DataObject))
|
|
30
|
+
self.assertTrue(isabstract(DataDict))
|
|
31
|
+
self.assertTrue(isabstract(DataList))
|
|
32
|
+
self.assertTrue(isabstract(DataSet))
|
|
33
|
+
|
|
34
|
+
self.assertTrue(isabstract(FrozenDataObject))
|
|
35
|
+
self.assertTrue(isabstract(FrozenDataDict))
|
|
36
|
+
self.assertTrue(isabstract(FrozenDataList))
|
|
37
|
+
self.assertTrue(isabstract(FrozenDataSet))
|
|
38
|
+
|
|
39
|
+
# hold
|
|
40
|
+
self.assertFalse(isabstract(FrozenHoldObject))
|
|
41
|
+
# self.assertFalse(isabstract(HoldObject))
|
|
42
|
+
|
|
43
|
+
def test_concrete_classes(self: Self) -> None:
|
|
44
|
+
FrozenHoldDict({"a": 1})
|
|
45
|
+
FrozenHoldList([1, 2])
|
|
46
|
+
FrozenHoldSet({1, 2})
|
|
47
|
+
|
|
48
|
+
HoldDict({"a": 1})
|
|
49
|
+
HoldList([1, 2])
|
|
50
|
+
HoldSet({1, 2})
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
if __name__ == "__main__":
|
|
54
|
+
unittest.main()
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from frozendict import frozendict
|
|
5
|
+
|
|
6
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
7
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
8
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
9
|
+
from datahold.core.HoldDict import HoldDict
|
|
10
|
+
from datahold.core.HoldList import HoldList
|
|
11
|
+
from datahold.core.HoldSet import HoldSet
|
|
12
|
+
|
|
13
|
+
__all__ = ["TestCopy"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestCopy(unittest.TestCase):
|
|
17
|
+
def test_frozen_have_no_copy(self: Self) -> None:
|
|
18
|
+
self.assertFalse(hasattr(FrozenHoldDict({"a": 1}), "copy"))
|
|
19
|
+
self.assertFalse(hasattr(FrozenHoldList([1, 2]), "copy"))
|
|
20
|
+
self.assertFalse(hasattr(FrozenHoldSet({1, 2}), "copy"))
|
|
21
|
+
|
|
22
|
+
def test_frozen_have_no_copy_2(self: Self) -> None:
|
|
23
|
+
"""
|
|
24
|
+
Frozen classes should not define their own copy method.
|
|
25
|
+
(If a parent class or wrapped object exposes one, we ignore that.)
|
|
26
|
+
"""
|
|
27
|
+
args: Any
|
|
28
|
+
cls: Any
|
|
29
|
+
copy_obj: Any
|
|
30
|
+
obj: Any
|
|
31
|
+
for cls, args in (
|
|
32
|
+
(FrozenHoldDict, ({"a": 1},)),
|
|
33
|
+
(FrozenHoldList, ([1, 2],)),
|
|
34
|
+
(FrozenHoldSet, ({1, 2},)),
|
|
35
|
+
):
|
|
36
|
+
# They must not *define* copy themselves
|
|
37
|
+
self.assertNotIn("copy", cls.__dict__)
|
|
38
|
+
|
|
39
|
+
# Optional: if they *do* expose copy on the instance, it should not
|
|
40
|
+
# create a mutable variant; you can drop this if you prefer.
|
|
41
|
+
obj = cls(*args)
|
|
42
|
+
if hasattr(obj, "copy"):
|
|
43
|
+
copy_obj = obj.copy()
|
|
44
|
+
self.assertIsInstance(copy_obj, cls)
|
|
45
|
+
|
|
46
|
+
def test_mutable_copy_returns_same_type_and_is_shallow(self: Self) -> None:
|
|
47
|
+
d: HoldDict
|
|
48
|
+
d_copy: HoldDict
|
|
49
|
+
d = HoldDict({"a": {"x": 1}})
|
|
50
|
+
d_copy = d.copy()
|
|
51
|
+
self.assertIsInstance(d_copy, type(d))
|
|
52
|
+
self.assertIsNot(d_copy, d)
|
|
53
|
+
self.assertEqual(dict(d_copy), dict(d))
|
|
54
|
+
|
|
55
|
+
# shallow: inner object is shared
|
|
56
|
+
d["a"]["x"] = 2
|
|
57
|
+
self.assertEqual(d_copy["a"]["x"], 2)
|
|
58
|
+
|
|
59
|
+
def test_list_copy(self: Self) -> None:
|
|
60
|
+
lst: HoldList
|
|
61
|
+
lst_copy: HoldList
|
|
62
|
+
lst = HoldList([[1], [2]])
|
|
63
|
+
lst_copy = lst.copy()
|
|
64
|
+
self.assertIsInstance(lst_copy, type(lst))
|
|
65
|
+
self.assertIsNot(lst_copy, lst)
|
|
66
|
+
self.assertEqual(list(lst_copy), list(lst))
|
|
67
|
+
|
|
68
|
+
lst[0].append(99)
|
|
69
|
+
self.assertEqual(lst_copy[0], [1, 99])
|
|
70
|
+
|
|
71
|
+
def test_set_copy(self: Self) -> None:
|
|
72
|
+
s: HoldSet
|
|
73
|
+
s_copy: HoldSet
|
|
74
|
+
s = HoldSet({1, 2, 3})
|
|
75
|
+
s_copy = s.copy()
|
|
76
|
+
self.assertIsInstance(s_copy, type(s))
|
|
77
|
+
self.assertIsNot(s_copy, s)
|
|
78
|
+
self.assertEqual(set(s_copy), set(s))
|
|
79
|
+
|
|
80
|
+
s.add(4)
|
|
81
|
+
self.assertNotIn(4, s_copy)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
unittest.main()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from frozendict import frozendict
|
|
5
|
+
|
|
6
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
7
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
8
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
9
|
+
from datahold.core.HoldDict import HoldDict
|
|
10
|
+
from datahold.core.HoldList import HoldList
|
|
11
|
+
from datahold.core.HoldSet import HoldSet
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestDataAttribute(unittest.TestCase):
|
|
15
|
+
def test_dict_data_is_immutable_mapping(self: Self) -> None:
|
|
16
|
+
f: FrozenHoldDict
|
|
17
|
+
m: HoldDict
|
|
18
|
+
obj: Any
|
|
19
|
+
f = FrozenHoldDict({"a": 1})
|
|
20
|
+
m = HoldDict({"a": 1})
|
|
21
|
+
|
|
22
|
+
for obj in (f, m):
|
|
23
|
+
self.assertIsInstance(obj.data, frozendict)
|
|
24
|
+
|
|
25
|
+
# try to mutate underlying data
|
|
26
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
27
|
+
obj.data["b"] = 2
|
|
28
|
+
|
|
29
|
+
def test_list_data_is_tuple(self: Self) -> None:
|
|
30
|
+
f: FrozenHoldList
|
|
31
|
+
m: HoldList
|
|
32
|
+
o: Any
|
|
33
|
+
f = FrozenHoldList([1, 2, 3])
|
|
34
|
+
m = HoldList([1, 2, 3])
|
|
35
|
+
|
|
36
|
+
for o in (f, m):
|
|
37
|
+
self.assertIsInstance(o.data, tuple)
|
|
38
|
+
with self.assertRaises(Exception):
|
|
39
|
+
o.data.append(4)
|
|
40
|
+
|
|
41
|
+
def test_set_data_is_frozenset(self: Self) -> None:
|
|
42
|
+
f: FrozenHoldSet
|
|
43
|
+
m: HoldSet
|
|
44
|
+
obj: Any
|
|
45
|
+
f = FrozenHoldSet({1, 2, 3})
|
|
46
|
+
m = HoldSet({1, 2, 3})
|
|
47
|
+
|
|
48
|
+
for obj in (f, m):
|
|
49
|
+
self.assertIsInstance(obj.data, frozenset)
|
|
50
|
+
with self.assertRaises(AttributeError):
|
|
51
|
+
obj.data.add(4)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
unittest.main()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from frozendict import frozendict
|
|
5
|
+
|
|
6
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
7
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
8
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class TestFrozenMutability(unittest.TestCase):
|
|
12
|
+
def test_frozen_dict_cannot_mutate(self: Self) -> None:
|
|
13
|
+
f: FrozenHoldDict
|
|
14
|
+
f = FrozenHoldDict({"a": 1})
|
|
15
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
16
|
+
f["b"] = 2
|
|
17
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
18
|
+
f.pop("a", None)
|
|
19
|
+
|
|
20
|
+
def test_frozen_list_cannot_mutate(self: Self) -> None:
|
|
21
|
+
f: FrozenHoldList
|
|
22
|
+
f = FrozenHoldList([1, 2, 3])
|
|
23
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
24
|
+
f.append(4)
|
|
25
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
26
|
+
f.pop()
|
|
27
|
+
|
|
28
|
+
def test_frozen_set_cannot_mutate(self: Self) -> None:
|
|
29
|
+
f: FrozenHoldSet
|
|
30
|
+
f = FrozenHoldSet({1, 2, 3})
|
|
31
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
32
|
+
f.add(4)
|
|
33
|
+
with self.assertRaises((TypeError, AttributeError)):
|
|
34
|
+
f.remove(1)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
unittest.main()
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Self
|
|
3
|
+
|
|
4
|
+
from frozendict import frozendict
|
|
5
|
+
|
|
6
|
+
from datahold.core.BaseDataDict import BaseDataDict
|
|
7
|
+
from datahold.core.BaseDataList import BaseDataList
|
|
8
|
+
from datahold.core.BaseDataSet import BaseDataSet
|
|
9
|
+
from datahold.core.BaseHoldDict import BaseHoldDict
|
|
10
|
+
from datahold.core.BaseHoldList import BaseHoldList
|
|
11
|
+
from datahold.core.BaseHoldSet import BaseHoldSet
|
|
12
|
+
from datahold.core.DataDict import DataDict
|
|
13
|
+
from datahold.core.DataList import DataList
|
|
14
|
+
from datahold.core.DataObject import DataObject
|
|
15
|
+
from datahold.core.DataSet import DataSet
|
|
16
|
+
from datahold.core.FrozenDataDict import FrozenDataDict
|
|
17
|
+
from datahold.core.FrozenDataList import FrozenDataList
|
|
18
|
+
from datahold.core.FrozenDataObject import FrozenDataObject
|
|
19
|
+
from datahold.core.FrozenDataSet import FrozenDataSet
|
|
20
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
21
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
22
|
+
from datahold.core.FrozenHoldObject import FrozenHoldObject
|
|
23
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
24
|
+
from datahold.core.HoldDict import HoldDict
|
|
25
|
+
from datahold.core.HoldList import HoldList
|
|
26
|
+
from datahold.core.HoldObject import HoldObject
|
|
27
|
+
from datahold.core.HoldSet import HoldSet
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class TestInheritance(unittest.TestCase):
|
|
31
|
+
def test_dict_inheritance(self: Self) -> None:
|
|
32
|
+
# base → concrete
|
|
33
|
+
self.assertTrue(issubclass(DataDict, DataObject))
|
|
34
|
+
self.assertTrue(issubclass(FrozenDataDict, FrozenDataObject))
|
|
35
|
+
self.assertTrue(issubclass(HoldDict, HoldObject))
|
|
36
|
+
self.assertTrue(issubclass(FrozenHoldDict, FrozenHoldObject))
|
|
37
|
+
|
|
38
|
+
# non-frozen data inherit from frozen
|
|
39
|
+
self.assertTrue(issubclass(DataDict, BaseDataDict))
|
|
40
|
+
self.assertTrue(issubclass(HoldDict, BaseHoldDict))
|
|
41
|
+
|
|
42
|
+
def test_list_inheritance(self: Self) -> None:
|
|
43
|
+
self.assertTrue(issubclass(DataList, DataObject))
|
|
44
|
+
self.assertTrue(issubclass(FrozenDataList, FrozenDataObject))
|
|
45
|
+
self.assertTrue(issubclass(HoldList, HoldObject))
|
|
46
|
+
self.assertTrue(issubclass(FrozenHoldList, FrozenHoldObject))
|
|
47
|
+
|
|
48
|
+
self.assertTrue(issubclass(DataList, BaseDataList))
|
|
49
|
+
self.assertTrue(issubclass(HoldList, BaseHoldList))
|
|
50
|
+
|
|
51
|
+
def test_set_inheritance(self: Self) -> None:
|
|
52
|
+
self.assertTrue(issubclass(DataSet, DataObject))
|
|
53
|
+
self.assertTrue(issubclass(FrozenDataSet, FrozenDataObject))
|
|
54
|
+
self.assertTrue(issubclass(HoldSet, HoldObject))
|
|
55
|
+
self.assertTrue(issubclass(FrozenHoldSet, FrozenHoldObject))
|
|
56
|
+
|
|
57
|
+
self.assertTrue(issubclass(DataSet, BaseDataSet))
|
|
58
|
+
self.assertTrue(issubclass(HoldSet, BaseHoldSet))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
if __name__ == "__main__":
|
|
62
|
+
unittest.main()
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from typing import Any, Self
|
|
3
|
+
|
|
4
|
+
from frozendict import frozendict
|
|
5
|
+
|
|
6
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
7
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
8
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
9
|
+
from datahold.core.HoldDict import HoldDict
|
|
10
|
+
from datahold.core.HoldList import HoldList
|
|
11
|
+
from datahold.core.HoldSet import HoldSet
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestMutableBehavior(unittest.TestCase):
|
|
15
|
+
def test_hold_dict_mutates_and_syncs_data(self: Self) -> None:
|
|
16
|
+
x: HoldDict
|
|
17
|
+
x = HoldDict({"a": 1})
|
|
18
|
+
x["b"] = 2
|
|
19
|
+
self.assertEqual(x["b"], 2)
|
|
20
|
+
self.assertEqual(x.data["b"], 2)
|
|
21
|
+
|
|
22
|
+
def test_hold_list_mutates_and_syncs_data(self: Self) -> None:
|
|
23
|
+
x: HoldList
|
|
24
|
+
x = HoldList([1, 2])
|
|
25
|
+
x.append(3)
|
|
26
|
+
self.assertEqual(list(x), [1, 2, 3])
|
|
27
|
+
self.assertEqual(x.data, (1, 2, 3))
|
|
28
|
+
|
|
29
|
+
def test_hold_set_mutates_and_syncs_data(self: Self) -> None:
|
|
30
|
+
s: HoldSet
|
|
31
|
+
s = HoldSet({1, 2})
|
|
32
|
+
s.add(3)
|
|
33
|
+
self.assertTrue(3 in s)
|
|
34
|
+
self.assertTrue(3 in s.data)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
if __name__ == "__main__":
|
|
38
|
+
unittest.main()
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from collections.abc import (
|
|
3
|
+
Mapping,
|
|
4
|
+
MutableMapping,
|
|
5
|
+
MutableSequence,
|
|
6
|
+
MutableSet,
|
|
7
|
+
Sequence,
|
|
8
|
+
)
|
|
9
|
+
from collections.abc import Set as AbstractSet
|
|
10
|
+
from typing import Self
|
|
11
|
+
|
|
12
|
+
from frozendict import frozendict
|
|
13
|
+
|
|
14
|
+
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
15
|
+
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
16
|
+
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
17
|
+
from datahold.core.HoldDict import HoldDict
|
|
18
|
+
from datahold.core.HoldList import HoldList
|
|
19
|
+
from datahold.core.HoldSet import HoldSet
|
|
20
|
+
|
|
21
|
+
__all__ = ["TestProtocols"]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class TestProtocols(unittest.TestCase):
|
|
25
|
+
def test_mapping_protocols_x(self: Self) -> None:
|
|
26
|
+
x: FrozenHoldDict
|
|
27
|
+
x = FrozenHoldDict({"a": 1})
|
|
28
|
+
|
|
29
|
+
self.assertIsInstance(x, Mapping)
|
|
30
|
+
self.assertNotIsInstance(x, MutableMapping)
|
|
31
|
+
|
|
32
|
+
def test_mapping_protocols_y(self: Self) -> None:
|
|
33
|
+
y: HoldDict
|
|
34
|
+
y = HoldDict({"a": 1})
|
|
35
|
+
|
|
36
|
+
self.assertIsInstance(y, Mapping)
|
|
37
|
+
self.assertIsInstance(y, MutableMapping)
|
|
38
|
+
|
|
39
|
+
def test_sequence_protocols_x(self: Self) -> None:
|
|
40
|
+
f: FrozenHoldList
|
|
41
|
+
f = FrozenHoldList([1, 2, 3])
|
|
42
|
+
|
|
43
|
+
self.assertIsInstance(f, Sequence)
|
|
44
|
+
self.assertNotIsInstance(f, MutableSequence)
|
|
45
|
+
|
|
46
|
+
def test_sequence_protocols_y(self: Self) -> None:
|
|
47
|
+
m: HoldList
|
|
48
|
+
m = HoldList([1, 2, 3])
|
|
49
|
+
self.assertIsInstance(m, Sequence)
|
|
50
|
+
self.assertIsInstance(m, MutableSequence)
|
|
51
|
+
|
|
52
|
+
def test_set_protocols(self: Self) -> None:
|
|
53
|
+
f: FrozenHoldSet
|
|
54
|
+
m: HoldSet
|
|
55
|
+
f = FrozenHoldSet({1, 2, 3})
|
|
56
|
+
m = HoldSet({1, 2, 3})
|
|
57
|
+
|
|
58
|
+
self.assertIsInstance(f, AbstractSet)
|
|
59
|
+
self.assertNotIsInstance(f, MutableSet)
|
|
60
|
+
|
|
61
|
+
self.assertIsInstance(m, AbstractSet)
|
|
62
|
+
self.assertIsInstance(m, MutableSet)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
if __name__ == "__main__":
|
|
66
|
+
unittest.main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: datahold
|
|
3
|
-
Version: 3.0.0.
|
|
3
|
+
Version: 3.0.0.dev3
|
|
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: The MIT License (MIT)
|
|
@@ -38,5 +38,11 @@ src/datahold/core/HoldSet.py
|
|
|
38
38
|
src/datahold/core/__init__.py
|
|
39
39
|
src/datahold/tests/__init__.py
|
|
40
40
|
src/datahold/tests/test_0.py
|
|
41
|
-
src/datahold/tests/
|
|
41
|
+
src/datahold/tests/test_datahold_TestAbstractness.py
|
|
42
|
+
src/datahold/tests/test_datahold_TestCopy.py
|
|
43
|
+
src/datahold/tests/test_datahold_TestDataAttribute.py
|
|
44
|
+
src/datahold/tests/test_datahold_TestFrozenMutability.py
|
|
45
|
+
src/datahold/tests/test_datahold_TestInheritance.py
|
|
46
|
+
src/datahold/tests/test_datahold_TestMutableBehavior.py
|
|
47
|
+
src/datahold/tests/test_datahold_TestProtocols.py
|
|
42
48
|
src/datahold/tests/test_generic.py
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from .BaseDataDict import BaseDataDict
|
|
2
|
-
from .BaseDataList import BaseDataList
|
|
3
|
-
from .BaseDataObject import BaseDataObject
|
|
4
|
-
from .BaseDataSet import BaseDataSet
|
|
5
|
-
from .BaseHoldDict import BaseHoldDict
|
|
6
|
-
from .BaseHoldList import BaseHoldList
|
|
7
|
-
from .BaseHoldObject import BaseHoldObject
|
|
8
|
-
from .BaseHoldSet import BaseHoldSet
|
|
9
|
-
from .DataDict import DataDict
|
|
10
|
-
from .DataList import DataList
|
|
11
|
-
from .DataObject import DataObject
|
|
12
|
-
from .DataSet import DataSet
|
|
13
|
-
from .FrozenDataDict import FrozenDataDict
|
|
14
|
-
from .FrozenDataList import FrozenDataList
|
|
15
|
-
from .FrozenDataObject import FrozenDataObject
|
|
16
|
-
from .FrozenDataSet import FrozenDataSet
|
|
17
|
-
from .FrozenHoldDict import FrozenHoldDict
|
|
18
|
-
from .FrozenHoldList import FrozenHoldList
|
|
19
|
-
from .FrozenHoldObject import FrozenHoldObject
|
|
20
|
-
from .FrozenHoldSet import FrozenHoldSet
|
|
21
|
-
from .HoldDict import HoldDict
|
|
22
|
-
from .HoldList import HoldList
|
|
23
|
-
from .HoldObject import HoldObject
|
|
24
|
-
from .HoldSet import HoldSet
|
|
@@ -1,298 +0,0 @@
|
|
|
1
|
-
import unittest
|
|
2
|
-
from collections.abc import (
|
|
3
|
-
Mapping,
|
|
4
|
-
MutableMapping,
|
|
5
|
-
MutableSequence,
|
|
6
|
-
MutableSet,
|
|
7
|
-
Sequence,
|
|
8
|
-
)
|
|
9
|
-
from collections.abc import Set as AbstractSet
|
|
10
|
-
from inspect import isabstract
|
|
11
|
-
from typing import Any, Self
|
|
12
|
-
|
|
13
|
-
from frozendict import frozendict
|
|
14
|
-
|
|
15
|
-
from datahold.core.BaseDataDict import BaseDataDict
|
|
16
|
-
from datahold.core.BaseDataList import BaseDataList
|
|
17
|
-
from datahold.core.BaseDataObject import BaseDataObject
|
|
18
|
-
from datahold.core.BaseDataSet import BaseDataSet
|
|
19
|
-
from datahold.core.BaseHoldDict import BaseHoldDict
|
|
20
|
-
from datahold.core.BaseHoldList import BaseHoldList
|
|
21
|
-
from datahold.core.BaseHoldObject import BaseHoldObject
|
|
22
|
-
from datahold.core.BaseHoldSet import BaseHoldSet
|
|
23
|
-
from datahold.core.DataDict import DataDict
|
|
24
|
-
from datahold.core.DataList import DataList
|
|
25
|
-
from datahold.core.DataObject import DataObject
|
|
26
|
-
from datahold.core.DataSet import DataSet
|
|
27
|
-
from datahold.core.FrozenDataDict import FrozenDataDict
|
|
28
|
-
from datahold.core.FrozenDataList import FrozenDataList
|
|
29
|
-
from datahold.core.FrozenDataObject import FrozenDataObject
|
|
30
|
-
from datahold.core.FrozenDataSet import FrozenDataSet
|
|
31
|
-
from datahold.core.FrozenHoldDict import FrozenHoldDict
|
|
32
|
-
from datahold.core.FrozenHoldList import FrozenHoldList
|
|
33
|
-
from datahold.core.FrozenHoldObject import FrozenHoldObject
|
|
34
|
-
from datahold.core.FrozenHoldSet import FrozenHoldSet
|
|
35
|
-
from datahold.core.HoldDict import HoldDict
|
|
36
|
-
from datahold.core.HoldList import HoldList
|
|
37
|
-
from datahold.core.HoldObject import HoldObject
|
|
38
|
-
from datahold.core.HoldSet import HoldSet
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class TestAbstractness(unittest.TestCase):
|
|
42
|
-
def test_abstract_classes(self: Self) -> None:
|
|
43
|
-
# data
|
|
44
|
-
self.assertTrue(isabstract(DataObject))
|
|
45
|
-
self.assertTrue(isabstract(DataDict))
|
|
46
|
-
self.assertTrue(isabstract(DataList))
|
|
47
|
-
self.assertTrue(isabstract(DataSet))
|
|
48
|
-
|
|
49
|
-
self.assertTrue(isabstract(FrozenDataObject))
|
|
50
|
-
self.assertTrue(isabstract(FrozenDataDict))
|
|
51
|
-
self.assertTrue(isabstract(FrozenDataList))
|
|
52
|
-
self.assertTrue(isabstract(FrozenDataSet))
|
|
53
|
-
|
|
54
|
-
# hold
|
|
55
|
-
self.assertFalse(isabstract(FrozenHoldObject))
|
|
56
|
-
# self.assertFalse(isabstract(HoldObject))
|
|
57
|
-
|
|
58
|
-
def test_concrete_classes(self: Self) -> None:
|
|
59
|
-
FrozenHoldDict({"a": 1})
|
|
60
|
-
FrozenHoldList([1, 2])
|
|
61
|
-
FrozenHoldSet({1, 2})
|
|
62
|
-
|
|
63
|
-
HoldDict({"a": 1})
|
|
64
|
-
HoldList([1, 2])
|
|
65
|
-
HoldSet({1, 2})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class TestInheritance(unittest.TestCase):
|
|
69
|
-
def test_dict_inheritance(self: Self) -> None:
|
|
70
|
-
# base → concrete
|
|
71
|
-
self.assertTrue(issubclass(DataDict, DataObject))
|
|
72
|
-
self.assertTrue(issubclass(FrozenDataDict, FrozenDataObject))
|
|
73
|
-
self.assertTrue(issubclass(HoldDict, HoldObject))
|
|
74
|
-
self.assertTrue(issubclass(FrozenHoldDict, FrozenHoldObject))
|
|
75
|
-
|
|
76
|
-
# non-frozen data inherit from frozen
|
|
77
|
-
self.assertTrue(issubclass(DataDict, BaseDataDict))
|
|
78
|
-
self.assertTrue(issubclass(HoldDict, BaseHoldDict))
|
|
79
|
-
|
|
80
|
-
def test_list_inheritance(self: Self) -> None:
|
|
81
|
-
self.assertTrue(issubclass(DataList, DataObject))
|
|
82
|
-
self.assertTrue(issubclass(FrozenDataList, FrozenDataObject))
|
|
83
|
-
self.assertTrue(issubclass(HoldList, HoldObject))
|
|
84
|
-
self.assertTrue(issubclass(FrozenHoldList, FrozenHoldObject))
|
|
85
|
-
|
|
86
|
-
self.assertTrue(issubclass(DataList, BaseDataList))
|
|
87
|
-
self.assertTrue(issubclass(HoldList, BaseHoldList))
|
|
88
|
-
|
|
89
|
-
def test_set_inheritance(self: Self) -> None:
|
|
90
|
-
self.assertTrue(issubclass(DataSet, DataObject))
|
|
91
|
-
self.assertTrue(issubclass(FrozenDataSet, FrozenDataObject))
|
|
92
|
-
self.assertTrue(issubclass(HoldSet, HoldObject))
|
|
93
|
-
self.assertTrue(issubclass(FrozenHoldSet, FrozenHoldObject))
|
|
94
|
-
|
|
95
|
-
self.assertTrue(issubclass(DataSet, BaseDataSet))
|
|
96
|
-
self.assertTrue(issubclass(HoldSet, BaseHoldSet))
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class TestProtocols(unittest.TestCase):
|
|
100
|
-
def test_mapping_protocols_x(self: Self) -> None:
|
|
101
|
-
x: FrozenHoldDict
|
|
102
|
-
x = FrozenHoldDict({"a": 1})
|
|
103
|
-
|
|
104
|
-
self.assertIsInstance(x, Mapping)
|
|
105
|
-
self.assertNotIsInstance(x, MutableMapping)
|
|
106
|
-
|
|
107
|
-
def test_mapping_protocols_y(self: Self) -> None:
|
|
108
|
-
y: HoldDict
|
|
109
|
-
y = HoldDict({"a": 1})
|
|
110
|
-
|
|
111
|
-
self.assertIsInstance(y, Mapping)
|
|
112
|
-
self.assertIsInstance(y, MutableMapping)
|
|
113
|
-
|
|
114
|
-
def test_sequence_protocols_x(self: Self) -> None:
|
|
115
|
-
f: FrozenHoldList
|
|
116
|
-
f = FrozenHoldList([1, 2, 3])
|
|
117
|
-
|
|
118
|
-
self.assertIsInstance(f, Sequence)
|
|
119
|
-
self.assertNotIsInstance(f, MutableSequence)
|
|
120
|
-
|
|
121
|
-
def test_sequence_protocols_y(self: Self) -> None:
|
|
122
|
-
m: HoldList
|
|
123
|
-
m = HoldList([1, 2, 3])
|
|
124
|
-
self.assertIsInstance(m, Sequence)
|
|
125
|
-
self.assertIsInstance(m, MutableSequence)
|
|
126
|
-
|
|
127
|
-
def test_set_protocols(self: Self) -> None:
|
|
128
|
-
f: FrozenHoldSet
|
|
129
|
-
m: HoldSet
|
|
130
|
-
f = FrozenHoldSet({1, 2, 3})
|
|
131
|
-
m = HoldSet({1, 2, 3})
|
|
132
|
-
|
|
133
|
-
self.assertIsInstance(f, AbstractSet)
|
|
134
|
-
self.assertNotIsInstance(f, MutableSet)
|
|
135
|
-
|
|
136
|
-
self.assertIsInstance(m, AbstractSet)
|
|
137
|
-
self.assertIsInstance(m, MutableSet)
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
class TestDataAttribute(unittest.TestCase):
|
|
141
|
-
def test_dict_data_is_immutable_mapping(self: Self) -> None:
|
|
142
|
-
f: FrozenHoldDict
|
|
143
|
-
m: HoldDict
|
|
144
|
-
obj: Any
|
|
145
|
-
f = FrozenHoldDict({"a": 1})
|
|
146
|
-
m = HoldDict({"a": 1})
|
|
147
|
-
|
|
148
|
-
for obj in (f, m):
|
|
149
|
-
self.assertIsInstance(obj.data, frozendict)
|
|
150
|
-
|
|
151
|
-
# try to mutate underlying data
|
|
152
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
153
|
-
obj.data["b"] = 2
|
|
154
|
-
|
|
155
|
-
def test_list_data_is_tuple(self: Self) -> None:
|
|
156
|
-
f: FrozenHoldList
|
|
157
|
-
m: HoldList
|
|
158
|
-
o: Any
|
|
159
|
-
f = FrozenHoldList([1, 2, 3])
|
|
160
|
-
m = HoldList([1, 2, 3])
|
|
161
|
-
|
|
162
|
-
for o in (f, m):
|
|
163
|
-
self.assertIsInstance(o.data, tuple)
|
|
164
|
-
with self.assertRaises(Exception):
|
|
165
|
-
o.data.append(4)
|
|
166
|
-
|
|
167
|
-
def test_set_data_is_frozenset(self: Self) -> None:
|
|
168
|
-
f: FrozenHoldSet
|
|
169
|
-
m: HoldSet
|
|
170
|
-
obj: Any
|
|
171
|
-
f = FrozenHoldSet({1, 2, 3})
|
|
172
|
-
m = HoldSet({1, 2, 3})
|
|
173
|
-
|
|
174
|
-
for obj in (f, m):
|
|
175
|
-
self.assertIsInstance(obj.data, frozenset)
|
|
176
|
-
with self.assertRaises(AttributeError):
|
|
177
|
-
obj.data.add(4)
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
class TestFrozenMutability(unittest.TestCase):
|
|
181
|
-
def test_frozen_dict_cannot_mutate(self: Self) -> None:
|
|
182
|
-
f: FrozenHoldDict
|
|
183
|
-
f = FrozenHoldDict({"a": 1})
|
|
184
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
185
|
-
f["b"] = 2
|
|
186
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
187
|
-
f.pop("a", None)
|
|
188
|
-
|
|
189
|
-
def test_frozen_list_cannot_mutate(self: Self) -> None:
|
|
190
|
-
f: FrozenHoldList
|
|
191
|
-
f = FrozenHoldList([1, 2, 3])
|
|
192
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
193
|
-
f.append(4)
|
|
194
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
195
|
-
f.pop()
|
|
196
|
-
|
|
197
|
-
def test_frozen_set_cannot_mutate(self: Self) -> None:
|
|
198
|
-
f: FrozenHoldSet
|
|
199
|
-
f = FrozenHoldSet({1, 2, 3})
|
|
200
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
201
|
-
f.add(4)
|
|
202
|
-
with self.assertRaises((TypeError, AttributeError)):
|
|
203
|
-
f.remove(1)
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
class TestMutableBehavior(unittest.TestCase):
|
|
207
|
-
def test_hold_dict_mutates_and_syncs_data(self: Self) -> None:
|
|
208
|
-
x: HoldDict
|
|
209
|
-
x = HoldDict({"a": 1})
|
|
210
|
-
x["b"] = 2
|
|
211
|
-
self.assertEqual(x["b"], 2)
|
|
212
|
-
self.assertEqual(x.data["b"], 2)
|
|
213
|
-
|
|
214
|
-
def test_hold_list_mutates_and_syncs_data(self: Self) -> None:
|
|
215
|
-
x: HoldList
|
|
216
|
-
x = HoldList([1, 2])
|
|
217
|
-
x.append(3)
|
|
218
|
-
self.assertEqual(list(x), [1, 2, 3])
|
|
219
|
-
self.assertEqual(x.data, (1, 2, 3))
|
|
220
|
-
|
|
221
|
-
def test_hold_set_mutates_and_syncs_data(self: Self) -> None:
|
|
222
|
-
s: HoldSet
|
|
223
|
-
s = HoldSet({1, 2})
|
|
224
|
-
s.add(3)
|
|
225
|
-
self.assertTrue(3 in s)
|
|
226
|
-
self.assertTrue(3 in s.data)
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
class TestCopy(unittest.TestCase):
|
|
230
|
-
def test_frozen_have_no_copy(self: Self) -> None:
|
|
231
|
-
self.assertFalse(hasattr(FrozenHoldDict({"a": 1}), "copy"))
|
|
232
|
-
self.assertFalse(hasattr(FrozenHoldList([1, 2]), "copy"))
|
|
233
|
-
self.assertFalse(hasattr(FrozenHoldSet({1, 2}), "copy"))
|
|
234
|
-
|
|
235
|
-
def test_frozen_have_no_copy_2(self: Self) -> None:
|
|
236
|
-
"""
|
|
237
|
-
Frozen classes should not define their own copy method.
|
|
238
|
-
(If a parent class or wrapped object exposes one, we ignore that.)
|
|
239
|
-
"""
|
|
240
|
-
cls: Any
|
|
241
|
-
args: Any
|
|
242
|
-
obj: Any
|
|
243
|
-
copy_obj: Any
|
|
244
|
-
for cls, args in (
|
|
245
|
-
(FrozenHoldDict, ({"a": 1},)),
|
|
246
|
-
(FrozenHoldList, ([1, 2],)),
|
|
247
|
-
(FrozenHoldSet, ({1, 2},)),
|
|
248
|
-
):
|
|
249
|
-
# They must not *define* copy themselves
|
|
250
|
-
self.assertNotIn("copy", cls.__dict__)
|
|
251
|
-
|
|
252
|
-
# Optional: if they *do* expose copy on the instance, it should not
|
|
253
|
-
# create a mutable variant; you can drop this if you prefer.
|
|
254
|
-
obj = cls(*args)
|
|
255
|
-
if hasattr(obj, "copy"):
|
|
256
|
-
copy_obj = obj.copy()
|
|
257
|
-
self.assertIsInstance(copy_obj, cls)
|
|
258
|
-
|
|
259
|
-
def test_mutable_copy_returns_same_type_and_is_shallow(self: Self) -> None:
|
|
260
|
-
d: HoldDict
|
|
261
|
-
d_copy: HoldDict
|
|
262
|
-
d = HoldDict({"a": {"x": 1}})
|
|
263
|
-
d_copy = d.copy()
|
|
264
|
-
self.assertIsInstance(d_copy, type(d))
|
|
265
|
-
self.assertIsNot(d_copy, d)
|
|
266
|
-
self.assertEqual(dict(d_copy), dict(d))
|
|
267
|
-
|
|
268
|
-
# shallow: inner object is shared
|
|
269
|
-
d["a"]["x"] = 2
|
|
270
|
-
self.assertEqual(d_copy["a"]["x"], 2)
|
|
271
|
-
|
|
272
|
-
def test_list_copy(self: Self) -> None:
|
|
273
|
-
lst: HoldList
|
|
274
|
-
lst_copy: HoldList
|
|
275
|
-
lst = HoldList([[1], [2]])
|
|
276
|
-
lst_copy = lst.copy()
|
|
277
|
-
self.assertIsInstance(lst_copy, type(lst))
|
|
278
|
-
self.assertIsNot(lst_copy, lst)
|
|
279
|
-
self.assertEqual(list(lst_copy), list(lst))
|
|
280
|
-
|
|
281
|
-
lst[0].append(99)
|
|
282
|
-
self.assertEqual(lst_copy[0], [1, 99])
|
|
283
|
-
|
|
284
|
-
def test_set_copy(self: Self) -> None:
|
|
285
|
-
s: HoldSet
|
|
286
|
-
s_copy: HoldSet
|
|
287
|
-
s = HoldSet({1, 2, 3})
|
|
288
|
-
s_copy = s.copy()
|
|
289
|
-
self.assertIsInstance(s_copy, type(s))
|
|
290
|
-
self.assertIsNot(s_copy, s)
|
|
291
|
-
self.assertEqual(set(s_copy), set(s))
|
|
292
|
-
|
|
293
|
-
s.add(4)
|
|
294
|
-
self.assertNotIn(4, s_copy)
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if __name__ == "__main__":
|
|
298
|
-
unittest.main()
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|