Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

super(cls, self) seemingly has no attribute it actually has #13497

Closed
pjoziak opened this issue Aug 24, 2022 · 5 comments
Closed

super(cls, self) seemingly has no attribute it actually has #13497

pjoziak opened this issue Aug 24, 2022 · 5 comments

Comments

@pjoziak
Copy link

pjoziak commented Aug 24, 2022

Bug Report

I wanted to have a quick way of concatenating results of several mixin-like implementations of similar algorithms. Below is a MWE of what I wanted to implement

To Reproduce

MWE:

from abc import abstractmethod
from typing import List

class A:
    @abstractmethod
    def foo(self, arg: str) -> str:
        raise NotImplementedError
    
    def bar(self, arg: str) -> List[str]:
        ret: List[str] = []
        for c in self.__class__.mro():
            c_super = super(c, self)
            if hasattr(c_super, 'foo'):
                try:
                    ret.append(c_super.foo(arg))
                except NotImplementedError:
                    pass
        try:
            ret.append(self.foo(arg))
        except NotImplementedError:
            pass
        return ret

class B(A):
    def foo(self, arg: str) -> str:
        return f'B.foo[{arg}]'

    
class C(B):
    def foo(self, arg: str) -> str:
        return f'C.foo[{arg}]'

hello = 'hello'

c = C()
print(f'foo: {c.foo(hello)}')
print(f'bar: {c.bar(hello)}')

Expected Behavior

No warning

Actual Behavior

mypy recognizes

mwe.py:15: error: "super" has no attribute "foo"

even though it is executed after if hasattr(...)

What's even more strange, if you construct a similar pattern but with the method foo with no arguments, then the same example just passes mypy checks.

Your Environment

  • Mypy version used: 0.812, 0.900, 0.971
  • Python version used: 3.8
  • Operating system and version: Ubuntu 22.04
@pjoziak pjoziak added the bug mypy got something wrong label Aug 24, 2022
@AlexWaygood AlexWaygood added feature and removed bug mypy got something wrong labels Aug 24, 2022
@AlexWaygood
Copy link
Member

AlexWaygood commented Aug 24, 2022

Mypy has to implement quite a lot of special-casing in order to support super() at all. I think it's pretty unlikely that mypy is going to add the necessary complexity in order to support highly dynamic (and quite unusual) uses of super() like this, unfortunately.

@n1ngu
Copy link

n1ngu commented Sep 23, 2022

This

class A():
    def foo(self) -> None:
        pass

class A1000(A):
    def foo(self) -> None:
        parent = super()
        for _ in range(1000):
            parent.foo()

already fails.

@erictraut
Copy link

This appears to have been fixed in mypy 0.990. It does not repro since that release.

@AlexWaygood
Copy link
Member

Wow, I never expected to see this one fixed

@hauntsaninja
Copy link
Collaborator

hauntsaninja commented Aug 13, 2023

Fixed by #13544. mypy will now get out of your way because of the hasattr

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

No branches or pull requests

5 participants