basedpyright icon indicating copy to clipboard operation
basedpyright copied to clipboard

option to ban abstract methods and protocols with implementations

Open DetachHead opened this issue 1 year ago • 8 comments

class Foo(ABC):
    @abstractmethod
    def foo(self):
        print(1)

apparently this is intentionally allowed but i think it's stupid so there should be an option to ban it

DetachHead avatar Aug 30 '24 01:08 DetachHead

Note Unlike Java abstract methods, these abstract methods may have an implementation. This implementation can be called via the super() mechanism from the class that overrides it. This could be useful as an end-point for a super-call in a framework that uses cooperative multiple-inheritance.

  • https://docs.python.org/3/library/abc.html#abc.abstractmethod

KotlinIsland avatar Aug 30 '24 09:08 KotlinIsland

That's got to be a peak level of Python idiocy. I fully support this. Ban it 🔨

mahyarmirrashed avatar Sep 12 '24 04:09 mahyarmirrashed

alternativly, could we require that it explicitly raises an exception:

from abc import ABC, abstractmethod
from typing import override

class A(ABC):
    @abstractmethod
    def foo(self) -> int: ...
    
class D:
    def foo(self) -> int:
        return 1

class C(D):
    @override
    def foo(self) -> int:
        return super().foo()
# mro = B, C, A, D
class B(C, A, D): pass

_ = B().foo() + 1  # no error, None at runtime

playground

maybe no implementation, or exception, your choice.

KotlinIsland avatar Sep 12 '24 04:09 KotlinIsland

I vote for no implementation. It's the most idiomatic choice IMO. Abstract methods are supposed to be abstract lol. I don't know if there are any other programming languages that allow this (they shouldn't).

mahyarmirrashed avatar Sep 12 '24 19:09 mahyarmirrashed

other programming languages tend to throw an error if you somehow end up calling an abstract method, python just returns None

KotlinIsland avatar Sep 13 '24 00:09 KotlinIsland

there should be an error on both the definition of an abstract method with an implementation, and any super() calls to it:

from abc import ABC, abstractmethod
from typing import override


class Foo(ABC):
    @abstractmethod
    def foo(self):
        print(1) # error


class Bar(Foo):
    @override
    def foo(self):
        return super().foo() # error

DetachHead avatar Jan 21 '25 06:01 DetachHead

when we do this, we also need to update the check introduced in #352 to account for this new rule

DetachHead avatar Jan 21 '25 06:01 DetachHead

same with protocols

DetachHead avatar Apr 07 '25 01:04 DetachHead