Skip to content

Commit 4e87b90

Browse files
authored
Improve collections.Counter stub (#7464)
1 parent c987c78 commit 4e87b90

File tree

1 file changed

+18
-16
lines changed

1 file changed

+18
-16
lines changed

stdlib/collections/__init__.pyi

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -266,15 +266,16 @@ class Counter(dict[_T, int], Generic[_T]):
266266
def subtract(self, __mapping: Mapping[_T, int]) -> None: ...
267267
@overload
268268
def subtract(self, __iterable: Iterable[_T]) -> None: ...
269-
# The Iterable[Tuple[...]] argument type is not actually desirable
270-
# (the tuples will be added as keys, breaking type safety) but
271-
# it's included so that the signature is compatible with
272-
# Dict.update. Not sure if we should use '# type: ignore' instead
273-
# and omit the type from the union.
269+
# Unlike dict.update(), use Mapping instead of SupportsKeysAndGetItem for the first overload
270+
# (source code does an `isinstance(other, Mapping)` check)
271+
#
272+
# The second overload is also deliberately different to dict.update()
273+
# (if it were `Iterable[_T] | Iterable[tuple[_T, int]]`,
274+
# the tuples would be added as keys, breaking type safety)
275+
@overload # type: ignore[override]
276+
def update(self, __m: Mapping[_T, int], **kwargs: int) -> None: ...
274277
@overload
275-
def update(self, __m: SupportsKeysAndGetItem[_T, int], **kwargs: int) -> None: ...
276-
@overload
277-
def update(self, __m: Iterable[_T] | Iterable[tuple[_T, int]], **kwargs: int) -> None: ...
278+
def update(self, __m: Iterable[_T], **kwargs: int) -> None: ...
278279
@overload
279280
def update(self, __m: None = ..., **kwargs: int) -> None: ...
280281
def __missing__(self, key: _T) -> int: ...
@@ -283,22 +284,23 @@ class Counter(dict[_T, int], Generic[_T]):
283284
def __eq__(self, other: object) -> bool: ...
284285
def __ne__(self, other: object) -> bool: ...
285286

286-
def __add__(self, other: Counter[_T]) -> Counter[_T]: ...
287+
def __add__(self, other: Counter[_S]) -> Counter[_T | _S]: ...
287288
def __sub__(self, other: Counter[_T]) -> Counter[_T]: ...
288289
def __and__(self, other: Counter[_T]) -> Counter[_T]: ...
289-
def __or__(self, other: Counter[_T]) -> Counter[_T]: ... # type: ignore[override]
290+
def __or__(self, other: Counter[_S]) -> Counter[_T | _S]: ... # type: ignore[override]
290291
def __pos__(self) -> Counter[_T]: ...
291292
def __neg__(self) -> Counter[_T]: ...
292-
def __iadd__(self: Self, other: Counter[_T]) -> Self: ...
293+
# several type: ignores because __iadd__ is supposedly incompatible with __add__, etc.
294+
def __iadd__(self: Self, other: Counter[_T]) -> Self: ... # type: ignore[misc]
293295
def __isub__(self: Self, other: Counter[_T]) -> Self: ...
294296
def __iand__(self: Self, other: Counter[_T]) -> Self: ...
295-
def __ior__(self: Self, other: Counter[_T]) -> Self: ... # type: ignore[override]
297+
def __ior__(self: Self, other: Counter[_T]) -> Self: ... # type: ignore[override,misc]
296298
if sys.version_info >= (3, 10):
297299
def total(self) -> int: ...
298-
def __le__(self, other: Counter[object]) -> bool: ...
299-
def __lt__(self, other: Counter[object]) -> bool: ...
300-
def __ge__(self, other: Counter[object]) -> bool: ...
301-
def __gt__(self, other: Counter[object]) -> bool: ...
300+
def __le__(self, other: Counter[Any]) -> bool: ...
301+
def __lt__(self, other: Counter[Any]) -> bool: ...
302+
def __ge__(self, other: Counter[Any]) -> bool: ...
303+
def __gt__(self, other: Counter[Any]) -> bool: ...
302304

303305
@final
304306
class _OrderedDictKeysView(dict_keys[_KT_co, _VT_co], Reversible[_KT_co]): # type: ignore[misc]

0 commit comments

Comments
 (0)