From e7e430af64ab924350af21cbd82a345f4bba5f61 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 05:02:40 +0100 Subject: [PATCH 01/19] Make Counter generic over the value Closes: #3438 --- stdlib/collections/__init__.pyi | 7 +++-- .../stdlib/collections/check_counter.py | 31 +++++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 test_cases/stdlib/collections/check_counter.py diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index 1d23ecd66a8d..ccd0023a9190 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -34,6 +34,7 @@ _KT = TypeVar("_KT") _VT = TypeVar("_VT") _KT_co = TypeVar("_KT_co", covariant=True) _VT_co = TypeVar("_VT_co", covariant=True) +_C = TypeVar("_C", default=int) # namedtuple is special-cased in the type checker; the initializer is ignored. def namedtuple( @@ -261,13 +262,13 @@ class deque(MutableSequence[_T]): if sys.version_info >= (3, 9): def __class_getitem__(cls, item: Any, /) -> GenericAlias: ... -class Counter(dict[_T, int], Generic[_T]): +class Counter(dict[_T, _C]): @overload def __init__(self, iterable: None = None, /) -> None: ... @overload - def __init__(self: Counter[str], iterable: None = None, /, **kwargs: int) -> None: ... + def __init__(self: Counter[str, _C], iterable: None = None, /, **kwargs: _C) -> None: ... @overload - def __init__(self, mapping: SupportsKeysAndGetItem[_T, int], /) -> None: ... + def __init__(self: Counter[_T, _C], mapping: SupportsKeysAndGetItem[_T, _C], /) -> None: ... @overload def __init__(self, iterable: Iterable[_T], /) -> None: ... def copy(self) -> Self: ... diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py new file mode 100644 index 000000000000..9b6f74b4736a --- /dev/null +++ b/test_cases/stdlib/collections/check_counter.py @@ -0,0 +1,31 @@ +from collections import Counter +from typing_extensions import assert_type, Never + + +class Foo: ... + + +# Test the constructor +assert_type(Counter(), Counter[Never, int]) +assert_type(Counter(foo=42.2), Counter[str, float]) +assert_type(Counter({42: "bar"}), Counter[int, str]) +assert_type(Counter([1, 2, 3]), Counter[int, int]) + +int_c: Counter[str] = Counter() +assert_type(int_c, Counter[str, int]) +int_c["a"] = 1 +int_c["a"] += 3 +int_c["a"] += 3.5 # type: ignore + +float_c = Counter(foo=42.2) +assert_type(float_c, Counter[str, float]) +float_c["a"] = 1.0 +float_c["a"] += 3.0 +float_c["a"] += 42 +float_c["a"] += "42" # type: ignore + +custom_c: Counter[str, Foo] = Counter() +assert_type(custom_c, Counter[str, Foo]) +custom_c["a"] = Foo() +custom_c["a"] += Foo() # type: ignore +custom_c["a"] += 42 # type: ignore From fc7af5567714b5d07be26c2cf45bd99db9259da8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 04:05:19 +0000 Subject: [PATCH 02/19] [pre-commit.ci] auto fixes from pre-commit.com hooks --- test_cases/stdlib/collections/check_counter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 9b6f74b4736a..921c6bea5420 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -1,5 +1,5 @@ from collections import Counter -from typing_extensions import assert_type, Never +from typing_extensions import Never, assert_type class Foo: ... From ab7f64c09412c85c14f527fc596cb1e98941ec9d Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 06:49:21 +0100 Subject: [PATCH 03/19] Replace some more ints, fix a test --- stdlib/collections/__init__.pyi | 22 +++++++++---------- .../stdlib/collections/check_counter.py | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index ccd0023a9190..a7c8b28caead 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -275,26 +275,26 @@ class Counter(dict[_T, _C]): def elements(self) -> Iterator[_T]: ... def most_common(self, n: int | None = None) -> list[tuple[_T, int]]: ... @classmethod - def fromkeys(cls, iterable: Any, v: int | None = None) -> NoReturn: ... # type: ignore[override] + def fromkeys(cls, iterable: Any, v: _C | None = None) -> NoReturn: ... # type: ignore[override] @overload def subtract(self, iterable: None = None, /) -> None: ... @overload - def subtract(self, mapping: Mapping[_T, int], /) -> None: ... + def subtract(self, mapping: Mapping[_T, _C], /) -> None: ... @overload def subtract(self, iterable: Iterable[_T], /) -> None: ... # Unlike dict.update(), use Mapping instead of SupportsKeysAndGetItem for the first overload # (source code does an `isinstance(other, Mapping)` check) # # The second overload is also deliberately different to dict.update() - # (if it were `Iterable[_T] | Iterable[tuple[_T, int]]`, + # (if it were `Iterable[_T] | Iterable[tuple[_T, _C]]`, # the tuples would be added as keys, breaking type safety) @overload # type: ignore[override] - def update(self, m: Mapping[_T, int], /, **kwargs: int) -> None: ... + def update(self, m: Mapping[_T, _C], /, **kwargs: _C) -> None: ... @overload - def update(self, iterable: Iterable[_T], /, **kwargs: int) -> None: ... + def update(self, iterable: Iterable[_T], /, **kwargs: _C) -> None: ... @overload - def update(self, iterable: None = None, /, **kwargs: int) -> None: ... - def __missing__(self, key: _T) -> int: ... + def update(self, iterable: None = None, /, **kwargs: _C) -> None: ... + def __missing__(self, key: _T) -> _C: ... def __delitem__(self, elem: object) -> None: ... if sys.version_info >= (3, 10): def __eq__(self, other: object) -> bool: ... @@ -307,10 +307,10 @@ class Counter(dict[_T, _C]): def __pos__(self) -> Counter[_T]: ... def __neg__(self) -> Counter[_T]: ... # several type: ignores because __iadd__ is supposedly incompatible with __add__, etc. - def __iadd__(self, other: SupportsItems[_T, int]) -> Self: ... # type: ignore[misc] - def __isub__(self, other: SupportsItems[_T, int]) -> Self: ... - def __iand__(self, other: SupportsItems[_T, int]) -> Self: ... - def __ior__(self, other: SupportsItems[_T, int]) -> Self: ... # type: ignore[override,misc] + def __iadd__(self, other: SupportsItems[_T, _C]) -> Self: ... # type: ignore[misc] + def __isub__(self, other: SupportsItems[_T, _C]) -> Self: ... + def __iand__(self, other: SupportsItems[_T, _C]) -> Self: ... + def __ior__(self, other: SupportsItems[_T, _C]) -> Self: ... # type: ignore[override,misc] if sys.version_info >= (3, 10): def total(self) -> int: ... def __le__(self, other: Counter[Any]) -> bool: ... diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 921c6bea5420..7c929db47abb 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -1,12 +1,12 @@ from collections import Counter -from typing_extensions import Never, assert_type +from typing_extensions import assert_type class Foo: ... # Test the constructor -assert_type(Counter(), Counter[Never, int]) +# assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" assert_type(Counter(foo=42.2), Counter[str, float]) assert_type(Counter({42: "bar"}), Counter[int, str]) assert_type(Counter([1, 2, 3]), Counter[int, int]) From 44ed688d5343e4f62b40536c3489589dd6493208 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 06:55:23 +0100 Subject: [PATCH 04/19] Add generic arguments --- stdlib/collections/__init__.pyi | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index a7c8b28caead..e8f8e24d22f7 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -300,12 +300,12 @@ class Counter(dict[_T, _C]): def __eq__(self, other: object) -> bool: ... def __ne__(self, other: object) -> bool: ... - def __add__(self, other: Counter[_S]) -> Counter[_T | _S]: ... - def __sub__(self, other: Counter[_T]) -> Counter[_T]: ... - def __and__(self, other: Counter[_T]) -> Counter[_T]: ... - def __or__(self, other: Counter[_S]) -> Counter[_T | _S]: ... # type: ignore[override] - def __pos__(self) -> Counter[_T]: ... - def __neg__(self) -> Counter[_T]: ... + def __add__(self, other: Counter[_S, _C]) -> Counter[_T | _S, _C]: ... + def __sub__(self, other: Counter[_T, _C]) -> Counter[_T, _C]: ... + def __and__(self, other: Counter[_T, _C]) -> Counter[_T, _C]: ... + def __or__(self, other: Counter[_S, _C]) -> Counter[_T | _S, _C]: ... # type: ignore[override] + def __pos__(self) -> Counter[_T, _C]: ... + def __neg__(self) -> Counter[_T, _C]: ... # several type: ignores because __iadd__ is supposedly incompatible with __add__, etc. def __iadd__(self, other: SupportsItems[_T, _C]) -> Self: ... # type: ignore[misc] def __isub__(self, other: SupportsItems[_T, _C]) -> Self: ... From 923d8e20cc5e74b19966aa7e7ec1365fcb354bf1 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 07:02:35 +0100 Subject: [PATCH 05/19] Add more tests --- test_cases/stdlib/collections/check_counter.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 7c929db47abb..a277c4ee54be 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -13,12 +13,14 @@ class Foo: ... int_c: Counter[str] = Counter() assert_type(int_c, Counter[str, int]) +assert_type(int_c["a"], int) int_c["a"] = 1 int_c["a"] += 3 int_c["a"] += 3.5 # type: ignore float_c = Counter(foo=42.2) assert_type(float_c, Counter[str, float]) +assert_type(float_c["a"], float) float_c["a"] = 1.0 float_c["a"] += 3.0 float_c["a"] += 42 @@ -26,6 +28,7 @@ class Foo: ... custom_c: Counter[str, Foo] = Counter() assert_type(custom_c, Counter[str, Foo]) +assert_type(custom_c["a"], Foo) custom_c["a"] = Foo() custom_c["a"] += Foo() # type: ignore custom_c["a"] += 42 # type: ignore From f460e39ddf6fdc8d88ffa0d792b197bab2f655ab Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 07:05:39 +0100 Subject: [PATCH 06/19] Disable a test --- test_cases/stdlib/collections/check_counter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index a277c4ee54be..291b8acaa061 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -31,4 +31,5 @@ class Foo: ... assert_type(custom_c["a"], Foo) custom_c["a"] = Foo() custom_c["a"] += Foo() # type: ignore -custom_c["a"] += 42 # type: ignore +# pyright incorrectly accepts the next line +# custom_c["a"] += 42 # type: ignore From 424d3c02ceaa63765967dfddad097fdcf7f754fa Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 07:07:45 +0100 Subject: [PATCH 07/19] Make pyright happy --- test_cases/stdlib/collections/check_counter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 291b8acaa061..4df4ee6dc640 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -32,4 +32,4 @@ class Foo: ... custom_c["a"] = Foo() custom_c["a"] += Foo() # type: ignore # pyright incorrectly accepts the next line -# custom_c["a"] += 42 # type: ignore +# custom_c["a"] += 42 # xtype: ignore From e3369269901d010d97cf10a9d5f391d5b3210a8c Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 07:14:40 +0100 Subject: [PATCH 08/19] pyright is quite unhappy today ... --- test_cases/stdlib/collections/check_counter.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 4df4ee6dc640..7bf2813ed388 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -7,19 +7,19 @@ class Foo: ... # Test the constructor # assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" -assert_type(Counter(foo=42.2), Counter[str, float]) -assert_type(Counter({42: "bar"}), Counter[int, str]) -assert_type(Counter([1, 2, 3]), Counter[int, int]) +assert_type(Counter(foo=42.2), "Counter[str, float]") +assert_type(Counter({42: "bar"}), "Counter[int, str]") +assert_type(Counter([1, 2, 3]), "Counter[int, int]") int_c: Counter[str] = Counter() -assert_type(int_c, Counter[str, int]) +assert_type(int_c, "Counter[str, int]") assert_type(int_c["a"], int) int_c["a"] = 1 int_c["a"] += 3 int_c["a"] += 3.5 # type: ignore float_c = Counter(foo=42.2) -assert_type(float_c, Counter[str, float]) +assert_type(float_c, "Counter[str, float]") assert_type(float_c["a"], float) float_c["a"] = 1.0 float_c["a"] += 3.0 @@ -27,7 +27,7 @@ class Foo: ... float_c["a"] += "42" # type: ignore custom_c: Counter[str, Foo] = Counter() -assert_type(custom_c, Counter[str, Foo]) +assert_type(custom_c, "Counter[str, Foo]") assert_type(custom_c["a"], Foo) custom_c["a"] = Foo() custom_c["a"] += Foo() # type: ignore From 2f5105bfb67936c43b55892e359e483be5dfe7ed Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Wed, 20 Mar 2024 07:17:03 +0100 Subject: [PATCH 09/19] ... --- test_cases/stdlib/collections/check_counter.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 7bf2813ed388..a9b857ff97a5 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from collections import Counter from typing_extensions import assert_type From dcf86cf418aeaf3a3be7dcb8cab1729c746d3b87 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 7 Apr 2024 15:18:38 +0200 Subject: [PATCH 10/19] Improve tests --- test_cases/stdlib/collections/check_counter.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index a9b857ff97a5..42b5f9212814 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -8,7 +8,10 @@ class Foo: ... # Test the constructor -# assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" +# We can't test the type of the constructor directly, because mypy and pyright +# derive different types (`Never` vs. `Unknown`) for the first type variable. +for value in Counter().values: + assert_type(value, int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") assert_type(Counter([1, 2, 3]), "Counter[int, int]") From caa5b1425ba9be2f72fb7d638d403c7859906ebd Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 7 Apr 2024 15:27:16 +0200 Subject: [PATCH 11/19] Fix test --- test_cases/stdlib/collections/check_counter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 42b5f9212814..4fc8752270a0 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -10,7 +10,7 @@ class Foo: ... # Test the constructor # We can't test the type of the constructor directly, because mypy and pyright # derive different types (`Never` vs. `Unknown`) for the first type variable. -for value in Counter().values: +for value in Counter().values(): assert_type(value, int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") From e10c23c9d46cbb35514fb0bef6eede1fc5b2010b Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Sun, 7 Apr 2024 15:41:05 +0200 Subject: [PATCH 12/19] Revert changes that make pyright unhappy --- test_cases/stdlib/collections/check_counter.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 4fc8752270a0..a9b857ff97a5 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -8,10 +8,7 @@ class Foo: ... # Test the constructor -# We can't test the type of the constructor directly, because mypy and pyright -# derive different types (`Never` vs. `Unknown`) for the first type variable. -for value in Counter().values(): - assert_type(value, int) +# assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") assert_type(Counter([1, 2, 3]), "Counter[int, int]") From b107d205002a99cb08727ad08cfdfacc98066869 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 9 Apr 2024 11:03:45 +0200 Subject: [PATCH 13/19] Use explicit cast in test cases --- test_cases/stdlib/collections/check_counter.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index a9b857ff97a5..0129df47b74d 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -1,6 +1,7 @@ from __future__ import annotations from collections import Counter +from typing import cast from typing_extensions import assert_type @@ -28,10 +29,9 @@ class Foo: ... float_c["a"] += 42 float_c["a"] += "42" # type: ignore -custom_c: Counter[str, Foo] = Counter() +custom_c = cast("Counter[str, Foo]", Counter()) assert_type(custom_c, "Counter[str, Foo]") assert_type(custom_c["a"], Foo) custom_c["a"] = Foo() custom_c["a"] += Foo() # type: ignore -# pyright incorrectly accepts the next line -# custom_c["a"] += 42 # xtype: ignore +custom_c["a"] += 42 # type: ignore From 4723e02e5b365ca7a69024d409f76e94c7741139 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 9 Apr 2024 11:18:05 +0200 Subject: [PATCH 14/19] Add a test --- test_cases/stdlib/collections/check_counter.py | 1 + 1 file changed, 1 insertion(+) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 0129df47b74d..9e3dcb86e038 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -10,6 +10,7 @@ class Foo: ... # Test the constructor # assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" +assert_type(next(Counter().values()), int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") assert_type(Counter([1, 2, 3]), "Counter[int, int]") From 39aa741481a64f2c42d043f4f62235e5a165b3d9 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 9 Apr 2024 11:36:50 +0200 Subject: [PATCH 15/19] Try using `Any` in type assertion --- test_cases/stdlib/collections/check_counter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 9e3dcb86e038..7c5b23c6b2c0 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections import Counter -from typing import cast +from typing import Any, cast from typing_extensions import assert_type @@ -10,6 +10,7 @@ class Foo: ... # Test the constructor # assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" +assert_type(Counter(), "Counter[Any, int]") assert_type(next(Counter().values()), int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") From f9a14bab10c44137ab5a62f35eb5860299b7e24b Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 9 Apr 2024 11:38:32 +0200 Subject: [PATCH 16/19] Fix test --- test_cases/stdlib/collections/check_counter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index 7c5b23c6b2c0..ed9ff93618cb 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -11,7 +11,7 @@ class Foo: ... # Test the constructor # assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" assert_type(Counter(), "Counter[Any, int]") -assert_type(next(Counter().values()), int) +assert_type(next(iter(Counter().values())), int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") assert_type(Counter([1, 2, 3]), "Counter[int, int]") From 3fe47e03c904ba4d9162379d1b367ba9b8ff7e90 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Tue, 9 Apr 2024 11:44:42 +0200 Subject: [PATCH 17/19] Streamline tests --- test_cases/stdlib/collections/check_counter.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test_cases/stdlib/collections/check_counter.py b/test_cases/stdlib/collections/check_counter.py index ed9ff93618cb..581ba67b98e4 100644 --- a/test_cases/stdlib/collections/check_counter.py +++ b/test_cases/stdlib/collections/check_counter.py @@ -9,9 +9,8 @@ class Foo: ... # Test the constructor -# assert_type(Counter(), Counter[Never, int]) # pyright derives "Unknown" instead of "Never" +# mypy derives Never for the first type argument while, pyright derives Unknown assert_type(Counter(), "Counter[Any, int]") -assert_type(next(iter(Counter().values())), int) assert_type(Counter(foo=42.2), "Counter[str, float]") assert_type(Counter({42: "bar"}), "Counter[int, str]") assert_type(Counter([1, 2, 3]), "Counter[int, int]") From a15d40713019ef18e9d32717a3ccdfebfeb11519 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 09:16:39 +0000 Subject: [PATCH 18/19] [pre-commit.ci] auto fixes from pre-commit.com hooks --- stdlib/collections/__init__.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index 9eea4e53a23a..a0c7e54e89aa 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -2,7 +2,7 @@ import sys from _collections_abc import dict_items, dict_keys, dict_values from _typeshed import SupportsItems, SupportsKeysAndGetItem, SupportsRichComparison, SupportsRichComparisonT from types import GenericAlias -from typing import Any, ClassVar, Generic, NoReturn, SupportsIndex, TypeVar, final, overload +from typing import Any, ClassVar, NoReturn, SupportsIndex, TypeVar, final, overload from typing_extensions import Self if sys.version_info >= (3, 10): From 2b1a6a07a6c1079ad9b33eab4aa4ee74313fa420 Mon Sep 17 00:00:00 2001 From: Sebastian Rittau Date: Mon, 14 Apr 2025 11:20:46 +0200 Subject: [PATCH 19/19] Remove unnecessary class-scoped variables --- stdlib/collections/__init__.pyi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stdlib/collections/__init__.pyi b/stdlib/collections/__init__.pyi index a0c7e54e89aa..f170566ea119 100644 --- a/stdlib/collections/__init__.pyi +++ b/stdlib/collections/__init__.pyi @@ -273,9 +273,9 @@ class Counter(dict[_T, _C]): @overload def __init__(self, iterable: None = None, /) -> None: ... @overload - def __init__(self: Counter[str, _C], iterable: None = None, /, **kwargs: _C) -> None: ... + def __init__(self: Counter[str], iterable: None = None, /, **kwargs: _C) -> None: ... @overload - def __init__(self: Counter[_T, _C], mapping: SupportsKeysAndGetItem[_T, _C], /) -> None: ... + def __init__(self, mapping: SupportsKeysAndGetItem[_T, _C], /) -> None: ... @overload def __init__(self, iterable: Iterable[_T], /) -> None: ... def copy(self) -> Self: ...