Skip to content

Commit 1efb36b

Browse files
Merge branch 'main' into restrict-compile-filename
2 parents 42ed44f + 12e7d4e commit 1efb36b

File tree

34 files changed

+423
-295
lines changed

34 files changed

+423
-295
lines changed

CONTRIBUTING.md

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -436,28 +436,24 @@ following criteria is met:
436436
* the upstream package was declared or appears to be unmaintained, and
437437
retaining the stubs causes maintenance issues in typeshed.
438438

439-
If a package ships its own `py.typed` file, please follow these steps:
439+
Case 1: If a package ships its own `py.typed` file, please follow these steps:
440440

441-
1. Open an issue with the earliest month of removal in the subject.
442-
2. A maintainer will add the
443-
["stubs: removal" label](https://github.com/python/typeshed/labels/%22stubs%3A%20removal%22).
444-
3. Open a PR that sets the `obsolete_since` field in the `METADATA.toml`
445-
file to the first version of the package that shipped `py.typed`.
446-
4. After at least six months, open a PR to remove the stubs.
441+
1. Make sure **stubsabot** open a PR that sets the `obsolete_since` field in the
442+
`METADATA.toml` file to the first version of the package that shipped `py.typed`.
443+
2. After at least six months, make sure **stubsabot** open a PR to remove the stubs.
447444

448-
If third-party stubs should be removed for other reasons, please follow these
449-
steps:
445+
Case 2: If third-party stubs should be removed for other reasons, please follow
446+
these steps:
450447

451448
1. Open an issue explaining why the stubs should be removed.
452449
2. A maintainer will add the
453450
["stubs: removal" label](https://github.com/python/typeshed/labels/%22stubs%3A%20removal%22).
454451
3. Open a PR that sets the `no_longer_updated` field in the `METADATA.toml`
455452
file to `true`.
456-
4. When a new version of the package was automatically uploaded to PyPI
457-
(which can take up to a day), open a PR to remove the stubs.
453+
4. When a new version of the package was automatically uploaded to PyPI (which
454+
can take up to a day), make sure **stubsabot** open a PR to remove the stubs.
458455

459-
Don't forget to make sure the library is not in the [`pyrightconfig.stricter.json`](./pyrightconfig.stricter.json)
460-
exclusion list. If feeling kindly, please update [mypy](https://github.com/python/mypy/blob/master/mypy/stubinfo.py)
456+
If feeling kindly, please update [mypy](https://github.com/python/mypy/blob/master/mypy/stubinfo.py)
461457
for any stub obsoletions or removals.
462458

463459
### Marking PRs as "deferred"
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from __future__ import annotations
2+
3+
from _typeshed import SupportsDunderGT, SupportsDunderLT, SupportsGetItem
4+
from collections.abc import Callable
5+
from operator import itemgetter
6+
from typing import Any, TypeVar
7+
from typing_extensions import assert_type
8+
9+
_T = TypeVar("_T")
10+
11+
12+
# This should be equivalent to itemgetter().__call__
13+
def standalone_call(obj: SupportsGetItem[Any, _T]) -> _T: ...
14+
15+
16+
# Expected type of itemgetter(1).__call__
17+
expected_type_itemgetter_call: Callable[[SupportsGetItem[int, _T]], _T] # pyright: ignore[reportGeneralTypeIssues]
18+
19+
# Expecting itemgetter(1) to be assignable to this
20+
# based on the example below: min({"first": 1, "second": 2}.items(), key=itemgetter(1))
21+
# That example and assigning to this variable are what failed in https://github.com/python/mypy/issues/14032
22+
expected_assignable_to: Callable[[tuple[str, int]], SupportsDunderLT[Any] | SupportsDunderGT[Any]]
23+
24+
25+
# Regression tests for https://github.com/python/mypy/issues/14032
26+
# assert_type(itemgetter("first")({"first": 1, "second": 2}), int) # See comment on itemgetter.__call__
27+
assert_type(min({"first": 1, "second": 2}, key=itemgetter(1)), str)
28+
assert_type(min({"first": 1, "second": 2}.items(), key=itemgetter(1)), tuple[str, int])
29+
assert_type(standalone_call({"first": 1, "second": 2}), int)
30+
assert_type(min({"first": 1, "second": 2}, key=standalone_call), str)
31+
assert_type(min({"first": 1, "second": 2}.items(), key=standalone_call), tuple[str, int])
32+
33+
expected_itemgetter_call_type = itemgetter(1).__call__
34+
expected_itemgetter_call_type = itemgetter(1)
35+
expected_assignable_to = itemgetter(1)
36+
37+
expected_itemgetter_call_type = standalone_call
38+
expected_assignable_to = standalone_call

stdlib/operator.pyi

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,8 +205,10 @@ class itemgetter(Generic[_T_co]):
205205
# "tuple[int, int]" is incompatible with protocol "SupportsIndex"
206206
# preventing [_T_co, ...] instead of [Any, ...]
207207
#
208-
# A suspected mypy issue prevents using [..., _T] instead of [..., Any] here.
209-
# https://github.com/python/mypy/issues/14032
208+
# If we can't infer a literal key from __new__ (ie: `itemgetter[Literal[0]]` for `itemgetter(0)`),
209+
# then we can't annotate __call__'s return type or it'll break on tuples
210+
#
211+
# These issues are best demonstrated by the `itertools.check_itertools_recipes.unique_justseen` test.
210212
def __call__(self, obj: SupportsGetItem[Any, Any]) -> Any: ...
211213

212214
@final

stdlib/types.pyi

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ if sys.version_info >= (3, 13):
6565

6666
_T1 = TypeVar("_T1")
6767
_T2 = TypeVar("_T2")
68-
_KT = TypeVar("_KT")
68+
_KT_co = TypeVar("_KT_co", covariant=True)
6969
_VT_co = TypeVar("_VT_co", covariant=True)
7070

7171
# Make sure this class definition stays roughly in line with `builtins.function`
@@ -309,27 +309,27 @@ class CodeType:
309309
__replace__ = replace
310310

311311
@final
312-
class MappingProxyType(Mapping[_KT, _VT_co]):
312+
class MappingProxyType(Mapping[_KT_co, _VT_co]): # type: ignore[type-var] # pyright: ignore[reportInvalidTypeArguments]
313313
__hash__: ClassVar[None] # type: ignore[assignment]
314-
def __new__(cls, mapping: SupportsKeysAndGetItem[_KT, _VT_co]) -> Self: ...
315-
def __getitem__(self, key: _KT, /) -> _VT_co: ...
316-
def __iter__(self) -> Iterator[_KT]: ...
314+
def __new__(cls, mapping: SupportsKeysAndGetItem[_KT_co, _VT_co]) -> Self: ...
315+
def __getitem__(self, key: _KT_co, /) -> _VT_co: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues]
316+
def __iter__(self) -> Iterator[_KT_co]: ...
317317
def __len__(self) -> int: ...
318318
def __eq__(self, value: object, /) -> bool: ...
319-
def copy(self) -> dict[_KT, _VT_co]: ...
320-
def keys(self) -> KeysView[_KT]: ...
319+
def copy(self) -> dict[_KT_co, _VT_co]: ...
320+
def keys(self) -> KeysView[_KT_co]: ...
321321
def values(self) -> ValuesView[_VT_co]: ...
322-
def items(self) -> ItemsView[_KT, _VT_co]: ...
322+
def items(self) -> ItemsView[_KT_co, _VT_co]: ...
323323
@overload
324-
def get(self, key: _KT, /) -> _VT_co | None: ...
324+
def get(self, key: _KT_co, /) -> _VT_co | None: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] # Covariant type as parameter
325325
@overload
326-
def get(self, key: _KT, default: _VT_co, /) -> _VT_co: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] # Covariant type as parameter
326+
def get(self, key: _KT_co, default: _VT_co, /) -> _VT_co: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] # Covariant type as parameter
327327
@overload
328-
def get(self, key: _KT, default: _T2, /) -> _VT_co | _T2: ...
328+
def get(self, key: _KT_co, default: _T2, /) -> _VT_co | _T2: ... # type: ignore[misc] # pyright: ignore[reportGeneralTypeIssues] # Covariant type as parameter
329329
def __class_getitem__(cls, item: Any, /) -> GenericAlias: ...
330-
def __reversed__(self) -> Iterator[_KT]: ...
331-
def __or__(self, value: Mapping[_T1, _T2], /) -> dict[_KT | _T1, _VT_co | _T2]: ...
332-
def __ror__(self, value: Mapping[_T1, _T2], /) -> dict[_KT | _T1, _VT_co | _T2]: ...
330+
def __reversed__(self) -> Iterator[_KT_co]: ...
331+
def __or__(self, value: Mapping[_T1, _T2], /) -> dict[_KT_co | _T1, _VT_co | _T2]: ...
332+
def __ror__(self, value: Mapping[_T1, _T2], /) -> dict[_KT_co | _T1, _VT_co | _T2]: ...
333333

334334
if sys.version_info >= (3, 12):
335335
@disjoint_base

stdlib/typing.pyi

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,28 +1133,23 @@ if sys.version_info >= (3, 10):
11331133
def _type_repr(obj: object) -> str: ...
11341134

11351135
if sys.version_info >= (3, 12):
1136+
_TypeParameter: typing_extensions.TypeAlias = (
1137+
TypeVar
1138+
| typing_extensions.TypeVar
1139+
| ParamSpec
1140+
| typing_extensions.ParamSpec
1141+
| TypeVarTuple
1142+
| typing_extensions.TypeVarTuple
1143+
)
1144+
11361145
def override(method: _F, /) -> _F: ...
11371146
@final
11381147
class TypeAliasType:
1139-
def __new__(
1140-
cls,
1141-
name: str,
1142-
value: Any,
1143-
*,
1144-
type_params: tuple[
1145-
TypeVar
1146-
| typing_extensions.TypeVar
1147-
| ParamSpec
1148-
| typing_extensions.ParamSpec
1149-
| TypeVarTuple
1150-
| typing_extensions.TypeVarTuple,
1151-
...,
1152-
] = (),
1153-
) -> Self: ...
1148+
def __new__(cls, name: str, value: Any, *, type_params: tuple[_TypeParameter, ...] = ()) -> Self: ...
11541149
@property
11551150
def __value__(self) -> Any: ... # AnnotationForm
11561151
@property
1157-
def __type_params__(self) -> tuple[TypeVar | ParamSpec | TypeVarTuple, ...]: ...
1152+
def __type_params__(self) -> tuple[_TypeParameter, ...]: ...
11581153
@property
11591154
def __parameters__(self) -> tuple[Any, ...]: ... # AnnotationForm
11601155
@property

stdlib/xml/etree/ElementTree.pyi

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ class Element(Generic[_Tag]):
9393
def __init__(self, tag: _Tag, attrib: dict[str, str] = {}, **extra: str) -> None: ...
9494
def append(self, subelement: Element[Any], /) -> None: ...
9595
def clear(self) -> None: ...
96-
def extend(self, elements: Iterable[Element], /) -> None: ...
96+
def extend(self, elements: Iterable[Element[Any]], /) -> None: ...
9797
def find(self, path: str, namespaces: dict[str, str] | None = None) -> Element | None: ...
9898
def findall(self, path: str, namespaces: dict[str, str] | None = None) -> list[Element]: ...
9999
@overload
@@ -104,7 +104,7 @@ class Element(Generic[_Tag]):
104104
def get(self, key: str, default: None = None) -> str | None: ...
105105
@overload
106106
def get(self, key: str, default: _T) -> str | _T: ...
107-
def insert(self, index: int, subelement: Element, /) -> None: ...
107+
def insert(self, index: int, subelement: Element[Any], /) -> None: ...
108108
def items(self) -> ItemsView[str, str]: ...
109109
def iter(self, tag: str | None = None) -> Generator[Element, None, None]: ...
110110
@overload
@@ -115,7 +115,7 @@ class Element(Generic[_Tag]):
115115
def keys(self) -> dict_keys[str, str]: ...
116116
# makeelement returns the type of self in Python impl, but not in C impl
117117
def makeelement(self, tag: _OtherTag, attrib: dict[str, str], /) -> Element[_OtherTag]: ...
118-
def remove(self, subelement: Element, /) -> None: ...
118+
def remove(self, subelement: Element[Any], /) -> None: ...
119119
def set(self, key: str, value: str, /) -> None: ...
120120
def __copy__(self) -> Element[_Tag]: ... # returns the type of self in Python impl, but not in C impl
121121
def __deepcopy__(self, memo: Any, /) -> Element: ... # Only exists in C impl
@@ -128,15 +128,15 @@ class Element(Generic[_Tag]):
128128
# Doesn't actually exist at runtime, but instance of the class are indeed iterable due to __getitem__.
129129
def __iter__(self) -> Iterator[Element]: ...
130130
@overload
131-
def __setitem__(self, key: SupportsIndex, value: Element, /) -> None: ...
131+
def __setitem__(self, key: SupportsIndex, value: Element[Any], /) -> None: ...
132132
@overload
133-
def __setitem__(self, key: slice, value: Iterable[Element], /) -> None: ...
133+
def __setitem__(self, key: slice, value: Iterable[Element[Any]], /) -> None: ...
134134

135135
# Doesn't really exist in earlier versions, where __len__ is called implicitly instead
136136
@deprecated("Testing an element's truth value is deprecated.")
137137
def __bool__(self) -> bool: ...
138138

139-
def SubElement(parent: Element, tag: str, attrib: dict[str, str] = ..., **extra: str) -> Element: ...
139+
def SubElement(parent: Element[Any], tag: str, attrib: dict[str, str] = ..., **extra: str) -> Element: ...
140140
def Comment(text: str | None = None) -> Element[_ElementCallable]: ...
141141
def ProcessingInstruction(target: str, text: str | None = None) -> Element[_ElementCallable]: ...
142142

@@ -155,7 +155,7 @@ class QName:
155155
_Root = TypeVar("_Root", Element, Element | None, default=Element | None)
156156

157157
class ElementTree(Generic[_Root]):
158-
def __init__(self, element: Element | None = None, file: _FileRead | None = None) -> None: ...
158+
def __init__(self, element: Element[Any] | None = None, file: _FileRead | None = None) -> None: ...
159159
def getroot(self) -> _Root: ...
160160
def parse(self, source: _FileRead, parser: XMLParser | None = None) -> Element: ...
161161
def iter(self, tag: str | None = None) -> Generator[Element, None, None]: ...
@@ -186,7 +186,7 @@ HTML_EMPTY: Final[set[str]]
186186
def register_namespace(prefix: str, uri: str) -> None: ...
187187
@overload
188188
def tostring(
189-
element: Element,
189+
element: Element[Any],
190190
encoding: None = None,
191191
method: Literal["xml", "html", "text", "c14n"] | None = None,
192192
*,
@@ -196,7 +196,7 @@ def tostring(
196196
) -> bytes: ...
197197
@overload
198198
def tostring(
199-
element: Element,
199+
element: Element[Any],
200200
encoding: Literal["unicode"],
201201
method: Literal["xml", "html", "text", "c14n"] | None = None,
202202
*,
@@ -206,7 +206,7 @@ def tostring(
206206
) -> str: ...
207207
@overload
208208
def tostring(
209-
element: Element,
209+
element: Element[Any],
210210
encoding: str,
211211
method: Literal["xml", "html", "text", "c14n"] | None = None,
212212
*,
@@ -216,7 +216,7 @@ def tostring(
216216
) -> Any: ...
217217
@overload
218218
def tostringlist(
219-
element: Element,
219+
element: Element[Any],
220220
encoding: None = None,
221221
method: Literal["xml", "html", "text", "c14n"] | None = None,
222222
*,
@@ -226,7 +226,7 @@ def tostringlist(
226226
) -> list[bytes]: ...
227227
@overload
228228
def tostringlist(
229-
element: Element,
229+
element: Element[Any],
230230
encoding: Literal["unicode"],
231231
method: Literal["xml", "html", "text", "c14n"] | None = None,
232232
*,
@@ -236,16 +236,16 @@ def tostringlist(
236236
) -> list[str]: ...
237237
@overload
238238
def tostringlist(
239-
element: Element,
239+
element: Element[Any],
240240
encoding: str,
241241
method: Literal["xml", "html", "text", "c14n"] | None = None,
242242
*,
243243
xml_declaration: bool | None = None,
244244
default_namespace: str | None = None,
245245
short_empty_elements: bool = True,
246246
) -> list[Any]: ...
247-
def dump(elem: Element | ElementTree[Any]) -> None: ...
248-
def indent(tree: Element | ElementTree[Any], space: str = " ", level: int = 0) -> None: ...
247+
def dump(elem: Element[Any] | ElementTree[Any]) -> None: ...
248+
def indent(tree: Element[Any] | ElementTree[Any], space: str = " ", level: int = 0) -> None: ...
249249
def parse(source: _FileRead, parser: XMLParser[Any] | None = None) -> ElementTree[Element]: ...
250250

251251
# This class is defined inside the body of iterparse

stubs/docker/METADATA.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version = "7.1.*"
22
upstream_repository = "https://github.com/docker/docker-py"
3-
requires = ["types-requests", "urllib3>=2"]
3+
requires = ["types-paramiko", "types-requests", "urllib3>=2"]

stubs/docker/docker/api/image.pyi

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
from _typeshed import Incomplete
1+
import logging
22
from typing import Any
33

4-
log: Incomplete
4+
log: logging.Logger
55

66
class ImageApiMixin:
77
def get_image(self, image: str, chunk_size: int | None = 2097152): ...

stubs/docker/docker/api/swarm.pyi

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
from _typeshed import Incomplete
1+
import logging
2+
from typing import Literal
23

3-
log: Incomplete
4+
from docker.types.swarm import SwarmSpec
5+
6+
log: logging.Logger
47

58
class SwarmApiMixin:
6-
def create_swarm_spec(self, *args, **kwargs): ...
9+
def create_swarm_spec(self, *args, **kwargs) -> SwarmSpec: ...
710
def get_unlock_key(self): ...
811
def init_swarm(
912
self,
@@ -20,17 +23,17 @@ class SwarmApiMixin:
2023
def inspect_node(self, node_id): ...
2124
def join_swarm(
2225
self, remote_addrs, join_token, listen_addr: str = "0.0.0.0:2377", advertise_addr=None, data_path_addr=None
23-
): ...
24-
def leave_swarm(self, force: bool = False): ...
26+
) -> Literal[True]: ...
27+
def leave_swarm(self, force: bool = False) -> Literal[True]: ...
2528
def nodes(self, filters=None): ...
26-
def remove_node(self, node_id, force: bool = False): ...
27-
def unlock_swarm(self, key): ...
28-
def update_node(self, node_id, version, node_spec=None): ...
29+
def remove_node(self, node_id, force: bool = False) -> Literal[True]: ...
30+
def unlock_swarm(self, key) -> Literal[True]: ...
31+
def update_node(self, node_id, version, node_spec=None) -> Literal[True]: ...
2932
def update_swarm(
3033
self,
3134
version,
3235
swarm_spec=None,
3336
rotate_worker_token: bool = False,
3437
rotate_manager_token: bool = False,
3538
rotate_manager_unlock_key: bool = False,
36-
): ...
39+
) -> Literal[True]: ...

stubs/docker/docker/credentials/store.pyi

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
from _typeshed import Incomplete
22

33
class Store:
4-
program: Incomplete
5-
exe: Incomplete
4+
program: str
5+
exe: str | None
66
environment: Incomplete
7-
def __init__(self, program, environment=None) -> None: ...
7+
def __init__(self, program: str, environment=None) -> None: ...
88
def get(self, server): ...
99
def store(self, server, username, secret): ...
1010
def erase(self, server) -> None: ...

0 commit comments

Comments
 (0)