Hello. I noticed that Pyright doesn’t check the signatures of abstractmethod
implementations when the abstractmethod
is __init__()
. Here’s an example:
from abc import ABC, abstractmethod
class AbstractA(ABC):
@abstractmethod
def __init__(self, x: int, y: int):
pass
@abstractmethod
def do_something(self, z: int, u: int):
pass
class RealA(AbstractA):
def __init__(self, x: int): ## No static type checker error
self.x = x
def do_something(self, z: int): ## Static type checker error
print(f"I hope I don't need anything other than {z}")
inst = RealA(3) ## No type checker errors for missing/bad method implementations
Here, Pyright gives me an error at the definition of RealA.do_something()
as expected (“overrides AbstractA
in an incompatible manner”), but I get no such error for RealA.__init__()
even though it is missing y
in its signature.
I don’t think this is a Pyright bug, at least not an accidental one. The developer addresses this issue here (for Protocol
rather than ABC
, but I think it should be similar enough). I’ll admit that I haven’t taken the deep dive into the spec to decide if the Pyright dev is correct that there’s too much uncertainty to address this issue at present, but I’ll yield to their expertise and accept that premise for my question.
Is it possible either now or in the future to write AbstractA
in such a way that it enforces a minimum signature for construction? I can’t think of a way around this that doesn’t involve trusting the author of RealA
to remember to call super().__init__()
in order to make sure that the correct type checker errors are thrown, and if the author does forget to add super().__init__()
, the runtime errors (“RealA
has no attribute y
”) aren’t immediately intuitive, especially if AbstractA
is part of an installed package that the author of RealA
didn’t write themselves.
This issue could also be avoided by implementing __init__()
in AbstractA
and having all implementations use it implicitly, but in my particular case, I came across this problem because I wanted to have implementation-specific keyword arguments for constructing RealA
on top of a minimally required signature for constructing any AbstractA
implementation.
Apologies if this is a duplicate topic, searches for various combinations of “__init__”, “signature”, “ABC”, etc. didn’t turn up any relevant posts.