return {"type": "string"}
+class StringLengthBase(StrBase):
+ """
+ Base class to work with string value length.
+ Just inherit the class and set the values for '_min_bytes' and '_max_bytes'.
+
+ class String32B(StringLengthBase):
+ _min_bytes: int = 32
+ """
+
+ _min_bytes: int = 1
+ _max_bytes: int
+
+ def __init__(self, source_value: Any, object_path: str = "/") -> None:
+ super().__init__(source_value, object_path)
+ value_bytes = len(self._value.encode("utf-8"))
+ if hasattr(self, "_min_bytes") and (value_bytes < self._min_bytes):
+ raise ValueError(
+ f"the string value {source_value} is shorter than the minimum {self._min_bytes} bytes.", object_path
+ )
+ if hasattr(self, "_max_bytes") and (value_bytes > self._max_bytes):
+ raise ValueError(
+ f"the string value {source_value} is longer than the maximum {self._max_bytes} bytes.", object_path
+ )
+
+ @classmethod
+ def json_schema(cls: Type["StringLengthBase"]) -> Dict[Any, Any]:
+ typ: Dict[str, Any] = {"type": "string"}
+ if hasattr(cls, "_min_bytes"):
+ typ["minLength"] = cls._min_bytes
+ if hasattr(cls, "_max_bytes"):
+ typ["maxLength"] = cls._max_bytes
+ return typ
+
+
class IntRangeBase(IntBase):
"""
Base class to work with integer value in range.
import pytest
from pytest import raises
-from knot_resolver_manager.datamodel.types.base_types import IntRangeBase
+from knot_resolver_manager.datamodel.types.base_types import IntRangeBase, StringLengthBase
from knot_resolver_manager.exceptions import KresManagerException
for inval in invals:
with raises(KresManagerException):
Test(inval)
+
+
+@pytest.mark.parametrize("min,max", [(10, None), (None, 10), (2, 32)])
+def test_str_bytes_length_base(min: Optional[int], max: Optional[int]):
+ class Test(StringLengthBase):
+ if min:
+ _min_bytes = min
+ if max:
+ _max_bytes = max
+
+ if min:
+ assert len(str(Test("x" * min)).encode("utf-8")) == min
+ if max:
+ assert len(str(Test("x" * max)).encode("utf-8")) == max
+
+ n = 100
+ rmin = 1 if not min else min
+ rmax = 1024 if not max else max
+ vals: List[str] = ["x" * random.randint(rmin, rmax) for _ in range(n)]
+ assert [str(Test(val)) == f"{val}" for val in vals]
+
+ invals: List[str] = []
+ invals.extend(["x" * random.randint(rmax + 1, 2048) for _ in range(n % 2)] if max else [])
+ invals.extend(["x" * random.randint(1, rmin - 1) for _ in range(n % 2)] if max else [])
+
+ for inval in invals:
+ with raises(KresManagerException):
+ Test(inval)