<div dir="ltr">Alternatively, the need for an overriding implementation to call super could be marked by a different decorator.  This would allow linters to check that subclasses call super when they should, which is a very useful check in my opinion.  Such a decorator could be called "@overrideable", and could be exposed in abc.   When used in combination with @abstractmethod, it could have the above behavior. <div><div><br>On Sunday, February 17, 2019 at 5:28:49 AM UTC-5, Neil Girdhar wrote:<blockquote class="gmail_quote" style="margin: 0;margin-left: 0.8ex;border-left: 1px #ccc solid;padding-left: 1ex;"><div dir="ltr">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.<div><br></div><div>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.</div><div><br></div><div>I think that this concept of *implementing* is different than *overriding*.</div><div><br></div><div>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.</div><div><br></div><div>This is extremely weird.  Understandably, the pylint people are confused by it (<a href="https://github.com/PyCQA/pylint/issues/1594" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FPyCQA%2Fpylint%2Fissues%2F1594\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEPXUA7R4tTnkQquOPcQltMpXsH_A';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FPyCQA%2Fpylint%2Fissues%2F1594\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEPXUA7R4tTnkQquOPcQltMpXsH_A';return true;">https://github.com/PyCQA/<wbr>pylint/issues/1594</a>) and raise bad warnings.</div><div><br>It also makes it impossible for me to raise warnings in my ipromise (<a href="https://github.com/NeilGirdhar/ipromise" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNeilGirdhar%2Fipromise\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEqHZw0T-56SekJXAC4OclWvY8Q_w';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNeilGirdhar%2Fipromise\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEqHZw0T-56SekJXAC4OclWvY8Q_w';return true;">https://github.com/<wbr>NeilGirdhar/ipromise</a>) project.  See, for example, <a href="https://github.com/NeilGirdhar/ipromise/blob/master/ipromise/test/test_overrides.py" target="_blank" rel="nofollow" onmousedown="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNeilGirdhar%2Fipromise%2Fblob%2Fmaster%2Fipromise%2Ftest%2Ftest_overrides.py\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFxjpF5sQFvJUqZwdO3M_PqpANppg';return true;" onclick="this.href='https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2FNeilGirdhar%2Fipromise%2Fblob%2Fmaster%2Fipromise%2Ftest%2Ftest_overrides.py\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFxjpF5sQFvJUqZwdO3M_PqpANppg';return true;">https://github.com/<wbr>NeilGirdhar/ipromise/blob/<wbr>master/ipromise/test/test_<wbr>overrides.py</a> classes Y and W, which ought to raise, but that would raise on reasonable code.</div><div><br></div><div>My suggestion is to add a rarely used flag to abstractmethod:</div><div><br></div><div>class AbstractContextManager:</div><div>    @abstractmethod(overrideable=<wbr>True)</div><div>    def __exit__(self, exc_type, exc_value, traceback):</div><div>        pass</div><div><br></div><div>This would set a flag on the method like __abstractmethod_overrideable_<wbr>_, 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.</div><div><br></div><div>Best,</div><div><br></div><div>Neil</div></div></blockquote></div></div></div>