From d43edd1f8c56ed06fd54df8b168a275e4013efeb Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 20 Aug 2025 13:09:55 -0400 Subject: [PATCH 1/5] merge networkx Graph classes from python-type-stubs and address a few recent issues --- .../networkx/algorithms/planarity.pyi | 9 +++++- stubs/networkx/networkx/classes/digraph.pyi | 27 ++++++++++------ stubs/networkx/networkx/classes/graph.pyi | 15 +++++---- .../networkx/classes/multidigraph.pyi | 16 +++++----- .../networkx/networkx/classes/multigraph.pyi | 31 ++++++++++++------- 5 files changed, 62 insertions(+), 36 deletions(-) diff --git a/stubs/networkx/networkx/algorithms/planarity.pyi b/stubs/networkx/networkx/algorithms/planarity.pyi index f8f0f621ff89..2eafeb6270cc 100644 --- a/stubs/networkx/networkx/algorithms/planarity.pyi +++ b/stubs/networkx/networkx/algorithms/planarity.pyi @@ -1,5 +1,6 @@ from _typeshed import Incomplete from collections.abc import Generator, Mapping, MutableSet, Reversible +from typing import NoReturn from networkx.classes.digraph import DiGraph from networkx.classes.graph import Graph, _Node @@ -67,6 +68,9 @@ class LRPlanarity: def sign(self, e): ... def sign_recursive(self, e): ... +# NOTE: Graph subclasses relationships are so complex +# we're only overriding methods that differ in signature from the base classes +# to use inheritance to our advantage and reduce complexity class PlanarEmbedding(DiGraph[_Node]): def get_data(self) -> dict[_Node, list[_Node]]: ... def set_data(self, data: Mapping[_Node, Reversible[_Node]]) -> None: ... @@ -81,4 +85,7 @@ class PlanarEmbedding(DiGraph[_Node]): def traverse_face( self, v: _Node, w: _Node, mark_half_edges: MutableSet[tuple[_Node, _Node]] | None = None ) -> list[_Node]: ... - def to_undirected(self, reciprocal: bool = False, as_view: bool = False) -> Graph[_Node]: ... # type: ignore[override] + # Overriden in __init__ + def add_edge(self, *args, **kwargs) -> NoReturn: ... + def add_edges_from(self, *args, **kwargs) -> NoReturn: ... + def add_weighted_edges_from(self, *args, **kwargs) -> NoReturn: ... diff --git a/stubs/networkx/networkx/classes/digraph.pyi b/stubs/networkx/networkx/classes/digraph.pyi index 27596d2600ef..f2b0ec3b2f52 100644 --- a/stubs/networkx/networkx/classes/digraph.pyi +++ b/stubs/networkx/networkx/classes/digraph.pyi @@ -4,12 +4,14 @@ from typing import Any from typing_extensions import Self from networkx.classes.coreviews import AdjacencyView -from networkx.classes.graph import Graph, _Node +from networkx.classes.graph import Graph, _EdgeWithData, _Node from networkx.classes.reportviews import ( DiDegreeView, InDegreeView, InEdgeView, InMultiDegreeView, + InMultiEdgeDataView, + InMultiEdgeView, OutDegreeView, OutEdgeView, OutMultiDegreeView, @@ -17,6 +19,9 @@ from networkx.classes.reportviews import ( __all__ = ["DiGraph"] +# NOTE: Graph subclasses relationships are so complex +# we're only overriding methods that differ in signature from the base classes +# to use inheritance to our advantage and reduce complexity class DiGraph(Graph[_Node]): @cached_property def succ(self) -> AdjacencyView[_Node, _Node, dict[str, Any]]: ... @@ -30,17 +35,19 @@ class DiGraph(Graph[_Node]): def predecessors(self, n: _Node) -> Iterator[_Node]: ... @cached_property - def out_edges(self) -> OutEdgeView[_Node]: ... + def edges(self) -> OutEdgeView[_Node]: ... @cached_property - def in_edges(self) -> InEdgeView[_Node]: ... + def out_edges(self) -> OutEdgeView[_Node]: ... @cached_property - def in_degree(self) -> int | InDegreeView[_Node] | InMultiDegreeView[_Node]: ... + # Including subtypes' possible return types for LSP + def in_edges(self) -> InEdgeView[_Node] | InMultiEdgeView[_Node] | InMultiEdgeDataView[_Node, _EdgeWithData[_Node]]: ... @cached_property - def out_degree(self) -> int | OutDegreeView[_Node] | OutMultiDegreeView[_Node]: ... - def to_undirected(self, reciprocal: bool = False, as_view: bool = False) -> Graph[_Node]: ... # type: ignore[override] - # reciprocal : If True, only edges that appear in both directions ... will be kept in the undirected graph. - def reverse(self, copy: bool = True) -> Self: ... + def degree(self) -> DiDegreeView[_Node]: ... @cached_property - def edges(self) -> OutEdgeView[_Node]: ... # type: ignore[override] # An OutEdgeView of the DiGraph as G.edges or G.edges(). + # Including subtypes' possible return types for LSP + def in_degree(self) -> InDegreeView[_Node] | InMultiDegreeView[_Node]: ... @cached_property - def degree(self) -> int | DiDegreeView[_Node]: ... # type: ignore[override] # Returns DiDegreeView or int + # Including subtypes' possible return types for LSP + def out_degree(self) -> OutDegreeView[_Node] | OutMultiDegreeView[_Node]: ... + def to_undirected(self, reciprocal: bool = False, as_view: bool = False) -> Graph[_Node]: ... # type: ignore[override] # Has an additional `reciprocal` keyword argument + def reverse(self, copy: bool = True) -> Self: ... diff --git a/stubs/networkx/networkx/classes/graph.pyi b/stubs/networkx/networkx/classes/graph.pyi index ffdab103eaad..cd618c653ac6 100644 --- a/stubs/networkx/networkx/classes/graph.pyi +++ b/stubs/networkx/networkx/classes/graph.pyi @@ -6,7 +6,7 @@ from typing_extensions import Self, TypeAlias import numpy from networkx.classes.coreviews import AdjacencyView, AtlasView from networkx.classes.digraph import DiGraph -from networkx.classes.reportviews import DegreeView, EdgeView, NodeView +from networkx.classes.reportviews import DegreeView, DiDegreeView, EdgeView, NodeView, OutEdgeView _Node = TypeVar("_Node", bound=Hashable) _NodeWithData: TypeAlias = tuple[_Node, dict[str, Any]] @@ -49,10 +49,10 @@ class Graph(Collection[_Node]): def name(self) -> str: ... @name.setter def name(self, s: str) -> None: ... - def __getitem__(self, n: _Node) -> AtlasView[_Node, str, Any]: ... def __iter__(self) -> Iterator[_Node]: ... def __contains__(self, n: object) -> bool: ... def __len__(self) -> int: ... + def __getitem__(self, n: _Node) -> AtlasView[_Node, str, Any]: ... def add_node(self, node_for_adding: _Node, **attr: Any) -> None: ... # attr: Set or change node attributes using key=value def add_nodes_from(self, nodes_for_adding: Iterable[_NodePlus[_Node]], **attr: Any) -> None: ... # attr: key=value pairs def remove_node(self, n: _Node) -> None: ... @@ -62,7 +62,8 @@ class Graph(Collection[_Node]): def number_of_nodes(self) -> int: ... def order(self) -> int: ... def has_node(self, n: _Node) -> bool: ... - def add_edge(self, u_of_edge: _Node, v_of_edge: _Node, **attr: Any) -> None: ... + # Including subtypes' possible return types for LSP + def add_edge(self, u_of_edge: _Node, v_of_edge: _Node, **attr: Any) -> Hashable | None: ... # attr: Edge data (or labels or objects) can be assigned using keyword arguments def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr: Any) -> None: ... # attr: Edge data (or labels or objects) can be assigned using keyword arguments @@ -81,12 +82,14 @@ class Graph(Collection[_Node]): def has_edge(self, u: _Node, v: _Node) -> bool: ... def neighbors(self, n: _Node) -> Iterator[_Node]: ... @cached_property - def edges(self) -> EdgeView[_Node]: ... + # Including subtypes' possible return types for LSP + def edges(self) -> EdgeView[_Node] | OutEdgeView[_Node]: ... def get_edge_data(self, u: _Node, v: _Node, default: Any = None) -> dict[str, Any]: ... # default: any Python object def adjacency(self) -> Iterator[tuple[_Node, dict[_Node, dict[str, Any]]]]: ... @cached_property - def degree(self) -> int | DegreeView[_Node]: ... + # Including subtypes' possible return types for LSP + def degree(self) -> DegreeView[_Node] | DiDegreeView[_Node]: ... def clear(self) -> None: ... def clear_edges(self) -> None: ... def is_multigraph(self) -> bool: ... @@ -94,7 +97,7 @@ class Graph(Collection[_Node]): def copy(self, as_view: bool = False) -> Self: ... def to_directed(self, as_view: bool = False) -> DiGraph[_Node]: ... def to_undirected(self, as_view: bool = False) -> Graph[_Node]: ... - def subgraph(self, nodes: Iterable[_Node]) -> Graph[_Node]: ... + def subgraph(self, nodes: _NBunch[_Node]) -> Graph[_Node]: ... def edge_subgraph(self, edges: Iterable[_Edge[_Node]]) -> Graph[_Node]: ... @overload def size(self, weight: None = None) -> int: ... diff --git a/stubs/networkx/networkx/classes/multidigraph.pyi b/stubs/networkx/networkx/classes/multidigraph.pyi index 374b793d842b..43fb3b0c51ea 100644 --- a/stubs/networkx/networkx/classes/multidigraph.pyi +++ b/stubs/networkx/networkx/classes/multidigraph.pyi @@ -6,6 +6,7 @@ from networkx.classes.digraph import DiGraph from networkx.classes.graph import _EdgeWithData, _Node from networkx.classes.multigraph import MultiGraph from networkx.classes.reportviews import ( + DiMultiDegreeView, InMultiDegreeView, InMultiEdgeDataView, InMultiEdgeView, @@ -15,23 +16,24 @@ from networkx.classes.reportviews import ( __all__ = ["MultiDiGraph"] +# NOTE: Graph subclasses relationships are so complex +# we're only overriding methods that differ in signature from the base classes +# to use inheritance to our advantage and reduce complexity class MultiDiGraph(MultiGraph[_Node], DiGraph[_Node]): @cached_property def succ(self) -> MultiAdjacencyView[_Node, _Node, dict[str, Any]]: ... @cached_property def pred(self) -> MultiAdjacencyView[_Node, _Node, dict[str, Any]]: ... @cached_property - def edges(self) -> OutMultiEdgeView[_Node]: ... # type: ignore[override] - # Returns: OutMultiEdgeView + def edges(self) -> OutMultiEdgeView[_Node]: ... @cached_property def out_edges(self) -> OutMultiEdgeView[_Node]: ... @cached_property - def in_edges(self) -> InMultiEdgeView[_Node] | InMultiEdgeDataView[_Node, _EdgeWithData[_Node]]: ... # type: ignore[override] - # Returns : InMultiEdgeView or InMultiEdgeDataView + def in_edges(self) -> InMultiEdgeView[_Node] | InMultiEdgeDataView[_Node, _EdgeWithData[_Node]]: ... + @cached_property + def degree(self) -> DiMultiDegreeView[_Node]: ... @cached_property def in_degree(self) -> InMultiDegreeView[_Node]: ... @cached_property def out_degree(self) -> OutMultiDegreeView[_Node]: ... - def to_undirected(self, reciprocal: bool = False, as_view: bool = False) -> MultiGraph[_Node]: ... # type: ignore[override] - def reverse(self, copy: bool = True) -> MultiDiGraph[_Node]: ... - def copy(self, as_view: bool = False) -> MultiDiGraph[_Node]: ... + def to_undirected(self, reciprocal: bool = False, as_view: bool = False) -> MultiGraph[_Node]: ... # type: ignore[override] # Has an additional `reciprocal` keyword argument diff --git a/stubs/networkx/networkx/classes/multigraph.pyi b/stubs/networkx/networkx/classes/multigraph.pyi index d0bb1ef27c82..510d58071aad 100644 --- a/stubs/networkx/networkx/classes/multigraph.pyi +++ b/stubs/networkx/networkx/classes/multigraph.pyi @@ -6,7 +6,7 @@ from typing_extensions import TypeAlias, TypeVar from networkx.classes.coreviews import MultiAdjacencyView from networkx.classes.graph import Graph, _MapFactory, _Node from networkx.classes.multidigraph import MultiDiGraph -from networkx.classes.reportviews import MultiEdgeView +from networkx.classes.reportviews import DiMultiDegreeView, MultiDegreeView, MultiEdgeView, OutMultiEdgeView _MultiEdge: TypeAlias = tuple[_Node, _Node, int] # noqa: Y047 @@ -15,36 +15,43 @@ _KeyT = TypeVar("_KeyT", bound=Hashable) __all__ = ["MultiGraph"] +# NOTE: Graph subclasses relationships are so complex +# we're only overriding methods that differ in signature from the base classes +# to use inheritance to our advantage and reduce complexity class MultiGraph(Graph[_Node]): edge_key_dict_factory: ClassVar[_MapFactory] + def to_directed_class(self) -> type[MultiDiGraph[_Node]]: ... + def to_undirected_class(self) -> type[MultiGraph[_Node]]: ... def __init__(self, incoming_graph_data=None, multigraph_input: bool | None = None, **attr: Any) -> None: ... @cached_property def adj(self) -> MultiAdjacencyView[_Node, _Node, dict[str, Any]]: ... # data can be any type def new_edge_key(self, u: _Node, v: _Node) -> int: ... - @overload # type: ignore[override] # Has an additional `key` keyword argument + # key : hashable identifier, optional (default=lowest unused integer) + @overload # type: ignore[override] # More complex overload def add_edge(self, u_for_edge: _Node, v_for_edge: _Node, key: int | None = None, **attr: Any) -> int: ... @overload def add_edge(self, u_for_edge: _Node, v_for_edge: _Node, key: _KeyT, **attr: Any) -> _KeyT: ... - # key : hashable identifier, optional (default=lowest unused integer) def remove_edge(self, u: _Node, v: _Node, key: Hashable | None = None) -> None: ... def has_edge(self, u: _Node, v: _Node, key: Hashable | None = None) -> bool: ... + @cached_property + # Including subtypes' possible return types for LSP + def edges(self) -> MultiEdgeView[_Node] | OutMultiEdgeView[_Node]: ... + # key : hashable identifier, optional (default=None). + # default : any Python object (default=None). Value to return if the specific edge (u, v, key) is not found. + # Returns: The edge attribute dictionary. @overload # type: ignore[override] def get_edge_data( self, u: _Node, v: _Node, key: Hashable, default: _DefaultT | None = None ) -> dict[str, Any] | _DefaultT: ... - # key : hashable identifier, optional (default=None). - # default : any Python object (default=None). Value to return if the specific edge (u, v, key) is not found. - # Returns: The edge attribute dictionary. + # default : any Python object (default=None). Value to return if there are no edges between u and v and no key is specified. + # Returns: A dictionary mapping edge keys to attribute dictionaries for each of those edges if no specific key is provided. @overload def get_edge_data( self, u: _Node, v: _Node, key: None = None, default: _DefaultT | None = None ) -> dict[Hashable, dict[str, Any] | _DefaultT]: ... - # default : any Python object (default=None). Value to return if there are no edges between u and v and no key is specified. - # Returns: A dictionary mapping edge keys to attribute dictionaries for each of those edges if no specific key is provided. def copy(self, as_view: bool = False) -> MultiGraph[_Node]: ... + @cached_property + # Including subtypes' possible return types for LSP + def degree(self) -> MultiDegreeView[_Node] | DiMultiDegreeView[_Node]: ... def to_directed(self, as_view: bool = False) -> MultiDiGraph[_Node]: ... def to_undirected(self, as_view: bool = False) -> MultiGraph[_Node]: ... - def number_of_edges(self, u: _Node | None = None, v: _Node | None = None) -> int: ... - @cached_property - def edges(self) -> MultiEdgeView[_Node]: ... # type: ignore[override] - # Returns: MultiEdgeView From cb4b1033dcce6dfc0d73b50d33136d7033b8b3e2 Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 20 Aug 2025 14:08:53 -0400 Subject: [PATCH 2/5] in_edges and stubtest --- stubs/networkx/networkx/algorithms/planarity.pyi | 16 +++++++++------- stubs/networkx/networkx/classes/digraph.pyi | 5 ++--- stubs/networkx/networkx/classes/multidigraph.pyi | 5 ++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/stubs/networkx/networkx/algorithms/planarity.pyi b/stubs/networkx/networkx/algorithms/planarity.pyi index 2eafeb6270cc..42b62d17ac21 100644 --- a/stubs/networkx/networkx/algorithms/planarity.pyi +++ b/stubs/networkx/networkx/algorithms/planarity.pyi @@ -1,9 +1,9 @@ -from _typeshed import Incomplete -from collections.abc import Generator, Mapping, MutableSet, Reversible +from _typeshed import Incomplete, Unused +from collections.abc import Generator, Iterable, Mapping, MutableSet, Reversible from typing import NoReturn from networkx.classes.digraph import DiGraph -from networkx.classes.graph import Graph, _Node +from networkx.classes.graph import Graph, _EdgePlus, _Node from networkx.utils.backends import _dispatchable __all__ = ["check_planarity", "is_planar", "PlanarEmbedding"] @@ -85,7 +85,9 @@ class PlanarEmbedding(DiGraph[_Node]): def traverse_face( self, v: _Node, w: _Node, mark_half_edges: MutableSet[tuple[_Node, _Node]] | None = None ) -> list[_Node]: ... - # Overriden in __init__ - def add_edge(self, *args, **kwargs) -> NoReturn: ... - def add_edges_from(self, *args, **kwargs) -> NoReturn: ... - def add_weighted_edges_from(self, *args, **kwargs) -> NoReturn: ... + # Overriden in __init__ to always raise + def add_edge(self, u_of_edge: _Node, v_of_edge: _Node, **attr: Unused) -> NoReturn: ... + def add_edges_from(self, ebunch_to_add: Iterable[_EdgePlus[_Node]], **attr: Unused) -> NoReturn: ... + def add_weighted_edges_from( + self, ebunch_to_add: Iterable[tuple[_Node, _Node, float]], weight: str = "weight", **attr: Unused + ) -> NoReturn: ... diff --git a/stubs/networkx/networkx/classes/digraph.pyi b/stubs/networkx/networkx/classes/digraph.pyi index f2b0ec3b2f52..281ee1415740 100644 --- a/stubs/networkx/networkx/classes/digraph.pyi +++ b/stubs/networkx/networkx/classes/digraph.pyi @@ -4,13 +4,12 @@ from typing import Any from typing_extensions import Self from networkx.classes.coreviews import AdjacencyView -from networkx.classes.graph import Graph, _EdgeWithData, _Node +from networkx.classes.graph import Graph, _Node from networkx.classes.reportviews import ( DiDegreeView, InDegreeView, InEdgeView, InMultiDegreeView, - InMultiEdgeDataView, InMultiEdgeView, OutDegreeView, OutEdgeView, @@ -40,7 +39,7 @@ class DiGraph(Graph[_Node]): def out_edges(self) -> OutEdgeView[_Node]: ... @cached_property # Including subtypes' possible return types for LSP - def in_edges(self) -> InEdgeView[_Node] | InMultiEdgeView[_Node] | InMultiEdgeDataView[_Node, _EdgeWithData[_Node]]: ... + def in_edges(self) -> InEdgeView[_Node] | InMultiEdgeView[_Node]: ... @cached_property def degree(self) -> DiDegreeView[_Node]: ... @cached_property diff --git a/stubs/networkx/networkx/classes/multidigraph.pyi b/stubs/networkx/networkx/classes/multidigraph.pyi index 43fb3b0c51ea..190d5c645c54 100644 --- a/stubs/networkx/networkx/classes/multidigraph.pyi +++ b/stubs/networkx/networkx/classes/multidigraph.pyi @@ -3,12 +3,11 @@ from typing import Any from networkx.classes.coreviews import MultiAdjacencyView from networkx.classes.digraph import DiGraph -from networkx.classes.graph import _EdgeWithData, _Node +from networkx.classes.graph import _Node from networkx.classes.multigraph import MultiGraph from networkx.classes.reportviews import ( DiMultiDegreeView, InMultiDegreeView, - InMultiEdgeDataView, InMultiEdgeView, OutMultiDegreeView, OutMultiEdgeView, @@ -29,7 +28,7 @@ class MultiDiGraph(MultiGraph[_Node], DiGraph[_Node]): @cached_property def out_edges(self) -> OutMultiEdgeView[_Node]: ... @cached_property - def in_edges(self) -> InMultiEdgeView[_Node] | InMultiEdgeDataView[_Node, _EdgeWithData[_Node]]: ... + def in_edges(self) -> InMultiEdgeView[_Node]: ... @cached_property def degree(self) -> DiMultiDegreeView[_Node]: ... @cached_property From 9369176d8708463654dc3ef1b1c607174694cf54 Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 20 Aug 2025 14:31:52 -0400 Subject: [PATCH 3/5] Adjust NodeView and DiDegreeView overloads --- stubs/networkx/networkx/classes/reportviews.pyi | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/stubs/networkx/networkx/classes/reportviews.pyi b/stubs/networkx/networkx/classes/reportviews.pyi index 0f5b8655b190..4bab70d071ed 100644 --- a/stubs/networkx/networkx/classes/reportviews.pyi +++ b/stubs/networkx/networkx/classes/reportviews.pyi @@ -43,8 +43,11 @@ class NodeView(Mapping[_Node, dict[str, Any]], AbstractSet[_Node]): @overload def __call__(self, data: Literal[False] = False, default=None) -> Self: ... @overload - def __call__(self, data: Literal[True] | str, default=None) -> Self: ... - def data(self, data: bool | str = True, default=None) -> Self: ... + def __call__(self, data: Literal[True] | str, default=None) -> NodeDataView[_Node]: ... + @overload + def data(self, data: Literal[False], default=None) -> Self: ... + @overload + def data(self, data: Literal[True] | str = True, default=None) -> NodeDataView[_Node]: ... class NodeDataView(AbstractSet[_Node]): def __init__(self, nodedict: Mapping[str, Incomplete], data: bool | str = False, default=None) -> None: ... @@ -56,9 +59,9 @@ class NodeDataView(AbstractSet[_Node]): class DiDegreeView(Generic[_Node]): def __init__(self, G: Graph[_Node], nbunch: _NBunch[_Node] = None, weight: None | bool | str = None) -> None: ... @overload - def __call__(self, nbunch: None = None, weight: None | bool | str = None) -> int: ... # type: ignore[overload-overlap] + def __call__(self, nbunch: None = None, weight: None | bool | str = None) -> Self: ... @overload - def __call__(self, nbunch: None | Iterable[_Node], weight: None | bool | str = None) -> Self: ... + def __call__(self, nbunch: Iterable[_Node], weight: None | bool | str = None) -> int: ... def __getitem__(self, n: _Node) -> float: ... def __iter__(self) -> Iterator[tuple[_Node, float]]: ... def __len__(self) -> int: ... From c3e9fbcde187ab15462529b9a49afc958c30681a Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 20 Aug 2025 14:57:00 -0400 Subject: [PATCH 4/5] Better call overload on DiDegreeView --- stubs/networkx/networkx/classes/reportviews.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stubs/networkx/networkx/classes/reportviews.pyi b/stubs/networkx/networkx/classes/reportviews.pyi index 4bab70d071ed..b02e319b5088 100644 --- a/stubs/networkx/networkx/classes/reportviews.pyi +++ b/stubs/networkx/networkx/classes/reportviews.pyi @@ -58,10 +58,10 @@ class NodeDataView(AbstractSet[_Node]): class DiDegreeView(Generic[_Node]): def __init__(self, G: Graph[_Node], nbunch: _NBunch[_Node] = None, weight: None | bool | str = None) -> None: ... + @overload # Use this overload first in case _Node=str, since `str` matches `Iterable[str]` + def __call__(self, nbunch: _Node, weight: None | bool | str = None) -> float: ... # type: ignore[overload-overlap] @overload - def __call__(self, nbunch: None = None, weight: None | bool | str = None) -> Self: ... - @overload - def __call__(self, nbunch: Iterable[_Node], weight: None | bool | str = None) -> int: ... + def __call__(self, nbunch: Iterable[_Node] | None = None, weight: None | bool | str = None) -> Self: ... def __getitem__(self, n: _Node) -> float: ... def __iter__(self) -> Iterator[tuple[_Node, float]]: ... def __len__(self) -> int: ... From 2c5d1d87f7b4191f611b58300f363cfa8a0d0d8b Mon Sep 17 00:00:00 2001 From: Avasam Date: Wed, 20 Aug 2025 15:19:04 -0400 Subject: [PATCH 5/5] degrees are integer --- stubs/networkx/networkx/classes/reportviews.pyi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/stubs/networkx/networkx/classes/reportviews.pyi b/stubs/networkx/networkx/classes/reportviews.pyi index b02e319b5088..43b369d802f2 100644 --- a/stubs/networkx/networkx/classes/reportviews.pyi +++ b/stubs/networkx/networkx/classes/reportviews.pyi @@ -59,11 +59,11 @@ class NodeDataView(AbstractSet[_Node]): class DiDegreeView(Generic[_Node]): def __init__(self, G: Graph[_Node], nbunch: _NBunch[_Node] = None, weight: None | bool | str = None) -> None: ... @overload # Use this overload first in case _Node=str, since `str` matches `Iterable[str]` - def __call__(self, nbunch: _Node, weight: None | bool | str = None) -> float: ... # type: ignore[overload-overlap] + def __call__(self, nbunch: _Node, weight: None | bool | str = None) -> int: ... # type: ignore[overload-overlap] @overload def __call__(self, nbunch: Iterable[_Node] | None = None, weight: None | bool | str = None) -> Self: ... - def __getitem__(self, n: _Node) -> float: ... - def __iter__(self) -> Iterator[tuple[_Node, float]]: ... + def __getitem__(self, n: _Node) -> int: ... + def __iter__(self) -> Iterator[tuple[_Node, int]]: ... def __len__(self) -> int: ... class DegreeView(DiDegreeView[_Node]): ...