With python static typing/mpy, can I say "this method has the same/similar type signature as method X"?

Viewed 322

I'm trying to override an initializer method but not copy all the static typing from the base method:

class BaseClass:
    def __init__(self, *, message: str, error_code: int):
        self.message = message
        self.error_code = error_code

class SubClass(BaseClass):
    def __init__(self, *, details: str, **kwargs):
        super().__init__(**kwargs)
        self.details = details

I'd really like to not have to copy the signature of BaseClass.__init__ into SubClass.__init__ in order to get static checking of the parameters. Is it possible to indicate to static typing/mypy that SubClass.__init__(**kwargs) are the parameters/types declared in BaseClass.__init__ ?

I was not able to find a syntax or "delegating typing" model that would allow this after having read through both the python typing documentation as well as the mypy cheat-sheet

Ideally, I'd like code like the following to raise a mypy error/warning:

SubClass(message="foo", error_code=13, details="badness", stack_trace=[1, 2, 3])

SubClass does not accept an argument with the name "stack_trace".

1 Answers

Short answer: no, there is an open feature request.

In your particular case, you can use dataclasses to tell mypy about the kwargs:

MYPY = False

if MYPY:
    from dataclasses import dataclass

    @dataclass
    class BaseClass:
        message: str
        error_code: int

    @dataclass
    class SubClass(BaseClass):
        details: str
else:
    class BaseClass:
        def __init__(self, *, message: str, error_code: int):
            self.message = message
            self.error_code = error_code

    class SubClass(BaseClass):
        def __init__(self, *, details: str, **kwargs):
            super().__init__(**kwargs)
            self.details = details

The code above typechecks with latest mypy and detects wrong usage of your class, and still runs on Python versions without dataclasses. You can put the dataclass definition into a .pyi file to enable support for Python 2.

You can also get rid of your __init__ code and use dataclasses all the way if you can drop older Python versions.

Related