Release/v0.6.0 #12
2 changed files with 41 additions and 13 deletions
|
|
@ -1,7 +1,14 @@
|
|||
from __future__ import annotations
|
||||
|
||||
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.utils import inherit
|
||||
|
|
@ -11,10 +18,6 @@ R = TypeVar("R")
|
|||
|
||||
|
||||
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
|
||||
def serialize(self, value: T, /) -> bytes:
|
||||
"""Serialize a value
|
||||
|
|
@ -42,14 +45,18 @@ class Field(ABC, PrivProperty[T], Generic[T]):
|
|||
serialize: Callable[[Field[R], R], bytes],
|
||||
deserialize: Callable[[Field[R], bytes], R],
|
||||
) -> type[Field[R]]:
|
||||
return inherit(cls, {"serialize": serialize, "deserialize": deserialize})
|
||||
return inherit(
|
||||
cls, {"serialize": serialize, "deserialize": deserialize}
|
||||
)
|
||||
|
||||
@final
|
||||
@staticmethod
|
||||
def get_fields(class_: type[Any] | Any, /) -> dict[str, Field[Any]]:
|
||||
if not isinstance(class_, type):
|
||||
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:
|
||||
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
||||
|
||||
class PrivProperty(Generic[T]):
|
||||
__slots__ = "__name", "__default_value"
|
||||
__slots__ = "__name", "__default_value", "__default_factory"
|
||||
|
||||
__name: str
|
||||
|
||||
def __init__(self, default_value: T | None = None) -> None:
|
||||
self.__default_value: T | None = default_value
|
||||
@overload
|
||||
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:
|
||||
self.__name = f"_{owner.__name__}__{name}"
|
||||
|
||||
def __get__(self, instance: Any, owner: type | None = None, /) -> T:
|
||||
if self.__default_value:
|
||||
return getattr(instance, self.__name, self.__default_value)
|
||||
if not hasattr(instance, self.__name):
|
||||
setattr(instance, self.__name, self._get_default())
|
||||
return getattr(instance, self.__name) # type: ignore
|
||||
|
||||
def __set__(self, instance: Any, value: T, /) -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue