diff --git a/src/snakia/field/auto.py b/src/snakia/field/auto.py index 12e7d25..f456a1d 100644 --- a/src/snakia/field/auto.py +++ b/src/snakia/field/auto.py @@ -3,6 +3,8 @@ from typing import Callable, Final, Generic, TypeVar, overload from typing_extensions import Self +from snakia.types import Unset + from .field import Field T = TypeVar("T") @@ -13,33 +15,38 @@ class AutoField(Field[T], Generic[T]): @overload def __init__( - self, default_value: T, *, target_type: type[T] | None = None + self, default_value: T, *, target_type: type[T] | Unset = Unset() ) -> None: ... + @overload def __init__( self, *, default_factory: Callable[[Self], T], - target_type: type[T] | None = None, + target_type: type[T] | Unset = Unset(), ) -> None: ... + def __init__( self, - default_value: T | None = None, + default_value: T | Unset = Unset(), *, - default_factory: Callable[[Self], T] | None = None, - target_type: type[T] | None = None, + default_factory: Callable[[Self], T] | Unset = Unset(), + target_type: type[T] | Unset = Unset(), ) -> None: - if default_factory is not None and default_value is None: - super().__init__(default_factory=default_factory) - elif default_value is not None and default_factory is None: - super().__init__(default_value) - self.__target_type: Final = target_type + if not Unset.itis(default_factory): + super().__init__(default_factory=Unset.unwrap(default_factory)) + elif not Unset.itis(default_value): + super().__init__(Unset.unwrap(default_value)) + else: + super().__init__() + self.__target_type: Final[type] = Unset.unwrap_or(target_type, object) def serialize(self, value: T, /) -> bytes: return pickle.dumps(value) def deserialize(self, serialized: bytes, /) -> T: value = pickle.loads(serialized) - if not isinstance(value, self.__target_type or object): + + if not isinstance(value, self.__target_type): return self._get_default() return value # type: ignore diff --git a/src/snakia/property/priv_property.py b/src/snakia/property/priv_property.py index 705a2e6..fba63da 100644 --- a/src/snakia/property/priv_property.py +++ b/src/snakia/property/priv_property.py @@ -1,6 +1,9 @@ from typing import Any, Callable, Final, Generic, TypeVar, overload + from typing_extensions import Self +from snakia.types import Unset + T = TypeVar("T") @@ -17,20 +20,18 @@ class PrivProperty(Generic[T]): def __init__(self, *, default_factory: Callable[[Self], T]) -> None: ... def __init__( self, - default_value: T | None = None, - default_factory: Callable[[Self], T] | None = None, + default_value: T | Unset = Unset(), + default_factory: Callable[[Self], T] | Unset = Unset(), ) -> None: - self.__default_value: Final[T | None] = default_value - self.__default_factory: Final[Callable[[Self], T] | None] = ( - default_factory - ) + self.__default_value: Final[T | Unset] = default_value + self.__default_factory: Final[Callable[[Self], T] | Unset] = default_factory def _get_default(self: Self) -> T: - if self.__default_value is not None: - return self.__default_value - if self.__default_factory is not None: - return self.__default_factory(self) - raise ValueError("Either default_value or default_factory must be set") + return Unset.map( + self.__default_factory, + lambda f: f(self), + lambda _: Unset.unwrap(self.__default_value), + ) def __set_name__(self, owner: type, name: str) -> None: self.__name = f"_{owner.__name__}__{name}"