Skip to content

Mypy incorrectly says signature is incompatible with supertype when using decorator #3260

Closed

Description

@fniessink

When checking the code below with mypy v0.501, mypy complains that

deco.py:10: error: Signature of "a" incompatible with supertype "A"

According to @ilevkivskyi this may be related to #1441.

import functools

class A:
  @functools.lru_cache()
  def a(self) -> str: 
    return 'a'

class B(A):
  @functools.lru_cache()
  def a(self) -> str:
    return super().a() + 'b'

Activity

  1. ilevkivskyi commented on Apr 26, 2017

    @ilevkivskyi
    Member

    I played with this a bit and it looks like this is specific to functools.lru_cache(), most probably since it is a class that defines a __call__ method with decorator-like signature. So this is different from #1441.

  2. JelleZijlstra commented on Jun 15, 2017

    @JelleZijlstra
    Member

    I just ran into this too with a method decorated with @contextlib.asynccontextmanager (https://docs.python.org/3.7/library/contextlib.html#contextlib.asynccontextmanager).

  3. jdferreira commented on Jul 7, 2018

    @jdferreira

    I also ran with this issue today, precisely with the @lry_cache decorator on a subclass's method overriding a base method. Are there any solutions or workarounds at this point?

  4. stlehmann commented on Jul 23, 2018

    @stlehmann

    I' ve als got this issue with a stub-file for PyQt5:

    class Qt:
        class Alignment: ...
    
    class QWidget: ...
    
    class QLayoutItem: ...
    
    class QObject: ...
    
    class QLayout(QObject, QLayoutItem):
        def addWidget(self, w: QWidget) -> None: ...
    
    class QGridLayout(QLayout):
        def addWidget(
            self, widget: QWidget, row: int, column: int, alignment: Qt.Alignment = ...
        ) -> None: ...
    

    Results in the following mypy error:

    test.pyi:14: error: Signature of "addWidget" incompatible with supertype "QLayout"
    
  5. gvanrossum commented on Jul 23, 2018

    @gvanrossum
    Member

    @stlehmann Mypy is right in your case, it fails Liskov. The subclass method requires more arguments than the superclass method, so it is not a proper subtype.

  6. JukkaL commented on Jul 23, 2018

    @JukkaL
    Collaborator

    @stlehmann You can silence the mypy error by adding a # type: ignore comment on line 14. It won't cause mypy to ignore the signature, but it will stop complaints about the Liskov violation.

  7. stlehmann commented on Jul 24, 2018

    @stlehmann

    @gvanrossum Thanks for the explanation. I googled Liskov and it makes perfectly sense. However in this case I can't change the API so I will use #type: ignore to silence the error message as proposed by @JukkaL

  8. gvanrossum commented on Jul 24, 2018

    @gvanrossum
    Member
  9. ilevkivskyi commented on Sep 26, 2018

    @ilevkivskyi
    Member

    I tried both examples (lru_cache() and asynccontextmanager) they both work correctly on master.

  10. ikelos commented on Feb 28, 2019

    @ikelos

    I'm not sure the lru_cache() issue is resolved as of 0.670? The example provided applied lru_cache() to both methods, but this error is still raised if lru_cache() is only used on one method. Is that expected? If not, I'm happy to open a new bug for it if that's the proper way to handle it.

    I found this when I had defined an abstractmethod (which therefore didn't need the lru_cache decorator).

    
    class A: 
      def a(self) -> str: 
        return 'a'
      
    class B(A): 
      @functools.lru_cache() 
      def a(self) -> str: 
        return super().a() + 'b'
    

    results in:

    mypy-test.py:9: error: Signature of "a" incompatible with supertype "A"
    
  11. ilevkivskyi commented on Feb 28, 2019

    @ilevkivskyi
    Member

    Yes, this is a bug, but we already have an issue for this, see #5836

  12. ikelos commented on Feb 28, 2019

    @ikelos

    Ok, cool. I'll follow along there, thanks! 5:)

  13. igor-petrik-invitae commented on Jan 20, 2023

    @igor-petrik-invitae

    I am still encountering this issue with the following use case on MyPy version 0.991:

    from functools import cache
    
    
    class Base:
        @classmethod
        @cache
        def value(cls) -> str:
            # Some expensive default implementation
            return "[computed default]"
    
    
    class Simple(Base):
        @classmethod
        def value(cls) -> str:
            return "Simple value that doesn't need caching"

    error: Signature of "value" incompatible with supertype "Base" [override]

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions