feat: add default_factory in PrivProperty
This commit is contained in:
parent
12c0f42f99
commit
1e82a457ac
2 changed files with 41 additions and 13 deletions
|
|
@ -1,7 +1,14 @@
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import TYPE_CHECKING, Any, Callable, Final, Generic, TypeVar, final
|
from typing import (
|
||||||
|
TYPE_CHECKING,
|
||||||
|
Any,
|
||||||
|
Callable,
|
||||||
|
Generic,
|
||||||
|
TypeVar,
|
||||||
|
final,
|
||||||
|
)
|
||||||
|
|
||||||
from snakia.property.priv_property import PrivProperty
|
from snakia.property.priv_property import PrivProperty
|
||||||
from snakia.utils import inherit
|
from snakia.utils import inherit
|
||||||
|
|
@ -11,10 +18,6 @@ R = TypeVar("R")
|
||||||
|
|
||||||
|
|
||||||
class Field(ABC, PrivProperty[T], Generic[T]):
|
class Field(ABC, PrivProperty[T], Generic[T]):
|
||||||
def __init__(self, default_value: T) -> None:
|
|
||||||
self.default_value: Final[T] = default_value
|
|
||||||
super().__init__(default_value)
|
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def serialize(self, value: T, /) -> bytes:
|
def serialize(self, value: T, /) -> bytes:
|
||||||
"""Serialize a value
|
"""Serialize a value
|
||||||
|
|
@ -42,14 +45,18 @@ class Field(ABC, PrivProperty[T], Generic[T]):
|
||||||
serialize: Callable[[Field[R], R], bytes],
|
serialize: Callable[[Field[R], R], bytes],
|
||||||
deserialize: Callable[[Field[R], bytes], R],
|
deserialize: Callable[[Field[R], bytes], R],
|
||||||
) -> type[Field[R]]:
|
) -> type[Field[R]]:
|
||||||
return inherit(cls, {"serialize": serialize, "deserialize": deserialize})
|
return inherit(
|
||||||
|
cls, {"serialize": serialize, "deserialize": deserialize}
|
||||||
|
)
|
||||||
|
|
||||||
@final
|
@final
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_fields(class_: type[Any] | Any, /) -> dict[str, Field[Any]]:
|
def get_fields(class_: type[Any] | Any, /) -> dict[str, Field[Any]]:
|
||||||
if not isinstance(class_, type):
|
if not isinstance(class_, type):
|
||||||
class_ = class_.__class__
|
class_ = class_.__class__
|
||||||
return {k: v for k, v in class_.__dict__.items() if isinstance(v, Field)}
|
return {
|
||||||
|
k: v for k, v in class_.__dict__.items() if isinstance(v, Field)
|
||||||
|
}
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,43 @@
|
||||||
from typing import Any, Generic, TypeVar
|
from typing import Any, Callable, Final, Generic, TypeVar, overload
|
||||||
|
from typing_extensions import Self
|
||||||
|
|
||||||
T = TypeVar("T")
|
T = TypeVar("T")
|
||||||
|
|
||||||
|
|
||||||
class PrivProperty(Generic[T]):
|
class PrivProperty(Generic[T]):
|
||||||
__slots__ = "__name", "__default_value"
|
__slots__ = "__name", "__default_value", "__default_factory"
|
||||||
|
|
||||||
__name: str
|
__name: str
|
||||||
|
|
||||||
def __init__(self, default_value: T | None = None) -> None:
|
@overload
|
||||||
self.__default_value: T | None = default_value
|
def __init__(self) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, default_value: T) -> None: ...
|
||||||
|
@overload
|
||||||
|
def __init__(self, *, default_factory: Callable[[Self], T]) -> None: ...
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
default_value: T | None = None,
|
||||||
|
default_factory: Callable[[Self], T] | None = None,
|
||||||
|
) -> None:
|
||||||
|
self.__default_value: Final[T | None] = default_value
|
||||||
|
self.__default_factory: Final[Callable[[Self], T] | None] = (
|
||||||
|
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")
|
||||||
|
|
||||||
def __set_name__(self, owner: type, name: str) -> None:
|
def __set_name__(self, owner: type, name: str) -> None:
|
||||||
self.__name = f"_{owner.__name__}__{name}"
|
self.__name = f"_{owner.__name__}__{name}"
|
||||||
|
|
||||||
def __get__(self, instance: Any, owner: type | None = None, /) -> T:
|
def __get__(self, instance: Any, owner: type | None = None, /) -> T:
|
||||||
if self.__default_value:
|
if not hasattr(instance, self.__name):
|
||||||
return getattr(instance, self.__name, self.__default_value)
|
setattr(instance, self.__name, self._get_default())
|
||||||
return getattr(instance, self.__name) # type: ignore
|
return getattr(instance, self.__name) # type: ignore
|
||||||
|
|
||||||
def __set__(self, instance: Any, value: T, /) -> None:
|
def __set__(self, instance: Any, value: T, /) -> None:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue