From 48b929335688d207057d3057e3dc60cd4f3c036c Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Thu, 24 Oct 2024 18:35:30 +0200 Subject: [PATCH 1/9] slice.__new__ pin start/step to None if not given --- stdlib/builtins.pyi | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index ce0ea609e8f0..c57220d7a2e8 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -9,7 +9,6 @@ from _typeshed import ( ConvertibleToFloat, ConvertibleToInt, FileDescriptorOrPath, - MaybeNone, OpenBinaryMode, OpenBinaryModeReading, OpenBinaryModeUpdating, @@ -948,15 +947,9 @@ class slice(Generic[_StartT, _StopT, _StepT]): @property def stop(self) -> _StopT: ... @overload - def __new__(cls, stop: int | None) -> slice[int | MaybeNone, int | MaybeNone, int | MaybeNone]: ... + def __new__(cls, stop: _T2, /) -> slice[None, _T2, None]: ... @overload - def __new__( - cls, start: int | None, stop: int | None, step: int | None = None - ) -> slice[int | MaybeNone, int | MaybeNone, int | MaybeNone]: ... - @overload - def __new__(cls, stop: _T2, /) -> slice[Any, _T2, Any]: ... - @overload - def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2, Any]: ... + def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2, None]: ... @overload def __new__(cls, start: _T1, stop: _T2, step: _T3, /) -> slice[_T1, _T2, _T3]: ... def __eq__(self, value: object, /) -> bool: ... From b491e4d108bcb2554a4173bf151c6b5f06cebc6d Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Thu, 24 Oct 2024 18:49:17 +0200 Subject: [PATCH 2/9] generic slice initialization --- stdlib/builtins.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index c57220d7a2e8..95713b0e704a 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -946,6 +946,8 @@ class slice(Generic[_StartT, _StopT, _StepT]): def step(self) -> _StepT: ... @property def stop(self) -> _StopT: ... + @overload # fallback, since often slice(None) is used for generic slices + def __new__(cls, stop: None, /) -> slice[Any, Any, Any]: ... @overload def __new__(cls, stop: _T2, /) -> slice[None, _T2, None]: ... @overload From 3010eda2245bc8f8ce21660035fb533423e7a475 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Thu, 24 Oct 2024 19:17:20 +0200 Subject: [PATCH 3/9] None-overloads --- stdlib/builtins.pyi | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 95713b0e704a..e65295e00a88 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -94,9 +94,9 @@ _SupportsAnextT = TypeVar("_SupportsAnextT", bound=SupportsAnext[Any], covariant _AwaitableT = TypeVar("_AwaitableT", bound=Awaitable[Any]) _AwaitableT_co = TypeVar("_AwaitableT_co", bound=Awaitable[Any], covariant=True) _P = ParamSpec("_P") -_StartT = TypeVar("_StartT", covariant=True, default=Any) -_StopT = TypeVar("_StopT", covariant=True, default=Any) -_StepT = TypeVar("_StepT", covariant=True, default=Any) +_StartT_co = TypeVar("_StartT_co", covariant=True, default=Any) +_StopT_co = TypeVar("_StopT_co", covariant=True, default=_StartT_co) # slice[A] -> slice[A, A, Any] +_StepT_co = TypeVar("_StepT_co", covariant=True, default=Any) # slice[A,B] -> slice[A, B, Any] class object: __doc__: str | None @@ -939,19 +939,27 @@ class bool(int): def __invert__(self) -> int: ... @final -class slice(Generic[_StartT, _StopT, _StepT]): +class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): @property - def start(self) -> _StartT: ... + def start(self) -> _StartT_co | None: ... @property - def step(self) -> _StepT: ... + def step(self) -> _StepT_co | None: ... @property - def stop(self) -> _StopT: ... - @overload # fallback, since often slice(None) is used for generic slices + def stop(self) -> _StopT_co | None: ... + @overload def __new__(cls, stop: None, /) -> slice[Any, Any, Any]: ... @overload - def __new__(cls, stop: _T2, /) -> slice[None, _T2, None]: ... + def __new__(cls, stop: _T2, /) -> slice[_T2]: ... + @overload + def __new__(cls, start: None, stop: _T2, /) -> slice[_T2]: ... + @overload + def __new__(cls, start: _T1, stop: None, /) -> slice[_T1]: ... + @overload + def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2]: ... + @overload + def __new__(cls, start: None, stop: _T2, step: _T3, /) -> slice[_T2, _T2, _T3]: ... @overload - def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2, None]: ... + def __new__(cls, start: _T1, stop: None, step: _T3, /) -> slice[_T1, _T1, _T3]: ... @overload def __new__(cls, start: _T1, stop: _T2, step: _T3, /) -> slice[_T1, _T2, _T3]: ... def __eq__(self, value: object, /) -> bool: ... From b4bcf86f901d007a959c8eef95f0e2024b9b4cdb Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Thu, 24 Oct 2024 20:10:32 +0200 Subject: [PATCH 4/9] explicit overloads --- CONTRIBUTING.md | 23 +++++++++++++++++++++ stdlib/builtins.pyi | 49 +++++++++++++++++++++++++++++---------------- 2 files changed, 55 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 05d3fd5735eb..98a1859da000 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -724,3 +724,26 @@ message when closing the PR. Example message: after three months of inactivity. If you are still interested, please feel free to open a new PR (or ping us to reopen this one). + + +- Type hint `slice` should be compatible with the **"all-slices"**: + - `slice(None)`, `slice(None, None)` and `slice(None, None, None)`. +- Type hint `slice[X]` should be compatible with: + - `slice(None)`, `slice(None, None)` and `slice(None, None, None)` + - `slice(x)`, `slice(None, x)` and `slice(None, x, None)`. + - `slice(x, None)` and `slice(x, None, None)`. + - `slice(x, x)` and `slice(x, x, None)`. +- Type hint `slice[X, Y]` should be compatible with: + - `slice(None)`, `slice(None, None)` and `slice(None, None, None)` + - `slice(y)`, `slice(None, y)` and `slice(None, y, None)`. + - `slice(x, None)` and `slice(x, None, None)` + - `slice(x, y)` and `slice(x, y, None)`. +- Type hint `slice[X, Y, Z]` should be compatible with: + - `slice(None)`, `slice(None, None)` and `slice(None, None, None)`. + - `slice(y)`, `slice(None, y)` and `slice(None, y, None)`. + - `slice(x, None)` and `slice(x, None, None)` + - `slice(x, y)` and `slice(x, y, None)`. + - `slice(None, None, z)` + - `slice(None, y, z)` + - `slice(x, None, z)` + - `slice(x, y, z)` diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index e65295e00a88..fa55519af066 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -941,26 +941,41 @@ class bool(int): @final class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): @property - def start(self) -> _StartT_co | None: ... + def start(self) -> _StartT_co: ... @property - def step(self) -> _StepT_co | None: ... + def step(self) -> _StepT_co: ... @property - def stop(self) -> _StopT_co | None: ... - @overload - def __new__(cls, stop: None, /) -> slice[Any, Any, Any]: ... - @overload - def __new__(cls, stop: _T2, /) -> slice[_T2]: ... - @overload - def __new__(cls, start: None, stop: _T2, /) -> slice[_T2]: ... - @overload - def __new__(cls, start: _T1, stop: None, /) -> slice[_T1]: ... - @overload + def stop(self) -> _StopT_co: ... + # unary overloads ------------------------------------------------------------------ + @overload # 1x None + def __new__(cls, stop: None, /) -> slice: ... + @overload # 0x None + def __new__(cls, stop: _T2, /) -> slice[_T2 | None]: ... + # binary overloads ----------------------------------------------------------------- + @overload # 2x None + def __new__(cls, start: None, stop: None, /) -> slice: ... + @overload # 1x None + def __new__(cls, start: _T1, stop: None, /) -> slice[_T1 | None]: ... + @overload # 1x None + def __new__(cls, start: None, stop: _T2, /) -> slice[_T2 | None]: ... + @overload # 0x None def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2]: ... - @overload - def __new__(cls, start: None, stop: _T2, step: _T3, /) -> slice[_T2, _T2, _T3]: ... - @overload - def __new__(cls, start: _T1, stop: None, step: _T3, /) -> slice[_T1, _T1, _T3]: ... - @overload + # tenary overloads ----------------------------------------------------------------- + @overload # 3x None + def __new__(cls, start: None, stop: None, step: None, /) -> slice: ... + @overload # 2x None + def __new__(cls, start: None, stop: None, step: _T3, /) -> slice[Any, Any, _T3]: ... + @overload # 2x None + def __new__(cls, start: _T1, stop: None, step: None, /) -> slice[_T1 | None, _T1 | None]: ... + @overload # 2x None + def __new__(cls, start: None, stop: _T2, step: None, /) -> slice[_T2 | None, _T2 | None]: ... + @overload # 1x None + def __new__(cls, start: _T1, stop: None, step: _T3, /) -> slice[_T1 | None, _T1 | None, _T3]: ... + @overload # 1x None + def __new__(cls, start: None, stop: _T2, step: _T3, /) -> slice[_T2 | None, _T2 | None, _T3]: ... + @overload # 1x None + def __new__(cls, start: _T1, stop: _T2, step: None, /) -> slice[_T1, _T2]: ... + @overload # 0x None def __new__(cls, start: _T1, stop: _T2, step: _T3, /) -> slice[_T1, _T2, _T3]: ... def __eq__(self, value: object, /) -> bool: ... if sys.version_info >= (3, 12): From e838b8f29dc662ecc1140e5e1b4be673cc63787c Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Fri, 25 Oct 2024 12:08:44 +0200 Subject: [PATCH 5/9] removed accidental copy pasta --- CONTRIBUTING.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 98a1859da000..05d3fd5735eb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -724,26 +724,3 @@ message when closing the PR. Example message: after three months of inactivity. If you are still interested, please feel free to open a new PR (or ping us to reopen this one). - - -- Type hint `slice` should be compatible with the **"all-slices"**: - - `slice(None)`, `slice(None, None)` and `slice(None, None, None)`. -- Type hint `slice[X]` should be compatible with: - - `slice(None)`, `slice(None, None)` and `slice(None, None, None)` - - `slice(x)`, `slice(None, x)` and `slice(None, x, None)`. - - `slice(x, None)` and `slice(x, None, None)`. - - `slice(x, x)` and `slice(x, x, None)`. -- Type hint `slice[X, Y]` should be compatible with: - - `slice(None)`, `slice(None, None)` and `slice(None, None, None)` - - `slice(y)`, `slice(None, y)` and `slice(None, y, None)`. - - `slice(x, None)` and `slice(x, None, None)` - - `slice(x, y)` and `slice(x, y, None)`. -- Type hint `slice[X, Y, Z]` should be compatible with: - - `slice(None)`, `slice(None, None)` and `slice(None, None, None)`. - - `slice(y)`, `slice(None, y)` and `slice(None, y, None)`. - - `slice(x, None)` and `slice(x, None, None)` - - `slice(x, y)` and `slice(x, y, None)`. - - `slice(None, None, z)` - - `slice(None, y, z)` - - `slice(x, None, z)` - - `slice(x, y, z)` From 0104927b7f53e0a8942940f307b0cf5dd52c54f8 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Fri, 25 Oct 2024 12:20:41 +0200 Subject: [PATCH 6/9] simplify overloads --- stdlib/builtins.pyi | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index fa55519af066..ba353f9676c3 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -953,28 +953,20 @@ class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): def __new__(cls, stop: _T2, /) -> slice[_T2 | None]: ... # binary overloads ----------------------------------------------------------------- @overload # 2x None - def __new__(cls, start: None, stop: None, /) -> slice: ... + def __new__(cls, start: None, stop: None, step: None = ..., /) -> slice: ... @overload # 1x None - def __new__(cls, start: _T1, stop: None, /) -> slice[_T1 | None]: ... + def __new__(cls, start: _T1, stop: None, step: None = ..., /) -> slice[_T1 | None]: ... @overload # 1x None - def __new__(cls, start: None, stop: _T2, /) -> slice[_T2 | None]: ... + def __new__(cls, start: None, stop: _T2, step: None = ..., /) -> slice[_T2 | None]: ... @overload # 0x None - def __new__(cls, start: _T1, stop: _T2, /) -> slice[_T1, _T2]: ... + def __new__(cls, start: _T1, stop: _T2, step: None = ..., /) -> slice[_T1, _T2]: ... # tenary overloads ----------------------------------------------------------------- - @overload # 3x None - def __new__(cls, start: None, stop: None, step: None, /) -> slice: ... @overload # 2x None def __new__(cls, start: None, stop: None, step: _T3, /) -> slice[Any, Any, _T3]: ... - @overload # 2x None - def __new__(cls, start: _T1, stop: None, step: None, /) -> slice[_T1 | None, _T1 | None]: ... - @overload # 2x None - def __new__(cls, start: None, stop: _T2, step: None, /) -> slice[_T2 | None, _T2 | None]: ... @overload # 1x None def __new__(cls, start: _T1, stop: None, step: _T3, /) -> slice[_T1 | None, _T1 | None, _T3]: ... @overload # 1x None def __new__(cls, start: None, stop: _T2, step: _T3, /) -> slice[_T2 | None, _T2 | None, _T3]: ... - @overload # 1x None - def __new__(cls, start: _T1, stop: _T2, step: None, /) -> slice[_T1, _T2]: ... @overload # 0x None def __new__(cls, start: _T1, stop: _T2, step: _T3, /) -> slice[_T1, _T2, _T3]: ... def __eq__(self, value: object, /) -> bool: ... From 72e94b7b3a18ac2aa2656e15ef4596cb29aa6d29 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Fri, 25 Oct 2024 12:28:09 +0200 Subject: [PATCH 7/9] more simplification --- stdlib/builtins.pyi | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index ba353f9676c3..383716c7e685 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -946,21 +946,20 @@ class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): def step(self) -> _StepT_co: ... @property def stop(self) -> _StopT_co: ... + # generic slice -------------------------------------------------------------------- + @overload # 2x None + def __new__(cls, start: None, stop: None = ..., step: None = ..., /) -> slice: ... # unary overloads ------------------------------------------------------------------ - @overload # 1x None - def __new__(cls, stop: None, /) -> slice: ... @overload # 0x None def __new__(cls, stop: _T2, /) -> slice[_T2 | None]: ... # binary overloads ----------------------------------------------------------------- - @overload # 2x None - def __new__(cls, start: None, stop: None, step: None = ..., /) -> slice: ... @overload # 1x None def __new__(cls, start: _T1, stop: None, step: None = ..., /) -> slice[_T1 | None]: ... @overload # 1x None def __new__(cls, start: None, stop: _T2, step: None = ..., /) -> slice[_T2 | None]: ... @overload # 0x None def __new__(cls, start: _T1, stop: _T2, step: None = ..., /) -> slice[_T1, _T2]: ... - # tenary overloads ----------------------------------------------------------------- + # ternary overloads ---------------------------------------------------------------- @overload # 2x None def __new__(cls, start: None, stop: None, step: _T3, /) -> slice[Any, Any, _T3]: ... @overload # 1x None From c73c28cf75c9de9750e0b5e885e337c9c863967a Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Fri, 25 Oct 2024 12:40:35 +0200 Subject: [PATCH 8/9] Update stdlib/builtins.pyi Co-authored-by: Alex Waygood --- stdlib/builtins.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index 383716c7e685..f357eb8f55f1 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -951,7 +951,7 @@ class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): def __new__(cls, start: None, stop: None = ..., step: None = ..., /) -> slice: ... # unary overloads ------------------------------------------------------------------ @overload # 0x None - def __new__(cls, stop: _T2, /) -> slice[_T2 | None]: ... + def __new__(cls, stop: _T2, /) -> slice[_T2 | None, _T2 | None]: ... # binary overloads ----------------------------------------------------------------- @overload # 1x None def __new__(cls, start: _T1, stop: None, step: None = ..., /) -> slice[_T1 | None]: ... From 2be2aa02de73766165564fd24bb70fa8b7e8c9a2 Mon Sep 17 00:00:00 2001 From: Randolf Scholz Date: Fri, 25 Oct 2024 12:42:35 +0200 Subject: [PATCH 9/9] always specify all generic parameters --- stdlib/builtins.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/stdlib/builtins.pyi b/stdlib/builtins.pyi index f357eb8f55f1..81475d7e5302 100644 --- a/stdlib/builtins.pyi +++ b/stdlib/builtins.pyi @@ -948,17 +948,17 @@ class slice(Generic[_StartT_co, _StopT_co, _StepT_co]): def stop(self) -> _StopT_co: ... # generic slice -------------------------------------------------------------------- @overload # 2x None - def __new__(cls, start: None, stop: None = ..., step: None = ..., /) -> slice: ... + def __new__(cls, start: None, stop: None = None, step: None = None, /) -> slice[Any, Any, Any]: ... # unary overloads ------------------------------------------------------------------ @overload # 0x None - def __new__(cls, stop: _T2, /) -> slice[_T2 | None, _T2 | None]: ... + def __new__(cls, stop: _T2, /) -> slice[_T2 | None, _T2 | None, Any]: ... # binary overloads ----------------------------------------------------------------- @overload # 1x None - def __new__(cls, start: _T1, stop: None, step: None = ..., /) -> slice[_T1 | None]: ... + def __new__(cls, start: _T1, stop: None, step: None = None, /) -> slice[_T1 | None, _T1 | None, Any]: ... @overload # 1x None - def __new__(cls, start: None, stop: _T2, step: None = ..., /) -> slice[_T2 | None]: ... + def __new__(cls, start: None, stop: _T2, step: None = None, /) -> slice[_T2 | None, _T2 | None, Any]: ... @overload # 0x None - def __new__(cls, start: _T1, stop: _T2, step: None = ..., /) -> slice[_T1, _T2]: ... + def __new__(cls, start: _T1, stop: _T2, step: None = None, /) -> slice[_T1, _T2, Any]: ... # ternary overloads ---------------------------------------------------------------- @overload # 2x None def __new__(cls, start: None, stop: None, step: _T3, /) -> slice[Any, Any, _T3]: ...