Home > database >  Why mypy is not throwing an error if interface and implementation has a different argument name
Why mypy is not throwing an error if interface and implementation has a different argument name

Time:02-02

I have discovered today this bug in our code base (simplified example):

from abc import ABC, abstractmethod


class Interface(ABC):
    @abstractmethod
    def method(self, variable: str) -> str:
        pass


class Implementation(Interface):
    def method(self, variable_changed: str) -> str:
        return "A"


Implementation().method("d")  # works
Implementation().method(variable="d")  # error
Implementation().method(variable_changed="d")  # works

Here we have a class implementing an interface. That's all good, but the implementation change the name of the first argument of the method. If I run mypy, I would expect to get an error, because implementation is not following the contract defined by the Interface. To my surprise, this is not the case at all.

I'm not sure if this is intended or not, but I would like to detect those kinds of mismatchs as soon as possible. Any idea how to fix mypy or how to enable this kind of detection in case it's not an error?

CodePudding user response:

Mypy treats parameters as positional if they aren’t explicitly specified as named. Your Interface therefore only requires that method accepts one argument, not that it have a particular name.

To specify it as a named parameter (forcing implementations to match the name) you’d do:

def method(self, *, variable: str) -> str:

to say that variable is a named parameter (and must always be called as such).

For discussion on changing this behavior in mypy see the related GitHub issue: https://github.com/python/mypy/issues/6709

  • Related