Please consider a decorator in typing to mark base class methods whose overrides must call super
Not calling super on __init__ is a common source of bugs. So much so, that some base classes explicitly check for it (e.g., https://github.com/deepmind/dm-haiku/blob/main/haiku/_src/module.py#L142). Besides the specific problem with __init__, this is a general pattern that some methods overrides must call super. I was wondering if we could get a a decorator in typing to mark base class methods whose overrides must call super. This suggestion is motivated by an issue I saw on pyright: https://github.com/microsoft/pyright/issues/2789 The basic idea would be something like this: from typing import augmentable class C: @aumentable def f(self, ...) -> None: ... class D(C): def f(self, ...) -> None: # Error: aumentable method override doesn't call super. print(10) By default, methods like __init__, __init_subclass__, __enter__, and __exit__ (any others?) should be "augmentable".
On 06.01.22 05:49, Neil Girdhar wrote:
Not calling super on __init__ is a common source of bugs. So much so, that some base classes explicitly check for it (e.g., https://github.com/deepmind/dm-haiku/blob/main/haiku/_src/module.py#L142).
Besides the specific problem with __init__, this is a general pattern that some methods overrides must call super. I was wondering if we could get a a decorator in typing to mark base class methods whose overrides must call super. This suggestion is motivated by an issue I saw on pyright: https://github.com/microsoft/pyright/issues/2789
A check that an __init__() method calls super() would be quite useful, but in my opinion out of scope for type checkers. This is better suited for general purpose linters such as flake8 or the libraries it depends on. I also don't think that a special decorator would be needed. __init__ methods should nearly always call super(), except when a class is deriving directly from object. - Sebastian
A check that an __init__() method calls super() would be quite useful, but in my opinion out of scope for type checkers. This is better suited for general purpose linters such as flake8 or the libraries it depends on.
Fair enough. I don't know what the dividing line is between linters and type checkers.
I also don't think that a special decorator would be needed.
The decorator is just about bringing this functionality to other methods that exhibit this pattern. A concrete example of a base class method that exhibits the pattern is ndarray.__array_finalize__, which is described here: https://github.com/numpy/numpy/blob/6d5bc233442c034d54e0c0b15fdd7ed27e36fcac.... It would be nice for some tool to check that all of its overrides call super. If there is going to be a decorator, doesn't it belong in typing? After all it's a declaration of intent just like the typing.final decorator.
__init__ methods should nearly always call super(), except when a class is deriving directly from object.
Even if a class C derives from object, it should still call super. The reason is that another class B can inherit from C and D, and then D's initializer won't be called. C has no way to know whether another class will inherit from it unless it's final. Best, Neil
A decorator seems unnecessary to me for this case. A type checker should be able to determine whether one or more base classes defines a custom `__init__` (or `__enter__`, etc.) method and optionally complain if that method is not invoked in some manner by a derived class. In my mind, there's a pretty clear line between a type checker and a linter. The former is about code correctness, and the latter is about code style. There can be gray areas between the two, but I've found this to be a good starting point for differentiation.
A decorator might be useful for the other case outlined, when non-constructor methods need to be call super() for correctness. This is probably much less common than the constructor case, but it still does happen and presumably causes bugs. It's not normally required to call super in an override, so we'd have to have some way of marking it for type checkers (or linters) to detect the problem.
participants (4)
-
Eric Traut
-
Neil Girdhar
-
Sebastian Rittau
-
Steven Troxler