I have the following function that returns a class with a generic type parameter:
T = TypeVar('T')
def create_property(event_bus: EventBus):
class Property(Generic[T]):
def __init__(self, validator: Callable[[T], bool]):
self._validator = validator
def __set_name__(self, obj: Any, name: str):
self.name = name
def __get__(self, obj: Any, type: Any) -> T:
return obj.__dict__.get(self.name)
def __set__(self, obj: Any, value: T):
if not self._validator(value):
raise ValueError("Invalid value")
obj.__dict__[self.name] = value
event_bus.publish()
return Property
What I’m trying to do here is to create a class that has an EventBus
bound to it so that I don’t have to pass it as a constructor parameter.
My problem with the above code is that this will resolve to Property[Any]
instead of Property[T]
so the generic is lost somewhere along the way. How can I fix this function to preserve the generic?
Your function create_property
needs a typed argument to deduce return value type. To make validations, you will probably need T
‘s type in Property
class. Also, I added event_bus
as class variable.
from typing import Any, Callable
class EventBus:
def publish(self):
...
class Property[T]:
event_bus: EventBus
type: type[T]
def __init__(self, validator: Callable[[T], bool]):
self._validator = validator
def __set_name__(self, obj: Any, name: str):
self.name = name
def __get__(self, obj: Any, type: Any) -> T:
return obj.__dict__.get(self.name)
def __set__(self, obj: Any, value: T):
if not self._validator(value):
raise ValueError("Invalid value")
obj.__dict__[self.name] = value
self.event_bus.publish()
def create_property[T](typ: type[T], event_bus: EventBus) -> type[Property[T]]:
class P[T](Property[T]):
...
P.event_bus = event_bus
P.type = typ
return P
Prop = create_property(int, event_bus=EventBus())
makukha is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
3