Skip to content

Experimenting with inheritance from numbers ABCs #12894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions stdlib/@tests/stubtest_allowlists/py310.txt
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,6 @@ tkinter.EventType.__new__
ctypes._endian.DEFAULT_MODE
ctypes._endian.RTLD_GLOBAL
ctypes._endian.RTLD_LOCAL

# This doesn't exist at runtime
builtins.complex.__complex__
5 changes: 5 additions & 0 deletions stdlib/@tests/stubtest_allowlists/py38.txt
Original file line number Diff line number Diff line change
Expand Up @@ -262,3 +262,8 @@ email._header_value_parser.SPECIALSNL
email.errors.HeaderWriteError
email.utils.getaddresses
email.utils.parseaddr

# These don't exist at runtime
builtins.complex.__complex__
builtins.float.__ceil__
builtins.float.__floor__
3 changes: 3 additions & 0 deletions stdlib/@tests/stubtest_allowlists/py39.txt
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,6 @@ _ssl.RAND_egd
ctypes._endian.DEFAULT_MODE
ctypes._endian.RTLD_GLOBAL
ctypes._endian.RTLD_LOCAL

# This doesn't exist at runtime
builtins.complex.__complex__
16 changes: 7 additions & 9 deletions stdlib/builtins.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# ruff: noqa: PYI036 # This is the module declaring BaseException
import _ast
import _typeshed
import numbers
import sys
import types
from _collections_abc import dict_items, dict_keys, dict_values
Expand Down Expand Up @@ -329,7 +330,7 @@ class int:
def __bool__(self) -> bool: ...
def __index__(self) -> int: ...

class float:
class float(numbers.Real):
def __new__(cls, x: ConvertibleToFloat = ..., /) -> Self: ...
def as_integer_ratio(self) -> tuple[int, int]: ...
def hex(self) -> str: ...
Expand All @@ -339,7 +340,7 @@ class float:
@property
def real(self) -> float: ...
@property
def imag(self) -> float: ...
def imag(self) -> float: ... # type: ignore[override]
def conjugate(self) -> float: ...
def __add__(self, value: float, /) -> float: ...
def __sub__(self, value: float, /) -> float: ...
Expand Down Expand Up @@ -370,10 +371,8 @@ class float:
def __rpow__(self, value: float, mod: None = None, /) -> Any: ...
def __getnewargs__(self) -> tuple[float]: ...
def __trunc__(self) -> int: ...
if sys.version_info >= (3, 9):
def __ceil__(self) -> int: ...
def __floor__(self) -> int: ...

def __ceil__(self) -> int: ...
def __floor__(self) -> int: ...
@overload
def __round__(self, ndigits: None = None, /) -> int: ...
@overload
Expand All @@ -392,7 +391,7 @@ class float:
def __hash__(self) -> int: ...
def __bool__(self) -> bool: ...

class complex:
class complex(numbers.Complex):
# Python doesn't currently accept SupportsComplex for the second argument
@overload
def __new__(
Expand Down Expand Up @@ -424,8 +423,7 @@ class complex:
def __abs__(self) -> float: ...
def __hash__(self) -> int: ...
def __bool__(self) -> bool: ...
if sys.version_info >= (3, 11):
def __complex__(self) -> complex: ...
def __complex__(self) -> complex: ...

class _FormatMapMapping(Protocol):
def __getitem__(self, key: str, /) -> Any: ...
Expand Down
3 changes: 2 additions & 1 deletion stdlib/decimal.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ from _decimal import (
setcontext as setcontext,
)
from collections.abc import Container, Sequence
from numbers import Number
from typing import Any, ClassVar, Literal, NamedTuple, overload
from typing_extensions import Self, TypeAlias

Expand Down Expand Up @@ -55,7 +56,7 @@ class Overflow(Inexact, Rounded): ...
class Underflow(Inexact, Rounded, Subnormal): ...
class FloatOperation(DecimalException, TypeError): ...

class Decimal:
class Decimal(Number):
def __new__(cls, value: _DecimalNew = ..., context: Context | None = ...) -> Self: ...
@classmethod
def from_float(cls, f: float, /) -> Self: ...
Expand Down
27 changes: 5 additions & 22 deletions stdlib/numbers.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from _typeshed import Incomplete
from abc import ABCMeta, abstractmethod
from typing import Literal, Protocol, overload
from typing_extensions import Self

__all__ = ["Number", "Complex", "Real", "Rational", "Integral"]

Expand All @@ -24,8 +25,8 @@ __all__ = ["Number", "Complex", "Real", "Rational", "Integral"]
# as we want `int` to be seen as a subtype of `_ComplexLike`,
# and `int.__complex__` does not exist :(
class _ComplexLike(Protocol):
def __neg__(self) -> _ComplexLike: ...
def __pos__(self) -> _ComplexLike: ...
def __neg__(self) -> Self: ...
def __pos__(self) -> Self: ...
def __abs__(self) -> _RealLike: ...

# _RealLike is a structural-typing approximation
Expand All @@ -35,10 +36,6 @@ class _RealLike(_ComplexLike, Protocol):
def __floor__(self) -> _IntegralLike: ...
def __ceil__(self) -> _IntegralLike: ...
def __float__(self) -> float: ...
# Overridden from `_ComplexLike`
# for a more precise return type:
def __neg__(self) -> _RealLike: ...
def __pos__(self) -> _RealLike: ...

# _IntegralLike is a structural-typing approximation
# of the `Integral` ABC, which is not (and cannot be) a protocol
Expand All @@ -49,10 +46,6 @@ class _IntegralLike(_RealLike, Protocol):
# Overridden from `_ComplexLike`
# for a more precise return type:
def __abs__(self) -> _IntegralLike: ...
# Overridden from `RealLike`
# for a more precise return type:
def __neg__(self) -> _IntegralLike: ...
def __pos__(self) -> _IntegralLike: ...

#################
# Module "proper"
Expand All @@ -79,9 +72,9 @@ class Complex(Number, _ComplexLike):
@abstractmethod
def __radd__(self, other) -> _ComplexLike: ...
@abstractmethod
def __neg__(self) -> _ComplexLike: ...
def __neg__(self) -> Self: ...
@abstractmethod
def __pos__(self) -> _ComplexLike: ...
def __pos__(self) -> Self: ...
def __sub__(self, other) -> _ComplexLike: ...
def __rsub__(self, other) -> _ComplexLike: ...
@abstractmethod
Expand Down Expand Up @@ -140,12 +133,6 @@ class Real(Complex, _RealLike):
@property
def imag(self) -> Literal[0]: ...
def conjugate(self) -> _RealLike: ...
# Not actually overridden at runtime,
# but we override these in the stub to give them more precise return types:
@abstractmethod
def __pos__(self) -> _RealLike: ...
@abstractmethod
def __neg__(self) -> _RealLike: ...

# See comment at the top of the file
# for why some of these return types are purposefully vague
Expand Down Expand Up @@ -196,10 +183,6 @@ class Integral(Rational, _IntegralLike):
# Not actually overridden at runtime,
# but we override these in the stub to give them more precise return types:
@abstractmethod
def __pos__(self) -> _IntegralLike: ...
@abstractmethod
def __neg__(self) -> _IntegralLike: ...
@abstractmethod
def __abs__(self) -> _IntegralLike: ...
@abstractmethod
@overload
Expand Down