You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Checking for abstractmethod implementation fails to consider MRO for builtins #79244
When checking whether a class implements all abstractmethods (to know whether the class can be instantiated), one should only consider methods that come *before* the abstractmethod in the MRO -- methods that come after cannot be said to override the abstractmethod. Indeed, this is currently the case:
Here FooImplFirst correctly overrides the foo method (using the HasFoo mixin first), so can be instantiated; FooImplSecond doesn't (by the MRO, FooImplSecond().foo would resolve to the abstract implementation), and we get a TypeError on instantiation.
However, this is not the case when considering builtins:
fromabcimportABC, abstractmethodclassNeedsKeys(ABC):
keys=abstractmethod(lambdaself: None)
HasKeys=dict# dict has a keys method.classKeysImplFirst(HasKeys, NeedsKeys): passclassKeysImplSecond(NeedsKeys, HasKeys): passKeysImplFirst()
try: KeysImplSecond()
exceptTypeError: passelse: raiseException("Expected error")
This example differs from the first only by having dict be the mixin that provides the keys method. However, running this example shows that KeysImplSecond() will incorrectly succeed: the ABC machinery does not realize that the keys method has not been overridden.
(Alternatively, one could say that "providing the method later in the MRO" is also sufficient; I think that goes against the expectations about ABCs but at least consistency between the non-builtin and builtin cases would be better.)
Activity
anntzer commentedon Oct 25, 2018
When checking whether a class implements all abstractmethods (to know whether the class can be instantiated), one should only consider methods that come *before* the abstractmethod in the MRO -- methods that come after cannot be said to override the abstractmethod. Indeed, this is currently the case:
Here FooImplFirst correctly overrides the foo method (using the HasFoo mixin first), so can be instantiated; FooImplSecond doesn't (by the MRO, FooImplSecond().foo would resolve to the abstract implementation), and we get a TypeError on instantiation.
However, this is not the case when considering builtins:
This example differs from the first only by having dict be the mixin that provides the keys method. However, running this example shows that KeysImplSecond() will incorrectly succeed: the ABC machinery does not realize that the keys method has not been overridden.
(Alternatively, one could say that "providing the method later in the MRO" is also sufficient; I think that goes against the expectations about ABCs but at least consistency between the non-builtin and builtin cases would be better.)
iritkatriel commentedon Dec 6, 2021
See also bpo-37927.