]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
simple custom implementation of dataclasses in order to prevent dependence on the...
authorVasek Sraier <git@vakabus.cz>
Fri, 22 Oct 2021 12:09:25 +0000 (14:09 +0200)
committerAleš Mrázek <ales.mrazek@nic.cz>
Fri, 8 Apr 2022 14:17:53 +0000 (16:17 +0200)
manager/knot_resolver_manager/compat/dataclasses.py
manager/tests/utils/test_dataclasses.py [new file with mode: 0644]

index 57f77fd2ff94fd1c2d95f9b0340fea8d605bc282..7f5628c4c13e4250b9fa9607f78f7c099be3e53e 100644 (file)
@@ -7,6 +7,49 @@ the option to do it transparently, without changing anything else.
 """
 
 
-from dataclasses import dataclass, field, is_dataclass
+from typing import Any, Dict, Set, Type
 
-__all__ = ["dataclass", "is_dataclass", "field"]
+_CUSTOM_DATACLASS_MARKER = "_CUSTOM_DATACLASS_MARKER"
+
+
+def dataclass(cls: Any):
+    anot: Dict[str, Type[Any]] = cls.__dict__.get("__annotations__", {})
+
+    def ninit(slf: Any, *args: Any, **kwargs: Any) -> None:
+        nonlocal anot
+
+        ianot = iter(anot.keys())
+        used: Set[str] = set()
+
+        # set normal arguments
+        for arg in args:
+            name = next(ianot)
+            setattr(slf, name, arg)
+            used.add(name)
+
+        # set keyd arguments
+        for key, val in kwargs.items():
+            assert key in anot, f"Key '{key}' not defined with a type annotation"
+            setattr(slf, key, val)
+            used.add(key)
+
+        # set default values
+        for key in anot:
+            if key in used:
+                continue
+            assert hasattr(
+                cls, key
+            ), f"Field '{key}' does not have default value and was not defined in the constructor"
+            dfl = getattr(cls, key)
+            setattr(slf, key, dfl)
+
+    setattr(cls, "__init__", ninit)
+    setattr(cls, _CUSTOM_DATACLASS_MARKER, ...)
+    return cls
+
+
+def is_dataclass(cls: Any) -> bool:
+    return hasattr(cls, _CUSTOM_DATACLASS_MARKER)
+
+
+__all__ = ["dataclass", "is_dataclass"]
diff --git a/manager/tests/utils/test_dataclasses.py b/manager/tests/utils/test_dataclasses.py
new file mode 100644 (file)
index 0000000..c402c09
--- /dev/null
@@ -0,0 +1,15 @@
+from knot_resolver_manager.compat.dataclasses import dataclass, is_dataclass
+
+
+def test_dataclass():
+    @dataclass
+    class A:
+        b: int = 5
+
+    val = A(6)
+    assert val.b == 6
+
+    val = A(b=7)
+    assert val.b == 7
+
+    assert is_dataclass(A)