From ccffc53492b12ca17af25249c8128ff54cbf82bf Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 00:27:37 -0700 Subject: [PATCH 1/6] decimal.Decimal is registered to numbers.Number --- stdlib/decimal.pyi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/stdlib/decimal.pyi b/stdlib/decimal.pyi index 3da75ec192ac..be158aa07f7f 100644 --- a/stdlib/decimal.pyi +++ b/stdlib/decimal.pyi @@ -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 @@ -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: ... From 517ef27fbc4f44bfe16af6530830a4908f75fc2c Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 01:51:04 -0700 Subject: [PATCH 2/6] just for the sake of it --- stdlib/builtins.pyi | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 40847ca1a4a5..03ba5bf0291d 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -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 @@ -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: ... @@ -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: ... @@ -392,7 +393,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__( From 9650ec31b37fec691b022ebecb5a54659efe5db5 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 11:31:26 -0700 Subject: [PATCH 3/6] lie about method existence --- stdlib/builtins.pyi | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 03ba5bf0291d..d4e4d9941467 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -371,10 +371,8 @@ class float(numbers.Real): 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 @@ -425,8 +423,7 @@ class complex(numbers.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: ... From b5eef9df19b33413318036863b73220f9f3d71ef Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 13:10:54 -0700 Subject: [PATCH 4/6] what happens if Self is used? --- stdlib/numbers.pyi | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/stdlib/numbers.pyi b/stdlib/numbers.pyi index e129de2cdc67..45f18dfe36b0 100644 --- a/stdlib/numbers.pyi +++ b/stdlib/numbers.pyi @@ -9,7 +9,7 @@ from _typeshed import Incomplete from abc import ABCMeta, abstractmethod -from typing import Literal, Protocol, overload +from typing import Literal, Protocol, Self, overload __all__ = ["Number", "Complex", "Real", "Rational", "Integral"] @@ -24,8 +24,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 @@ -37,8 +37,8 @@ class _RealLike(_ComplexLike, Protocol): def __float__(self) -> float: ... # Overridden from `_ComplexLike` # for a more precise return type: - def __neg__(self) -> _RealLike: ... - def __pos__(self) -> _RealLike: ... + # def __neg__(self) -> Self: ... + # def __pos__(self) -> Self: ... # _IntegralLike is a structural-typing approximation # of the `Integral` ABC, which is not (and cannot be) a protocol @@ -51,8 +51,8 @@ class _IntegralLike(_RealLike, Protocol): def __abs__(self) -> _IntegralLike: ... # Overridden from `RealLike` # for a more precise return type: - def __neg__(self) -> _IntegralLike: ... - def __pos__(self) -> _IntegralLike: ... + # def __neg__(self) -> _IntegralLike: ... + # def __pos__(self) -> _IntegralLike: ... ################# # Module "proper" @@ -79,9 +79,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 @@ -142,10 +142,10 @@ class Real(Complex, _RealLike): 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: ... + # @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 @@ -196,9 +196,9 @@ 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: ... + def __pos__(self) -> Self: ... @abstractmethod - def __neg__(self) -> _IntegralLike: ... + def __neg__(self) -> Self: ... @abstractmethod def __abs__(self) -> _IntegralLike: ... @abstractmethod From 0146877b0aa4618196124a04e1cfadba43f97375 Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 13:33:47 -0700 Subject: [PATCH 5/6] clean it up a little --- stdlib/@tests/stubtest_allowlists/py310.txt | 3 +++ stdlib/@tests/stubtest_allowlists/py38.txt | 5 +++++ stdlib/@tests/stubtest_allowlists/py39.txt | 3 +++ stdlib/numbers.pyi | 21 ++------------------- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py310.txt b/stdlib/@tests/stubtest_allowlists/py310.txt index 8d0631cdd291..43498f63c9be 100644 --- a/stdlib/@tests/stubtest_allowlists/py310.txt +++ b/stdlib/@tests/stubtest_allowlists/py310.txt @@ -259,3 +259,6 @@ tkinter.EventType.__new__ ctypes._endian.DEFAULT_MODE ctypes._endian.RTLD_GLOBAL ctypes._endian.RTLD_LOCAL + +# This don't exist at runtime +builtins.complex.__complex__ diff --git a/stdlib/@tests/stubtest_allowlists/py38.txt b/stdlib/@tests/stubtest_allowlists/py38.txt index 8a8cebab1364..2f80a247f1f4 100644 --- a/stdlib/@tests/stubtest_allowlists/py38.txt +++ b/stdlib/@tests/stubtest_allowlists/py38.txt @@ -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__ diff --git a/stdlib/@tests/stubtest_allowlists/py39.txt b/stdlib/@tests/stubtest_allowlists/py39.txt index 9c646178b383..8ccf14c436e2 100644 --- a/stdlib/@tests/stubtest_allowlists/py39.txt +++ b/stdlib/@tests/stubtest_allowlists/py39.txt @@ -237,3 +237,6 @@ _ssl.RAND_egd ctypes._endian.DEFAULT_MODE ctypes._endian.RTLD_GLOBAL ctypes._endian.RTLD_LOCAL + +# This don't exist at runtime +builtins.complex.__complex__ diff --git a/stdlib/numbers.pyi b/stdlib/numbers.pyi index 45f18dfe36b0..86340df5e3b0 100644 --- a/stdlib/numbers.pyi +++ b/stdlib/numbers.pyi @@ -9,7 +9,8 @@ from _typeshed import Incomplete from abc import ABCMeta, abstractmethod -from typing import Literal, Protocol, Self, overload +from typing import Literal, Protocol, overload +from typing_extensions import Self __all__ = ["Number", "Complex", "Real", "Rational", "Integral"] @@ -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) -> Self: ... - # def __pos__(self) -> Self: ... # _IntegralLike is a structural-typing approximation # of the `Integral` ABC, which is not (and cannot be) a protocol @@ -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" @@ -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 @@ -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) -> Self: ... - @abstractmethod - def __neg__(self) -> Self: ... - @abstractmethod def __abs__(self) -> _IntegralLike: ... @abstractmethod @overload From 52c268c2535b1a53add12d9aa334efc8505c087d Mon Sep 17 00:00:00 2001 From: Stephen Morton Date: Thu, 24 Oct 2024 13:35:00 -0700 Subject: [PATCH 6/6] typo --- stdlib/@tests/stubtest_allowlists/py310.txt | 2 +- stdlib/@tests/stubtest_allowlists/py39.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/@tests/stubtest_allowlists/py310.txt b/stdlib/@tests/stubtest_allowlists/py310.txt index 43498f63c9be..0fd777dcc7a4 100644 --- a/stdlib/@tests/stubtest_allowlists/py310.txt +++ b/stdlib/@tests/stubtest_allowlists/py310.txt @@ -260,5 +260,5 @@ ctypes._endian.DEFAULT_MODE ctypes._endian.RTLD_GLOBAL ctypes._endian.RTLD_LOCAL -# This don't exist at runtime +# This doesn't exist at runtime builtins.complex.__complex__ diff --git a/stdlib/@tests/stubtest_allowlists/py39.txt b/stdlib/@tests/stubtest_allowlists/py39.txt index 8ccf14c436e2..1420d8b6b142 100644 --- a/stdlib/@tests/stubtest_allowlists/py39.txt +++ b/stdlib/@tests/stubtest_allowlists/py39.txt @@ -238,5 +238,5 @@ ctypes._endian.DEFAULT_MODE ctypes._endian.RTLD_GLOBAL ctypes._endian.RTLD_LOCAL -# This don't exist at runtime +# This doesn't exist at runtime builtins.complex.__complex__