59 lines
1.7 KiB
Python
59 lines
1.7 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any, Callable, Generic, TypeVar
|
|
|
|
from typing_extensions import Self
|
|
|
|
from snakia.types import empty
|
|
|
|
from .priv_property import PrivProperty
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class HookProperty(PrivProperty[T], Generic[T]):
|
|
"""
|
|
A property that calls a function when the property is set, get, or deleted.
|
|
"""
|
|
|
|
__slots__ = ("__on_set", "__on_get", "__on_del")
|
|
|
|
def __init__(
|
|
self,
|
|
on_get: Callable[[T], None],
|
|
on_set: Callable[[T], None] = empty.func,
|
|
on_del: Callable[[T], None] = empty.func,
|
|
) -> None:
|
|
super().__init__()
|
|
self.__on_set: Callable[[T], None] = on_set
|
|
self.__on_get: Callable[[T], None] = on_get
|
|
self.__on_del: Callable[[T], None] = on_del
|
|
|
|
def __get__(self, instance: Any, owner: type | None = None, /) -> T:
|
|
value = super().__get__(instance, owner)
|
|
self.__on_get(value)
|
|
return value
|
|
|
|
def __set__(self, instance: Any, value: T, /) -> None:
|
|
self.__on_set(value)
|
|
return super().__set__(instance, value)
|
|
|
|
def __delete__(self, instance: Any, /) -> None:
|
|
value = super().__get__(instance)
|
|
self.__on_del(value)
|
|
return super().__delete__(instance)
|
|
|
|
def getter(self, on_get: Callable[[T], None], /) -> Self:
|
|
"""Descriptor getter."""
|
|
self.__on_get = on_get
|
|
return self
|
|
|
|
def setter(self, on_set: Callable[[T], None], /) -> Self:
|
|
"""Descriptor setter."""
|
|
self.__on_set = on_set
|
|
return self
|
|
|
|
def deleter(self, on_del: Callable[[T], None], /) -> Self:
|
|
"""Descriptor deleter."""
|
|
self.__on_del = on_del
|
|
return self
|