Marking a method M declared in C with abstractmethod indicates that M needs 
to be *implemented* in any subclass D of C for D to be instantiated.

We usually think of overriding a method N to mean replacing one 
implementation in some class E with another in some subclass of E, F.  
Often, the subclass implementation calls super to add behavior rather than 
replace it.

I think that this concept of *implementing* is different than *overriding*.

However, abstract classes can have reasonable definition, and should 
sometimes be overridden in the sense that subclasses should call super.  
For example, when inheriting from AbstractContextManager, you need to 
*override* the abstractmethod (!) __exit__, and if you want your class to 
work polymorphically, you should call super.

This is extremely weird.  Understandably, the pylint people are confused by 
it (https://github.com/PyCQA/pylint/issues/1594) and raise bad warnings.

It also makes it impossible for me to raise warnings in my ipromise 
(https://github.com/NeilGirdhar/ipromise) project.  See, for 
example, 
https://github.com/NeilGirdhar/ipromise/blob/master/ipromise/test/test_overrides.py
 
classes Y and W, which ought to raise, but that would raise on reasonable 
code.

My suggestion is to add a rarely used flag to abstractmethod:

class AbstractContextManager:
    @abstractmethod(overrideable=True)
    def __exit__(self, exc_type, exc_value, traceback):
        pass

This would set a flag on the method like __abstractmethod_overrideable__, 
which could be checked by ipromise's @overrides decorator, pylint's call 
check, and anyone else that wants to know that a method should be 
overridden.

Best,

Neil
_______________________________________________
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to