mypy-zope
mypy-zope copied to clipboard
make it possible to define a generic interface
This probably requires some implementation support from the zope.interface side, but I find myself wanting to be able to write this:
from dataclasses import dataclass
from typing import Generic, TypeVar
from zope.interface import Interface, implementer
T = TypeVar("T")
class IA(Generic[T], Interface):
def m() -> T:
...
@implementer(IA)
@dataclass
class A(Generic[T]):
_v: T
def m(self) -> T:
return self._v
a: IA[int] = A(3)
This actually appears to do what I want at type-check time! But then it (somewhat obviously) crashes at runtime.
This horrible hack almost works though, which suggests that this could work properly with some very small changes:
# from __future__ import annotations
from dataclasses import dataclass
from typing import Generic, TypeVar, TYPE_CHECKING
from zope.interface import Interface, implementer
T = TypeVar("T")
if TYPE_CHECKING:
from typing import Generic as GenericInterface
else:
from zope.interface.interface import InterfaceClass
class SpecialInterfaceClass(InterfaceClass):
def __getitem__(self, key):
return self
EmptyInterface = SpecialInterfaceClass("<Empty>", __module__=__name__)
class GenericInterfaceClass:
def __getitem__(self, typevars):
return EmptyInterface
GenericInterface = GenericInterfaceClass()
class IA(Interface, GenericInterface[T]):
def m() -> T:
...
@implementer(IA)
@dataclass
class A(Generic[T]):
_v: T
def m(self) -> T:
return self._v
@dataclass
class B:
...
a: IA[int] = A(3) # works, hooray
a = B() # error, hooray
a = A("oops") # no error, boo