typeshed icon indicating copy to clipboard operation
typeshed copied to clipboard

`BaseException` lacks `__new__()`

Open finite-state-machine opened this issue 7 months ago • 0 comments

Summary

When overriding __new__() in a BaseException subclass, a call of form super().__new__(cls, arg0, [arg1, [arg2, ...]]]) causes type checkers to complain about unused positional argument(s), even though the positional args are both accepted and used by BaseException.__new__() — they become <BaseException>.args.

Root cause: type checkers believe super().__new__(...) in this context is a call to object.__new__(), rather than BaseException.__new__().

Proposed fix: typeshed should include a definition for BaseException.__new__() analogous to and compatible with to its existing signature for BaseException.__init__():

class BaseException:
    ...
    def __init__(self, *args: object) -> None: ...
    ...

Concrete example

Analyzing the following code....

from __future__ import annotations

class SomeException(Exception):

    def __new__(cls, alfa: str, bravo: str) -> SomeException:

        msg = f"{alfa} ({bravo})"
        return super().__new__(cls, msg)  # ᐊ── errors occur here

    def __init__(self, alfa: str, bravo: str):

        # (preserve these as attributes)
        pass

...with mypy causes this report:

bug.py|8| error: Too many arguments for "__new__" of "object"  [call-arg]
|| Found 1 error in 1 file (checked 1 source file)

...while pyright (without strict) says:

|| .../bug.py
bug.py|8| 37 - error: Expected 1 positional argument (reportCallIssue)
|| 1 error, 0 warnings, 0 informations 

finite-state-machine avatar Jun 28 '24 08:06 finite-state-machine