]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
python: modeling: added base class for custom types (BaseCustomType)
authorAleš Mrázek <ales.mrazek@nic.cz>
Mon, 16 Feb 2026 18:34:42 +0000 (19:34 +0100)
committerAleš Mrázek <ales.mrazek@nic.cz>
Mon, 20 Apr 2026 22:25:58 +0000 (00:25 +0200)
python/knot_resolver/utils/modeling/types/base_custom_type.py [new file with mode: 0644]

diff --git a/python/knot_resolver/utils/modeling/types/base_custom_type.py b/python/knot_resolver/utils/modeling/types/base_custom_type.py
new file mode 100644 (file)
index 0000000..d2fb6ba
--- /dev/null
@@ -0,0 +1,96 @@
+from __future__ import annotations
+
+from abc import ABC, abstractmethod
+from pathlib import Path
+from typing import Any, TypeVar
+
+from knot_resolver.utils.modeling.context import Context, Strictness
+
+T = TypeVar("T")
+
+NoneType = type(None)
+
+
+class BaseCustomType(ABC):
+    """
+    Base class for custom types that just wraps the value.
+
+    This class provides the basis for other custom types.
+    """
+
+    _is_valid: bool = False
+
+    def __init__(self, value: Any, tree_path: str = "/", base_path: Path = Path()) -> None:
+        self._value = value
+        self._tree_path = tree_path
+        self._base_path = base_path
+
+    def __repr__(self) -> str:
+        return f'{type(self).__name__}("{self._value!r}")'
+
+    def __eq__(self, obj: object) -> bool:
+        if not isinstance(obj, type(self)):
+            return NotImplemented
+        return self._value == obj._value
+
+    def __hash__(self) -> int:
+        return hash(self._value)
+
+    def __str__(self) -> str:
+        return str(self._value)
+
+    def __int__(self) -> int:
+        msg = f"int() not supported for {type(self).__name__}"
+        raise TypeError(msg)
+
+    def __float__(self) -> float:
+        msg = f"float() not supported for {type(self).__name__}"
+        raise TypeError(msg)
+
+    @abstractmethod
+    def _validate(self, context: Context) -> None:
+        """
+        Validate data value wrapped by the custom type.
+
+        All validation should be done here.
+        This method is automatically called during validation.
+        Subclasses must implement this method.
+        """
+
+    def validate(self, context: Context | None = None) -> None:
+        """
+        Validate data value wrapped by the custom type.
+
+        Args:
+            context (Context | None):
+                Optional, validation context for the validation operations, e.g. validation strictness
+                or username and groupname to check permissions on paths.
+                If set to None, Context() with defaults is used.
+
+        Raises:
+            DataTypeError: When input data type validation fails.
+            DataValueError: When input data value validation fails.
+            DataValidationError: When some other input data validation fails.
+
+        At least BASIC validation strictness is required
+        for the data value to be considered valid.
+        If validation is successful, no error is raised.
+        """
+
+        if context is None:
+            # use default context
+            context = Context()
+
+        self._validate(context)
+        if context.strictness > Strictness.PERMISSIVE:
+            self._is_valid = True
+
+    @classmethod
+    @abstractmethod
+    def json_schema(cls) -> dict[Any, Any]:
+        """
+        Get JSON schema of the custom type.
+
+        Returns:
+            JSON schema of the custom type in dictionary.
+        """