diff --git a/stubs/networkx/@tests/stubtest_allowlist.txt b/stubs/networkx/@tests/stubtest_allowlist.txt index b297bf9b2153..c55b28c08921 100644 --- a/stubs/networkx/@tests/stubtest_allowlist.txt +++ b/stubs/networkx/@tests/stubtest_allowlist.txt @@ -30,3 +30,17 @@ networkx\.algorithms\.bipartite\.(cluster\.)?clustering # failing to account for explicitly passing in the default value." # Which is true, but would require some way of concatenating `backend` to ParamSpec.kwargs networkx\.(utils\.)?(backends\.)?_dispatchable\.__call__ + +# Tests are excluded +networkx.conftest +networkx(\..+?)?\.tests(\..+?)? + +# "..._DT is not present at runtime" but we don't set it in stubs, I don't understand this one +networkx(\.algorithms)?(\.tree)?(\.mst)?\.SpanningTreeIterator\.Partition\._DT +networkx(\.algorithms)?(\.tree)?(\.branchings)?\.ArborescenceIterator\.Partition\._DT + +# variable differs from runtime type abc.ABCMeta +networkx.classes.reportviews.EdgeView.dataview +networkx.classes.reportviews.InEdgeView.dataview +networkx.classes.reportviews.OutEdgeView.dataview +networkx.classes.reportviews.OutMultiEdgeView.dataview diff --git a/stubs/networkx/METADATA.toml b/stubs/networkx/METADATA.toml index 97f4bd7321ca..387904a34abb 100644 --- a/stubs/networkx/METADATA.toml +++ b/stubs/networkx/METADATA.toml @@ -2,9 +2,9 @@ version = "3.4.2" upstream_repository = "https://github.com/networkx/networkx" # requires a version of numpy with a `py.typed` file requires = ["numpy>=1.20"] -partial_stub = true +# Uses more recent dataclass kwargs +requires_python = ">=3.10" [tool.stubtest] -ignore_missing_stub = true # stub_uploader won't allow pandas-stubs in the requires field https://github.com/typeshed-internal/stub_uploader/issues/90 stubtest_requirements = ["pandas"] diff --git a/stubs/networkx/networkx/algorithms/planarity.pyi b/stubs/networkx/networkx/algorithms/planarity.pyi index 9b1ba3b297fe..43d10d50a84e 100644 --- a/stubs/networkx/networkx/algorithms/planarity.pyi +++ b/stubs/networkx/networkx/algorithms/planarity.pyi @@ -67,6 +67,7 @@ class PlanarEmbedding(DiGraph[_Node]): def get_data(self) -> dict[_Node, list[_Node]]: ... def set_data(self, data: Mapping[_Node, Reversible[_Node]]) -> None: ... def neighbors_cw_order(self, v: _Node) -> Generator[_Node, None, None]: ... + def add_half_edge(self, start_node: _Node, end_node: _Node, *, cw: _Node | None = None, ccw: _Node | None = None): ... def check_structure(self) -> None: ... def add_half_edge_ccw(self, start_node: _Node, end_node: _Node, reference_neighbor: _Node) -> None: ... def add_half_edge_cw(self, start_node: _Node, end_node: _Node, reference_neighbor: _Node) -> None: ... diff --git a/stubs/networkx/networkx/algorithms/tree/branchings.pyi b/stubs/networkx/networkx/algorithms/tree/branchings.pyi index f04b808be8ba..bc07c60e06eb 100644 --- a/stubs/networkx/networkx/algorithms/tree/branchings.pyi +++ b/stubs/networkx/networkx/algorithms/tree/branchings.pyi @@ -44,10 +44,11 @@ def minimum_spanning_arborescence( ): ... class ArborescenceIterator: - @dataclass + @dataclass(order=True) class Partition: mst_weight: float partition_dict: dict[Incomplete, Incomplete] + def __copy__(self) -> ArborescenceIterator.Partition: ... G: Incomplete weight: Incomplete diff --git a/stubs/networkx/networkx/algorithms/tree/mst.pyi b/stubs/networkx/networkx/algorithms/tree/mst.pyi index 5cd518995676..30854ffd12e0 100644 --- a/stubs/networkx/networkx/algorithms/tree/mst.pyi +++ b/stubs/networkx/networkx/algorithms/tree/mst.pyi @@ -57,10 +57,11 @@ def random_spanning_tree( ): ... class SpanningTreeIterator: - @dataclass + @dataclass(order=True) class Partition: mst_weight: float partition_dict: dict[Incomplete, Incomplete] + def __copy__(self) -> SpanningTreeIterator.Partition: ... G: Incomplete weight: Incomplete diff --git a/stubs/networkx/networkx/classes/graph.pyi b/stubs/networkx/networkx/classes/graph.pyi index 5fda0dcc5843..0679630a9c07 100644 --- a/stubs/networkx/networkx/classes/graph.pyi +++ b/stubs/networkx/networkx/classes/graph.pyi @@ -29,12 +29,13 @@ _Data: TypeAlias = ( __all__ = ["Graph"] class Graph(Collection[_Node]): - node_dict_factory: ClassVar[_MapFactory] = ... - node_attr_dict_factory: ClassVar[_MapFactory] = ... - adjlist_outer_dict_factory: ClassVar[_MapFactory] = ... - adjlist_inner_dict_factory: ClassVar[_MapFactory] = ... - edge_attr_dict_factory: ClassVar[_MapFactory] = ... - graph_attr_dict_factory: ClassVar[_MapFactory] = ... + __networkx_backend__: ClassVar[str] + node_dict_factory: ClassVar[_MapFactory] + node_attr_dict_factory: ClassVar[_MapFactory] + adjlist_outer_dict_factory: ClassVar[_MapFactory] + adjlist_inner_dict_factory: ClassVar[_MapFactory] + edge_attr_dict_factory: ClassVar[_MapFactory] + graph_attr_dict_factory: ClassVar[_MapFactory] graph: dict[str, Any] diff --git a/stubs/networkx/networkx/classes/multigraph.pyi b/stubs/networkx/networkx/classes/multigraph.pyi index 63b159ad06d9..1fce3b56522e 100644 --- a/stubs/networkx/networkx/classes/multigraph.pyi +++ b/stubs/networkx/networkx/classes/multigraph.pyi @@ -1,9 +1,10 @@ from _typeshed import Incomplete from functools import cached_property +from typing import ClassVar from typing_extensions import TypeAlias from networkx.classes.coreviews import MultiAdjacencyView -from networkx.classes.graph import Graph, _Node +from networkx.classes.graph import Graph, _MapFactory, _Node from networkx.classes.multidigraph import MultiDiGraph from networkx.classes.reportviews import OutMultiEdgeView @@ -12,6 +13,7 @@ _MultiEdge: TypeAlias = tuple[_Node, _Node, int] # noqa: Y047 __all__ = ["MultiGraph"] class MultiGraph(Graph[_Node]): + edge_key_dict_factory: ClassVar[_MapFactory] def __init__(self, incoming_graph_data: Incomplete | None = None, multigraph_input: bool | None = None, **attr) -> None: ... @cached_property def adj(self) -> MultiAdjacencyView[_Node, _Node, dict[str, Incomplete]]: ... diff --git a/stubs/networkx/networkx/classes/reportviews.pyi b/stubs/networkx/networkx/classes/reportviews.pyi index 2a2a5c6d7286..0337ba24c45d 100644 --- a/stubs/networkx/networkx/classes/reportviews.pyi +++ b/stubs/networkx/networkx/classes/reportviews.pyi @@ -85,6 +85,7 @@ class EdgeDataView(OutEdgeDataView[_Node, _D]): ... class InEdgeDataView(OutEdgeDataView[_Node, _D]): ... class OutMultiEdgeDataView(OutEdgeDataView[_Node, _D]): + keys: bool def __init__( self, viewer, nbunch: _NBunch[_Node] = None, data: bool = False, *, default: Incomplete | None = None, keys: bool = False ) -> None: ... @@ -92,12 +93,13 @@ class OutMultiEdgeDataView(OutEdgeDataView[_Node, _D]): class MultiEdgeDataView(OutEdgeDataView[_Node, _D]): ... class InMultiEdgeDataView(OutEdgeDataView[_Node, _D]): ... -class OutEdgeView(AbstractSet[Incomplete], Mapping[Incomplete, Incomplete], Generic[_Node]): +class OutEdgeView(AbstractSet[Incomplete], Mapping[Incomplete, Incomplete], EdgeViewABC, Generic[_Node]): def __init__(self, G: Graph[_Node]) -> None: ... def __len__(self) -> int: ... def __iter__(self) -> Iterator[tuple[_Node, _Node]]: ... def __contains__(self, e: _Edge[_Node]) -> bool: ... # type: ignore[override] def __getitem__(self, e: _Edge[_Node]) -> dict[str, Any]: ... + dataview = OutEdgeDataView @overload def __call__(self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None) -> Self: ... # type: ignore[overload-overlap] @overload @@ -131,12 +133,82 @@ class OutEdgeView(AbstractSet[Incomplete], Mapping[Incomplete, Incomplete], Gene self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None ) -> OutEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... -class EdgeView(OutEdgeView[_Node]): ... -class InEdgeView(OutEdgeView[_Node]): ... +class EdgeView(OutEdgeView[_Node]): + dataview = EdgeDataView + # Have to override parent's overloads with the proper return type based on dataview + @overload + def __call__(self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None) -> Self: ... # type: ignore[overload-overlap] + @overload + def __call__( + self, nbunch: _Node | Iterable[_Node], data: Literal[False] = False, *, default: None = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: Literal[True], *, default: None = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: str, *, default: _U | None = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def data(self, data: Literal[False], default: Unused = None, nbunch: None = None) -> Self: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None + ) -> EdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + +class InEdgeView(OutEdgeView[_Node]): + dataview = InEdgeDataView + # Have to override parent's overloads with the proper return type based on dataview + @overload + def __call__(self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None) -> Self: ... # type: ignore[overload-overlap] + @overload + def __call__( + self, nbunch: _Node | Iterable[_Node], data: Literal[False] = False, *, default: None = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: Literal[True], *, default: None = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: str, *, default: _U | None = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def data(self, data: Literal[False], default: Unused = None, nbunch: None = None) -> Self: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None + ) -> InEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... class OutMultiEdgeView(OutEdgeView[_Node]): def __iter__(self) -> Iterator[tuple[_Node, _Node, Incomplete]]: ... # type: ignore[override] def __getitem__(self, e: tuple[_Node, _Node, Incomplete]) -> dict[str, Any]: ... # type: ignore[override] + dataview = OutMultiEdgeDataView @overload # type: ignore[override] # Has an additional `keys` keyword argument def __call__( # type: ignore[overload-overlap] self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None, keys: Literal[True] @@ -196,5 +268,126 @@ class OutMultiEdgeView(OutEdgeView[_Node]): self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None, *, keys: Literal[True] ) -> OutMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, _U]]: ... -class MultiEdgeView(OutMultiEdgeView[_Node]): ... -class InMultiEdgeView(OutMultiEdgeView[_Node]): ... +class MultiEdgeView(OutMultiEdgeView[_Node]): + dataview = MultiEdgeDataView # type: ignore[assignment] + # Have to override parent's overloads with the proper return type based on dataview + @overload # type: ignore[override] # Has an additional `keys` keyword argument + def __call__( # type: ignore[overload-overlap] + self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None, keys: Literal[True] + ) -> Self: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, data: Literal[False] = False, *, default: None = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def __call__( + self, nbunch: _Node | Iterable[_Node], data: Literal[False] = False, *, default: None = None, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: Literal[True], *, default: None = None, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: str, *, default: _U | None = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload # type: ignore[override] + def data(self, data: Literal[False], default: Unused = None, nbunch: None = None, *, keys: Literal[True]) -> Self: ... + @overload + def data( + self, data: Literal[False], default: None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None, *, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None, *, keys: Literal[True] + ) -> MultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, _U]]: ... + +class InMultiEdgeView(OutMultiEdgeView[_Node]): + dataview = InMultiEdgeDataView # type: ignore[assignment] + # Have to override parent's overloads with the proper return type based on dataview + @overload # type: ignore[override] + def __call__( # type: ignore[overload-overlap] + self, nbunch: None = None, data: Literal[False] = False, *, default: Unused = None, keys: Literal[True] + ) -> Self: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, data: Literal[False] = False, *, default: None = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def __call__( + self, nbunch: _Node | Iterable[_Node], data: Literal[False] = False, *, default: None = None, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: Literal[True], *, default: None = None, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: Literal[True], default: None = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node], data: str, *, default: _U | None = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, _U]]: ... + @overload + def __call__( + self, nbunch: _NBunch[_Node] = None, *, data: str, default: _U | None = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload # type: ignore[override] + def data(self, data: Literal[False], default: Unused = None, nbunch: None = None, *, keys: Literal[True]) -> Self: ... + @overload + def data( + self, data: Literal[False], default: None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node]]: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: Literal[True] = True, default: None = None, nbunch: _NBunch[_Node] = None, *, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, dict[str, Incomplete]]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None, keys: Literal[False] = False + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, _U]]: ... + @overload + def data( + self, data: str, default: _U | None = None, nbunch: _NBunch[_Node] = None, *, keys: Literal[True] + ) -> InMultiEdgeDataView[_Node, tuple[_Node, _Node, Incomplete, _U]]: ... diff --git a/stubs/networkx/networkx/readwrite/text.pyi b/stubs/networkx/networkx/readwrite/text.pyi index 1f96ae0a135a..8a2bf32fb8f0 100644 --- a/stubs/networkx/networkx/readwrite/text.pyi +++ b/stubs/networkx/networkx/readwrite/text.pyi @@ -4,7 +4,11 @@ from typing import ClassVar __all__ = ["generate_network_text", "write_network_text"] -class _AsciiBaseGlyphs: +class BaseGlyphs: + @classmethod + def as_dict(cls) -> dict[str, str]: ... + +class AsciiBaseGlyphs(BaseGlyphs): empty: ClassVar[str] newtree_last: ClassVar[str] newtree_mid: ClassVar[str] @@ -12,17 +16,19 @@ class _AsciiBaseGlyphs: within_forest: ClassVar[str] within_tree: ClassVar[str] -class AsciiDirectedGlyphs(_AsciiBaseGlyphs): +class AsciiDirectedGlyphs(AsciiBaseGlyphs): last: ClassVar[str] mid: ClassVar[str] backedge: ClassVar[str] + vertical_edge: ClassVar[str] -class AsciiUndirectedGlyphs(_AsciiBaseGlyphs): +class AsciiUndirectedGlyphs(AsciiBaseGlyphs): last: ClassVar[str] mid: ClassVar[str] backedge: ClassVar[str] + vertical_edge: ClassVar[str] -class _UtfBaseGlyphs: +class UtfBaseGlyphs(BaseGlyphs): empty: ClassVar[str] newtree_last: ClassVar[str] newtree_mid: ClassVar[str] @@ -30,15 +36,17 @@ class _UtfBaseGlyphs: within_forest: ClassVar[str] within_tree: ClassVar[str] -class UtfDirectedGlyphs(_UtfBaseGlyphs): +class UtfDirectedGlyphs(UtfBaseGlyphs): last: ClassVar[str] mid: ClassVar[str] backedge: ClassVar[str] + vertical_edge: ClassVar[str] -class UtfUndirectedGlyphs(_UtfBaseGlyphs): +class UtfUndirectedGlyphs(UtfBaseGlyphs): last: ClassVar[str] mid: ClassVar[str] backedge: ClassVar[str] + vertical_edge: ClassVar[str] def generate_network_text( graph, diff --git a/stubs/networkx/networkx/utils/configs.pyi b/stubs/networkx/networkx/utils/configs.pyi index 42f48e2dc433..1d165b9fb1b5 100644 --- a/stubs/networkx/networkx/utils/configs.pyi +++ b/stubs/networkx/networkx/utils/configs.pyi @@ -1,26 +1,65 @@ +import sys from _typeshed import Incomplete -from collections.abc import ItemsView, Iterable, Iterator, KeysView, Mapping, ValuesView +from collections.abc import Callable, ItemsView, Iterable, Iterator, KeysView, ValuesView +from dataclasses import dataclass +from types import TracebackType from typing_extensions import Self __all__ = ["Config"] -class Config(Mapping[str, Incomplete]): - def __init_subclass__(cls, strict: bool = True) -> None: ... - def __new__(cls, **kwargs) -> Self: ... - def __dir__(self) -> Iterable[str]: ... - def __setattr__(self, name: str, value) -> None: ... - def __delattr__(self, name: str) -> None: ... - def __contains__(self, key: object) -> bool: ... - def __iter__(self) -> Iterator[str]: ... - def __len__(self) -> int: ... - def __reversed__(self) -> Iterator[str]: ... - def __getitem__(self, key: str): ... - def __setitem__(self, key: str, value) -> None: ... - def __delitem__(self, key: str) -> None: ... - def get(self, key: str, default: Incomplete | None = None): ... - def items(self) -> ItemsView[str, Incomplete]: ... - def keys(self) -> KeysView[str]: ... - def values(self) -> ValuesView[Incomplete]: ... +# TODO: Our pyright test doesn't understand `requires_python` in METADATA.toml +# https://github.com/python/typeshed/issues/14025 +if sys.version_info >= (3, 10): + @dataclass(init=False, eq=False, slots=True, kw_only=True, match_args=False) + class Config: + def __init_subclass__(cls, strict: bool = True) -> None: ... + def __new__(cls, **kwargs) -> Self: ... + def __dir__(self) -> Iterable[str]: ... + def __setattr__(self, name: str, value) -> None: ... + def __delattr__(self, name: str) -> None: ... + def __contains__(self, key: object) -> bool: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ... + def __reversed__(self) -> Iterator[str]: ... + def __getitem__(self, key: str): ... + def __setitem__(self, key: str, value) -> None: ... + def __delitem__(self, key: str) -> None: ... + def get(self, key: str, default: Incomplete | None = None): ... + def items(self) -> ItemsView[str, Incomplete]: ... + def keys(self) -> KeysView[str]: ... + def values(self) -> ValuesView[Incomplete]: ... + def __reduce__(self) -> tuple[Callable[..., Self], tuple[type[Self], dict[Incomplete, Incomplete]]]: ... + def __call__(self, **kwargs) -> Self: ... + def __enter__(self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None + ) -> None: ... + +else: + @dataclass(init=False, eq=False) + class Config: + def __init_subclass__(cls, strict: bool = True) -> None: ... + def __new__(cls, **kwargs) -> Self: ... + def __dir__(self) -> Iterable[str]: ... + def __setattr__(self, name: str, value) -> None: ... + def __delattr__(self, name: str) -> None: ... + def __contains__(self, key: object) -> bool: ... + def __iter__(self) -> Iterator[str]: ... + def __len__(self) -> int: ... + def __reversed__(self) -> Iterator[str]: ... + def __getitem__(self, key: str): ... + def __setitem__(self, key: str, value) -> None: ... + def __delitem__(self, key: str) -> None: ... + def get(self, key: str, default: Incomplete | None = None): ... + def items(self) -> ItemsView[str, Incomplete]: ... + def keys(self) -> KeysView[str]: ... + def values(self) -> ValuesView[Incomplete]: ... + def __reduce__(self) -> tuple[Callable[..., Self], tuple[type[Self], dict[Incomplete, Incomplete]]]: ... + def __call__(self, **kwargs) -> Self: ... + def __enter__(self) -> Self: ... + def __exit__( + self, exc_type: type[BaseException] | None, exc_value: BaseException | None, traceback: TracebackType | None + ) -> None: ... class NetworkXConfig(Config): backend_priority: list[str] diff --git a/tests/stubtest_third_party.py b/tests/stubtest_third_party.py index 0530f6279628..0339f5b2173d 100755 --- a/tests/stubtest_third_party.py +++ b/tests/stubtest_third_party.py @@ -125,7 +125,13 @@ def run_stubtest( # It seems that some other environment variables are needed too, # because the CI fails if we pass only os.environ["DISPLAY"]. I didn't # "bisect" to see which variables are actually needed. - stubtest_env = os.environ | {"MYPYPATH": mypypath, "MYPY_FORCE_COLOR": "1"} + stubtest_env = os.environ | { + "MYPYPATH": mypypath, + "MYPY_FORCE_COLOR": "1", + # Prevent stubtest crash due to special unicode character + # https://github.com/python/mypy/issues/19071 + "PYTHONUTF8": "1", + } # Perform some black magic in order to run stubtest inside uWSGI if dist_name == "uWSGI":