Skip to content

Subclass method parameter names are not checked against superclass #6709

Open

Description

@benclifford
  • Are you reporting a bug, or opening a feature request?

Bug

  • Please insert below the code you are checking with mypy,
    or a mock-up repro if the source is private. We would appreciate
    if you try to simplify your case to a minimal repro.

When a subclass renames the parameters of a method, this results in runtime errors; but this seems like something that should be statically detectable.

The below code provides a superclass A, and two similar subclasses B and C that differ in that C renames the parameter to the method f, but B does not.

mypy vs runtime behaviour for variables c and c2 seems inconsistent, while for c3 and c4 it seems ok.

I was expecting some mypy error to be raised when defining f in class C.

class A:
    def f(self, x: int) -> None:
      print("A: ", x)

class B(A):
    def f(self, x: int) -> None:
      print("B: ", x)

class C(A):
    def f(self, n: int) -> None:
      print("C: ", n)

a = A()
a.f(x=3)

b = B()  # type: A
b.f(x=3)

c = C()  # type: A
c.f(x=3)  # mypy passes, but gives runtime error: TypeError: f() got an unexpected keyword argument 'x'

c2 = C()  # type: A
c2.f(n=3) # mypy gives an error:  error: Unexpected keyword argument "n" for "f" of "A"   but runtime works.

c3 = C()  # type: C
c3.f(x=3)    # mypy give type error: error: Unexpected keyword argument "x" for "f" of "C", and runtime error: mypy-issue.py:25: error: Unexpected keyword argument "x" for "f" of "C"

c4 = C()  # type: C
c4.f(n=3)  # no errors in mypy or at runtime
  • What are the versions of mypy and Python you are using?

$ mypy --version
mypy 0.670
$ python --version
Python 3.7.2+

  • Do you see the same issue after installing mypy from Git master?

yes - mypy 0.710+dev.f10528a5a8d9e98939ceb84d40e614d1f159d9a0

  • What are the mypy flags you are using? (For example --strict-optional)

With no flags, and with --strict.

Activity

  1. gvanrossum commented on Apr 22, 2019

    @gvanrossum
    Member

    This is actually done intentionally because for calls with positional parameters the argument name is irrelevant. If we were to change this behavior a lot of code that works and is considered correct in practice would be found out of compliance.

    However I could see us accepting a PR that adds a flag that makes this behavior more strict, and adds that flag to the set of flags turned on by --strict.

  2. wkschwartz commented on Sep 10, 2019

    @wkschwartz
    Contributor

    It seems that Mypy does actually check parameter names if **kwargs is part of the signature. The following Python file has the output below (on Python 3.7.3, Mypy 0.720 under the default configuration). Notice changing the name of the parameter from x to n, and adding **kwargs arguments.

    class A:
        def f(self, x: int               ) -> int: return x
    class B(A):
        def f(self, n: int               ) -> int: return super().f(n)
    
    class C:
        def f(self, x: int, **kwargs: int) -> int: return x
    class D(C):
        def f(self, n: int, **kwargs: int) -> int: return super().f(n, **kwargs)

    Output:

    mypy-test.py:9: error: Signature of "f" incompatible with supertype "C"
    

    B.f is compatible with A.f but C.f is not compatible with D.f. Adding **kwargs made Mypy decide that changing the parameter name from x to n was bad.

    If nothing else, this error is very difficult to understand. However, I agree with #6709 (comment) and think that logic applies even when there are **kwargs: the absence of **kwawrgs in no way indicates that client code will call the function only with positional arguments.

  3. JukkaL commented on Sep 11, 2019

    @JukkaL
    Collaborator

    One major problem with checking argument names is that typeshed stubs may have dummy argument names in methods. Some of the argument names are probably just incorrect, while others should be positional-only. For example, many methods implemented in C should have positional-only arguments to facilitate precise checking of argument names. I'm not sure how useful strict checking of argument names would be if we don't improve typeshed first.

  4. antoniogamizdelgado commented on Feb 1, 2023

    @antoniogamizdelgado

    Any updates on this? I think the idea of having a flag to allow this for those users that need it is fine. For those cases where this flag mayb create some problems it can be deactivated (which would be its default value I suppose).

  5. AlexWaygood commented on Aug 13, 2026

    @AlexWaygood
    Member

    One major problem with checking argument names is that typeshed stubs may have dummy argument names in methods. Some of the argument names are probably just incorrect, while others should be positional-only. For example, many methods implemented in C should have positional-only arguments to facilitate precise checking of argument names. I'm not sure how useful strict checking of argument names would be if we don't improve typeshed first.

    FWIW I would wager that nearly all typeshed's parameter names are correct now, because we've improved stubtest a lot since 2019 and we've also ratcheted up the strictness of our stubtest settings in typeshed.

  6. hauntsaninja commented on Aug 14, 2026

    @hauntsaninja
    Collaborator

    stubtest didn't really exist in 2019, so we've definitely improved it since then!

    However, the PR to enable this check is truly awful on primer #18355 so when we do this it will need to be opt-in

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions