From be25f8bd665d7d1e0d7dcfce5843119fcab16f8c Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 09:29:58 -0700 Subject: [PATCH 01/71] Initial check-in of stub files --- retworkx/custom_return_types.pyi | 247 +++++++++++++++++++++++++++++++ retworkx/py.typed | 1 + retworkx/retworkx.pyi | 222 +++++++++++++++++++++++++++ retworkx/retworkx_generators.pyi | 27 ++++ setup.py | 1 + 5 files changed, 498 insertions(+) create mode 100644 retworkx/custom_return_types.pyi create mode 100644 retworkx/py.typed create mode 100644 retworkx/retworkx.pyi create mode 100644 retworkx/retworkx_generators.pyi diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi new file mode 100644 index 000000000..7c2d773c6 --- /dev/null +++ b/retworkx/custom_return_types.pyi @@ -0,0 +1,247 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + +from typing import Any, ClassVar + +class AllPairsPathLengthMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class AllPairsPathMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class BFSSuccessors: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class EdgeIndexMap: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class EdgeIndices: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class EdgeList: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class NodeIndices: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class NodeMap: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class NodesCountMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class PathLengthMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class PathMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class Pos2DMapping: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def items(self, *args, **kwargs) -> Any: ... + def keys(self, *args, **kwargs) -> Any: ... + def values(self, *args, **kwargs) -> Any: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class WeightedEdgeList: + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def __eq__(self, other) -> Any: ... + def __ge__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> Any: ... + def __hash__(self) -> Any: ... + def __le__(self, other) -> Any: ... + def __len__(self) -> Any: ... + def __lt__(self, other) -> Any: ... + def __ne__(self, other) -> Any: ... + def __setstate__(self, state) -> Any: ... diff --git a/retworkx/py.typed b/retworkx/py.typed new file mode 100644 index 000000000..b648ac923 --- /dev/null +++ b/retworkx/py.typed @@ -0,0 +1 @@ +partial diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi new file mode 100644 index 000000000..15dfabd99 --- /dev/null +++ b/retworkx/retworkx.pyi @@ -0,0 +1,222 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + +import retworkx_generators as generators +from .custom_return_types import * + +from typing import Any, ClassVar + +class DAGHasCycle(Exception): ... +class DAGWouldCycle(Exception): ... +class InvalidNode(Exception): ... +class NoEdgeBetweenNodes(Exception): ... +class NoPathFound(Exception): ... +class NoSuitableNeighbors(Exception): ... +class NullGraph(Exception): ... + +class PyDiGraph: + check_cycle: ClassVar[Any] = ... + multigraph: ClassVar[Any] = ... + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def add_child(self, *args, **kwargs) -> Any: ... + def add_edge(self, *args, **kwargs) -> Any: ... + def add_edges_from(self, *args, **kwargs) -> Any: ... + def add_edges_from_no_data(self, *args, **kwargs) -> Any: ... + def add_node(self, *args, **kwargs) -> Any: ... + def add_nodes_from(self, *args, **kwargs) -> Any: ... + def add_parent(self, *args, **kwargs) -> Any: ... + def adj(self, *args, **kwargs) -> Any: ... + def adj_direction(self, *args, **kwargs) -> Any: ... + def compose(other_graph, node_map) -> Any: ... + def copy(self, *args, **kwargs) -> Any: ... + def edge_index_map(self, *args, **kwargs) -> Any: ... + def edge_indices(self, *args, **kwargs) -> Any: ... + def edge_list(self, *args, **kwargs) -> Any: ... + def edges(self, *args, **kwargs) -> Any: ... + def extend_from_edge_list(self, *args, **kwargs) -> Any: ... + def extend_from_weighted_edge_list(self, *args, **kwargs) -> Any: ... + def find_adjacent_node_by_edge(self, *args, **kwargs) -> Any: ... + def find_node_by_weight(self, *args, **kwargs) -> Any: ... + def find_predecessors_by_edge(self, *args, **kwargs) -> Any: ... + def find_successors_by_edge(self, *args, **kwargs) -> Any: ... + def from_adjacency_matrix(self, *args, **kwargs) -> Any: ... + def get_all_edge_data(self, *args, **kwargs) -> Any: ... + def get_edge_data(self, *args, **kwargs) -> Any: ... + def get_node_data(self, *args, **kwargs) -> Any: ... + def has_edge(self, *args, **kwargs) -> Any: ... + def in_degree(self, *args, **kwargs) -> Any: ... + def in_edges(self, *args, **kwargs) -> Any: ... + def insert_node_on_in_edges(self, *args, **kwargs) -> Any: ... + def insert_node_on_in_edges_multiple(self, *args, **kwargs) -> Any: ... + def insert_node_on_out_edges(self, *args, **kwargs) -> Any: ... + def insert_node_on_out_edges_multiple(self, *args, **kwargs) -> Any: ... + def is_symmetric(self, *args, **kwargs) -> Any: ... + def merge_nodes(self, *args, **kwargs) -> Any: ... + def neighbors(self, *args, **kwargs) -> Any: ... + def node_indexes(self, *args, **kwargs) -> Any: ... + def nodes(self, *args, **kwargs) -> Any: ... + def num_edges(self, *args, **kwargs) -> Any: ... + def num_nodes(self, *args, **kwargs) -> Any: ... + def out_degree(self, *args, **kwargs) -> Any: ... + def out_edges(self, *args, **kwargs) -> Any: ... + def predecessor_indices(self, *args, **kwargs) -> Any: ... + def predecessors(self, *args, **kwargs) -> Any: ... + def read_edge_list(self, *args, **kwargs) -> Any: ... + def remove_edge(self, *args, **kwargs) -> Any: ... + def remove_edge_from_index(self, *args, **kwargs) -> Any: ... + def remove_edges_from(self, *args, **kwargs) -> Any: ... + def remove_node(self, *args, **kwargs) -> Any: ... + def remove_node_retain_edges(self, *args, **kwargs) -> Any: ... + def remove_nodes_from(self, *args, **kwargs) -> Any: ... + def subgraph(self, *args, **kwargs) -> Any: ... + def substitute_node_with_subgraph(self, *args, **kwargs) -> Any: ... + def successor_indices(self, *args, **kwargs) -> Any: ... + def successors(self, *args, **kwargs) -> Any: ... + def to_dot(lambdanode) -> Any: ... + def to_undirected(self, *args, **kwargs) -> Any: ... + def update_edge(self, *args, **kwargs) -> Any: ... + def update_edge_by_index(self, *args, **kwargs) -> Any: ... + def weighted_edge_list(self, *args, **kwargs) -> Any: ... + def write_edge_list(self, *args, **kwargs) -> Any: ... + def __delitem__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __len__(self) -> Any: ... + def __setitem__(self, index, object) -> Any: ... + def __setstate__(self, state) -> Any: ... + +class PyGraph: + multigraph: ClassVar[Any] = ... + @classmethod + def __init__(self, *args, **kwargs) -> None: ... + def add_edge(self, *args, **kwargs) -> Any: ... + def add_edges_from(self, *args, **kwargs) -> Any: ... + def add_edges_from_no_data(self, *args, **kwargs) -> Any: ... + def add_node(self, *args, **kwargs) -> Any: ... + def add_nodes_from(self, *args, **kwargs) -> Any: ... + def adj(self, *args, **kwargs) -> Any: ... + def compose(other_graph, node_map) -> Any: ... + def copy(self, *args, **kwargs) -> Any: ... + def degree(self, *args, **kwargs) -> Any: ... + def edge_index_map(self, *args, **kwargs) -> Any: ... + def edge_indices(self, *args, **kwargs) -> Any: ... + def edge_list(self, *args, **kwargs) -> Any: ... + def edges(self, *args, **kwargs) -> Any: ... + def extend_from_edge_list(self, *args, **kwargs) -> Any: ... + def extend_from_weighted_edge_list(self, *args, **kwargs) -> Any: ... + def from_adjacency_matrix(self, *args, **kwargs) -> Any: ... + def get_all_edge_data(self, *args, **kwargs) -> Any: ... + def get_edge_data(self, *args, **kwargs) -> Any: ... + def get_node_data(self, *args, **kwargs) -> Any: ... + def has_edge(self, *args, **kwargs) -> Any: ... + def neighbors(self, *args, **kwargs) -> Any: ... + def node_indexes(self, *args, **kwargs) -> Any: ... + def nodes(self, *args, **kwargs) -> Any: ... + def num_edges(self, *args, **kwargs) -> Any: ... + def num_nodes(self, *args, **kwargs) -> Any: ... + def read_edge_list(self, *args, **kwargs) -> Any: ... + def remove_edge(self, *args, **kwargs) -> Any: ... + def remove_edge_from_index(self, *args, **kwargs) -> Any: ... + def remove_edges_from(self, *args, **kwargs) -> Any: ... + def remove_node(self, *args, **kwargs) -> Any: ... + def remove_nodes_from(self, *args, **kwargs) -> Any: ... + def subgraph(self, *args, **kwargs) -> Any: ... + def to_dot(lambdanode) -> Any: ... + def update_edge(self, *args, **kwargs) -> Any: ... + def update_edge_by_index(self, *args, **kwargs) -> Any: ... + def weighted_edge_list(self, *args, **kwargs) -> Any: ... + def write_edge_list(self, *args, **kwargs) -> Any: ... + def __delitem__(self, other) -> Any: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __len__(self) -> Any: ... + def __setitem__(self, index, object) -> Any: ... + def __setstate__(self, state) -> Any: ... + +def ancestors(*args, **kwargs) -> Any: ... +def bfs_successors(*args, **kwargs) -> Any: ... +def collect_runs(*args, **kwargs) -> Any: ... +def cycle_basis(*args, **kwargs) -> Any: ... +def dag_longest_path(*args, **kwargs) -> Any: ... +def dag_longest_path_length(*args, **kwargs) -> Any: ... +def dag_weighted_longest_path(*args, **kwargs) -> Any: ... +def dag_weighted_longest_path_length(*args, **kwargs) -> Any: ... +def descendants(*args, **kwargs) -> Any: ... +def digraph_adjacency_matrix(*args, **kwargs) -> Any: ... +def digraph_all_pairs_dijkstra_path_lengths(*args, **kwargs) -> Any: ... +def digraph_all_pairs_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... +def digraph_all_simple_paths(*args, **kwargs) -> Any: ... +def digraph_astar_shortest_path(*args, **kwargs) -> Any: ... +def digraph_bipartite_layout(*args, **kwargs) -> Any: ... +def digraph_circular_layout(*args, **kwargs) -> Any: ... +def digraph_complement(*args, **kwargs) -> Any: ... +def digraph_core_number(*args, **kwargs) -> Any: ... +def digraph_dfs_edges(*args, **kwargs) -> Any: ... +def digraph_dijkstra_shortest_path_lengths(*args, **kwargs) -> Any: ... +def digraph_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... +def digraph_distance_matrix(*args, **kwargs) -> Any: ... +def digraph_find_cycle(*args, **kwargs) -> Any: ... +def digraph_floyd_warshall(graph, weight_fn=...) -> Any: ... +def digraph_floyd_warshall_numpy(*args, **kwargs) -> Any: ... +def digraph_is_isomorphic(*args, **kwargs) -> Any: ... +def digraph_is_subgraph_isomorphic(*args, **kwargs) -> Any: ... +def digraph_k_shortest_path_lengths(*args, **kwargs) -> Any: ... +def digraph_num_shortest_paths_unweighted(*args, **kwargs) -> Any: ... +def digraph_random_layout(*args, **kwargs) -> Any: ... +def digraph_shell_layout(*args, **kwargs) -> Any: ... +def digraph_spiral_layout(*args, **kwargs) -> Any: ... +def digraph_spring_layout(*args, **kwargs) -> Any: ... +def digraph_transitivity(*args, **kwargs) -> Any: ... +def digraph_union(*args, **kwargs) -> Any: ... +def directed_gnm_random_graph(*args, **kwargs) -> Any: ... +def directed_gnp_random_graph(*args, **kwargs) -> Any: ... +def graph_adjacency_matrix(graph, weight_fn) -> Any: ... +def graph_all_pairs_dijkstra_path_lengths(*args, **kwargs) -> Any: ... +def graph_all_pairs_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... +def graph_all_simple_paths(*args, **kwargs) -> Any: ... +def graph_astar_shortest_path(*args, **kwargs) -> Any: ... +def graph_bipartite_layout(*args, **kwargs) -> Any: ... +def graph_circular_layout(*args, **kwargs) -> Any: ... +def graph_complement(*args, **kwargs) -> Any: ... +def graph_core_number(*args, **kwargs) -> Any: ... +def graph_dfs_edges(*args, **kwargs) -> Any: ... +def graph_dijkstra_shortest_path_lengths(*args, **kwargs) -> Any: ... +def graph_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... +def graph_distance_matrix(*args, **kwargs) -> Any: ... +def graph_floyd_warshall(graph, weight_fn=...) -> Any: ... +def graph_floyd_warshall_numpy(graph, weight_fn) -> Any: ... +def graph_greedy_color(*args, **kwargs) -> Any: ... +def graph_is_isomorphic(*args, **kwargs) -> Any: ... +def graph_is_subgraph_isomorphic(*args, **kwargs) -> Any: ... +def graph_k_shortest_path_lengths(*args, **kwargs) -> Any: ... +def graph_num_shortest_paths_unweighted(*args, **kwargs) -> Any: ... +def graph_random_layout(*args, **kwargs) -> Any: ... +def graph_shell_layout(*args, **kwargs) -> Any: ... +def graph_spiral_layout(*args, **kwargs) -> Any: ... +def graph_spring_layout(*args, **kwargs) -> Any: ... +def graph_transitivity(*args, **kwargs) -> Any: ... +def is_directed_acyclic_graph(*args, **kwargs) -> Any: ... +def is_matching(*args, **kwargs) -> Any: ... +def is_maximal_matching(*args, **kwargs) -> Any: ... +def is_weakly_connected(*args, **kwargs) -> Any: ... +def layers(*args, **kwargs) -> Any: ... +def lexicographical_topological_sort(*args, **kwargs) -> Any: ... +def max_weight_matching(*args, **kwargs) -> Any: ... +def minimum_spanning_edges(graph, weight_fn) -> Any: ... +def minimum_spanning_tree(graph, weight_fn) -> Any: ... +def number_weakly_connected_components(*args, **kwargs) -> Any: ... +def random_geometric_graph(*args, **kwargs) -> Any: ... +def strongly_connected_components(*args, **kwargs) -> Any: ... +def topological_sort(*args, **kwargs) -> Any: ... +def undirected_gnm_random_graph(*args, **kwargs) -> Any: ... +def undirected_gnp_random_graph(*args, **kwargs) -> Any: ... +def weakly_connected_components(*args, **kwargs) -> Any: ... diff --git a/retworkx/retworkx_generators.pyi b/retworkx/retworkx_generators.pyi new file mode 100644 index 000000000..6eed47854 --- /dev/null +++ b/retworkx/retworkx_generators.pyi @@ -0,0 +1,27 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + +from typing import Any + +def binomial_tree_graph(*args, **kwargs) -> Any: ... +def cycle_graph(*args, **kwargs) -> Any: ... +def directed_binomial_tree_graph(*args, **kwargs) -> Any: ... +def directed_cycle_graph(*args, **kwargs) -> Any: ... +def directed_grid_graph(*args, **kwargs) -> Any: ... +def directed_hexagonal_lattice_graph(*args, **kwargs) -> Any: ... +def directed_mesh_graph(*args, **kwargs) -> Any: ... +def directed_path_graph(*args, **kwargs) -> Any: ... +def directed_star_graph(*args, **kwargs) -> Any: ... +def grid_graph(*args, **kwargs) -> Any: ... +def hexagonal_lattice_graph(*args, **kwargs) -> Any: ... +def mesh_graph(*args, **kwargs) -> Any: ... +def path_graph(*args, **kwargs) -> Any: ... +def star_graph(*args, **kwargs) -> Any: ... diff --git a/setup.py b/setup.py index b26ecc000..8993befd1 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,7 @@ def readme(): binding=Binding.PyO3)], include_package_data=True, packages=["retworkx", "retworkx.visualization"], + package_data={"retworkx": ["py.typed", "*.pyi"]}, zip_safe=False, python_requires=">=3.6", install_requires=['numpy>=1.16.0'], From 1292561f61b5cc876f8929d4af2366a46591d643 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 12:44:23 -0700 Subject: [PATCH 02/71] Add types to PyDiGraph --- retworkx/retworkx.pyi | 233 +++++++++++++++++++++++++++++------------- 1 file changed, 162 insertions(+), 71 deletions(-) diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 15dfabd99..8ce8d2564 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -9,10 +9,25 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs +import numpy as np import retworkx_generators as generators from .custom_return_types import * -from typing import Any, ClassVar +from typing import ( + Any, + Callable, + ClassVar, + Dict, + Generic, + TypeVar, + Optional, + List, + Tuple, + Union, +) + +S = TypeVar("S") +T = TypeVar("T") class DAGHasCycle(Exception): ... class DAGWouldCycle(Exception): ... @@ -22,80 +37,156 @@ class NoPathFound(Exception): ... class NoSuitableNeighbors(Exception): ... class NullGraph(Exception): ... -class PyDiGraph: - check_cycle: ClassVar[Any] = ... - multigraph: ClassVar[Any] = ... +class PyDiGraph(Generic[S, T]): + check_cycle: bool = ... + multigraph: bool = ... + def __init__( + self, + check_cycle: bool = False, + multigraph: bool = True, + /, + ) -> None: ... + def add_child(self, parent: int, obj: S, edge: T, /) -> int: ... + def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... + def add_edges_from( + self, + obj_list: List[Union[Tuple[int, int, T], List[Union[int, T]]]], + /, + ) -> List[int]: ... + def add_edges_from_no_data( + self, obj_list: Union[List[Tuple[int, int]], List[List[int]]], / + ) -> List[int]: ... + def add_node(self, obj: S, /) -> int: ... + def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... + def adj(self, node: int, /) -> Dict[int, T]: ... + def adj_direction(self, node: int, direction: bool, /) -> Dict[int, T]: ... + def compose( + self, + other: PyDiGraph[S, T], + node_map: Dict[int, Tuple[int, T]], + /, + node_map_func: Optional[Callable[[S], int]] = None, + edge_map_func: Optional[Callable[[T], int]] = None, + ) -> Dict[int, int]: ... + def copy(self) -> PyDiGraph[S, T]: ... + def edge_index_map(self) -> EdgeIndexMap: ... + def edge_indices(self) -> EdgeIndices: ... + def edge_list(self) -> EdgeList: ... + def edges(self) -> List[T]: ... + def extend_from_edge_list( + self, edge_list: Union[List[Tuple[int, int]], List[List[int]]], / + ) -> None: ... + def extend_from_weighted_edge_list( + self, + edge_list: List[Union[Tuple[int, int, T], List[Union[int, T]]]], + /, + ) -> None: ... + def find_adjacent_node_by_edge( + self, node: int, predicate: Callable[[T], bool], / + ) -> S: ... + def find_node_by_weight( + self, obj: Callable[[S], bool] + ) -> Optional[int]: ... + def find_predecessors_by_edge( + self, node: int, filter_fn: Callable[[T], bool], / + ) -> List[S]: ... + def find_successors_by_edge( + self, node: int, filter_fn: Callable[[T], bool], / + ) -> List[S]: ... @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def add_child(self, *args, **kwargs) -> Any: ... - def add_edge(self, *args, **kwargs) -> Any: ... - def add_edges_from(self, *args, **kwargs) -> Any: ... - def add_edges_from_no_data(self, *args, **kwargs) -> Any: ... - def add_node(self, *args, **kwargs) -> Any: ... - def add_nodes_from(self, *args, **kwargs) -> Any: ... - def add_parent(self, *args, **kwargs) -> Any: ... - def adj(self, *args, **kwargs) -> Any: ... - def adj_direction(self, *args, **kwargs) -> Any: ... - def compose(other_graph, node_map) -> Any: ... - def copy(self, *args, **kwargs) -> Any: ... - def edge_index_map(self, *args, **kwargs) -> Any: ... - def edge_indices(self, *args, **kwargs) -> Any: ... - def edge_list(self, *args, **kwargs) -> Any: ... - def edges(self, *args, **kwargs) -> Any: ... - def extend_from_edge_list(self, *args, **kwargs) -> Any: ... - def extend_from_weighted_edge_list(self, *args, **kwargs) -> Any: ... - def find_adjacent_node_by_edge(self, *args, **kwargs) -> Any: ... - def find_node_by_weight(self, *args, **kwargs) -> Any: ... - def find_predecessors_by_edge(self, *args, **kwargs) -> Any: ... - def find_successors_by_edge(self, *args, **kwargs) -> Any: ... - def from_adjacency_matrix(self, *args, **kwargs) -> Any: ... - def get_all_edge_data(self, *args, **kwargs) -> Any: ... - def get_edge_data(self, *args, **kwargs) -> Any: ... - def get_node_data(self, *args, **kwargs) -> Any: ... - def has_edge(self, *args, **kwargs) -> Any: ... - def in_degree(self, *args, **kwargs) -> Any: ... - def in_edges(self, *args, **kwargs) -> Any: ... - def insert_node_on_in_edges(self, *args, **kwargs) -> Any: ... - def insert_node_on_in_edges_multiple(self, *args, **kwargs) -> Any: ... - def insert_node_on_out_edges(self, *args, **kwargs) -> Any: ... - def insert_node_on_out_edges_multiple(self, *args, **kwargs) -> Any: ... - def is_symmetric(self, *args, **kwargs) -> Any: ... - def merge_nodes(self, *args, **kwargs) -> Any: ... - def neighbors(self, *args, **kwargs) -> Any: ... - def node_indexes(self, *args, **kwargs) -> Any: ... - def nodes(self, *args, **kwargs) -> Any: ... - def num_edges(self, *args, **kwargs) -> Any: ... - def num_nodes(self, *args, **kwargs) -> Any: ... - def out_degree(self, *args, **kwargs) -> Any: ... - def out_edges(self, *args, **kwargs) -> Any: ... - def predecessor_indices(self, *args, **kwargs) -> Any: ... - def predecessors(self, *args, **kwargs) -> Any: ... - def read_edge_list(self, *args, **kwargs) -> Any: ... - def remove_edge(self, *args, **kwargs) -> Any: ... - def remove_edge_from_index(self, *args, **kwargs) -> Any: ... - def remove_edges_from(self, *args, **kwargs) -> Any: ... - def remove_node(self, *args, **kwargs) -> Any: ... - def remove_node_retain_edges(self, *args, **kwargs) -> Any: ... - def remove_nodes_from(self, *args, **kwargs) -> Any: ... - def subgraph(self, *args, **kwargs) -> Any: ... - def substitute_node_with_subgraph(self, *args, **kwargs) -> Any: ... - def successor_indices(self, *args, **kwargs) -> Any: ... - def successors(self, *args, **kwargs) -> Any: ... - def to_dot(lambdanode) -> Any: ... - def to_undirected(self, *args, **kwargs) -> Any: ... - def update_edge(self, *args, **kwargs) -> Any: ... - def update_edge_by_index(self, *args, **kwargs) -> Any: ... + def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_node_data(self, node: int, /) -> S: ... + def has_edge(self, node_a: int, node_b: int, /) -> bool: ... + def in_degree(self, node: int, /) -> int: ... + def in_edges(self, node: int, /) -> WeightedEdgeList: ... + def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... + def insert_node_on_in_edges_multiple( + self, node: int, ref_nodes: List[int], / + ) -> None: ... + def insert_node_on_out_edges(self, node: int, ref_node: int, /) -> None: ... + def insert_node_on_out_edges_multiple( + self, node: int, ref_nodes: List[int], / + ) -> None: ... + def is_symmetric(self) -> bool: ... + def merge_nodes(self, u: int, v: int, /) -> None: ... + def neighbors(self, node: int, /) -> NodeIndices: ... + def node_indexes(self) -> NodeIndices: ... + def nodes(self) -> List[S]: ... + def num_edges(self) -> int: ... + def num_nodes(self) -> int: ... + def out_degree(self, node: int, /) -> int: ... + def out_edges(self, node: int, /) -> WeightedEdgeList: ... + def predecessor_indices(self, node: int, /) -> NodeIndices: ... + def predecessors(self, node: int, /) -> List[S]: ... + @classmethod + def read_edge_list( + path: str, + /, + comment: Optional[str] = None, + deliminator: Optional[str] = None, + ) -> PyDiGraph: ... + def remove_edge(self, parent: int, child: int, /) -> None: ... + def remove_edge_from_index(self, edge: int, /) -> None: ... + def remove_edges_from( + self, index_list: List[Union[Tuple[int, int], List[int]]], / + ) -> None: ... + def remove_node(self, node: int, /) -> None: ... + def remove_node_retain_edges( + self, + node: int, + /, + use_outgoing: Optional[bool] = None, + condition: Optional[Callable[[S, S], bool]] = None, + ) -> None: ... + def remove_nodes_from(self, index_list: List[int], /) -> None: ... + def subgraph(self, nodes: List[int], /) -> PyDiGraph[S, T]: ... + def substitute_node_with_subgraph( + self, + node: int, + other: PyDiGraph[S, T], + edge_map_fn: Callable[[int, int, T], Optional[int]], + /, + node_filter: Optional[Callable[[S], bool]] = None, + edge_weight_map: Optional[Callable[T], T] = None, + ) -> NodeMap: ... + def successor_indices(self, node: int, /) -> NodeIndices: ... + def successors(self, node: int, /) -> List[S]: ... + def to_dot( + self, + /, + node_attr: Optional[Callable[[S], Dict[str, str]]] = None, + edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, + graph_attr: Optional[Dict[str, str]] = None, + filename: Optional[str] = None, + ) -> Any: ... + def to_undirected( + self, + /, + multigraph: bool = True, + weight_combo_fn: Optional[Callable[[T, T], T]] = None, + ) -> PyGraph[S, T]: ... + def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... def weighted_edge_list(self, *args, **kwargs) -> Any: ... - def write_edge_list(self, *args, **kwargs) -> Any: ... - def __delitem__(self, other) -> Any: ... - def __getitem__(self, index) -> Any: ... + def write_edge_list( + self, + path: str, + /, + deliminator: Optional[str] = None, + weight_fn: Optional[Callable[[T]], str] = None, + ) -> None: ... + def __delitem__(self, idx: int, /) -> None: ... + def __getitem__(self, idx: int, /) -> S: ... def __getstate__(self) -> Any: ... - def __len__(self) -> Any: ... - def __setitem__(self, index, object) -> Any: ... - def __setstate__(self, state) -> Any: ... + def __len__(self) -> int: ... + def __setitem__(self, idx: int, value: S, /) -> None: ... + def __setstate__(self, state, /) -> None: ... -class PyGraph: - multigraph: ClassVar[Any] = ... +class PyGraph(Generic[S, T]): + multigraph: bool = ... @classmethod def __init__(self, *args, **kwargs) -> None: ... def add_edge(self, *args, **kwargs) -> Any: ... From cd98bda50294ec7a66edeabeb2ca145796683a03 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 12:57:37 -0700 Subject: [PATCH 03/71] Remove Union types --- retworkx/retworkx.pyi | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 8ce8d2564..3cc3a8450 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -50,11 +50,11 @@ class PyDiGraph(Generic[S, T]): def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... def add_edges_from( self, - obj_list: List[Union[Tuple[int, int, T], List[Union[int, T]]]], + obj_list: List[Tuple[int, int, T]], /, ) -> List[int]: ... def add_edges_from_no_data( - self, obj_list: Union[List[Tuple[int, int]], List[List[int]]], / + self, obj_list: List[Tuple[int, int]], / ) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... @@ -75,11 +75,11 @@ class PyDiGraph(Generic[S, T]): def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... def extend_from_edge_list( - self, edge_list: Union[List[Tuple[int, int]], List[List[int]]], / + self, edge_list: List[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( self, - edge_list: List[Union[Tuple[int, int, T], List[Union[int, T]]]], + edge_list: List[Tuple[int, int, T]], /, ) -> None: ... def find_adjacent_node_by_edge( @@ -131,7 +131,7 @@ class PyDiGraph(Generic[S, T]): def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... def remove_edges_from( - self, index_list: List[Union[Tuple[int, int], List[int]]], / + self, index_list: List[Tuple[int, int]], / ) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_node_retain_edges( @@ -189,8 +189,10 @@ class PyGraph(Generic[S, T]): multigraph: bool = ... @classmethod def __init__(self, *args, **kwargs) -> None: ... - def add_edge(self, *args, **kwargs) -> Any: ... - def add_edges_from(self, *args, **kwargs) -> Any: ... + def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... + def add_edges_from( + self, obj_list: List[Tuple[int, int, T]] + ) -> List[int]: ... def add_edges_from_no_data(self, *args, **kwargs) -> Any: ... def add_node(self, *args, **kwargs) -> Any: ... def add_nodes_from(self, *args, **kwargs) -> Any: ... @@ -226,12 +228,12 @@ class PyGraph(Generic[S, T]): def update_edge_by_index(self, *args, **kwargs) -> Any: ... def weighted_edge_list(self, *args, **kwargs) -> Any: ... def write_edge_list(self, *args, **kwargs) -> Any: ... - def __delitem__(self, other) -> Any: ... - def __getitem__(self, index) -> Any: ... + def __delitem__(self, idx: int, /) -> None: ... + def __getitem__(self, idx: int, /) -> S: ... def __getstate__(self) -> Any: ... - def __len__(self) -> Any: ... - def __setitem__(self, index, object) -> Any: ... - def __setstate__(self, state) -> Any: ... + def __len__(self) -> int: ... + def __setitem__(self, idx: int, value: S, /) -> None: ... + def __setstate__(self, state, /) -> None: ... def ancestors(*args, **kwargs) -> Any: ... def bfs_successors(*args, **kwargs) -> Any: ... From 7cc697d69b90ad8587d4228f19c27d1743b48e7d Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 13:14:57 -0700 Subject: [PATCH 04/71] Start adding types to PyGraph --- retworkx/retworkx.pyi | 59 ++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 3cc3a8450..1f95ed9cd 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -193,19 +193,34 @@ class PyGraph(Generic[S, T]): def add_edges_from( self, obj_list: List[Tuple[int, int, T]] ) -> List[int]: ... - def add_edges_from_no_data(self, *args, **kwargs) -> Any: ... - def add_node(self, *args, **kwargs) -> Any: ... - def add_nodes_from(self, *args, **kwargs) -> Any: ... - def adj(self, *args, **kwargs) -> Any: ... - def compose(other_graph, node_map) -> Any: ... - def copy(self, *args, **kwargs) -> Any: ... - def degree(self, *args, **kwargs) -> Any: ... - def edge_index_map(self, *args, **kwargs) -> Any: ... - def edge_indices(self, *args, **kwargs) -> Any: ... - def edge_list(self, *args, **kwargs) -> Any: ... - def edges(self, *args, **kwargs) -> Any: ... - def extend_from_edge_list(self, *args, **kwargs) -> Any: ... - def extend_from_weighted_edge_list(self, *args, **kwargs) -> Any: ... + def add_edges_from_no_data( + self, obj_list: List[Tuple[int, int]], / + ) -> List[int]: ... + def add_node(self, obj: S, /) -> int: ... + def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def adj(self, node: int, /) -> Dict[int, T]: ... + def compose( + self, + other: PyGraph[S, T], + node_map: Dict[int, Tuple[int, T]], + /, + node_map_func: Optional[Callable[[S], int]] = None, + edge_map_func: Optional[Callable[[T], int]] = None, + ) -> Dict[int, int]: ... + def copy(self) -> PyGraph[S, T]: ... + def degree(self, node: int, /) -> int: ... + def edge_index_map(self) -> EdgeIndexMap: ... + def edge_indices(self) -> EdgeIndices: ... + def edge_list(self) -> EdgeList: ... + def edges(self) -> List[T]: ... + def extend_from_edge_list( + self, edge_list: List[Tuple[int, int]], / + ) -> None: ... + def extend_from_weighted_edge_list( + self, + edge_list: List[Tuple[int, int, T]], + /, + ) -> None: ... def from_adjacency_matrix(self, *args, **kwargs) -> Any: ... def get_all_edge_data(self, *args, **kwargs) -> Any: ... def get_edge_data(self, *args, **kwargs) -> Any: ... @@ -217,15 +232,17 @@ class PyGraph(Generic[S, T]): def num_edges(self, *args, **kwargs) -> Any: ... def num_nodes(self, *args, **kwargs) -> Any: ... def read_edge_list(self, *args, **kwargs) -> Any: ... - def remove_edge(self, *args, **kwargs) -> Any: ... - def remove_edge_from_index(self, *args, **kwargs) -> Any: ... - def remove_edges_from(self, *args, **kwargs) -> Any: ... - def remove_node(self, *args, **kwargs) -> Any: ... - def remove_nodes_from(self, *args, **kwargs) -> Any: ... - def subgraph(self, *args, **kwargs) -> Any: ... + def remove_edge(self, node_a: int, node_b: int, /) -> None: ... + def remove_edge_from_index(self, edge: int, /) -> None: ... + def remove_edges_from( + self, index_list: List[Tuple[int, int]], / + ) -> None: ... + def remove_node(self, node: int, /) -> None: ... + def remove_nodes_from(self, index_list: List[int], /) -> None: ... + def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... def to_dot(lambdanode) -> Any: ... - def update_edge(self, *args, **kwargs) -> Any: ... - def update_edge_by_index(self, *args, **kwargs) -> Any: ... + def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... def weighted_edge_list(self, *args, **kwargs) -> Any: ... def write_edge_list(self, *args, **kwargs) -> Any: ... def __delitem__(self, idx: int, /) -> None: ... From 12b39e20818cc2b24853034e6a3b83bf718fd310 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 15:46:41 -0700 Subject: [PATCH 05/71] Tweak __init__ --- retworkx/retworkx.pyi | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 1f95ed9cd..f9935eb33 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -42,9 +42,9 @@ class PyDiGraph(Generic[S, T]): multigraph: bool = ... def __init__( self, + /, check_cycle: bool = False, multigraph: bool = True, - /, ) -> None: ... def add_child(self, parent: int, obj: S, edge: T, /) -> int: ... def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... @@ -187,8 +187,7 @@ class PyDiGraph(Generic[S, T]): class PyGraph(Generic[S, T]): multigraph: bool = ... - @classmethod - def __init__(self, *args, **kwargs) -> None: ... + def __init__(self, /, multigraph: bool = True) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... def add_edges_from( self, obj_list: List[Tuple[int, int, T]] From 6fa0cf92e36d250965e38583399e9a8d9c701c72 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 17:17:27 -0700 Subject: [PATCH 06/71] Finish adding types for PyGraph --- retworkx/retworkx.pyi | 54 ++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 18 deletions(-) diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index f9935eb33..04be58278 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -16,14 +16,12 @@ from .custom_return_types import * from typing import ( Any, Callable, - ClassVar, Dict, Generic, TypeVar, Optional, List, Tuple, - Union, ) S = TypeVar("S") @@ -161,7 +159,7 @@ class PyDiGraph(Generic[S, T]): edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, graph_attr: Optional[Dict[str, str]] = None, filename: Optional[str] = None, - ) -> Any: ... + ) -> Optional[str]: ... def to_undirected( self, /, @@ -170,7 +168,7 @@ class PyDiGraph(Generic[S, T]): ) -> PyGraph[S, T]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self, *args, **kwargs) -> Any: ... + def weighted_edge_list(self) -> WeightedEdgeList: ... def write_edge_list( self, path: str, @@ -220,17 +218,24 @@ class PyGraph(Generic[S, T]): edge_list: List[Tuple[int, int, T]], /, ) -> None: ... - def from_adjacency_matrix(self, *args, **kwargs) -> Any: ... - def get_all_edge_data(self, *args, **kwargs) -> Any: ... - def get_edge_data(self, *args, **kwargs) -> Any: ... - def get_node_data(self, *args, **kwargs) -> Any: ... - def has_edge(self, *args, **kwargs) -> Any: ... - def neighbors(self, *args, **kwargs) -> Any: ... - def node_indexes(self, *args, **kwargs) -> Any: ... - def nodes(self, *args, **kwargs) -> Any: ... - def num_edges(self, *args, **kwargs) -> Any: ... - def num_nodes(self, *args, **kwargs) -> Any: ... - def read_edge_list(self, *args, **kwargs) -> Any: ... + @classmethod + def from_adjacency_matrix(matrix: np.array, /) -> PyGraph: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_node_data(self, node: int, /) -> S: ... + def has_edge(self, node_a: int, node_b: int, /) -> bool: ... + def neighbors(self, node: int, /) -> NodeIndices: ... + def node_indexes(self) -> NodeIndices: ... + def nodes(self) -> List[S]: ... + def num_edges(self) -> int: ... + def num_nodes(self) -> int: ... + @classmethod + def read_edge_list( + path: str, + /, + comment: Optional[str] = None, + deliminator: Optional[str] = None, + ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... def remove_edges_from( @@ -239,11 +244,24 @@ class PyGraph(Generic[S, T]): def remove_node(self, node: int, /) -> None: ... def remove_nodes_from(self, index_list: List[int], /) -> None: ... def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... - def to_dot(lambdanode) -> Any: ... + def to_dot( + self, + /, + node_attr: Optional[Callable[[S], Dict[str, str]]] = None, + edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, + graph_attr: Optional[Dict[str, str]] = None, + filename: Optional[str] = None, + ) -> Optional[str]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self, *args, **kwargs) -> Any: ... - def write_edge_list(self, *args, **kwargs) -> Any: ... + def weighted_edge_list(self) -> WeightedEdgeList: ... + def write_edge_list( + self, + path: str, + /, + deliminator: Optional[str] = None, + weight_fn: Optional[Callable[[T]], str] = None, + ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... def __getstate__(self) -> Any: ... From aa3bcd90ce61b73ae8caa7b3252453dac6bd48e5 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 17:21:29 -0700 Subject: [PATCH 07/71] Move PyGraph and PyDiGraph to own stub files --- retworkx/pydigraph.pyi | 176 ++++++++++++++++++++++++++++++ retworkx/pygraph.pyi | 113 ++++++++++++++++++++ retworkx/retworkx.pyi | 237 +---------------------------------------- 3 files changed, 292 insertions(+), 234 deletions(-) create mode 100644 retworkx/pydigraph.pyi create mode 100644 retworkx/pygraph.pyi diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi new file mode 100644 index 000000000..e84253ca3 --- /dev/null +++ b/retworkx/pydigraph.pyi @@ -0,0 +1,176 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + +import numpy as np +from .custom_return_types import * +from .pygraph import PyGraph + +from typing import ( + Any, + Callable, + Dict, + Generic, + TypeVar, + Optional, + List, + Tuple, +) + +S = TypeVar("S") +T = TypeVar("T") + +class PyDiGraph(Generic[S, T]): + check_cycle: bool = ... + multigraph: bool = ... + def __init__( + self, + /, + check_cycle: bool = False, + multigraph: bool = True, + ) -> None: ... + def add_child(self, parent: int, obj: S, edge: T, /) -> int: ... + def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... + def add_edges_from( + self, + obj_list: List[Tuple[int, int, T]], + /, + ) -> List[int]: ... + def add_edges_from_no_data( + self, obj_list: List[Tuple[int, int]], / + ) -> List[int]: ... + def add_node(self, obj: S, /) -> int: ... + def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... + def adj(self, node: int, /) -> Dict[int, T]: ... + def adj_direction(self, node: int, direction: bool, /) -> Dict[int, T]: ... + def compose( + self, + other: PyDiGraph[S, T], + node_map: Dict[int, Tuple[int, T]], + /, + node_map_func: Optional[Callable[[S], int]] = None, + edge_map_func: Optional[Callable[[T], int]] = None, + ) -> Dict[int, int]: ... + def copy(self) -> PyDiGraph[S, T]: ... + def edge_index_map(self) -> EdgeIndexMap: ... + def edge_indices(self) -> EdgeIndices: ... + def edge_list(self) -> EdgeList: ... + def edges(self) -> List[T]: ... + def extend_from_edge_list( + self, edge_list: List[Tuple[int, int]], / + ) -> None: ... + def extend_from_weighted_edge_list( + self, + edge_list: List[Tuple[int, int, T]], + /, + ) -> None: ... + def find_adjacent_node_by_edge( + self, node: int, predicate: Callable[[T], bool], / + ) -> S: ... + def find_node_by_weight( + self, obj: Callable[[S], bool] + ) -> Optional[int]: ... + def find_predecessors_by_edge( + self, node: int, filter_fn: Callable[[T], bool], / + ) -> List[S]: ... + def find_successors_by_edge( + self, node: int, filter_fn: Callable[[T], bool], / + ) -> List[S]: ... + @classmethod + def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_node_data(self, node: int, /) -> S: ... + def has_edge(self, node_a: int, node_b: int, /) -> bool: ... + def in_degree(self, node: int, /) -> int: ... + def in_edges(self, node: int, /) -> WeightedEdgeList: ... + def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... + def insert_node_on_in_edges_multiple( + self, node: int, ref_nodes: List[int], / + ) -> None: ... + def insert_node_on_out_edges(self, node: int, ref_node: int, /) -> None: ... + def insert_node_on_out_edges_multiple( + self, node: int, ref_nodes: List[int], / + ) -> None: ... + def is_symmetric(self) -> bool: ... + def merge_nodes(self, u: int, v: int, /) -> None: ... + def neighbors(self, node: int, /) -> NodeIndices: ... + def node_indexes(self) -> NodeIndices: ... + def nodes(self) -> List[S]: ... + def num_edges(self) -> int: ... + def num_nodes(self) -> int: ... + def out_degree(self, node: int, /) -> int: ... + def out_edges(self, node: int, /) -> WeightedEdgeList: ... + def predecessor_indices(self, node: int, /) -> NodeIndices: ... + def predecessors(self, node: int, /) -> List[S]: ... + @classmethod + def read_edge_list( + path: str, + /, + comment: Optional[str] = None, + deliminator: Optional[str] = None, + ) -> PyDiGraph: ... + def remove_edge(self, parent: int, child: int, /) -> None: ... + def remove_edge_from_index(self, edge: int, /) -> None: ... + def remove_edges_from( + self, index_list: List[Tuple[int, int]], / + ) -> None: ... + def remove_node(self, node: int, /) -> None: ... + def remove_node_retain_edges( + self, + node: int, + /, + use_outgoing: Optional[bool] = None, + condition: Optional[Callable[[S, S], bool]] = None, + ) -> None: ... + def remove_nodes_from(self, index_list: List[int], /) -> None: ... + def subgraph(self, nodes: List[int], /) -> PyDiGraph[S, T]: ... + def substitute_node_with_subgraph( + self, + node: int, + other: PyDiGraph[S, T], + edge_map_fn: Callable[[int, int, T], Optional[int]], + /, + node_filter: Optional[Callable[[S], bool]] = None, + edge_weight_map: Optional[Callable[T], T] = None, + ) -> NodeMap: ... + def successor_indices(self, node: int, /) -> NodeIndices: ... + def successors(self, node: int, /) -> List[S]: ... + def to_dot( + self, + /, + node_attr: Optional[Callable[[S], Dict[str, str]]] = None, + edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, + graph_attr: Optional[Dict[str, str]] = None, + filename: Optional[str] = None, + ) -> Optional[str]: ... + def to_undirected( + self, + /, + multigraph: bool = True, + weight_combo_fn: Optional[Callable[[T, T], T]] = None, + ) -> PyGraph[S, T]: ... + def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... + def weighted_edge_list(self) -> WeightedEdgeList: ... + def write_edge_list( + self, + path: str, + /, + deliminator: Optional[str] = None, + weight_fn: Optional[Callable[[T]], str] = None, + ) -> None: ... + def __delitem__(self, idx: int, /) -> None: ... + def __getitem__(self, idx: int, /) -> S: ... + def __getstate__(self) -> Any: ... + def __len__(self) -> int: ... + def __setitem__(self, idx: int, value: S, /) -> None: ... + def __setstate__(self, state, /) -> None: ... diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi new file mode 100644 index 000000000..62c5a0d9d --- /dev/null +++ b/retworkx/pygraph.pyi @@ -0,0 +1,113 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + +import numpy as np +from .custom_return_types import * + +from typing import ( + Any, + Callable, + Dict, + Generic, + TypeVar, + Optional, + List, + Tuple, +) + +S = TypeVar("S") +T = TypeVar("T") + +class PyGraph(Generic[S, T]): + multigraph: bool = ... + def __init__(self, /, multigraph: bool = True) -> None: ... + def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... + def add_edges_from( + self, obj_list: List[Tuple[int, int, T]] + ) -> List[int]: ... + def add_edges_from_no_data( + self, obj_list: List[Tuple[int, int]], / + ) -> List[int]: ... + def add_node(self, obj: S, /) -> int: ... + def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def adj(self, node: int, /) -> Dict[int, T]: ... + def compose( + self, + other: PyGraph[S, T], + node_map: Dict[int, Tuple[int, T]], + /, + node_map_func: Optional[Callable[[S], int]] = None, + edge_map_func: Optional[Callable[[T], int]] = None, + ) -> Dict[int, int]: ... + def copy(self) -> PyGraph[S, T]: ... + def degree(self, node: int, /) -> int: ... + def edge_index_map(self) -> EdgeIndexMap: ... + def edge_indices(self) -> EdgeIndices: ... + def edge_list(self) -> EdgeList: ... + def edges(self) -> List[T]: ... + def extend_from_edge_list( + self, edge_list: List[Tuple[int, int]], / + ) -> None: ... + def extend_from_weighted_edge_list( + self, + edge_list: List[Tuple[int, int, T]], + /, + ) -> None: ... + @classmethod + def from_adjacency_matrix(matrix: np.array, /) -> PyGraph: ... + def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_node_data(self, node: int, /) -> S: ... + def has_edge(self, node_a: int, node_b: int, /) -> bool: ... + def neighbors(self, node: int, /) -> NodeIndices: ... + def node_indexes(self) -> NodeIndices: ... + def nodes(self) -> List[S]: ... + def num_edges(self) -> int: ... + def num_nodes(self) -> int: ... + @classmethod + def read_edge_list( + path: str, + /, + comment: Optional[str] = None, + deliminator: Optional[str] = None, + ) -> PyGraph: ... + def remove_edge(self, node_a: int, node_b: int, /) -> None: ... + def remove_edge_from_index(self, edge: int, /) -> None: ... + def remove_edges_from( + self, index_list: List[Tuple[int, int]], / + ) -> None: ... + def remove_node(self, node: int, /) -> None: ... + def remove_nodes_from(self, index_list: List[int], /) -> None: ... + def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... + def to_dot( + self, + /, + node_attr: Optional[Callable[[S], Dict[str, str]]] = None, + edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, + graph_attr: Optional[Dict[str, str]] = None, + filename: Optional[str] = None, + ) -> Optional[str]: ... + def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... + def weighted_edge_list(self) -> WeightedEdgeList: ... + def write_edge_list( + self, + path: str, + /, + deliminator: Optional[str] = None, + weight_fn: Optional[Callable[[T]], str] = None, + ) -> None: ... + def __delitem__(self, idx: int, /) -> None: ... + def __getitem__(self, idx: int, /) -> S: ... + def __getstate__(self) -> Any: ... + def __len__(self) -> int: ... + def __setitem__(self, idx: int, value: S, /) -> None: ... + def __setstate__(self, state, /) -> None: ... diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 04be58278..7dc38c6f9 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -12,6 +12,9 @@ import numpy as np import retworkx_generators as generators from .custom_return_types import * +from .pygraph import PyGraph +from .pydigraph import PyDiGraph + from typing import ( Any, @@ -35,240 +38,6 @@ class NoPathFound(Exception): ... class NoSuitableNeighbors(Exception): ... class NullGraph(Exception): ... -class PyDiGraph(Generic[S, T]): - check_cycle: bool = ... - multigraph: bool = ... - def __init__( - self, - /, - check_cycle: bool = False, - multigraph: bool = True, - ) -> None: ... - def add_child(self, parent: int, obj: S, edge: T, /) -> int: ... - def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... - def add_edges_from( - self, - obj_list: List[Tuple[int, int, T]], - /, - ) -> List[int]: ... - def add_edges_from_no_data( - self, obj_list: List[Tuple[int, int]], / - ) -> List[int]: ... - def add_node(self, obj: S, /) -> int: ... - def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... - def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... - def adj(self, node: int, /) -> Dict[int, T]: ... - def adj_direction(self, node: int, direction: bool, /) -> Dict[int, T]: ... - def compose( - self, - other: PyDiGraph[S, T], - node_map: Dict[int, Tuple[int, T]], - /, - node_map_func: Optional[Callable[[S], int]] = None, - edge_map_func: Optional[Callable[[T], int]] = None, - ) -> Dict[int, int]: ... - def copy(self) -> PyDiGraph[S, T]: ... - def edge_index_map(self) -> EdgeIndexMap: ... - def edge_indices(self) -> EdgeIndices: ... - def edge_list(self) -> EdgeList: ... - def edges(self) -> List[T]: ... - def extend_from_edge_list( - self, edge_list: List[Tuple[int, int]], / - ) -> None: ... - def extend_from_weighted_edge_list( - self, - edge_list: List[Tuple[int, int, T]], - /, - ) -> None: ... - def find_adjacent_node_by_edge( - self, node: int, predicate: Callable[[T], bool], / - ) -> S: ... - def find_node_by_weight( - self, obj: Callable[[S], bool] - ) -> Optional[int]: ... - def find_predecessors_by_edge( - self, node: int, filter_fn: Callable[[T], bool], / - ) -> List[S]: ... - def find_successors_by_edge( - self, node: int, filter_fn: Callable[[T], bool], / - ) -> List[S]: ... - @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... - def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_node_data(self, node: int, /) -> S: ... - def has_edge(self, node_a: int, node_b: int, /) -> bool: ... - def in_degree(self, node: int, /) -> int: ... - def in_edges(self, node: int, /) -> WeightedEdgeList: ... - def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_in_edges_multiple( - self, node: int, ref_nodes: List[int], / - ) -> None: ... - def insert_node_on_out_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_out_edges_multiple( - self, node: int, ref_nodes: List[int], / - ) -> None: ... - def is_symmetric(self) -> bool: ... - def merge_nodes(self, u: int, v: int, /) -> None: ... - def neighbors(self, node: int, /) -> NodeIndices: ... - def node_indexes(self) -> NodeIndices: ... - def nodes(self) -> List[S]: ... - def num_edges(self) -> int: ... - def num_nodes(self) -> int: ... - def out_degree(self, node: int, /) -> int: ... - def out_edges(self, node: int, /) -> WeightedEdgeList: ... - def predecessor_indices(self, node: int, /) -> NodeIndices: ... - def predecessors(self, node: int, /) -> List[S]: ... - @classmethod - def read_edge_list( - path: str, - /, - comment: Optional[str] = None, - deliminator: Optional[str] = None, - ) -> PyDiGraph: ... - def remove_edge(self, parent: int, child: int, /) -> None: ... - def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from( - self, index_list: List[Tuple[int, int]], / - ) -> None: ... - def remove_node(self, node: int, /) -> None: ... - def remove_node_retain_edges( - self, - node: int, - /, - use_outgoing: Optional[bool] = None, - condition: Optional[Callable[[S, S], bool]] = None, - ) -> None: ... - def remove_nodes_from(self, index_list: List[int], /) -> None: ... - def subgraph(self, nodes: List[int], /) -> PyDiGraph[S, T]: ... - def substitute_node_with_subgraph( - self, - node: int, - other: PyDiGraph[S, T], - edge_map_fn: Callable[[int, int, T], Optional[int]], - /, - node_filter: Optional[Callable[[S], bool]] = None, - edge_weight_map: Optional[Callable[T], T] = None, - ) -> NodeMap: ... - def successor_indices(self, node: int, /) -> NodeIndices: ... - def successors(self, node: int, /) -> List[S]: ... - def to_dot( - self, - /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = None, - edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, - graph_attr: Optional[Dict[str, str]] = None, - filename: Optional[str] = None, - ) -> Optional[str]: ... - def to_undirected( - self, - /, - multigraph: bool = True, - weight_combo_fn: Optional[Callable[[T, T], T]] = None, - ) -> PyGraph[S, T]: ... - def update_edge(self, source: int, target: int, edge: T, /) -> None: ... - def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self) -> WeightedEdgeList: ... - def write_edge_list( - self, - path: str, - /, - deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T]], str] = None, - ) -> None: ... - def __delitem__(self, idx: int, /) -> None: ... - def __getitem__(self, idx: int, /) -> S: ... - def __getstate__(self) -> Any: ... - def __len__(self) -> int: ... - def __setitem__(self, idx: int, value: S, /) -> None: ... - def __setstate__(self, state, /) -> None: ... - -class PyGraph(Generic[S, T]): - multigraph: bool = ... - def __init__(self, /, multigraph: bool = True) -> None: ... - def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... - def add_edges_from( - self, obj_list: List[Tuple[int, int, T]] - ) -> List[int]: ... - def add_edges_from_no_data( - self, obj_list: List[Tuple[int, int]], / - ) -> List[int]: ... - def add_node(self, obj: S, /) -> int: ... - def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... - def adj(self, node: int, /) -> Dict[int, T]: ... - def compose( - self, - other: PyGraph[S, T], - node_map: Dict[int, Tuple[int, T]], - /, - node_map_func: Optional[Callable[[S], int]] = None, - edge_map_func: Optional[Callable[[T], int]] = None, - ) -> Dict[int, int]: ... - def copy(self) -> PyGraph[S, T]: ... - def degree(self, node: int, /) -> int: ... - def edge_index_map(self) -> EdgeIndexMap: ... - def edge_indices(self) -> EdgeIndices: ... - def edge_list(self) -> EdgeList: ... - def edges(self) -> List[T]: ... - def extend_from_edge_list( - self, edge_list: List[Tuple[int, int]], / - ) -> None: ... - def extend_from_weighted_edge_list( - self, - edge_list: List[Tuple[int, int, T]], - /, - ) -> None: ... - @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyGraph: ... - def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_node_data(self, node: int, /) -> S: ... - def has_edge(self, node_a: int, node_b: int, /) -> bool: ... - def neighbors(self, node: int, /) -> NodeIndices: ... - def node_indexes(self) -> NodeIndices: ... - def nodes(self) -> List[S]: ... - def num_edges(self) -> int: ... - def num_nodes(self) -> int: ... - @classmethod - def read_edge_list( - path: str, - /, - comment: Optional[str] = None, - deliminator: Optional[str] = None, - ) -> PyGraph: ... - def remove_edge(self, node_a: int, node_b: int, /) -> None: ... - def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from( - self, index_list: List[Tuple[int, int]], / - ) -> None: ... - def remove_node(self, node: int, /) -> None: ... - def remove_nodes_from(self, index_list: List[int], /) -> None: ... - def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... - def to_dot( - self, - /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = None, - edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, - graph_attr: Optional[Dict[str, str]] = None, - filename: Optional[str] = None, - ) -> Optional[str]: ... - def update_edge(self, source: int, target: int, edge: T, /) -> None: ... - def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self) -> WeightedEdgeList: ... - def write_edge_list( - self, - path: str, - /, - deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T]], str] = None, - ) -> None: ... - def __delitem__(self, idx: int, /) -> None: ... - def __getitem__(self, idx: int, /) -> S: ... - def __getstate__(self) -> Any: ... - def __len__(self) -> int: ... - def __setitem__(self, idx: int, value: S, /) -> None: ... - def __setstate__(self, state, /) -> None: ... - def ancestors(*args, **kwargs) -> Any: ... def bfs_successors(*args, **kwargs) -> Any: ... def collect_runs(*args, **kwargs) -> Any: ... From e799e0f8b78161995530e5867e66184c479b082a Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 17:22:09 -0700 Subject: [PATCH 08/71] Import graph annotations in generators module --- retworkx/retworkx_generators.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/retworkx/retworkx_generators.pyi b/retworkx/retworkx_generators.pyi index 6eed47854..3ae1ce7c3 100644 --- a/retworkx/retworkx_generators.pyi +++ b/retworkx/retworkx_generators.pyi @@ -10,6 +10,8 @@ # For implementation details, see __init__.py and lib.rs from typing import Any +from .pygraph import PyGraph +from .pydigraph import PyDiGraph def binomial_tree_graph(*args, **kwargs) -> Any: ... def cycle_graph(*args, **kwargs) -> Any: ... From e6cec75d9799ad84ba4c13822860da3c18a246ed Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 18:04:31 -0700 Subject: [PATCH 09/71] Start adding types to custom return types --- retworkx/custom_return_types.pyi | 314 +++++++++++++++---------------- retworkx/retworkx.pyi | 1 - 2 files changed, 152 insertions(+), 163 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index 7c2d773c6..b3388d058 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -9,239 +9,229 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, ClassVar +from typing import Any, Dict, Generic, List, Sequence, TypeVar, Tuple + +S = TypeVar("S") +T = TypeVar("T") + +class NodeIndices: + def __init__(self) -> None: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... + def __getitem__(self, index: int) -> int: ... + def __getstate__(self) -> List[int]: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... + def __setstate__(self, state: List[int]) -> None: ... + +class PathLengthMapping: + def __init__(self) -> None: ... + def items(self) -> Sequence[Tuple[int, float]]: ... + def keys(self) -> Sequence[int]: ... + def values(self) -> Sequence[float]: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Dict[int, int]: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... + def __setstate__(self, state: Dict[int, int]) -> None: ... + +class PathMapping: + def __init__(self) -> None: ... + def items(self) -> Sequence[Tuple[int, NodeIndices]]: ... + def keys(self) -> Sequence[int]: ... + def values(self) -> Sequence[NodeIndices]: ... + def __contains__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... + def __getitem__(self, index) -> Any: ... + def __getstate__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __iter__(self) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... + def __setstate__(self, state: Dict[int, List[int]]) -> None: ... class AllPairsPathLengthMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... + def __init__(self) -> None: ... + def items(self) -> Sequence[Tuple[int, PathLengthMapping]]: ... + def keys(self) -> Sequence[int]: ... + def values(self) -> Sequence[PathLengthMapping]: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class AllPairsPathMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... + def __init__(self) -> None: ... + def items(self) -> Sequence[Tuple[int, PathMapping]]: ... + def keys(self) -> Sequence[int]: ... + def values(self) -> Sequence[PathMapping]: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class BFSSuccessors: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __init__(self) -> None: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class EdgeIndexMap: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... + def __init__(self) -> None: ... def items(self, *args, **kwargs) -> Any: ... def keys(self, *args, **kwargs) -> Any: ... def values(self, *args, **kwargs) -> Any: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class EdgeIndices: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __init__(self) -> None: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class EdgeList: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __init__(self) -> None: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class NodeIndices: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... - def __getitem__(self, index) -> Any: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class NodeMap: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... + def __init__(self) -> None: ... def items(self, *args, **kwargs) -> Any: ... def keys(self, *args, **kwargs) -> Any: ... def values(self, *args, **kwargs) -> Any: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class NodesCountMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... - def __getitem__(self, index) -> Any: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PathLengthMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... - def __getitem__(self, index) -> Any: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... - def __setstate__(self, state) -> Any: ... - -class PathMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... + def __init__(self) -> None: ... def items(self, *args, **kwargs) -> Any: ... def keys(self, *args, **kwargs) -> Any: ... def values(self, *args, **kwargs) -> Any: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class Pos2DMapping: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... + def __init__(self) -> None: ... def items(self, *args, **kwargs) -> Any: ... def keys(self, *args, **kwargs) -> Any: ... def values(self, *args, **kwargs) -> Any: ... def __contains__(self, other) -> Any: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... def __iter__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... class WeightedEdgeList: - @classmethod - def __init__(self, *args, **kwargs) -> None: ... - def __eq__(self, other) -> Any: ... - def __ge__(self, other) -> Any: ... + def __init__(self) -> None: ... + def __eq__(self, other) -> bool: ... + def __ge__(self, other) -> bool: ... def __getitem__(self, index) -> Any: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> Any: ... - def __hash__(self) -> Any: ... - def __le__(self, other) -> Any: ... - def __len__(self) -> Any: ... - def __lt__(self, other) -> Any: ... - def __ne__(self, other) -> Any: ... + def __gt__(self, other) -> bool: ... + def __hash__(self) -> int: ... + def __le__(self, other) -> bool: ... + def __len__(self) -> int: ... + def __lt__(self, other) -> bool: ... + def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> Any: ... diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 7dc38c6f9..e9ad22182 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -15,7 +15,6 @@ from .custom_return_types import * from .pygraph import PyGraph from .pydigraph import PyDiGraph - from typing import ( Any, Callable, From ec48656eb4586ff55255ea5f68a85d57614d240f Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 18:58:05 -0700 Subject: [PATCH 10/71] Conclude adding types to custom_return_types --- retworkx/custom_return_types.pyi | 143 +++++++++++++++---------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index b3388d058..e7955557e 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -9,9 +9,8 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, Dict, Generic, List, Sequence, TypeVar, Tuple +from typing import Any, Dict, Generic, List, Iterable, TypeVar, Tuple -S = TypeVar("S") T = TypeVar("T") class NodeIndices: @@ -19,96 +18,96 @@ class NodeIndices: def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... def __getitem__(self, index: int) -> int: ... - def __getstate__(self) -> List[int]: ... + def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state: List[int]) -> None: ... + def __setstate__(self, state) -> None: ... class PathLengthMapping: def __init__(self) -> None: ... - def items(self) -> Sequence[Tuple[int, float]]: ... - def keys(self) -> Sequence[int]: ... - def values(self) -> Sequence[float]: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, float]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[float]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... - def __getstate__(self) -> Dict[int, int]: ... + def __getitem__(self, index: int) -> float: ... + def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state: Dict[int, int]) -> None: ... + def __setstate__(self, state) -> None: ... class PathMapping: def __init__(self) -> None: ... - def items(self) -> Sequence[Tuple[int, NodeIndices]]: ... - def keys(self) -> Sequence[int]: ... - def values(self) -> Sequence[NodeIndices]: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, NodeIndices]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[NodeIndices]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> NodeIndices: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state: Dict[int, List[int]]) -> None: ... + def __setstate__(self, state) -> None: ... class AllPairsPathLengthMapping: def __init__(self) -> None: ... - def items(self) -> Sequence[Tuple[int, PathLengthMapping]]: ... - def keys(self) -> Sequence[int]: ... - def values(self) -> Sequence[PathLengthMapping]: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, PathLengthMapping]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[PathLengthMapping]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> PathLengthMapping: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class AllPairsPathMapping: def __init__(self) -> None: ... - def items(self) -> Sequence[Tuple[int, PathMapping]]: ... - def keys(self) -> Sequence[int]: ... - def values(self) -> Sequence[PathMapping]: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, PathMapping]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[PathMapping]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> PathMapping: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... -class BFSSuccessors: +class BFSSuccessors(Generic[T]): def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> Tuple[T, List[T]]: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... @@ -116,32 +115,32 @@ class BFSSuccessors: def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... -class EdgeIndexMap: +class EdgeIndexMap(Generic[T]): def __init__(self) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, Tuple[int, int, T]]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[Tuple[int, int, T]]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> Tuple[int, int, T]: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class EdgeIndices: def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> int: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... @@ -149,13 +148,13 @@ class EdgeIndices: def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class EdgeList: def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> Tuple[int, int]: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... @@ -163,70 +162,70 @@ class EdgeList: def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class NodeMap: def __init__(self) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, int]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[int]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> int: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class NodesCountMapping: def __init__(self) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, int]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[int]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> int: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... class Pos2DMapping: def __init__(self) -> None: ... - def items(self, *args, **kwargs) -> Any: ... - def keys(self, *args, **kwargs) -> Any: ... - def values(self, *args, **kwargs) -> Any: ... - def __contains__(self, other) -> Any: ... + def items(self) -> Iterable[Tuple[int, Tuple[float, float]]]: ... + def keys(self) -> Iterable[int]: ... + def values(self) -> Iterable[Tuple[float, float]]: ... + def __contains__(self, other) -> int: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> Tuple[float, float]: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Any: ... + def __iter__(self) -> Iterable[int]: ... def __le__(self, other) -> bool: ... def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... -class WeightedEdgeList: +class WeightedEdgeList(Generic[T]): def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... - def __getitem__(self, index) -> Any: ... + def __getitem__(self, index: int) -> Tuple[int, int, T]: ... def __getstate__(self) -> Any: ... def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... @@ -234,4 +233,4 @@ class WeightedEdgeList: def __len__(self) -> int: ... def __lt__(self, other) -> bool: ... def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> Any: ... + def __setstate__(self, state) -> None: ... From 3691bf457582d9ac975d603f4747b853380818ef Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 19:35:13 -0700 Subject: [PATCH 11/71] Move stubs to their own package --- retworkx-stubs/__init__.pyi | 110 ++++++++++++++++++ .../custom_return_types.pyi | 0 {retworkx => retworkx-stubs}/py.typed | 0 {retworkx => retworkx-stubs}/pydigraph.pyi | 0 {retworkx => retworkx-stubs}/pygraph.pyi | 0 {retworkx => retworkx-stubs}/retworkx.pyi | 4 +- .../retworkx_generators.pyi | 0 setup.py | 4 +- 8 files changed, 114 insertions(+), 4 deletions(-) create mode 100644 retworkx-stubs/__init__.pyi rename {retworkx => retworkx-stubs}/custom_return_types.pyi (100%) rename {retworkx => retworkx-stubs}/py.typed (100%) rename {retworkx => retworkx-stubs}/pydigraph.pyi (100%) rename {retworkx => retworkx-stubs}/pygraph.pyi (100%) rename {retworkx => retworkx-stubs}/retworkx.pyi (98%) rename {retworkx => retworkx-stubs}/retworkx_generators.pyi (100%) diff --git a/retworkx-stubs/__init__.pyi b/retworkx-stubs/__init__.pyi new file mode 100644 index 000000000..85fd2c8a0 --- /dev/null +++ b/retworkx-stubs/__init__.pyi @@ -0,0 +1,110 @@ +from .retworkx import * +from typing import Any + +class PyDAG(PyDiGraph): ... + +def distance_matrix(graph, parallel_threshold: int = ...) -> None: ... +def adjacency_matrix( + graph, weight_fn: Any | None = ..., default_weight: float = ... +) -> None: ... +def all_simple_paths( + graph, from_, to, min_depth: Any | None = ..., cutoff: Any | None = ... +) -> None: ... +def floyd_warshall( + graph, + weight_fn: Any | None = ..., + default_weight: float = ..., + parallel_threshold: int = ..., +) -> None: ... +def floyd_warshall_numpy( + graph, + weight_fn: Any | None = ..., + default_weight: float = ..., + parallel_threshold: int = ..., +) -> None: ... +def astar_shortest_path( + graph, node, goal_fn, edge_cost_fn, estimate_cost_fn +) -> None: ... +def dijkstra_shortest_paths( + graph, + source, + target: Any | None = ..., + weight_fn: Any | None = ..., + default_weight: float = ..., + as_undirected: bool = ..., +) -> None: ... +def all_pairs_dijkstra_shortest_paths(graph, edge_cost_fn) -> None: ... +def all_pairs_dijkstra_path_lengths(graph, edge_cost_fn) -> None: ... +def dijkstra_shortest_path_lengths( + graph, node, edge_cost_fn, goal: Any | None = ... +) -> None: ... +def k_shortest_path_lengths( + graph, start, k, edge_cost, goal: Any | None = ... +) -> None: ... +def dfs_edges(graph, source) -> None: ... +def is_isomorphic( + first, + second, + node_matcher: Any | None = ..., + edge_matcher: Any | None = ..., + id_order: bool = ..., +) -> None: ... +def is_isomorphic_node_match( + first, second, matcher, id_order: bool = ... +) -> None: ... +def is_subgraph_isomorphic( + first, + second, + node_matcher: Any | None = ..., + edge_matcher: Any | None = ..., + id_order: bool = ..., + induced: bool = ..., +) -> None: ... +def transitivity(graph) -> None: ... +def core_number(graph) -> None: ... +def complement(graph) -> None: ... +def random_layout( + graph, center: Any | None = ..., seed: Any | None = ... +) -> None: ... +def spring_layout( + graph, + pos: Any | None = ..., + fixed: Any | None = ..., + k: Any | None = ..., + repulsive_exponent: int = ..., + adaptive_cooling: bool = ..., + num_iter: int = ..., + tol: float = ..., + weight_fn: Any | None = ..., + default_weight: int = ..., + scale: int = ..., + center: Any | None = ..., + seed: Any | None = ..., +) -> None: ... +def networkx_converter(graph): ... +def bipartite_layout( + graph, + first_nodes, + horizontal: bool = ..., + scale: int = ..., + center: Any | None = ..., + aspect_ratio=..., +) -> None: ... +def circular_layout( + graph, scale: int = ..., center: Any | None = ... +) -> None: ... +def shell_layout( + graph, + nlist: Any | None = ..., + rotate: Any | None = ..., + scale: int = ..., + center: Any | None = ..., +) -> None: ... +def spiral_layout( + graph, + scale: int = ..., + center: Any | None = ..., + resolution: float = ..., + equidistant: bool = ..., +) -> None: ... +def num_shortest_paths_unweighted(graph, source) -> None: ... diff --git a/retworkx/custom_return_types.pyi b/retworkx-stubs/custom_return_types.pyi similarity index 100% rename from retworkx/custom_return_types.pyi rename to retworkx-stubs/custom_return_types.pyi diff --git a/retworkx/py.typed b/retworkx-stubs/py.typed similarity index 100% rename from retworkx/py.typed rename to retworkx-stubs/py.typed diff --git a/retworkx/pydigraph.pyi b/retworkx-stubs/pydigraph.pyi similarity index 100% rename from retworkx/pydigraph.pyi rename to retworkx-stubs/pydigraph.pyi diff --git a/retworkx/pygraph.pyi b/retworkx-stubs/pygraph.pyi similarity index 100% rename from retworkx/pygraph.pyi rename to retworkx-stubs/pygraph.pyi diff --git a/retworkx/retworkx.pyi b/retworkx-stubs/retworkx.pyi similarity index 98% rename from retworkx/retworkx.pyi rename to retworkx-stubs/retworkx.pyi index e9ad22182..79ae56168 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx-stubs/retworkx.pyi @@ -12,8 +12,8 @@ import numpy as np import retworkx_generators as generators from .custom_return_types import * -from .pygraph import PyGraph -from .pydigraph import PyDiGraph +from .pygraph import PyGraph as PyGraph +from .pydigraph import PyDiGraph as PyDiGraph from typing import ( Any, diff --git a/retworkx/retworkx_generators.pyi b/retworkx-stubs/retworkx_generators.pyi similarity index 100% rename from retworkx/retworkx_generators.pyi rename to retworkx-stubs/retworkx_generators.pyi diff --git a/setup.py b/setup.py index 8993befd1..fc55a945e 100644 --- a/setup.py +++ b/setup.py @@ -52,8 +52,8 @@ def readme(): rust_extensions=[RustExtension("retworkx.retworkx", "Cargo.toml", binding=Binding.PyO3)], include_package_data=True, - packages=["retworkx", "retworkx.visualization"], - package_data={"retworkx": ["py.typed", "*.pyi"]}, + packages=["retworkx", "retworkx.visualization", "retworkx-stubs"], + package_data={"retworkx-stubs": ["py.typed", "*.pyi"]}, zip_safe=False, python_requires=">=3.6", install_requires=['numpy>=1.16.0'], From 78d458b9121e7e71b746d2265cbb6c83f5f31fe0 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 22:20:32 -0700 Subject: [PATCH 12/71] Declare package-dir for retworkx-stubs --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index fc55a945e..43aee8a3c 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,7 @@ def readme(): binding=Binding.PyO3)], include_package_data=True, packages=["retworkx", "retworkx.visualization", "retworkx-stubs"], + package_dir={'retworkx-stubs': 'retworkx-stubs'}, package_data={"retworkx-stubs": ["py.typed", "*.pyi"]}, zip_safe=False, python_requires=">=3.6", From fe73243ff77d8f179820ec6e4e56cde66e964a55 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 23:14:58 -0700 Subject: [PATCH 13/71] Use data_files in setup.py --- setup.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 43aee8a3c..aaa866910 100644 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +import pathlib + from setuptools import setup try: from setuptools_rust import Binding, RustExtension @@ -9,11 +11,23 @@ 'setuptools-rust']) from setuptools_rust import Binding, RustExtension +STUBS_DIR = "retworkx-stubs" def readme(): with open('README.md') as f: return f.read() +def get_stub_files(): + current_dir = pathlib.Path(__file__).parents[0] + pyi_files = [ + str(pyi_file.relative_to(current_dir)) for pyi_file in current_dir.glob(f"{STUBS_DIR}/**/*.pyi") + ] + py_typed_files = [ + str(typed_file.relative_to(current_dir)) for typed_file in current_dir.glob(f"{STUBS_DIR}/**/py.typed") + ] + print(pyi_files + py_typed_files) + return pyi_files + py_typed_files + mpl_extras = ['matplotlib>=3.0'] graphviz_extras = ['pydot>=1.4', 'pillow>=5.4'] @@ -53,8 +67,7 @@ def readme(): binding=Binding.PyO3)], include_package_data=True, packages=["retworkx", "retworkx.visualization", "retworkx-stubs"], - package_dir={'retworkx-stubs': 'retworkx-stubs'}, - package_data={"retworkx-stubs": ["py.typed", "*.pyi"]}, + data_files=[("", get_stub_files())], zip_safe=False, python_requires=">=3.6", install_requires=['numpy>=1.16.0'], From 530b26d669989b04e72691ddef6b6b74c6fef607 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 23:15:33 -0700 Subject: [PATCH 14/71] Remove print in setup.py --- setup.py | 1 - 1 file changed, 1 deletion(-) diff --git a/setup.py b/setup.py index aaa866910..ca388db45 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,6 @@ def get_stub_files(): py_typed_files = [ str(typed_file.relative_to(current_dir)) for typed_file in current_dir.glob(f"{STUBS_DIR}/**/py.typed") ] - print(pyi_files + py_typed_files) return pyi_files + py_typed_files From 48b536e73050366c436567bb5ca76bf3307040b0 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 2 Aug 2021 23:22:03 -0700 Subject: [PATCH 15/71] Fix minor styling issues --- setup.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index ca388db45..f3ac07354 100644 --- a/setup.py +++ b/setup.py @@ -13,17 +13,21 @@ STUBS_DIR = "retworkx-stubs" + def readme(): with open('README.md') as f: return f.read() + def get_stub_files(): current_dir = pathlib.Path(__file__).parents[0] pyi_files = [ - str(pyi_file.relative_to(current_dir)) for pyi_file in current_dir.glob(f"{STUBS_DIR}/**/*.pyi") + str(pyi_file.relative_to(current_dir)) + for pyi_file in current_dir.glob(f"{STUBS_DIR}/**/*.pyi") ] py_typed_files = [ - str(typed_file.relative_to(current_dir)) for typed_file in current_dir.glob(f"{STUBS_DIR}/**/py.typed") + str(typed_file.relative_to(current_dir)) + for typed_file in current_dir.glob(f"{STUBS_DIR}/**/py.typed") ] return pyi_files + py_typed_files From f6e37a9d545506e46c3c6f707b27dbaf6bfc83aa Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 00:41:07 -0700 Subject: [PATCH 16/71] Add simple stubs test case --- stubs-tests/pygraph_test.py | 24 ++++++++++++++++++++++++ tox.ini | 9 +++++++++ 2 files changed, 33 insertions(+) create mode 100644 stubs-tests/pygraph_test.py diff --git a/stubs-tests/pygraph_test.py b/stubs-tests/pygraph_test.py new file mode 100644 index 000000000..438f37910 --- /dev/null +++ b/stubs-tests/pygraph_test.py @@ -0,0 +1,24 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from retworkx import PyGraph + +import pytest + +@pytest.mark.mypy_testing +def test_pygraph_simple() -> None: + graph: PyGraph[str, int] = PyGraph() + node_a = graph.add_node("A") + node_b = graph.add_node("B") + edge_ab = graph.add_edge(node_a, node_b, 3) + reveal_type(node_a) # note: Revealed type is "builtins.int" + reveal_type(edge_ab) # note: Revealed type is "builtins.int" diff --git a/tox.ini b/tox.ini index 9179a4d61..fcd4a9df8 100644 --- a/tox.ini +++ b/tox.ini @@ -54,6 +54,15 @@ deps = black==21.5b0 commands = black {posargs} '../retworkx' '../tests' +[testenv:stubs] +basepython = python3 +envdir = .tox/stubs +deps = + pytest + mypy + pytest-mypy-testing==0.0.8 +commands = python -m pytest '../stubs-tests' + [flake8] # E125 is deliberately excluded. See https://github.com/jcrocholl/pep8/issues/126 # E123 skipped because it is ignored by default in the default pep8 From 87d0834c13e6ae5de1436e41f5c23c69322a7ddb Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 00:49:48 -0700 Subject: [PATCH 17/71] Run stub-tests in CI --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64cdceb02..fdc9696cb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -81,6 +81,8 @@ jobs: if: runner.os == 'Linux' - name: 'Run tests' run: tox -epy + - name: 'Run stubs-tests' + run: tox -estubs coverage: needs: [tests] name: Coverage From 1b3b7475caac9f662bb49f2cfff3ae1c9fff44bf Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 01:11:06 -0700 Subject: [PATCH 18/71] Only run stub checks on linux with Python >= 3.7 --- .github/workflows/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fdc9696cb..881bfd952 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,6 +83,7 @@ jobs: run: tox -epy - name: 'Run stubs-tests' run: tox -estubs + if: runner.os == 'Linux' && python-version != 3.6 coverage: needs: [tests] name: Coverage From bb1cf8f13b79b45f62412da705a930fea3c995a8 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 01:14:30 -0700 Subject: [PATCH 19/71] Fix error in workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 881bfd952..7e9b418d4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,7 +83,7 @@ jobs: run: tox -epy - name: 'Run stubs-tests' run: tox -estubs - if: runner.os == 'Linux' && python-version != 3.6 + if: runner.os == 'Linux' && ${{ matrix.python-version }} != 3.6 coverage: needs: [tests] name: Coverage From e460c110eeb4ee78c795cddf973d98131d8e389e Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 10:40:16 -0700 Subject: [PATCH 20/71] Try to fix 3.6 build --- .github/workflows/main.yml | 2 +- tox.ini | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7e9b418d4..92fb0bce2 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -83,7 +83,7 @@ jobs: run: tox -epy - name: 'Run stubs-tests' run: tox -estubs - if: runner.os == 'Linux' && ${{ matrix.python-version }} != 3.6 + if: runner.os == 'Linux' coverage: needs: [tests] name: Coverage diff --git a/tox.ini b/tox.ini index fcd4a9df8..2d4394143 100644 --- a/tox.ini +++ b/tox.ini @@ -61,6 +61,7 @@ deps = pytest mypy pytest-mypy-testing==0.0.8 + dataclasses; python_version<'3.7' commands = python -m pytest '../stubs-tests' [flake8] From acc7e4bfc5479893328875d97791f6f154c2fcae Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 21:08:11 -0700 Subject: [PATCH 21/71] Improve custom return types --- retworkx-stubs/custom_return_types.pyi | 7 +++--- retworkx-stubs/pydigraph.pyi | 10 ++++---- retworkx-stubs/pygraph.pyi | 4 ++-- stubs-tests/pygraph_test.py | 32 ++++++++++++++++++++++---- 4 files changed, 39 insertions(+), 14 deletions(-) diff --git a/retworkx-stubs/custom_return_types.pyi b/retworkx-stubs/custom_return_types.pyi index e7955557e..f316b6657 100644 --- a/retworkx-stubs/custom_return_types.pyi +++ b/retworkx-stubs/custom_return_types.pyi @@ -10,10 +10,11 @@ # For implementation details, see __init__.py and lib.rs from typing import Any, Dict, Generic, List, Iterable, TypeVar, Tuple +from collections.abc import Sequence T = TypeVar("T") -class NodeIndices: +class NodeIndices(Sequence[int]): def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... @@ -150,7 +151,7 @@ class EdgeIndices: def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> None: ... -class EdgeList: +class EdgeList(Sequence[Tuple[int, int]]): def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... @@ -221,7 +222,7 @@ class Pos2DMapping: def __ne__(self, other) -> bool: ... def __setstate__(self, state) -> None: ... -class WeightedEdgeList(Generic[T]): +class WeightedEdgeList(Generic[T], Sequence[Tuple[int, int, T]]): def __init__(self) -> None: ... def __eq__(self, other) -> bool: ... def __ge__(self, other) -> bool: ... diff --git a/retworkx-stubs/pydigraph.pyi b/retworkx-stubs/pydigraph.pyi index e84253ca3..bc70fa993 100644 --- a/retworkx-stubs/pydigraph.pyi +++ b/retworkx-stubs/pydigraph.pyi @@ -91,7 +91,7 @@ class PyDiGraph(Generic[S, T]): def get_node_data(self, node: int, /) -> S: ... def has_edge(self, node_a: int, node_b: int, /) -> bool: ... def in_degree(self, node: int, /) -> int: ... - def in_edges(self, node: int, /) -> WeightedEdgeList: ... + def in_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... def insert_node_on_in_edges_multiple( self, node: int, ref_nodes: List[int], / @@ -108,7 +108,7 @@ class PyDiGraph(Generic[S, T]): def num_edges(self) -> int: ... def num_nodes(self) -> int: ... def out_degree(self, node: int, /) -> int: ... - def out_edges(self, node: int, /) -> WeightedEdgeList: ... + def out_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def predecessor_indices(self, node: int, /) -> NodeIndices: ... def predecessors(self, node: int, /) -> List[S]: ... @classmethod @@ -140,7 +140,7 @@ class PyDiGraph(Generic[S, T]): edge_map_fn: Callable[[int, int, T], Optional[int]], /, node_filter: Optional[Callable[[S], bool]] = None, - edge_weight_map: Optional[Callable[T], T] = None, + edge_weight_map: Optional[Callable[[T], T]] = None, ) -> NodeMap: ... def successor_indices(self, node: int, /) -> NodeIndices: ... def successors(self, node: int, /) -> List[S]: ... @@ -160,13 +160,13 @@ class PyDiGraph(Generic[S, T]): ) -> PyGraph[S, T]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self) -> WeightedEdgeList: ... + def weighted_edge_list(self) -> WeightedEdgeList[T]: ... def write_edge_list( self, path: str, /, deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T]], str] = None, + weight_fn: Optional[Callable[[T], str]] = None, ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... diff --git a/retworkx-stubs/pygraph.pyi b/retworkx-stubs/pygraph.pyi index 62c5a0d9d..59e82937c 100644 --- a/retworkx-stubs/pygraph.pyi +++ b/retworkx-stubs/pygraph.pyi @@ -97,13 +97,13 @@ class PyGraph(Generic[S, T]): ) -> Optional[str]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... - def weighted_edge_list(self) -> WeightedEdgeList: ... + def weighted_edge_list(self) -> WeightedEdgeList[T]: ... def write_edge_list( self, path: str, /, deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T]], str] = None, + weight_fn: Optional[Callable[[T], str]] = None, ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... diff --git a/stubs-tests/pygraph_test.py b/stubs-tests/pygraph_test.py index 438f37910..09f209925 100644 --- a/stubs-tests/pygraph_test.py +++ b/stubs-tests/pygraph_test.py @@ -10,15 +10,39 @@ # License for the specific language governing permissions and limitations # under the License. -from retworkx import PyGraph +from typing import List, Tuple +from retworkx import EdgeList, PyGraph, NodeIndices, WeightedEdgeList import pytest @pytest.mark.mypy_testing def test_pygraph_simple() -> None: graph: PyGraph[str, int] = PyGraph() - node_a = graph.add_node("A") - node_b = graph.add_node("B") - edge_ab = graph.add_edge(node_a, node_b, 3) + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + edge_ab: int = graph.add_edge(node_a, node_b, 3) reveal_type(node_a) # note: Revealed type is "builtins.int" reveal_type(edge_ab) # note: Revealed type is "builtins.int" + +@pytest.mark.mypy_testing +def test_custom_return_types() -> None: + graph: PyGraph[str, int] = PyGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + graph.add_edge(node_a, node_b, 3) + + edges: EdgeList = graph.edge_list() + weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() + node_indices: NodeIndices = graph.node_indexes() + + reveal_type(edges) # note: Revealed type is "EdgeList" + reveal_type(weighted_edges) # note: Revealed type is "WeightedEdgeList[int]" + reveal_type(node_indices) # note: Revealed type is "NodeIndices" + + list_of_edges: List[Tuple[int, int]] = list(edges) + list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) + list_of_nodes: List[int] = list(node_indices) + + reveal_type(list_of_edges) # note: Revealed type is "List[Tuple[int, int]]" + reveal_type(list_of_weights) # note: Revealed type is "List[Tuple[int, int, int]]" + reveal_type(list_of_nodes) # note: Revealed type is "List[int]" From 81aec086dd7a7b81f552026393e13cc5208f87ac Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 21:43:13 -0700 Subject: [PATCH 22/71] Add PyDiGraph test --- stubs-tests/pydigraph_test.py | 48 +++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 stubs-tests/pydigraph_test.py diff --git a/stubs-tests/pydigraph_test.py b/stubs-tests/pydigraph_test.py new file mode 100644 index 000000000..0b3ffe3d0 --- /dev/null +++ b/stubs-tests/pydigraph_test.py @@ -0,0 +1,48 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from typing import List, Tuple +from retworkx import EdgeList, PyDiGraph, NodeIndices, WeightedEdgeList + +import pytest + +@pytest.mark.mypy_testing +def test_pydigraph_simple() -> None: + graph: PyDiGraph[str, int] = PyDiGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + edge_ab: int = graph.add_edge(node_a, node_b, 3) + reveal_type(node_a) # note: Revealed type is "builtins.int" + reveal_type(edge_ab) # note: Revealed type is "builtins.int" + +@pytest.mark.mypy_testing +def test_custom_return_types() -> None: + graph: PyDiGraph[str, int] = PyDiGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + graph.add_edge(node_a, node_b, 3) + + edges: EdgeList = graph.edge_list() + weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() + node_indices: NodeIndices = graph.node_indexes() + + reveal_type(edges) # note: Revealed type is "EdgeList" + reveal_type(weighted_edges) # note: Revealed type is "WeightedEdgeList[int]" + reveal_type(node_indices) # note: Revealed type is "NodeIndices" + + list_of_edges: List[Tuple[int, int]] = list(edges) + list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) + list_of_nodes: List[int] = list(node_indices) + + reveal_type(list_of_edges) # note: Revealed type is "List[Tuple[int, int]]" + reveal_type(list_of_weights) # note: Revealed type is "List[Tuple[int, int, int]]" + reveal_type(list_of_nodes) # note: Revealed type is "List[int]" From e31ea4919bf72e13de66f0602904bb9e17fad885 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 4 Aug 2021 23:12:28 -0700 Subject: [PATCH 23/71] Add new merge functions --- retworkx-stubs/retworkx.pyi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/retworkx-stubs/retworkx.pyi b/retworkx-stubs/retworkx.pyi index 79ae56168..afbab8715 100644 --- a/retworkx-stubs/retworkx.pyi +++ b/retworkx-stubs/retworkx.pyi @@ -39,6 +39,7 @@ class NullGraph(Exception): ... def ancestors(*args, **kwargs) -> Any: ... def bfs_successors(*args, **kwargs) -> Any: ... +def collect_bicolor_runs(*args, **kwargs) -> Any: ... def collect_runs(*args, **kwargs) -> Any: ... def cycle_basis(*args, **kwargs) -> Any: ... def dag_longest_path(*args, **kwargs) -> Any: ... @@ -106,6 +107,7 @@ def is_weakly_connected(*args, **kwargs) -> Any: ... def layers(*args, **kwargs) -> Any: ... def lexicographical_topological_sort(*args, **kwargs) -> Any: ... def max_weight_matching(*args, **kwargs) -> Any: ... +def metric_closure(*args, **kwargs) -> Any: ... def minimum_spanning_edges(graph, weight_fn) -> Any: ... def minimum_spanning_tree(graph, weight_fn) -> Any: ... def number_weakly_connected_components(*args, **kwargs) -> Any: ... From 7ce2b9b20d2603637740a89cb19e6d2e719510d2 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 16 Oct 2021 10:01:43 -0700 Subject: [PATCH 24/71] Add retworkx-stub to MANIFEST.in --- MANIFEST.in | 1 + 1 file changed, 1 insertion(+) diff --git a/MANIFEST.in b/MANIFEST.in index e0f95ac8d..7d1f2efa8 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,3 +3,4 @@ include Cargo.toml include Cargo.lock recursive-include src * recursive-include retworkx-core * +recursive-include retworkx-stub * From e1feaf28241378242bed8fc970991aa9cd4d76a8 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 16 Oct 2021 12:14:33 -0700 Subject: [PATCH 25/71] Move stubs to retworkx folder --- MANIFEST.in | 2 +- {retworkx-stubs => retworkx}/__init__.pyi | 0 .../custom_return_types.pyi | 0 {retworkx-stubs => retworkx}/py.typed | 0 {retworkx-stubs => retworkx}/pydigraph.pyi | 0 {retworkx-stubs => retworkx}/pygraph.pyi | 0 {retworkx-stubs => retworkx}/retworkx.pyi | 0 .../retworkx_generators.pyi | 0 setup.py | 21 ++----------------- 9 files changed, 3 insertions(+), 20 deletions(-) rename {retworkx-stubs => retworkx}/__init__.pyi (100%) rename {retworkx-stubs => retworkx}/custom_return_types.pyi (100%) rename {retworkx-stubs => retworkx}/py.typed (100%) rename {retworkx-stubs => retworkx}/pydigraph.pyi (100%) rename {retworkx-stubs => retworkx}/pygraph.pyi (100%) rename {retworkx-stubs => retworkx}/retworkx.pyi (100%) rename {retworkx-stubs => retworkx}/retworkx_generators.pyi (100%) diff --git a/MANIFEST.in b/MANIFEST.in index 7d1f2efa8..bb69d2b8f 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -3,4 +3,4 @@ include Cargo.toml include Cargo.lock recursive-include src * recursive-include retworkx-core * -recursive-include retworkx-stub * +recursive-include retworkx *.pyi *.typed diff --git a/retworkx-stubs/__init__.pyi b/retworkx/__init__.pyi similarity index 100% rename from retworkx-stubs/__init__.pyi rename to retworkx/__init__.pyi diff --git a/retworkx-stubs/custom_return_types.pyi b/retworkx/custom_return_types.pyi similarity index 100% rename from retworkx-stubs/custom_return_types.pyi rename to retworkx/custom_return_types.pyi diff --git a/retworkx-stubs/py.typed b/retworkx/py.typed similarity index 100% rename from retworkx-stubs/py.typed rename to retworkx/py.typed diff --git a/retworkx-stubs/pydigraph.pyi b/retworkx/pydigraph.pyi similarity index 100% rename from retworkx-stubs/pydigraph.pyi rename to retworkx/pydigraph.pyi diff --git a/retworkx-stubs/pygraph.pyi b/retworkx/pygraph.pyi similarity index 100% rename from retworkx-stubs/pygraph.pyi rename to retworkx/pygraph.pyi diff --git a/retworkx-stubs/retworkx.pyi b/retworkx/retworkx.pyi similarity index 100% rename from retworkx-stubs/retworkx.pyi rename to retworkx/retworkx.pyi diff --git a/retworkx-stubs/retworkx_generators.pyi b/retworkx/retworkx_generators.pyi similarity index 100% rename from retworkx-stubs/retworkx_generators.pyi rename to retworkx/retworkx_generators.pyi diff --git a/setup.py b/setup.py index 1b4a236ef..4c27bf48e 100644 --- a/setup.py +++ b/setup.py @@ -6,6 +6,7 @@ # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. import pathlib +import shutil from setuptools import setup try: @@ -18,31 +19,14 @@ 'setuptools-rust']) from setuptools_rust import Binding, RustExtension -STUBS_DIR = "retworkx-stubs" - def readme(): with open('README.md') as f: return f.read() - -def get_stub_files(): - current_dir = pathlib.Path(__file__).parents[0] - pyi_files = [ - str(pyi_file.relative_to(current_dir)) - for pyi_file in current_dir.glob(f"{STUBS_DIR}/**/*.pyi") - ] - py_typed_files = [ - str(typed_file.relative_to(current_dir)) - for typed_file in current_dir.glob(f"{STUBS_DIR}/**/py.typed") - ] - return pyi_files + py_typed_files - - mpl_extras = ['matplotlib>=3.0'] graphviz_extras = ['pydot>=1.4', 'pillow>=5.4'] - setup( name="retworkx", version="0.11.0", @@ -77,8 +61,7 @@ def get_stub_files(): rust_extensions=[RustExtension("retworkx.retworkx", "Cargo.toml", binding=Binding.PyO3)], include_package_data=True, - packages=["retworkx", "retworkx.visualization", "retworkx-stubs"], - data_files=[("", get_stub_files())], + packages=["retworkx", "retworkx.visualization"], zip_safe=False, python_requires=">=3.6", install_requires=['numpy>=1.16.0'], From 837efb2ad7691f8ea0394c5540f2978aa0828171 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 16 Oct 2021 12:17:47 -0700 Subject: [PATCH 26/71] Reduce scope of the PR --- retworkx/__init__.pyi | 117 +++---------------------------- retworkx/retworkx.pyi | 82 ---------------------- retworkx/retworkx_generators.pyi | 29 -------- 3 files changed, 11 insertions(+), 217 deletions(-) delete mode 100644 retworkx/retworkx_generators.pyi diff --git a/retworkx/__init__.pyi b/retworkx/__init__.pyi index 85fd2c8a0..659602633 100644 --- a/retworkx/__init__.pyi +++ b/retworkx/__init__.pyi @@ -1,110 +1,15 @@ +# This code is licensed under the Apache License, Version 2.0. You may +# obtain a copy of this license in the LICENSE.txt file in the root directory +# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. +# +# Any modifications or derivative works of this code must retain this +# copyright notice, and modified files need to carry a notice indicating +# that they have been altered from the originals. + +# This file contains only type annotations for PyO3 functions and classes +# For implementation details, see __init__.py and lib.rs + from .retworkx import * from typing import Any class PyDAG(PyDiGraph): ... - -def distance_matrix(graph, parallel_threshold: int = ...) -> None: ... -def adjacency_matrix( - graph, weight_fn: Any | None = ..., default_weight: float = ... -) -> None: ... -def all_simple_paths( - graph, from_, to, min_depth: Any | None = ..., cutoff: Any | None = ... -) -> None: ... -def floyd_warshall( - graph, - weight_fn: Any | None = ..., - default_weight: float = ..., - parallel_threshold: int = ..., -) -> None: ... -def floyd_warshall_numpy( - graph, - weight_fn: Any | None = ..., - default_weight: float = ..., - parallel_threshold: int = ..., -) -> None: ... -def astar_shortest_path( - graph, node, goal_fn, edge_cost_fn, estimate_cost_fn -) -> None: ... -def dijkstra_shortest_paths( - graph, - source, - target: Any | None = ..., - weight_fn: Any | None = ..., - default_weight: float = ..., - as_undirected: bool = ..., -) -> None: ... -def all_pairs_dijkstra_shortest_paths(graph, edge_cost_fn) -> None: ... -def all_pairs_dijkstra_path_lengths(graph, edge_cost_fn) -> None: ... -def dijkstra_shortest_path_lengths( - graph, node, edge_cost_fn, goal: Any | None = ... -) -> None: ... -def k_shortest_path_lengths( - graph, start, k, edge_cost, goal: Any | None = ... -) -> None: ... -def dfs_edges(graph, source) -> None: ... -def is_isomorphic( - first, - second, - node_matcher: Any | None = ..., - edge_matcher: Any | None = ..., - id_order: bool = ..., -) -> None: ... -def is_isomorphic_node_match( - first, second, matcher, id_order: bool = ... -) -> None: ... -def is_subgraph_isomorphic( - first, - second, - node_matcher: Any | None = ..., - edge_matcher: Any | None = ..., - id_order: bool = ..., - induced: bool = ..., -) -> None: ... -def transitivity(graph) -> None: ... -def core_number(graph) -> None: ... -def complement(graph) -> None: ... -def random_layout( - graph, center: Any | None = ..., seed: Any | None = ... -) -> None: ... -def spring_layout( - graph, - pos: Any | None = ..., - fixed: Any | None = ..., - k: Any | None = ..., - repulsive_exponent: int = ..., - adaptive_cooling: bool = ..., - num_iter: int = ..., - tol: float = ..., - weight_fn: Any | None = ..., - default_weight: int = ..., - scale: int = ..., - center: Any | None = ..., - seed: Any | None = ..., -) -> None: ... -def networkx_converter(graph): ... -def bipartite_layout( - graph, - first_nodes, - horizontal: bool = ..., - scale: int = ..., - center: Any | None = ..., - aspect_ratio=..., -) -> None: ... -def circular_layout( - graph, scale: int = ..., center: Any | None = ... -) -> None: ... -def shell_layout( - graph, - nlist: Any | None = ..., - rotate: Any | None = ..., - scale: int = ..., - center: Any | None = ..., -) -> None: ... -def spiral_layout( - graph, - scale: int = ..., - center: Any | None = ..., - resolution: float = ..., - equidistant: bool = ..., -) -> None: ... -def num_shortest_paths_unweighted(graph, source) -> None: ... diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index afbab8715..66d7776dc 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -10,7 +10,6 @@ # For implementation details, see __init__.py and lib.rs import numpy as np -import retworkx_generators as generators from .custom_return_types import * from .pygraph import PyGraph as PyGraph from .pydigraph import PyDiGraph as PyDiGraph @@ -36,84 +35,3 @@ class NoEdgeBetweenNodes(Exception): ... class NoPathFound(Exception): ... class NoSuitableNeighbors(Exception): ... class NullGraph(Exception): ... - -def ancestors(*args, **kwargs) -> Any: ... -def bfs_successors(*args, **kwargs) -> Any: ... -def collect_bicolor_runs(*args, **kwargs) -> Any: ... -def collect_runs(*args, **kwargs) -> Any: ... -def cycle_basis(*args, **kwargs) -> Any: ... -def dag_longest_path(*args, **kwargs) -> Any: ... -def dag_longest_path_length(*args, **kwargs) -> Any: ... -def dag_weighted_longest_path(*args, **kwargs) -> Any: ... -def dag_weighted_longest_path_length(*args, **kwargs) -> Any: ... -def descendants(*args, **kwargs) -> Any: ... -def digraph_adjacency_matrix(*args, **kwargs) -> Any: ... -def digraph_all_pairs_dijkstra_path_lengths(*args, **kwargs) -> Any: ... -def digraph_all_pairs_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... -def digraph_all_simple_paths(*args, **kwargs) -> Any: ... -def digraph_astar_shortest_path(*args, **kwargs) -> Any: ... -def digraph_bipartite_layout(*args, **kwargs) -> Any: ... -def digraph_circular_layout(*args, **kwargs) -> Any: ... -def digraph_complement(*args, **kwargs) -> Any: ... -def digraph_core_number(*args, **kwargs) -> Any: ... -def digraph_dfs_edges(*args, **kwargs) -> Any: ... -def digraph_dijkstra_shortest_path_lengths(*args, **kwargs) -> Any: ... -def digraph_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... -def digraph_distance_matrix(*args, **kwargs) -> Any: ... -def digraph_find_cycle(*args, **kwargs) -> Any: ... -def digraph_floyd_warshall(graph, weight_fn=...) -> Any: ... -def digraph_floyd_warshall_numpy(*args, **kwargs) -> Any: ... -def digraph_is_isomorphic(*args, **kwargs) -> Any: ... -def digraph_is_subgraph_isomorphic(*args, **kwargs) -> Any: ... -def digraph_k_shortest_path_lengths(*args, **kwargs) -> Any: ... -def digraph_num_shortest_paths_unweighted(*args, **kwargs) -> Any: ... -def digraph_random_layout(*args, **kwargs) -> Any: ... -def digraph_shell_layout(*args, **kwargs) -> Any: ... -def digraph_spiral_layout(*args, **kwargs) -> Any: ... -def digraph_spring_layout(*args, **kwargs) -> Any: ... -def digraph_transitivity(*args, **kwargs) -> Any: ... -def digraph_union(*args, **kwargs) -> Any: ... -def directed_gnm_random_graph(*args, **kwargs) -> Any: ... -def directed_gnp_random_graph(*args, **kwargs) -> Any: ... -def graph_adjacency_matrix(graph, weight_fn) -> Any: ... -def graph_all_pairs_dijkstra_path_lengths(*args, **kwargs) -> Any: ... -def graph_all_pairs_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... -def graph_all_simple_paths(*args, **kwargs) -> Any: ... -def graph_astar_shortest_path(*args, **kwargs) -> Any: ... -def graph_bipartite_layout(*args, **kwargs) -> Any: ... -def graph_circular_layout(*args, **kwargs) -> Any: ... -def graph_complement(*args, **kwargs) -> Any: ... -def graph_core_number(*args, **kwargs) -> Any: ... -def graph_dfs_edges(*args, **kwargs) -> Any: ... -def graph_dijkstra_shortest_path_lengths(*args, **kwargs) -> Any: ... -def graph_dijkstra_shortest_paths(*args, **kwargs) -> Any: ... -def graph_distance_matrix(*args, **kwargs) -> Any: ... -def graph_floyd_warshall(graph, weight_fn=...) -> Any: ... -def graph_floyd_warshall_numpy(graph, weight_fn) -> Any: ... -def graph_greedy_color(*args, **kwargs) -> Any: ... -def graph_is_isomorphic(*args, **kwargs) -> Any: ... -def graph_is_subgraph_isomorphic(*args, **kwargs) -> Any: ... -def graph_k_shortest_path_lengths(*args, **kwargs) -> Any: ... -def graph_num_shortest_paths_unweighted(*args, **kwargs) -> Any: ... -def graph_random_layout(*args, **kwargs) -> Any: ... -def graph_shell_layout(*args, **kwargs) -> Any: ... -def graph_spiral_layout(*args, **kwargs) -> Any: ... -def graph_spring_layout(*args, **kwargs) -> Any: ... -def graph_transitivity(*args, **kwargs) -> Any: ... -def is_directed_acyclic_graph(*args, **kwargs) -> Any: ... -def is_matching(*args, **kwargs) -> Any: ... -def is_maximal_matching(*args, **kwargs) -> Any: ... -def is_weakly_connected(*args, **kwargs) -> Any: ... -def layers(*args, **kwargs) -> Any: ... -def lexicographical_topological_sort(*args, **kwargs) -> Any: ... -def max_weight_matching(*args, **kwargs) -> Any: ... -def metric_closure(*args, **kwargs) -> Any: ... -def minimum_spanning_edges(graph, weight_fn) -> Any: ... -def minimum_spanning_tree(graph, weight_fn) -> Any: ... -def number_weakly_connected_components(*args, **kwargs) -> Any: ... -def random_geometric_graph(*args, **kwargs) -> Any: ... -def strongly_connected_components(*args, **kwargs) -> Any: ... -def topological_sort(*args, **kwargs) -> Any: ... -def undirected_gnm_random_graph(*args, **kwargs) -> Any: ... -def undirected_gnp_random_graph(*args, **kwargs) -> Any: ... -def weakly_connected_components(*args, **kwargs) -> Any: ... diff --git a/retworkx/retworkx_generators.pyi b/retworkx/retworkx_generators.pyi deleted file mode 100644 index 3ae1ce7c3..000000000 --- a/retworkx/retworkx_generators.pyi +++ /dev/null @@ -1,29 +0,0 @@ -# This code is licensed under the Apache License, Version 2.0. You may -# obtain a copy of this license in the LICENSE.txt file in the root directory -# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0. -# -# Any modifications or derivative works of this code must retain this -# copyright notice, and modified files need to carry a notice indicating -# that they have been altered from the originals. - -# This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs - -from typing import Any -from .pygraph import PyGraph -from .pydigraph import PyDiGraph - -def binomial_tree_graph(*args, **kwargs) -> Any: ... -def cycle_graph(*args, **kwargs) -> Any: ... -def directed_binomial_tree_graph(*args, **kwargs) -> Any: ... -def directed_cycle_graph(*args, **kwargs) -> Any: ... -def directed_grid_graph(*args, **kwargs) -> Any: ... -def directed_hexagonal_lattice_graph(*args, **kwargs) -> Any: ... -def directed_mesh_graph(*args, **kwargs) -> Any: ... -def directed_path_graph(*args, **kwargs) -> Any: ... -def directed_star_graph(*args, **kwargs) -> Any: ... -def grid_graph(*args, **kwargs) -> Any: ... -def hexagonal_lattice_graph(*args, **kwargs) -> Any: ... -def mesh_graph(*args, **kwargs) -> Any: ... -def path_graph(*args, **kwargs) -> Any: ... -def star_graph(*args, **kwargs) -> Any: ... From 0ceac477be463f8df995efd06826d0c5fd294ddf Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 16 Oct 2021 12:23:23 -0700 Subject: [PATCH 27/71] Revert changes in setup.py --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index 4c27bf48e..3fe828f02 100644 --- a/setup.py +++ b/setup.py @@ -5,8 +5,6 @@ # Any modifications or derivative works of this code must retain this # copyright notice, and modified files need to carry a notice indicating # that they have been altered from the originals. -import pathlib -import shutil from setuptools import setup try: @@ -24,9 +22,11 @@ def readme(): with open('README.md') as f: return f.read() + mpl_extras = ['matplotlib>=3.0'] graphviz_extras = ['pydot>=1.4', 'pillow>=5.4'] + setup( name="retworkx", version="0.11.0", From 7e2f8837e85be4d0481b3252119fd381387213df Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 16 Oct 2021 12:25:14 -0700 Subject: [PATCH 28/71] Pin mypy version --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 3734bb3ee..d4bc09fe1 100644 --- a/tox.ini +++ b/tox.ini @@ -76,7 +76,7 @@ basepython = python3 envdir = .tox/stubs deps = pytest - mypy + mypy==0.910 pytest-mypy-testing==0.0.8 dataclasses; python_version<'3.7' commands = python -m pytest '../stubs-tests' From 047daba4f97f7001f44370c46e8ec2f41a1e3fef Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 19 Oct 2021 11:57:11 -0700 Subject: [PATCH 29/71] Minor improvements for annotations --- retworkx/__init__.pyi | 1 - retworkx/custom_return_types.pyi | 2 +- retworkx/pydigraph.pyi | 36 ++++++++++++++++---------------- retworkx/pygraph.pyi | 22 +++++++++---------- retworkx/retworkx.pyi | 15 ------------- 5 files changed, 30 insertions(+), 46 deletions(-) diff --git a/retworkx/__init__.pyi b/retworkx/__init__.pyi index 659602633..e82bc0720 100644 --- a/retworkx/__init__.pyi +++ b/retworkx/__init__.pyi @@ -10,6 +10,5 @@ # For implementation details, see __init__.py and lib.rs from .retworkx import * -from typing import Any class PyDAG(PyDiGraph): ... diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index f316b6657..35c2aa9c3 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -9,7 +9,7 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, Dict, Generic, List, Iterable, TypeVar, Tuple +from typing import Any, Generic, List, Iterable, TypeVar, Tuple from collections.abc import Sequence T = TypeVar("T") diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index bc70fa993..b3e82c00f 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -33,8 +33,8 @@ class PyDiGraph(Generic[S, T]): def __init__( self, /, - check_cycle: bool = False, - multigraph: bool = True, + check_cycle: bool = ..., + multigraph: bool = ..., ) -> None: ... def add_child(self, parent: int, obj: S, edge: T, /) -> int: ... def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... @@ -56,8 +56,8 @@ class PyDiGraph(Generic[S, T]): other: PyDiGraph[S, T], node_map: Dict[int, Tuple[int, T]], /, - node_map_func: Optional[Callable[[S], int]] = None, - edge_map_func: Optional[Callable[[T], int]] = None, + node_map_func: Optional[Callable[[S], int]] = ..., + edge_map_func: Optional[Callable[[T], int]] = ..., ) -> Dict[int, int]: ... def copy(self) -> PyDiGraph[S, T]: ... def edge_index_map(self) -> EdgeIndexMap: ... @@ -115,8 +115,8 @@ class PyDiGraph(Generic[S, T]): def read_edge_list( path: str, /, - comment: Optional[str] = None, - deliminator: Optional[str] = None, + comment: Optional[str] = ..., + deliminator: Optional[str] = ..., ) -> PyDiGraph: ... def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... @@ -128,8 +128,8 @@ class PyDiGraph(Generic[S, T]): self, node: int, /, - use_outgoing: Optional[bool] = None, - condition: Optional[Callable[[S, S], bool]] = None, + use_outgoing: Optional[bool] = ..., + condition: Optional[Callable[[S, S], bool]] = ..., ) -> None: ... def remove_nodes_from(self, index_list: List[int], /) -> None: ... def subgraph(self, nodes: List[int], /) -> PyDiGraph[S, T]: ... @@ -139,24 +139,24 @@ class PyDiGraph(Generic[S, T]): other: PyDiGraph[S, T], edge_map_fn: Callable[[int, int, T], Optional[int]], /, - node_filter: Optional[Callable[[S], bool]] = None, - edge_weight_map: Optional[Callable[[T], T]] = None, + node_filter: Optional[Callable[[S], bool]] = ..., + edge_weight_map: Optional[Callable[[T], T]] = ..., ) -> NodeMap: ... def successor_indices(self, node: int, /) -> NodeIndices: ... def successors(self, node: int, /) -> List[S]: ... def to_dot( self, /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = None, - edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, - graph_attr: Optional[Dict[str, str]] = None, - filename: Optional[str] = None, + node_attr: Optional[Callable[[S], Dict[str, str]]] = ..., + edge_attr: Optional[Callable[[T], Dict[str, str]]] = ..., + graph_attr: Optional[Dict[str, str]] = ..., + filename: Optional[str] = ..., ) -> Optional[str]: ... def to_undirected( self, /, - multigraph: bool = True, - weight_combo_fn: Optional[Callable[[T, T], T]] = None, + multigraph: bool = ..., + weight_combo_fn: Optional[Callable[[T, T], T]] = ..., ) -> PyGraph[S, T]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... @@ -165,8 +165,8 @@ class PyDiGraph(Generic[S, T]): self, path: str, /, - deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T], str]] = None, + deliminator: Optional[str] = ..., + weight_fn: Optional[Callable[[T], str]] = ..., ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index 59e82937c..89a8de587 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -28,7 +28,7 @@ T = TypeVar("T") class PyGraph(Generic[S, T]): multigraph: bool = ... - def __init__(self, /, multigraph: bool = True) -> None: ... + def __init__(self, /, multigraph: bool = ...) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... def add_edges_from( self, obj_list: List[Tuple[int, int, T]] @@ -44,8 +44,8 @@ class PyGraph(Generic[S, T]): other: PyGraph[S, T], node_map: Dict[int, Tuple[int, T]], /, - node_map_func: Optional[Callable[[S], int]] = None, - edge_map_func: Optional[Callable[[T], int]] = None, + node_map_func: Optional[Callable[[S], int]] = ..., + edge_map_func: Optional[Callable[[T], int]] = ..., ) -> Dict[int, int]: ... def copy(self) -> PyGraph[S, T]: ... def degree(self, node: int, /) -> int: ... @@ -76,8 +76,8 @@ class PyGraph(Generic[S, T]): def read_edge_list( path: str, /, - comment: Optional[str] = None, - deliminator: Optional[str] = None, + comment: Optional[str] = ..., + deliminator: Optional[str] = ..., ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... @@ -90,10 +90,10 @@ class PyGraph(Generic[S, T]): def to_dot( self, /, - node_attr: Optional[Callable[[S], Dict[str, str]]] = None, - edge_attr: Optional[Callable[[T], Dict[str, str]]] = None, - graph_attr: Optional[Dict[str, str]] = None, - filename: Optional[str] = None, + node_attr: Optional[Callable[[S], Dict[str, str]]] = ..., + edge_attr: Optional[Callable[[T], Dict[str, str]]] = ..., + graph_attr: Optional[Dict[str, str]] = ..., + filename: Optional[str] = ..., ) -> Optional[str]: ... def update_edge(self, source: int, target: int, edge: T, /) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... @@ -102,8 +102,8 @@ class PyGraph(Generic[S, T]): self, path: str, /, - deliminator: Optional[str] = None, - weight_fn: Optional[Callable[[T], str]] = None, + deliminator: Optional[str] = ..., + weight_fn: Optional[Callable[[T], str]] = ..., ) -> None: ... def __delitem__(self, idx: int, /) -> None: ... def __getitem__(self, idx: int, /) -> S: ... diff --git a/retworkx/retworkx.pyi b/retworkx/retworkx.pyi index 66d7776dc..cff46052c 100644 --- a/retworkx/retworkx.pyi +++ b/retworkx/retworkx.pyi @@ -9,25 +9,10 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -import numpy as np from .custom_return_types import * from .pygraph import PyGraph as PyGraph from .pydigraph import PyDiGraph as PyDiGraph -from typing import ( - Any, - Callable, - Dict, - Generic, - TypeVar, - Optional, - List, - Tuple, -) - -S = TypeVar("S") -T = TypeVar("T") - class DAGHasCycle(Exception): ... class DAGWouldCycle(Exception): ... class InvalidNode(Exception): ... From 68d3310def8e09e678a6e2c403caf57a1596dfc6 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 19 Oct 2021 12:05:53 -0700 Subject: [PATCH 30/71] Add release note --- releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml diff --git a/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml b/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml new file mode 100644 index 000000000..3d3e7ed5b --- /dev/null +++ b/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml @@ -0,0 +1,6 @@ +--- +features: + - | + Added type annotations to :class:`~retworkx.PyDiGraph` and + :class:`~retworkx.PyGraph`. They can now be statically type checked + with `mypy `_ From 44a59dec0a063fbfed2f9991d92a755b005c290b Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 19 Oct 2021 12:36:52 -0700 Subject: [PATCH 31/71] Add section to CONTRIBUTING.md about annotations --- CONTRIBUTING.md | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 784ee2fac..67b868e51 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -272,6 +272,25 @@ web browser by running: cargo doc --open ``` +### Type Annotations + +If you have added new methods or changed method signatures, we encourage you to add annotations for +those methods in stub files. The stub files are in the `retworkx` directory and have a `.pyi` file extension. +They contain annotated signatures for Python functions, stripped of their implementation. + +Albeit this step is optional, it is very helpful for end-users. Adding annotations let users type check +their code with [mypy](http://mypy-lang.org/), which can helpful to finding bugs. + +Just like with tests for the code, annotations are also tested via tox. On Linux and Mac OS +machines, the tests can be executed via: + +``` +tox -estubs +``` + +which will execute the annotation tests. We also encourage type annotation contributions +to add tests in the `stubs-tests` directory to verify the correctness of the annotations. + ### Release Notes It is important to document any end user facing changes when we release a new From ac6825ad6e507fe20bccce82c7dc122588ad672b Mon Sep 17 00:00:00 2001 From: Ivan Carvalho <8753214+IvanIsCoding@users.noreply.github.com> Date: Wed, 8 Dec 2021 12:19:03 -0800 Subject: [PATCH 32/71] Apply suggestions from code review Co-authored-by: Jake Lishman --- CONTRIBUTING.md | 6 +++--- MANIFEST.in | 2 +- releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 67b868e51..bd2fd34c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -278,8 +278,8 @@ If you have added new methods or changed method signatures, we encourage you to those methods in stub files. The stub files are in the `retworkx` directory and have a `.pyi` file extension. They contain annotated signatures for Python functions, stripped of their implementation. -Albeit this step is optional, it is very helpful for end-users. Adding annotations let users type check -their code with [mypy](http://mypy-lang.org/), which can helpful to finding bugs. +While this step is optional, it is very helpful for end-users. Adding annotations lets users type check +their code with [mypy](http://mypy-lang.org/), which can be helpful for finding bugs. Just like with tests for the code, annotations are also tested via tox. On Linux and Mac OS machines, the tests can be executed via: @@ -288,7 +288,7 @@ machines, the tests can be executed via: tox -estubs ``` -which will execute the annotation tests. We also encourage type annotation contributions +We also encourage type annotation contributions to add tests in the `stubs-tests` directory to verify the correctness of the annotations. ### Release Notes diff --git a/MANIFEST.in b/MANIFEST.in index 9800a47b8..3aaba2f91 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -4,4 +4,4 @@ include Cargo.toml include Cargo.lock recursive-include src * recursive-include retworkx-core * -recursive-include retworkx *.pyi *.typed +recursive-include retworkx *.pyi py.typed diff --git a/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml b/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml index 3d3e7ed5b..df7a94409 100644 --- a/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml +++ b/releasenotes/notes/graph-annotations-1d436930bf60c5c2.yaml @@ -3,4 +3,4 @@ features: - | Added type annotations to :class:`~retworkx.PyDiGraph` and :class:`~retworkx.PyGraph`. They can now be statically type checked - with `mypy `_ + with `mypy `__. From 9803970302e422ce9d51effff70c6fbc6b39aa92 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 3 Feb 2022 10:42:07 -0800 Subject: [PATCH 33/71] Format with Black --- retworkx/pydigraph.pyi | 32 ++++++++------------------------ retworkx/pygraph.pyi | 16 ++++------------ 2 files changed, 12 insertions(+), 36 deletions(-) diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index b3e82c00f..6edc90292 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -43,9 +43,7 @@ class PyDiGraph(Generic[S, T]): obj_list: List[Tuple[int, int, T]], /, ) -> List[int]: ... - def add_edges_from_no_data( - self, obj_list: List[Tuple[int, int]], / - ) -> List[int]: ... + def add_edges_from_no_data(self, obj_list: List[Tuple[int, int]], /) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... @@ -64,26 +62,18 @@ class PyDiGraph(Generic[S, T]): def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... - def extend_from_edge_list( - self, edge_list: List[Tuple[int, int]], / - ) -> None: ... + def extend_from_edge_list(self, edge_list: List[Tuple[int, int]], /) -> None: ... def extend_from_weighted_edge_list( self, edge_list: List[Tuple[int, int, T]], /, ) -> None: ... - def find_adjacent_node_by_edge( - self, node: int, predicate: Callable[[T], bool], / - ) -> S: ... - def find_node_by_weight( - self, obj: Callable[[S], bool] - ) -> Optional[int]: ... + def find_adjacent_node_by_edge(self, node: int, predicate: Callable[[T], bool], /) -> S: ... + def find_node_by_weight(self, obj: Callable[[S], bool]) -> Optional[int]: ... def find_predecessors_by_edge( self, node: int, filter_fn: Callable[[T], bool], / ) -> List[S]: ... - def find_successors_by_edge( - self, node: int, filter_fn: Callable[[T], bool], / - ) -> List[S]: ... + def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> List[S]: ... @classmethod def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... @@ -93,13 +83,9 @@ class PyDiGraph(Generic[S, T]): def in_degree(self, node: int, /) -> int: ... def in_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_in_edges_multiple( - self, node: int, ref_nodes: List[int], / - ) -> None: ... + def insert_node_on_in_edges_multiple(self, node: int, ref_nodes: List[int], /) -> None: ... def insert_node_on_out_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_out_edges_multiple( - self, node: int, ref_nodes: List[int], / - ) -> None: ... + def insert_node_on_out_edges_multiple(self, node: int, ref_nodes: List[int], /) -> None: ... def is_symmetric(self) -> bool: ... def merge_nodes(self, u: int, v: int, /) -> None: ... def neighbors(self, node: int, /) -> NodeIndices: ... @@ -120,9 +106,7 @@ class PyDiGraph(Generic[S, T]): ) -> PyDiGraph: ... def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from( - self, index_list: List[Tuple[int, int]], / - ) -> None: ... + def remove_edges_from(self, index_list: List[Tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_node_retain_edges( self, diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index 89a8de587..40c772b23 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -30,12 +30,8 @@ class PyGraph(Generic[S, T]): multigraph: bool = ... def __init__(self, /, multigraph: bool = ...) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... - def add_edges_from( - self, obj_list: List[Tuple[int, int, T]] - ) -> List[int]: ... - def add_edges_from_no_data( - self, obj_list: List[Tuple[int, int]], / - ) -> List[int]: ... + def add_edges_from(self, obj_list: List[Tuple[int, int, T]]) -> List[int]: ... + def add_edges_from_no_data(self, obj_list: List[Tuple[int, int]], /) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... def adj(self, node: int, /) -> Dict[int, T]: ... @@ -53,9 +49,7 @@ class PyGraph(Generic[S, T]): def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... - def extend_from_edge_list( - self, edge_list: List[Tuple[int, int]], / - ) -> None: ... + def extend_from_edge_list(self, edge_list: List[Tuple[int, int]], /) -> None: ... def extend_from_weighted_edge_list( self, edge_list: List[Tuple[int, int, T]], @@ -81,9 +75,7 @@ class PyGraph(Generic[S, T]): ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from( - self, index_list: List[Tuple[int, int]], / - ) -> None: ... + def remove_edges_from(self, index_list: List[Tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_nodes_from(self, index_list: List[int], /) -> None: ... def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... From 7190bf517af80817890deca0b05b0a6d267f4c06 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 15 Feb 2022 18:52:52 -0800 Subject: [PATCH 34/71] Update dependencies --- tox.ini | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tox.ini b/tox.ini index 1ab40b65c..96a93a485 100644 --- a/tox.ini +++ b/tox.ini @@ -76,10 +76,9 @@ commands = black {posargs} '../retworkx' '../tests' basepython = python3 envdir = .tox/stubs deps = - pytest - mypy==0.910 - pytest-mypy-testing==0.0.8 - dataclasses; python_version<'3.7' + pytest~=6.2 + mypy==0.931 + pytest-mypy-testing==0.0.9 commands = python -m pytest '../stubs-tests' [flake8] From b35bb025a730a5827d8453d18013141d7506b835 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 15 Feb 2022 18:55:28 -0800 Subject: [PATCH 35/71] Correct pytest-mypy-testing version --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 96a93a485..8e623f0ae 100644 --- a/tox.ini +++ b/tox.ini @@ -78,7 +78,7 @@ envdir = .tox/stubs deps = pytest~=6.2 mypy==0.931 - pytest-mypy-testing==0.0.9 + pytest-mypy-testing==0.0.8 commands = python -m pytest '../stubs-tests' [flake8] From 7d964af0efcab0185d38cffd729b670e4f92311c Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 17:20:06 -0700 Subject: [PATCH 36/71] Move tests to new folder --- {stubs-tests => tests/stubs}/pydigraph_test.py | 16 ++++++++-------- {stubs-tests => tests/stubs}/pygraph_test.py | 16 ++++++++-------- tox.ini | 8 ++++---- 3 files changed, 20 insertions(+), 20 deletions(-) rename {stubs-tests => tests/stubs}/pydigraph_test.py (71%) rename {stubs-tests => tests/stubs}/pygraph_test.py (71%) diff --git a/stubs-tests/pydigraph_test.py b/tests/stubs/pydigraph_test.py similarity index 71% rename from stubs-tests/pydigraph_test.py rename to tests/stubs/pydigraph_test.py index 0b3ffe3d0..04ab9d299 100644 --- a/stubs-tests/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -21,8 +21,8 @@ def test_pydigraph_simple() -> None: node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") edge_ab: int = graph.add_edge(node_a, node_b, 3) - reveal_type(node_a) # note: Revealed type is "builtins.int" - reveal_type(edge_ab) # note: Revealed type is "builtins.int" + reveal_type(node_a) # R: builtins.int + reveal_type(edge_ab) # R: builtins.int @pytest.mark.mypy_testing def test_custom_return_types() -> None: @@ -35,14 +35,14 @@ def test_custom_return_types() -> None: weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() - reveal_type(edges) # note: Revealed type is "EdgeList" - reveal_type(weighted_edges) # note: Revealed type is "WeightedEdgeList[int]" - reveal_type(node_indices) # note: Revealed type is "NodeIndices" + reveal_type(edges) # R: retworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) - reveal_type(list_of_edges) # note: Revealed type is "List[Tuple[int, int]]" - reveal_type(list_of_weights) # note: Revealed type is "List[Tuple[int, int, int]]" - reveal_type(list_of_nodes) # note: Revealed type is "List[int]" + reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_nodes) # R: builtins.list[builtins.int] diff --git a/stubs-tests/pygraph_test.py b/tests/stubs/pygraph_test.py similarity index 71% rename from stubs-tests/pygraph_test.py rename to tests/stubs/pygraph_test.py index 09f209925..030c44f60 100644 --- a/stubs-tests/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -21,8 +21,8 @@ def test_pygraph_simple() -> None: node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") edge_ab: int = graph.add_edge(node_a, node_b, 3) - reveal_type(node_a) # note: Revealed type is "builtins.int" - reveal_type(edge_ab) # note: Revealed type is "builtins.int" + reveal_type(node_a) # R: builtins.int + reveal_type(edge_ab) # R: builtins.int @pytest.mark.mypy_testing def test_custom_return_types() -> None: @@ -35,14 +35,14 @@ def test_custom_return_types() -> None: weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() - reveal_type(edges) # note: Revealed type is "EdgeList" - reveal_type(weighted_edges) # note: Revealed type is "WeightedEdgeList[int]" - reveal_type(node_indices) # note: Revealed type is "NodeIndices" + reveal_type(edges) # R: retworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) - reveal_type(list_of_edges) # note: Revealed type is "List[Tuple[int, int]]" - reveal_type(list_of_weights) # note: Revealed type is "List[Tuple[int, int, int]]" - reveal_type(list_of_nodes) # note: Revealed type is "List[int]" + reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_nodes) # R: builtins.list[builtins.int] diff --git a/tox.ini b/tox.ini index 8e623f0ae..56a06c480 100644 --- a/tox.ini +++ b/tox.ini @@ -76,10 +76,10 @@ commands = black {posargs} '../retworkx' '../tests' basepython = python3 envdir = .tox/stubs deps = - pytest~=6.2 - mypy==0.931 - pytest-mypy-testing==0.0.8 -commands = python -m pytest '../stubs-tests' + pytest~=7.1 + mypy==0.950 + pytest-mypy-testing==0.0.10 +commands = python -m pytest '../tests/stubs-tests' [flake8] # E125 is deliberately excluded. See https://github.com/jcrocholl/pep8/issues/126 From e02561701dc06af5191cc7465fcad9f142a3b4c9 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 17:23:55 -0700 Subject: [PATCH 37/71] Black fmt --- tests/stubs/pydigraph_test.py | 22 +++++++++++++--------- tests/stubs/pygraph_test.py | 22 +++++++++++++--------- 2 files changed, 26 insertions(+), 18 deletions(-) diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index 04ab9d299..0049f6e79 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -15,14 +15,16 @@ import pytest + @pytest.mark.mypy_testing def test_pydigraph_simple() -> None: graph: PyDiGraph[str, int] = PyDiGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") edge_ab: int = graph.add_edge(node_a, node_b, 3) - reveal_type(node_a) # R: builtins.int - reveal_type(edge_ab) # R: builtins.int + reveal_type(node_a) # R: builtins.int + reveal_type(edge_ab) # R: builtins.int + @pytest.mark.mypy_testing def test_custom_return_types() -> None: @@ -34,15 +36,17 @@ def test_custom_return_types() -> None: edges: EdgeList = graph.edge_list() weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() - - reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] - reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + + reveal_type(edges) # R: retworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) - reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] - reveal_type(list_of_nodes) # R: builtins.list[builtins.int] + reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] + reveal_type( + list_of_weights + ) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_nodes) # R: builtins.list[builtins.int] diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 030c44f60..3f0f8a194 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -15,14 +15,16 @@ import pytest + @pytest.mark.mypy_testing def test_pygraph_simple() -> None: graph: PyGraph[str, int] = PyGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") edge_ab: int = graph.add_edge(node_a, node_b, 3) - reveal_type(node_a) # R: builtins.int - reveal_type(edge_ab) # R: builtins.int + reveal_type(node_a) # R: builtins.int + reveal_type(edge_ab) # R: builtins.int + @pytest.mark.mypy_testing def test_custom_return_types() -> None: @@ -34,15 +36,17 @@ def test_custom_return_types() -> None: edges: EdgeList = graph.edge_list() weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() - - reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] - reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + + reveal_type(edges) # R: retworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) - reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] - reveal_type(list_of_nodes) # R: builtins.list[builtins.int] + reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] + reveal_type( + list_of_weights + ) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_nodes) # R: builtins.list[builtins.int] From a83cce7a3f20584c08f6e29df3301a5438e2eaa5 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 17:39:15 -0700 Subject: [PATCH 38/71] Add reveal_type to builtins to help flake8 --- tox.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tox.ini b/tox.ini index 56a06c480..e21479481 100644 --- a/tox.ini +++ b/tox.ini @@ -87,7 +87,9 @@ commands = python -m pytest '../tests/stubs-tests' # E129 skipped because it is too limiting when combined with other rules # E711 skipped because sqlalchemy filter() requires using == instead of is # max-line-length, E203, W503 are added for black compatibility +# builtins includes reveal_type because mypy injects it max-line-length = 110 ignore = E125,E123,E129,E711 extend-ignore = E203, W503 exclude = .venv,.git,.tox,dist,doc,*egg,build +builtins=reveal_type \ No newline at end of file From 59a9f90385e3e9ccd1f6c819f2c2e9b7f0859d73 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 17:54:19 -0700 Subject: [PATCH 39/71] Fix path to tests --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index e21479481..97a74a561 100644 --- a/tox.ini +++ b/tox.ini @@ -79,7 +79,7 @@ deps = pytest~=7.1 mypy==0.950 pytest-mypy-testing==0.0.10 -commands = python -m pytest '../tests/stubs-tests' +commands = python -m pytest '../tests/stubs' [flake8] # E125 is deliberately excluded. See https://github.com/jcrocholl/pep8/issues/126 From c3dad5509bac5d0d595a110d3d00f02db56c6109 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 19:23:22 -0700 Subject: [PATCH 40/71] Fix error due to line split --- retworkx/pydigraph.pyi | 2 +- retworkx/pygraph.pyi | 10 +++++++--- tests/stubs/pydigraph_test.py | 8 +++++--- tests/stubs/pygraph_test.py | 8 +++++--- tox.ini | 5 ++++- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index 6edc90292..cd2406cb0 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -77,7 +77,7 @@ class PyDiGraph(Generic[S, T]): @classmethod def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... def has_edge(self, node_a: int, node_b: int, /) -> bool: ... def in_degree(self, node: int, /) -> int: ... diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index 40c772b23..2ee0c4664 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -31,7 +31,9 @@ class PyGraph(Generic[S, T]): def __init__(self, /, multigraph: bool = ...) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... def add_edges_from(self, obj_list: List[Tuple[int, int, T]]) -> List[int]: ... - def add_edges_from_no_data(self, obj_list: List[Tuple[int, int]], /) -> List[int]: ... + def add_edges_from_no_data( + self: PyGraph[S, Optional[T]], obj_list: List[Tuple[int, int]], / + ) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... def adj(self, node: int, /) -> Dict[int, T]: ... @@ -49,7 +51,9 @@ class PyGraph(Generic[S, T]): def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... - def extend_from_edge_list(self, edge_list: List[Tuple[int, int]], /) -> None: ... + def extend_from_edge_list( + self: PyGraph[Optional[S], Optional[T]], edge_list: List[Tuple[int, int]], / + ) -> None: ... def extend_from_weighted_edge_list( self, edge_list: List[Tuple[int, int, T]], @@ -58,7 +62,7 @@ class PyGraph(Generic[S, T]): @classmethod def from_adjacency_matrix(matrix: np.array, /) -> PyGraph: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... - def get_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... + def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... def has_edge(self, node_a: int, node_b: int, /) -> bool: ... def neighbors(self, node: int, /) -> NodeIndices: ... diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index 0049f6e79..febf9e30b 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -37,16 +37,18 @@ def test_custom_return_types() -> None: weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() + # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + # fmt: on list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) + # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type( - list_of_weights - ) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] reveal_type(list_of_nodes) # R: builtins.list[builtins.int] + # fmt: on diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 3f0f8a194..3834e2e74 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -37,16 +37,18 @@ def test_custom_return_types() -> None: weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() + # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + # fmt: on list_of_edges: List[Tuple[int, int]] = list(edges) list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) + # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type( - list_of_weights - ) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] reveal_type(list_of_nodes) # R: builtins.list[builtins.int] + # fmt: on diff --git a/tox.ini b/tox.ini index 97a74a561..38896ea06 100644 --- a/tox.ini +++ b/tox.ini @@ -88,8 +88,11 @@ commands = python -m pytest '../tests/stubs' # E711 skipped because sqlalchemy filter() requires using == instead of is # max-line-length, E203, W503 are added for black compatibility # builtins includes reveal_type because mypy injects it +# pytest-mypy-testing needs reveal_type to be a one-liner hence we ignore lenght warnings max-line-length = 110 ignore = E125,E123,E129,E711 extend-ignore = E203, W503 exclude = .venv,.git,.tox,dist,doc,*egg,build -builtins=reveal_type \ No newline at end of file +builtins=reveal_type +per-file-ignores = + tests/stubs/*:E501 \ No newline at end of file From ed8ea1c7bd837ae48b2f7d4029838a19719c55d5 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 19:46:52 -0700 Subject: [PATCH 41/71] Do not test stubs on Python 3.7 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 84e915aca..a2c92858e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,7 +90,7 @@ jobs: run: tox -epy - name: 'Run stubs-tests' run: tox -estubs - if: runner.os == 'Linux' + if: runner.os == 'Linux' && ${{ matrix.python-version }} != 3.7 coverage: needs: [tests] name: Coverage From 63c87a6a9b7c94484992d1ad98f40dea080102ed Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 23:09:14 -0700 Subject: [PATCH 42/71] Add test cases handling restricted methods --- retworkx/pydigraph.pyi | 8 ++- tests/stubs/restrict_operations_test.py | 86 +++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 tests/stubs/restrict_operations_test.py diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index cd2406cb0..253d51bdc 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -43,7 +43,9 @@ class PyDiGraph(Generic[S, T]): obj_list: List[Tuple[int, int, T]], /, ) -> List[int]: ... - def add_edges_from_no_data(self, obj_list: List[Tuple[int, int]], /) -> List[int]: ... + def add_edges_from_no_data( + self: PyDiGraph[S, Optional[T]], obj_list: List[Tuple[int, int]], / + ) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... @@ -62,7 +64,9 @@ class PyDiGraph(Generic[S, T]): def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... - def extend_from_edge_list(self, edge_list: List[Tuple[int, int]], /) -> None: ... + def extend_from_edge_list( + self: PyDiGraph[Optional[S], Optional[T]], edge_list: List[Tuple[int, int]], / + ) -> None: ... def extend_from_weighted_edge_list( self, edge_list: List[Tuple[int, int, T]], diff --git a/tests/stubs/restrict_operations_test.py b/tests/stubs/restrict_operations_test.py new file mode 100644 index 000000000..16151d51d --- /dev/null +++ b/tests/stubs/restrict_operations_test.py @@ -0,0 +1,86 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from typing import List, Tuple, Optional +from retworkx import PyGraph, PyDiGraph + +import pytest + + +@pytest.mark.mypy_testing +def test_pygraph_add_edges_from_no_data_illegal() -> None: + graph: PyGraph[str, float] = PyGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + + # fmt: off + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + # fmt: on + + +@pytest.mark.mypy_testing +def test_pygraph_add_edges_from_no_data_legal() -> None: + graph: PyGraph[str, Optional[float]] = PyGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + + graph.add_edges_from_no_data([(node_a, node_b)]) + + +@pytest.mark.mypy_testing +def test_pygraph_extend_from_edge_list_illegal() -> None: + graph: PyGraph[str, float] = PyGraph() + + # fmt: off + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + # fmt: on + + +@pytest.mark.mypy_testing +def test_pygraph_extend_from_edge_list_legal() -> None: + graph: PyGraph[Optional[str], Optional[float]] = PyGraph() + graph.extend_from_edge_list([(0, 5)]) + + +@pytest.mark.mypy_testing +def test_pydigraph_add_edges_from_no_data_illegal() -> None: + graph: PyDiGraph[str, float] = PyDiGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + + # fmt: off + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + # fmt: on + + +@pytest.mark.mypy_testing +def test_pydigraph_add_edges_from_no_data_legal() -> None: + graph: PyDiGraph[str, Optional[float]] = PyDiGraph() + node_a: int = graph.add_node("A") + node_b: int = graph.add_node("B") + + graph.add_edges_from_no_data([(node_a, node_b)]) + + +@pytest.mark.mypy_testing +def test_pydigraph_extend_from_edge_list_illegal() -> None: + graph: PyDiGraph[str, float] = PyDiGraph() + + # fmt: off + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + # fmt: on + + +@pytest.mark.mypy_testing +def test_pydigraph_extend_from_edge_list_legal() -> None: + graph: PyDiGraph[Optional[str], Optional[float]] = PyDiGraph() + graph.extend_from_edge_list([(0, 5)]) From ed0c0535ec4bcab41a376fbb7fd925460bf78823 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Thu, 5 May 2022 23:17:44 -0700 Subject: [PATCH 43/71] Handle lint --- .github/workflows/main.yml | 2 +- tests/stubs/restrict_operations_test.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a2c92858e..f1549ef48 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,7 +39,7 @@ jobs: - name: Black Codestyle Format run: black --check --diff retworkx tests - name: Python Lint - run: flake8 --per-file-ignores='retworkx/__init__.py:F405,F403' setup.py retworkx tests + run: flake8 --per-file-ignores='retworkx/__init__.py:F405,F403 tests/stubs/*:E501' setup.py retworkx tests - name: retworkx-core Rust Tests run: pushd retworkx-core && cargo test && popd - name: retworkx-core Docs diff --git a/tests/stubs/restrict_operations_test.py b/tests/stubs/restrict_operations_test.py index 16151d51d..2a073ea02 100644 --- a/tests/stubs/restrict_operations_test.py +++ b/tests/stubs/restrict_operations_test.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -from typing import List, Tuple, Optional +from typing import Optional from retworkx import PyGraph, PyDiGraph import pytest @@ -23,7 +23,7 @@ def test_pygraph_add_edges_from_no_data_illegal() -> None: node_b: int = graph.add_node("B") # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" # fmt: on @@ -41,7 +41,7 @@ def test_pygraph_extend_from_edge_list_illegal() -> None: graph: PyGraph[str, float] = PyGraph() # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" # fmt: on @@ -58,7 +58,7 @@ def test_pydigraph_add_edges_from_no_data_illegal() -> None: node_b: int = graph.add_node("B") # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" # fmt: on @@ -76,7 +76,7 @@ def test_pydigraph_extend_from_edge_list_illegal() -> None: graph: PyDiGraph[str, float] = PyDiGraph() # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" # fmt: on From 54a795c72a899500fca12176da1bb4b7be9635e5 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Fri, 6 May 2022 10:39:02 -0700 Subject: [PATCH 44/71] Use Sequence instead of lists --- retworkx/pydigraph.pyi | 21 +++++++++++---------- retworkx/pygraph.pyi | 17 +++++++++-------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index 253d51bdc..efb2d32d8 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -22,6 +22,7 @@ from typing import ( Optional, List, Tuple, + Sequence ) S = TypeVar("S") @@ -40,14 +41,14 @@ class PyDiGraph(Generic[S, T]): def add_edge(self, parent: int, child: int, edge: T, /) -> int: ... def add_edges_from( self, - obj_list: List[Tuple[int, int, T]], + obj_list: Sequence[Tuple[int, int, T]], /, ) -> List[int]: ... def add_edges_from_no_data( - self: PyDiGraph[S, Optional[T]], obj_list: List[Tuple[int, int]], / + self: PyDiGraph[S, Optional[T]], obj_list: Sequence[Tuple[int, int]], / ) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... - def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def add_nodes_from(self, obj_list: Sequence[S], /) -> NodeIndices: ... def add_parent(self, child: int, obj: S, edge: T, /) -> int: ... def adj(self, node: int, /) -> Dict[int, T]: ... def adj_direction(self, node: int, direction: bool, /) -> Dict[int, T]: ... @@ -65,11 +66,11 @@ class PyDiGraph(Generic[S, T]): def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... def extend_from_edge_list( - self: PyDiGraph[Optional[S], Optional[T]], edge_list: List[Tuple[int, int]], / + self: PyDiGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( self, - edge_list: List[Tuple[int, int, T]], + edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... def find_adjacent_node_by_edge(self, node: int, predicate: Callable[[T], bool], /) -> S: ... @@ -87,9 +88,9 @@ class PyDiGraph(Generic[S, T]): def in_degree(self, node: int, /) -> int: ... def in_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def insert_node_on_in_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_in_edges_multiple(self, node: int, ref_nodes: List[int], /) -> None: ... + def insert_node_on_in_edges_multiple(self, node: int, ref_nodes: Sequence[int], /) -> None: ... def insert_node_on_out_edges(self, node: int, ref_node: int, /) -> None: ... - def insert_node_on_out_edges_multiple(self, node: int, ref_nodes: List[int], /) -> None: ... + def insert_node_on_out_edges_multiple(self, node: int, ref_nodes: Sequence[int], /) -> None: ... def is_symmetric(self) -> bool: ... def merge_nodes(self, u: int, v: int, /) -> None: ... def neighbors(self, node: int, /) -> NodeIndices: ... @@ -110,7 +111,7 @@ class PyDiGraph(Generic[S, T]): ) -> PyDiGraph: ... def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from(self, index_list: List[Tuple[int, int]], /) -> None: ... + def remove_edges_from(self, index_list: Sequence[Tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_node_retain_edges( self, @@ -119,8 +120,8 @@ class PyDiGraph(Generic[S, T]): use_outgoing: Optional[bool] = ..., condition: Optional[Callable[[S, S], bool]] = ..., ) -> None: ... - def remove_nodes_from(self, index_list: List[int], /) -> None: ... - def subgraph(self, nodes: List[int], /) -> PyDiGraph[S, T]: ... + def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... + def subgraph(self, nodes: Sequence[int], /) -> PyDiGraph[S, T]: ... def substitute_node_with_subgraph( self, node: int, diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index 2ee0c4664..b13d2f21f 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -21,6 +21,7 @@ from typing import ( Optional, List, Tuple, + Sequence, ) S = TypeVar("S") @@ -30,12 +31,12 @@ class PyGraph(Generic[S, T]): multigraph: bool = ... def __init__(self, /, multigraph: bool = ...) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... - def add_edges_from(self, obj_list: List[Tuple[int, int, T]]) -> List[int]: ... + def add_edges_from(self, obj_list: Sequence[Tuple[int, int, T]]) -> List[int]: ... def add_edges_from_no_data( - self: PyGraph[S, Optional[T]], obj_list: List[Tuple[int, int]], / + self: PyGraph[S, Optional[T]], obj_list: Sequence[Tuple[int, int]], / ) -> List[int]: ... def add_node(self, obj: S, /) -> int: ... - def add_nodes_from(self, obj_list: List[S], /) -> NodeIndices: ... + def add_nodes_from(self, obj_list: Sequence[S], /) -> NodeIndices: ... def adj(self, node: int, /) -> Dict[int, T]: ... def compose( self, @@ -52,11 +53,11 @@ class PyGraph(Generic[S, T]): def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... def extend_from_edge_list( - self: PyGraph[Optional[S], Optional[T]], edge_list: List[Tuple[int, int]], / + self: PyGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( self, - edge_list: List[Tuple[int, int, T]], + edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... @classmethod @@ -79,10 +80,10 @@ class PyGraph(Generic[S, T]): ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... - def remove_edges_from(self, index_list: List[Tuple[int, int]], /) -> None: ... + def remove_edges_from(self, index_list: Sequence[Tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... - def remove_nodes_from(self, index_list: List[int], /) -> None: ... - def subgraph(self, nodes: List[int], /) -> PyGraph[S, T]: ... + def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... + def subgraph(self, nodes: Sequence[int], /) -> PyGraph[S, T]: ... def to_dot( self, /, From 8f22bb739ae63d139f389f7583b174f50e2c68df Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Fri, 6 May 2022 10:54:03 -0700 Subject: [PATCH 45/71] Minor updates in tests --- retworkx/pydigraph.pyi | 12 +----------- tests/stubs/pydigraph_test.py | 16 ++++++++-------- tests/stubs/pygraph_test.py | 16 ++++++++-------- tests/stubs/restrict_operations_test.py | 8 ++++---- 4 files changed, 21 insertions(+), 31 deletions(-) diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index efb2d32d8..2248cc476 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -13,17 +13,7 @@ import numpy as np from .custom_return_types import * from .pygraph import PyGraph -from typing import ( - Any, - Callable, - Dict, - Generic, - TypeVar, - Optional, - List, - Tuple, - Sequence -) +from typing import Any, Callable, Dict, Generic, TypeVar, Optional, List, Tuple, Sequence S = TypeVar("S") T = TypeVar("T") diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index febf9e30b..8e19b3449 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -18,37 +18,37 @@ @pytest.mark.mypy_testing def test_pydigraph_simple() -> None: - graph: PyDiGraph[str, int] = PyDiGraph() + graph: PyDiGraph[str, float] = PyDiGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") - edge_ab: int = graph.add_edge(node_a, node_b, 3) + edge_ab: int = graph.add_edge(node_a, node_b, 3.5) reveal_type(node_a) # R: builtins.int reveal_type(edge_ab) # R: builtins.int @pytest.mark.mypy_testing def test_custom_return_types() -> None: - graph: PyDiGraph[str, int] = PyDiGraph() + graph: PyDiGraph[str, float] = PyDiGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") - graph.add_edge(node_a, node_b, 3) + graph.add_edge(node_a, node_b, 3.5) edges: EdgeList = graph.edge_list() - weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() + weighted_edges: WeightedEdgeList[float] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.float] reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices # fmt: on list_of_edges: List[Tuple[int, int]] = list(edges) - list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) + list_of_weights: List[Tuple[int, int, float]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.float]] reveal_type(list_of_nodes) # R: builtins.list[builtins.int] # fmt: on diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 3834e2e74..709fc4eca 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -18,37 +18,37 @@ @pytest.mark.mypy_testing def test_pygraph_simple() -> None: - graph: PyGraph[str, int] = PyGraph() + graph: PyGraph[str, float] = PyGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") - edge_ab: int = graph.add_edge(node_a, node_b, 3) + edge_ab: int = graph.add_edge(node_a, node_b, 3.5) reveal_type(node_a) # R: builtins.int reveal_type(edge_ab) # R: builtins.int @pytest.mark.mypy_testing def test_custom_return_types() -> None: - graph: PyGraph[str, int] = PyGraph() + graph: PyGraph[str, float] = PyGraph() node_a: int = graph.add_node("A") node_b: int = graph.add_node("B") - graph.add_edge(node_a, node_b, 3) + graph.add_edge(node_a, node_b, 3.5) edges: EdgeList = graph.edge_list() - weighted_edges: WeightedEdgeList[int] = graph.weighted_edge_list() + weighted_edges: WeightedEdgeList[float] = graph.weighted_edge_list() node_indices: NodeIndices = graph.node_indexes() # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.int] + reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.float] reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices # fmt: on list_of_edges: List[Tuple[int, int]] = list(edges) - list_of_weights: List[Tuple[int, int, int]] = list(weighted_edges) + list_of_weights: List[Tuple[int, int, float]] = list(weighted_edges) list_of_nodes: List[int] = list(node_indices) # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.int]] + reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.float]] reveal_type(list_of_nodes) # R: builtins.list[builtins.int] # fmt: on diff --git a/tests/stubs/restrict_operations_test.py b/tests/stubs/restrict_operations_test.py index 2a073ea02..5ca58a263 100644 --- a/tests/stubs/restrict_operations_test.py +++ b/tests/stubs/restrict_operations_test.py @@ -23,7 +23,7 @@ def test_pygraph_add_edges_from_no_data_illegal() -> None: node_b: int = graph.add_node("B") # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], Sequence[Tuple[int, int]]], List[int]]" # fmt: on @@ -41,7 +41,7 @@ def test_pygraph_extend_from_edge_list_illegal() -> None: graph: PyGraph[str, float] = PyGraph() # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], Sequence[Tuple[int, int]]], None]" # fmt: on @@ -58,7 +58,7 @@ def test_pydigraph_add_edges_from_no_data_illegal() -> None: node_b: int = graph.add_node("B") # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], List[Tuple[int, int]]], List[int]]" + graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], Sequence[Tuple[int, int]]], List[int]]" # fmt: on @@ -76,7 +76,7 @@ def test_pydigraph_extend_from_edge_list_illegal() -> None: graph: PyDiGraph[str, float] = PyDiGraph() # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], List[Tuple[int, int]]], None]" + graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], Sequence[Tuple[int, int]]], None]" # fmt: on From 342d2f585ed97d5b532abb151e6c476bfb17f286 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Fri, 6 May 2022 15:44:04 -0700 Subject: [PATCH 46/71] Completely rewrite custom type annotations --- retworkx/custom_return_types.pyi | 256 +++++++------------------------ 1 file changed, 54 insertions(+), 202 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index 35c2aa9c3..15bfeea69 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -9,229 +9,81 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, Generic, List, Iterable, TypeVar, Tuple -from collections.abc import Sequence +from typing import Any, Generic, List, Iterable, Mapping, TypeVar, Tuple, overload +from collections.abc import ABC, Sequence -T = TypeVar("T") +# Until PEP 673 is implemented in Python 3.11, we need to use this hack +Self = TypeVar("Self", bound="RetworkxCustomVecIter") -class NodeIndices(Sequence[int]): - def __init__(self) -> None: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> int: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +S = TypeVar("S") +T_co = TypeVar("T_co", covariant=True) -class PathLengthMapping: +class RetworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, float]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[float]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> float: ... + def __eq__(self, other: Sequence[T_co]) -> bool: ... + @overload + def __getitem__(self, index: int) -> T_co: ... + @overload + def __getitem__(self: Self, index: slice) -> Self: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... + def __ne__(self, other: Sequence[T_co]) -> bool: ... def __setstate__(self, state) -> None: ... -class PathMapping: +class RetworkxCustomHashMapIter(Generic[S], Generic[T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, NodeIndices]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[NodeIndices]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> NodeIndices: ... + def items(self) -> Iterable[Tuple[S, T_co]]: ... + def keys(self) -> Iterable[S]: ... + def values(self) -> Iterable[T_co]: ... + def __contains__(self, other: S) -> bool: ... + def __eq__(self, other: Mapping[S, T_co]) -> bool: ... + def __getitem__(self, index: S) -> T_co: ... def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... + def __iter__(self) -> Iterable[S]: ... def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... + def __ne__(self, other: Mapping[S, T_co]) -> bool: ... def __setstate__(self, state) -> None: ... -class AllPairsPathLengthMapping: - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, PathLengthMapping]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[PathLengthMapping]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> PathLengthMapping: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class NodeIndices(RetworkxCustomVecIter[int]): + pass -class AllPairsPathMapping: - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, PathMapping]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[PathMapping]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> PathMapping: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class PathLengthMapping(RetworkxCustomHashMapIter[int, float]): + pass -class BFSSuccessors(Generic[T]): - def __init__(self) -> None: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> Tuple[T, List[T]]: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class PathMapping(RetworkxCustomHashMapIter[int, NodeIndices]): + pass -class EdgeIndexMap(Generic[T]): - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, Tuple[int, int, T]]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[Tuple[int, int, T]]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> Tuple[int, int, T]: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class AllPairsPathLengthMapping(RetworkxCustomHashMapIter[int, PathLengthMapping]): + pass -class EdgeIndices: - def __init__(self) -> None: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> int: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class AllPairsPathMapping(RetworkxCustomHashMapIter[int, PathMapping]): + pass -class EdgeList(Sequence[Tuple[int, int]]): - def __init__(self) -> None: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> Tuple[int, int]: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class BFSSuccessors(Generic[T_co], RetworkxCustomVecIter[Tuple[T_co, List[T_co]]]): + pass -class NodeMap: - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, int]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[int]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> int: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class EdgeIndexMap(Generic[T_co], RetworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): + pass -class NodesCountMapping: - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, int]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[int]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> int: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class EdgeIndices(RetworkxCustomVecIter[int]): + pass -class Pos2DMapping: - def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[int, Tuple[float, float]]]: ... - def keys(self) -> Iterable[int]: ... - def values(self) -> Iterable[Tuple[float, float]]: ... - def __contains__(self, other) -> int: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> Tuple[float, float]: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __iter__(self) -> Iterable[int]: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class Chains(RetworkxCustomVecIter[EdgeIndices]): + pass -class WeightedEdgeList(Generic[T], Sequence[Tuple[int, int, T]]): - def __init__(self) -> None: ... - def __eq__(self, other) -> bool: ... - def __ge__(self, other) -> bool: ... - def __getitem__(self, index: int) -> Tuple[int, int, T]: ... - def __getstate__(self) -> Any: ... - def __gt__(self, other) -> bool: ... - def __hash__(self) -> int: ... - def __le__(self, other) -> bool: ... - def __len__(self) -> int: ... - def __lt__(self, other) -> bool: ... - def __ne__(self, other) -> bool: ... - def __setstate__(self, state) -> None: ... +class EdgeList(RetworkxCustomVecIter[Tuple[int, int]]): + pass + +class NodeMap(RetworkxCustomHashMapIter[int, int]): + pass + +class NodesCountMapping(RetworkxCustomHashMapIter[int, int]): + pass + +class Pos2DMapping(RetworkxCustomHashMapIter[int, Tuple[float, float]]): + pass + +class WeightedEdgeList(Generic[T_co], RetworkxCustomVecIter[Tuple[int, int, T_co]]): + pass From 23c9a6dd91e0590b2d0141761cd3962a412d1cb8 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Fri, 6 May 2022 17:29:30 -0700 Subject: [PATCH 47/71] Make PyDAG be generic --- CONTRIBUTING.md | 2 +- retworkx/__init__.pyi | 6 +++++- retworkx/custom_return_types.pyi | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a740c9abf..3e218227c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -289,7 +289,7 @@ tox -estubs ``` We also encourage type annotation contributions -to add tests in the `stubs-tests` directory to verify the correctness of the annotations. +to add tests in the `tests/stubs` directory to verify the correctness of the annotations. ### Release Notes diff --git a/retworkx/__init__.pyi b/retworkx/__init__.pyi index e82bc0720..6b2aab0fc 100644 --- a/retworkx/__init__.pyi +++ b/retworkx/__init__.pyi @@ -10,5 +10,9 @@ # For implementation details, see __init__.py and lib.rs from .retworkx import * +from typing import Generic, TypeVar -class PyDAG(PyDiGraph): ... +S = TypeVar("S") +T = TypeVar("T") + +class PyDAG(Generic[S, T], PyDiGraph[S, T]): ... diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index 15bfeea69..9468a4d5b 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -31,7 +31,7 @@ class RetworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __ne__(self, other: Sequence[T_co]) -> bool: ... def __setstate__(self, state) -> None: ... -class RetworkxCustomHashMapIter(Generic[S], Generic[T_co], Mapping[S, T_co], ABC): +class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... def items(self) -> Iterable[Tuple[S, T_co]]: ... def keys(self) -> Iterable[S]: ... From d0cb298b871d5e380cdae008f78321a77d431095 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 7 May 2022 14:01:26 -0700 Subject: [PATCH 48/71] Shorten custom return types --- retworkx/custom_return_types.pyi | 55 ++++++++------------------------ 1 file changed, 14 insertions(+), 41 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index 9468a4d5b..c8eaa50dc 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -46,44 +46,17 @@ class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __ne__(self, other: Mapping[S, T_co]) -> bool: ... def __setstate__(self, state) -> None: ... -class NodeIndices(RetworkxCustomVecIter[int]): - pass - -class PathLengthMapping(RetworkxCustomHashMapIter[int, float]): - pass - -class PathMapping(RetworkxCustomHashMapIter[int, NodeIndices]): - pass - -class AllPairsPathLengthMapping(RetworkxCustomHashMapIter[int, PathLengthMapping]): - pass - -class AllPairsPathMapping(RetworkxCustomHashMapIter[int, PathMapping]): - pass - -class BFSSuccessors(Generic[T_co], RetworkxCustomVecIter[Tuple[T_co, List[T_co]]]): - pass - -class EdgeIndexMap(Generic[T_co], RetworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): - pass - -class EdgeIndices(RetworkxCustomVecIter[int]): - pass - -class Chains(RetworkxCustomVecIter[EdgeIndices]): - pass - -class EdgeList(RetworkxCustomVecIter[Tuple[int, int]]): - pass - -class NodeMap(RetworkxCustomHashMapIter[int, int]): - pass - -class NodesCountMapping(RetworkxCustomHashMapIter[int, int]): - pass - -class Pos2DMapping(RetworkxCustomHashMapIter[int, Tuple[float, float]]): - pass - -class WeightedEdgeList(Generic[T_co], RetworkxCustomVecIter[Tuple[int, int, T_co]]): - pass +class NodeIndices(RetworkxCustomVecIter[int]): ... +class PathLengthMapping(RetworkxCustomHashMapIter[int, float]): ... +class PathMapping(RetworkxCustomHashMapIter[int, NodeIndices]): ... +class AllPairsPathLengthMapping(RetworkxCustomHashMapIter[int, PathLengthMapping]): ... +class AllPairsPathMapping(RetworkxCustomHashMapIter[int, PathMapping]): ... +class BFSSuccessors(Generic[T_co], RetworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... +class EdgeIndexMap(Generic[T_co], RetworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... +class EdgeIndices(RetworkxCustomVecIter[int]): ... +class Chains(RetworkxCustomVecIter[EdgeIndices]): ... +class EdgeList(RetworkxCustomVecIter[Tuple[int, int]]): ... +class NodeMap(RetworkxCustomHashMapIter[int, int]): ... +class NodesCountMapping(RetworkxCustomHashMapIter[int, int]): ... +class Pos2DMapping(RetworkxCustomHashMapIter[int, Tuple[float, float]]): ... +class WeightedEdgeList(Generic[T_co], RetworkxCustomVecIter[Tuple[int, int, T_co]]): ... From fc16d4143fe911dfa51c8d51de3b9ea68997f195 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 7 May 2022 14:22:21 -0700 Subject: [PATCH 49/71] Correct extend_from_weighted_edge_list signature --- retworkx/pydigraph.pyi | 2 +- retworkx/pygraph.pyi | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index 2248cc476..7ba5a714c 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -59,7 +59,7 @@ class PyDiGraph(Generic[S, T]): self: PyDiGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self, + self: PyDiGraph[Optional[S], T], edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index b13d2f21f..b05a011ff 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -56,7 +56,7 @@ class PyGraph(Generic[S, T]): self: PyGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self, + self: self: PyGraph[Optional[S], T],, edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... From b34afe401fd22a0143f7a9ad6c36b7f424be3450 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 7 May 2022 14:30:16 -0700 Subject: [PATCH 50/71] Fix signature --- retworkx/pygraph.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index b05a011ff..4d1b1a2c0 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -56,7 +56,7 @@ class PyGraph(Generic[S, T]): self: PyGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self: self: PyGraph[Optional[S], T],, + self: PyGraph[Optional[S], T],, edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... From 2bb0ac3937b248bc5f4378e7a88f5d5821269de8 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Sat, 7 May 2022 14:33:56 -0700 Subject: [PATCH 51/71] Yet another signature fix --- retworkx/pygraph.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index 4d1b1a2c0..fdd6c9e23 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -56,7 +56,7 @@ class PyGraph(Generic[S, T]): self: PyGraph[Optional[S], Optional[T]], edge_list: Sequence[Tuple[int, int]], / ) -> None: ... def extend_from_weighted_edge_list( - self: PyGraph[Optional[S], T],, + self: PyGraph[Optional[S], T], edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... From 42f77ac06f0fb59116ac45f4ad93c726859bd5d5 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 16 May 2022 17:14:41 -0700 Subject: [PATCH 52/71] Use Self from typing_extensions --- retworkx/custom_return_types.pyi | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index c8eaa50dc..2c97dfafe 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -11,9 +11,7 @@ from typing import Any, Generic, List, Iterable, Mapping, TypeVar, Tuple, overload from collections.abc import ABC, Sequence - -# Until PEP 673 is implemented in Python 3.11, we need to use this hack -Self = TypeVar("Self", bound="RetworkxCustomVecIter") +from typing_extensions import Self S = TypeVar("S") T_co = TypeVar("T_co", covariant=True) From ff58a0cfd67d37c8a8b0768831be89d3770b235d Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 16 May 2022 18:03:16 -0700 Subject: [PATCH 53/71] Address PR comments --- tests/stubs/pydigraph_test.py | 22 +++++++++++----------- tests/stubs/pygraph_test.py | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index 8e19b3449..183f947b3 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -19,9 +19,9 @@ @pytest.mark.mypy_testing def test_pydigraph_simple() -> None: graph: PyDiGraph[str, float] = PyDiGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - edge_ab: int = graph.add_edge(node_a, node_b, 3.5) + node_a = graph.add_node("A") + node_b = graph.add_node("B") + edge_ab = graph.add_edge(node_a, node_b, 3.5) reveal_type(node_a) # R: builtins.int reveal_type(edge_ab) # R: builtins.int @@ -29,13 +29,13 @@ def test_pydigraph_simple() -> None: @pytest.mark.mypy_testing def test_custom_return_types() -> None: graph: PyDiGraph[str, float] = PyDiGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") + node_a = graph.add_node("A") + node_b = graph.add_node("B") graph.add_edge(node_a, node_b, 3.5) - edges: EdgeList = graph.edge_list() - weighted_edges: WeightedEdgeList[float] = graph.weighted_edge_list() - node_indices: NodeIndices = graph.node_indexes() + edges = graph.edge_list() + weighted_edges = graph.weighted_edge_list() + node_indices = graph.node_indexes() # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList @@ -43,9 +43,9 @@ def test_custom_return_types() -> None: reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices # fmt: on - list_of_edges: List[Tuple[int, int]] = list(edges) - list_of_weights: List[Tuple[int, int, float]] = list(weighted_edges) - list_of_nodes: List[int] = list(node_indices) + list_of_edges = list(edges) + list_of_weights = list(weighted_edges) + list_of_nodes = list(node_indices) # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 709fc4eca..8706872be 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -19,9 +19,9 @@ @pytest.mark.mypy_testing def test_pygraph_simple() -> None: graph: PyGraph[str, float] = PyGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - edge_ab: int = graph.add_edge(node_a, node_b, 3.5) + node_a = graph.add_node("A") + node_b = graph.add_node("B") + edge_ab = graph.add_edge(node_a, node_b, 3.5) reveal_type(node_a) # R: builtins.int reveal_type(edge_ab) # R: builtins.int @@ -29,13 +29,13 @@ def test_pygraph_simple() -> None: @pytest.mark.mypy_testing def test_custom_return_types() -> None: graph: PyGraph[str, float] = PyGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") + node_a = graph.add_node("A") + node_b = graph.add_node("B") graph.add_edge(node_a, node_b, 3.5) - edges: EdgeList = graph.edge_list() - weighted_edges: WeightedEdgeList[float] = graph.weighted_edge_list() - node_indices: NodeIndices = graph.node_indexes() + edges = graph.edge_list() + weighted_edges = graph.weighted_edge_list() + node_indices = graph.node_indexes() # fmt: off reveal_type(edges) # R: retworkx.custom_return_types.EdgeList @@ -43,9 +43,9 @@ def test_custom_return_types() -> None: reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices # fmt: on - list_of_edges: List[Tuple[int, int]] = list(edges) - list_of_weights: List[Tuple[int, int, float]] = list(weighted_edges) - list_of_nodes: List[int] = list(node_indices) + list_of_edges = list(edges) + list_of_weights = list(weighted_edges) + list_of_nodes = list(node_indices) # fmt: off reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] From a7aaf481911dd35732eda8d71be4cfd15536912e Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 16 May 2022 18:10:01 -0700 Subject: [PATCH 54/71] Address lint --- tests/stubs/pydigraph_test.py | 3 +-- tests/stubs/pygraph_test.py | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index 183f947b3..5cb65f783 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -10,8 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -from typing import List, Tuple -from retworkx import EdgeList, PyDiGraph, NodeIndices, WeightedEdgeList +from retworkx import PyDiGraph import pytest diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 8706872be..682ed1179 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -10,8 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -from typing import List, Tuple -from retworkx import EdgeList, PyGraph, NodeIndices, WeightedEdgeList +from retworkx import PyGraph import pytest From 20777a6d8aee70d2c2f68c5ffd8146dae433929f Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 17 May 2022 12:46:21 -0700 Subject: [PATCH 55/71] Add __str__ and from_complex_adjacency_matrix --- retworkx/custom_return_types.pyi | 6 ++++-- retworkx/pydigraph.pyi | 6 ++++-- retworkx/pygraph.pyi | 6 ++++-- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/retworkx/custom_return_types.pyi b/retworkx/custom_return_types.pyi index 2c97dfafe..53aa2714c 100644 --- a/retworkx/custom_return_types.pyi +++ b/retworkx/custom_return_types.pyi @@ -25,9 +25,10 @@ class RetworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __getitem__(self: Self, index: slice) -> Self: ... def __getstate__(self) -> Any: ... def __hash__(self) -> int: ... + def __str__(self) -> str: ... def __len__(self) -> int: ... def __ne__(self, other: Sequence[T_co]) -> bool: ... - def __setstate__(self, state) -> None: ... + def __setstate__(self, state: Sequence[T_co]) -> None: ... class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... @@ -39,10 +40,11 @@ class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __getitem__(self, index: S) -> T_co: ... def __getstate__(self) -> Any: ... def __hash__(self) -> int: ... + def __str__(self) -> str: ... def __iter__(self) -> Iterable[S]: ... def __len__(self) -> int: ... def __ne__(self, other: Mapping[S, T_co]) -> bool: ... - def __setstate__(self, state) -> None: ... + def __setstate__(self, state: Mapping[S, T_co]) -> None: ... class NodeIndices(RetworkxCustomVecIter[int]): ... class PathLengthMapping(RetworkxCustomHashMapIter[int, float]): ... diff --git a/retworkx/pydigraph.pyi b/retworkx/pydigraph.pyi index 7ba5a714c..39748effb 100644 --- a/retworkx/pydigraph.pyi +++ b/retworkx/pydigraph.pyi @@ -51,7 +51,7 @@ class PyDiGraph(Generic[S, T]): edge_map_func: Optional[Callable[[T], int]] = ..., ) -> Dict[int, int]: ... def copy(self) -> PyDiGraph[S, T]: ... - def edge_index_map(self) -> EdgeIndexMap: ... + def edge_index_map(self) -> EdgeIndexMap[T]: ... def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... @@ -70,7 +70,9 @@ class PyDiGraph(Generic[S, T]): ) -> List[S]: ... def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> List[S]: ... @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph: ... + def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph[int, float]: ... + @classmethod + def from_complex_adjacency_matrix(matrix: np.array, /) -> PyDiGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... diff --git a/retworkx/pygraph.pyi b/retworkx/pygraph.pyi index fdd6c9e23..bd82e8d87 100644 --- a/retworkx/pygraph.pyi +++ b/retworkx/pygraph.pyi @@ -48,7 +48,7 @@ class PyGraph(Generic[S, T]): ) -> Dict[int, int]: ... def copy(self) -> PyGraph[S, T]: ... def degree(self, node: int, /) -> int: ... - def edge_index_map(self) -> EdgeIndexMap: ... + def edge_index_map(self) -> EdgeIndexMap[T]: ... def edge_indices(self) -> EdgeIndices: ... def edge_list(self) -> EdgeList: ... def edges(self) -> List[T]: ... @@ -61,7 +61,9 @@ class PyGraph(Generic[S, T]): /, ) -> None: ... @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyGraph: ... + def from_adjacency_matrix(matrix: np.array, /) -> PyGraph[int, float]: ... + @classmethod + def from_complex_adjacency_matrix(matrix: np.array, /) -> PyGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... From f6bc49f880d690d78c5eac3a2de15f264a796458 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 1 Aug 2022 15:33:25 -0700 Subject: [PATCH 56/71] Rename to rustworkx --- .github/workflows/main.yml | 3 +++ CONTRIBUTING.md | 4 ++-- {retworkx => rustworkx}/__init__.pyi | 2 +- {retworkx => rustworkx}/custom_return_types.pyi | 0 {retworkx => rustworkx}/py.typed | 0 {retworkx => rustworkx}/pydigraph.pyi | 0 {retworkx => rustworkx}/pygraph.pyi | 0 retworkx/retworkx.pyi => rustworkx/rustworkx.pyi | 0 tests/stubs/pydigraph_test.py | 8 ++++---- tests/stubs/pygraph_test.py | 8 ++++---- tests/stubs/restrict_operations_test.py | 2 +- 11 files changed, 15 insertions(+), 12 deletions(-) rename {retworkx => rustworkx}/__init__.pyi (96%) rename {retworkx => rustworkx}/custom_return_types.pyi (100%) rename {retworkx => rustworkx}/py.typed (100%) rename {retworkx => rustworkx}/pydigraph.pyi (100%) rename {retworkx => rustworkx}/pygraph.pyi (100%) rename retworkx/retworkx.pyi => rustworkx/rustworkx.pyi (100%) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 8ebd016a0..5a0962be0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -88,6 +88,9 @@ jobs: if: runner.os == 'Linux' - name: 'Run tests' run: tox -epy + - name: 'Run stubs-tests' + run: tox -estubs + if: runner.os == 'Linux' tests_retworkx_compat: needs: [build_lint] name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} ${{ matrix.msrv }} diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0cc79c80..94e0f70a2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -16,7 +16,7 @@ contributing to rustworkx, these are documented below. ### Making changes to the code -Retworkx is implemented primarily in Rust with a thin layer of Python. +Rustworkx is implemented primarily in Rust with a thin layer of Python. Because of that, most of your code changes will involve modifications to Rust files in `src`. To understand which files you need to change, we invite you for an overview of our simplified source tree: @@ -275,7 +275,7 @@ cargo doc --open ### Type Annotations If you have added new methods or changed method signatures, we encourage you to add annotations for -those methods in stub files. The stub files are in the `retworkx` directory and have a `.pyi` file extension. +those methods in stub files. The stub files are in the `rustworkx` directory and have a `.pyi` file extension. They contain annotated signatures for Python functions, stripped of their implementation. While this step is optional, it is very helpful for end-users. Adding annotations lets users type check diff --git a/retworkx/__init__.pyi b/rustworkx/__init__.pyi similarity index 96% rename from retworkx/__init__.pyi rename to rustworkx/__init__.pyi index 6b2aab0fc..7b5d23ebd 100644 --- a/retworkx/__init__.pyi +++ b/rustworkx/__init__.pyi @@ -9,7 +9,7 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from .retworkx import * +from .rustworkx import * from typing import Generic, TypeVar S = TypeVar("S") diff --git a/retworkx/custom_return_types.pyi b/rustworkx/custom_return_types.pyi similarity index 100% rename from retworkx/custom_return_types.pyi rename to rustworkx/custom_return_types.pyi diff --git a/retworkx/py.typed b/rustworkx/py.typed similarity index 100% rename from retworkx/py.typed rename to rustworkx/py.typed diff --git a/retworkx/pydigraph.pyi b/rustworkx/pydigraph.pyi similarity index 100% rename from retworkx/pydigraph.pyi rename to rustworkx/pydigraph.pyi diff --git a/retworkx/pygraph.pyi b/rustworkx/pygraph.pyi similarity index 100% rename from retworkx/pygraph.pyi rename to rustworkx/pygraph.pyi diff --git a/retworkx/retworkx.pyi b/rustworkx/rustworkx.pyi similarity index 100% rename from retworkx/retworkx.pyi rename to rustworkx/rustworkx.pyi diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py index 5cb65f783..920fc4603 100644 --- a/tests/stubs/pydigraph_test.py +++ b/tests/stubs/pydigraph_test.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -from retworkx import PyDiGraph +from rustworkx import PyDiGraph import pytest @@ -37,9 +37,9 @@ def test_custom_return_types() -> None: node_indices = graph.node_indexes() # fmt: off - reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.float] - reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + reveal_type(edges) # R: rustworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: rustworkx.custom_return_types.WeightedEdgeList[builtins.float] + reveal_type(node_indices) # R: rustworkx.custom_return_types.NodeIndices # fmt: on list_of_edges = list(edges) diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py index 682ed1179..8d6fbd967 100644 --- a/tests/stubs/pygraph_test.py +++ b/tests/stubs/pygraph_test.py @@ -10,7 +10,7 @@ # License for the specific language governing permissions and limitations # under the License. -from retworkx import PyGraph +from rustworkx import PyGraph import pytest @@ -37,9 +37,9 @@ def test_custom_return_types() -> None: node_indices = graph.node_indexes() # fmt: off - reveal_type(edges) # R: retworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: retworkx.custom_return_types.WeightedEdgeList[builtins.float] - reveal_type(node_indices) # R: retworkx.custom_return_types.NodeIndices + reveal_type(edges) # R: rustworkx.custom_return_types.EdgeList + reveal_type(weighted_edges) # R: rustworkx.custom_return_types.WeightedEdgeList[builtins.float] + reveal_type(node_indices) # R: rustworkx.custom_return_types.NodeIndices # fmt: on list_of_edges = list(edges) diff --git a/tests/stubs/restrict_operations_test.py b/tests/stubs/restrict_operations_test.py index 5ca58a263..13b7e5497 100644 --- a/tests/stubs/restrict_operations_test.py +++ b/tests/stubs/restrict_operations_test.py @@ -11,7 +11,7 @@ # under the License. from typing import Optional -from retworkx import PyGraph, PyDiGraph +from rustworkx import PyGraph, PyDiGraph import pytest From 0cd9c9fb793cb9366c66883aa976566589a0d772 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 1 Aug 2022 15:34:46 -0700 Subject: [PATCH 57/71] Change name of in custom_return_types.pyi --- rustworkx/custom_return_types.pyi | 32 +++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/rustworkx/custom_return_types.pyi b/rustworkx/custom_return_types.pyi index 53aa2714c..9cf2314a8 100644 --- a/rustworkx/custom_return_types.pyi +++ b/rustworkx/custom_return_types.pyi @@ -16,7 +16,7 @@ from typing_extensions import Self S = TypeVar("S") T_co = TypeVar("T_co", covariant=True) -class RetworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): +class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __init__(self) -> None: ... def __eq__(self, other: Sequence[T_co]) -> bool: ... @overload @@ -30,7 +30,7 @@ class RetworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __ne__(self, other: Sequence[T_co]) -> bool: ... def __setstate__(self, state: Sequence[T_co]) -> None: ... -class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): +class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... def items(self) -> Iterable[Tuple[S, T_co]]: ... def keys(self) -> Iterable[S]: ... @@ -46,17 +46,17 @@ class RetworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __ne__(self, other: Mapping[S, T_co]) -> bool: ... def __setstate__(self, state: Mapping[S, T_co]) -> None: ... -class NodeIndices(RetworkxCustomVecIter[int]): ... -class PathLengthMapping(RetworkxCustomHashMapIter[int, float]): ... -class PathMapping(RetworkxCustomHashMapIter[int, NodeIndices]): ... -class AllPairsPathLengthMapping(RetworkxCustomHashMapIter[int, PathLengthMapping]): ... -class AllPairsPathMapping(RetworkxCustomHashMapIter[int, PathMapping]): ... -class BFSSuccessors(Generic[T_co], RetworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... -class EdgeIndexMap(Generic[T_co], RetworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... -class EdgeIndices(RetworkxCustomVecIter[int]): ... -class Chains(RetworkxCustomVecIter[EdgeIndices]): ... -class EdgeList(RetworkxCustomVecIter[Tuple[int, int]]): ... -class NodeMap(RetworkxCustomHashMapIter[int, int]): ... -class NodesCountMapping(RetworkxCustomHashMapIter[int, int]): ... -class Pos2DMapping(RetworkxCustomHashMapIter[int, Tuple[float, float]]): ... -class WeightedEdgeList(Generic[T_co], RetworkxCustomVecIter[Tuple[int, int, T_co]]): ... +class NodeIndices(RustworkxCustomVecIter[int]): ... +class PathLengthMapping(RustworkxCustomHashMapIter[int, float]): ... +class PathMapping(RustworkxCustomHashMapIter[int, NodeIndices]): ... +class AllPairsPathLengthMapping(RustworkxCustomHashMapIter[int, PathLengthMapping]): ... +class AllPairsPathMapping(RustworkxCustomHashMapIter[int, PathMapping]): ... +class BFSSuccessors(Generic[T_co], RustworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... +class EdgeIndexMap(Generic[T_co], RustworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... +class EdgeIndices(RustworkxCustomVecIter[int]): ... +class Chains(RustworkxCustomVecIter[EdgeIndices]): ... +class EdgeList(RustworkxCustomVecIter[Tuple[int, int]]): ... +class NodeMap(RustworkxCustomHashMapIter[int, int]): ... +class NodesCountMapping(RustworkxCustomHashMapIter[int, int]): ... +class Pos2DMapping(RustworkxCustomHashMapIter[int, Tuple[float, float]]): ... +class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[Tuple[int, int, T_co]]): ... From dc0d9b3cca896e97f2697ed24a73dd4c0a55981c Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 1 Aug 2022 16:48:11 -0700 Subject: [PATCH 58/71] Skip tests if Python < 3.8 --- tests/stubs/conftest.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tests/stubs/conftest.py diff --git a/tests/stubs/conftest.py b/tests/stubs/conftest.py new file mode 100644 index 000000000..050ecc8ff --- /dev/null +++ b/tests/stubs/conftest.py @@ -0,0 +1,6 @@ +# Configure Pytest to ignore stub tests in early versions +import sys + +collect_ignore_glob = [] +if sys.version_info < (3, 8): + collect_ignore_glob.append("*.py") From ad83bab59a8bdfc4fb09752b57204658532dac47 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Mon, 1 Aug 2022 17:24:21 -0700 Subject: [PATCH 59/71] Ignore no tests found --- tests/stubs/conftest.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/stubs/conftest.py b/tests/stubs/conftest.py index 050ecc8ff..a7b43783a 100644 --- a/tests/stubs/conftest.py +++ b/tests/stubs/conftest.py @@ -2,5 +2,10 @@ import sys collect_ignore_glob = [] -if sys.version_info < (3, 8): +if sys.version_info < (3, 12): collect_ignore_glob.append("*.py") + + +def pytest_sessionfinish(session, exitstatus): + if exitstatus == 5: + session.exitstatus = 0 # ignore no tests found, it's intentional From 05c7d605eb674d48b00f8f588afbe7bf0427422e Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 12:08:48 -0800 Subject: [PATCH 60/71] Try using pytest==7.1.3 --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 506cded75..4ebb812ce 100644 --- a/tox.ini +++ b/tox.ini @@ -60,7 +60,7 @@ commands = black {posargs} '../rustworkx' '../tests' '../retworkx' basepython = python3 envdir = .tox/stubs deps = - pytest~=7.1 + pytest==7.1.3 mypy==0.950 pytest-mypy-testing==0.0.10 commands = python -m pytest '../tests/stubs' From 37d3c232b230d8bef102a6bdd0aa591d6e75f46a Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 15:10:29 -0800 Subject: [PATCH 61/71] Improvements after running mypy.stubtest --- rustworkx/custom_return_types.pyi | 40 ++++++++++++++++++++++--------- rustworkx/pydigraph.pyi | 2 ++ rustworkx/pygraph.pyi | 2 ++ 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/rustworkx/custom_return_types.pyi b/rustworkx/custom_return_types.pyi index 9cf2314a8..d131d5e23 100644 --- a/rustworkx/custom_return_types.pyi +++ b/rustworkx/custom_return_types.pyi @@ -9,16 +9,34 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, Generic, List, Iterable, Mapping, TypeVar, Tuple, overload -from collections.abc import ABC, Sequence +from typing import Any, Generic, List, ItemsView, KeysView, ValuesView, Iterator, Mapping, TypeVar, Tuple, overload +from abc import ABC +from collections.abc import Sequence from typing_extensions import Self S = TypeVar("S") T_co = TypeVar("T_co", covariant=True) +__all__ = [ + 'NodeIndices', + 'PathLengthMapping', + 'PathMapping', + 'AllPairsPathLengthMapping', + 'AllPairsPathMapping', + 'BFSSuccessors', + 'EdgeIndexMap', + 'EdgeIndices', + 'Chains', + 'EdgeList', + 'NodeMap', + 'NodesCountMapping', + 'Pos2DMapping', + 'WeightedEdgeList', +] + class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __init__(self) -> None: ... - def __eq__(self, other: Sequence[T_co]) -> bool: ... + def __eq__(self, other: object) -> bool: ... @overload def __getitem__(self, index: int) -> T_co: ... @overload @@ -27,23 +45,23 @@ class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __hash__(self) -> int: ... def __str__(self) -> str: ... def __len__(self) -> int: ... - def __ne__(self, other: Sequence[T_co]) -> bool: ... + def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Sequence[T_co]) -> None: ... class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... - def items(self) -> Iterable[Tuple[S, T_co]]: ... - def keys(self) -> Iterable[S]: ... - def values(self) -> Iterable[T_co]: ... - def __contains__(self, other: S) -> bool: ... - def __eq__(self, other: Mapping[S, T_co]) -> bool: ... + def items(self) -> ItemsView[S, T_co]: ... + def keys(self) -> KeysView[S]: ... + def values(self) -> ValuesView[T_co]: ... + def __contains__(self, other: object) -> bool: ... + def __eq__(self, other: object) -> bool: ... def __getitem__(self, index: S) -> T_co: ... def __getstate__(self) -> Any: ... def __hash__(self) -> int: ... def __str__(self) -> str: ... - def __iter__(self) -> Iterable[S]: ... + def __iter__(self) -> Iterator[S]: ... def __len__(self) -> int: ... - def __ne__(self, other: Mapping[S, T_co]) -> bool: ... + def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Mapping[S, T_co]) -> None: ... class NodeIndices(RustworkxCustomVecIter[int]): ... diff --git a/rustworkx/pydigraph.pyi b/rustworkx/pydigraph.pyi index 39748effb..28f13a4b7 100644 --- a/rustworkx/pydigraph.pyi +++ b/rustworkx/pydigraph.pyi @@ -15,6 +15,8 @@ from .pygraph import PyGraph from typing import Any, Callable, Dict, Generic, TypeVar, Optional, List, Tuple, Sequence +__all__ = ['PyDiGraph'] + S = TypeVar("S") T = TypeVar("T") diff --git a/rustworkx/pygraph.pyi b/rustworkx/pygraph.pyi index bd82e8d87..4958bf205 100644 --- a/rustworkx/pygraph.pyi +++ b/rustworkx/pygraph.pyi @@ -24,6 +24,8 @@ from typing import ( Sequence, ) +__all__ = ['PyGraph'] + S = TypeVar("S") T = TypeVar("T") From 5e9c86ee7f3832b1e9cab3953eb6040f577c2788 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 15:33:35 -0800 Subject: [PATCH 62/71] More improvements after mypy.stubtest --- rustworkx/custom_return_types.pyi | 19 ++++++++++++++++++- rustworkx/pydigraph.pyi | 10 +++++----- rustworkx/pygraph.pyi | 10 +++++----- rustworkx/rustworkx.pyi | 3 +++ src/digraph.rs | 2 +- src/graph.rs | 2 +- 6 files changed, 33 insertions(+), 13 deletions(-) diff --git a/rustworkx/custom_return_types.pyi b/rustworkx/custom_return_types.pyi index d131d5e23..892f5019f 100644 --- a/rustworkx/custom_return_types.pyi +++ b/rustworkx/custom_return_types.pyi @@ -9,11 +9,13 @@ # This file contains only type annotations for PyO3 functions and classes # For implementation details, see __init__.py and lib.rs -from typing import Any, Generic, List, ItemsView, KeysView, ValuesView, Iterator, Mapping, TypeVar, Tuple, overload +from typing import Any, Generic, List, ItemsView, KeysView, ValuesView, Iterator, Mapping, TypeVar, Tuple, overload, final from abc import ABC from collections.abc import Sequence from typing_extensions import Self +import numpy as np + S = TypeVar("S") T_co = TypeVar("T_co", covariant=True) @@ -47,6 +49,7 @@ class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __len__(self) -> int: ... def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Sequence[T_co]) -> None: ... + def __array__(self, _dt: np.dtype=...) -> np.ndarray: ... class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... @@ -64,17 +67,31 @@ class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Mapping[S, T_co]) -> None: ... +@final class NodeIndices(RustworkxCustomVecIter[int]): ... +@final class PathLengthMapping(RustworkxCustomHashMapIter[int, float]): ... +@final class PathMapping(RustworkxCustomHashMapIter[int, NodeIndices]): ... +@final class AllPairsPathLengthMapping(RustworkxCustomHashMapIter[int, PathLengthMapping]): ... +@final class AllPairsPathMapping(RustworkxCustomHashMapIter[int, PathMapping]): ... +@final class BFSSuccessors(Generic[T_co], RustworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... +@final class EdgeIndexMap(Generic[T_co], RustworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... +@final class EdgeIndices(RustworkxCustomVecIter[int]): ... +@final class Chains(RustworkxCustomVecIter[EdgeIndices]): ... +@final class EdgeList(RustworkxCustomVecIter[Tuple[int, int]]): ... +@final class NodeMap(RustworkxCustomHashMapIter[int, int]): ... +@final class NodesCountMapping(RustworkxCustomHashMapIter[int, int]): ... +@final class Pos2DMapping(RustworkxCustomHashMapIter[int, Tuple[float, float]]): ... +@final class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[Tuple[int, int, T_co]]): ... diff --git a/rustworkx/pydigraph.pyi b/rustworkx/pydigraph.pyi index 28f13a4b7..f4f23429c 100644 --- a/rustworkx/pydigraph.pyi +++ b/rustworkx/pydigraph.pyi @@ -71,10 +71,10 @@ class PyDiGraph(Generic[S, T]): self, node: int, filter_fn: Callable[[T], bool], / ) -> List[S]: ... def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> List[S]: ... - @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyDiGraph[int, float]: ... - @classmethod - def from_complex_adjacency_matrix(matrix: np.array, /) -> PyDiGraph[int, complex]: ... + @staticmethod + def from_adjacency_matrix(matrix: np.ndarray, /) -> PyDiGraph[int, float]: ... + @staticmethod + def from_complex_adjacency_matrix(matrix: np.ndarray, /) -> PyDiGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... @@ -96,7 +96,7 @@ class PyDiGraph(Generic[S, T]): def out_edges(self, node: int, /) -> WeightedEdgeList[T]: ... def predecessor_indices(self, node: int, /) -> NodeIndices: ... def predecessors(self, node: int, /) -> List[S]: ... - @classmethod + @staticmethod def read_edge_list( path: str, /, diff --git a/rustworkx/pygraph.pyi b/rustworkx/pygraph.pyi index 4958bf205..e3fa405b6 100644 --- a/rustworkx/pygraph.pyi +++ b/rustworkx/pygraph.pyi @@ -62,10 +62,10 @@ class PyGraph(Generic[S, T]): edge_list: Sequence[Tuple[int, int, T]], /, ) -> None: ... - @classmethod - def from_adjacency_matrix(matrix: np.array, /) -> PyGraph[int, float]: ... - @classmethod - def from_complex_adjacency_matrix(matrix: np.array, /) -> PyGraph[int, complex]: ... + @staticmethod + def from_adjacency_matrix(matrix: np.ndarray, /) -> PyGraph[int, float]: ... + @staticmethod + def from_complex_adjacency_matrix(matrix: np.ndarray, /) -> PyGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... @@ -75,7 +75,7 @@ class PyGraph(Generic[S, T]): def nodes(self) -> List[S]: ... def num_edges(self) -> int: ... def num_nodes(self) -> int: ... - @classmethod + @staticmethod def read_edge_list( path: str, /, diff --git a/rustworkx/rustworkx.pyi b/rustworkx/rustworkx.pyi index cff46052c..d6ae3006d 100644 --- a/rustworkx/rustworkx.pyi +++ b/rustworkx/rustworkx.pyi @@ -20,3 +20,6 @@ class NoEdgeBetweenNodes(Exception): ... class NoPathFound(Exception): ... class NoSuitableNeighbors(Exception): ... class NullGraph(Exception): ... +class NegativeCycle(Exception): ... +class JSONSerializationError(Exception): ... +class FailedToConverge(Exception): ... \ No newline at end of file diff --git a/src/digraph.rs b/src/digraph.rs index 0fcddde12..7ece57dc9 100644 --- a/src/digraph.rs +++ b/src/digraph.rs @@ -1066,7 +1066,7 @@ impl PyDiGraph { /// ``(source, target, weight)`` where source and target are integer /// node indices. If the node index is not present in the graph /// nodes will be added (with a node weight of ``None``) to that index. - #[pyo3(text_signature = "(self, edge_lsit, /)")] + #[pyo3(text_signature = "(self, edge_list, /)")] pub fn extend_from_weighted_edge_list( &mut self, py: Python, diff --git a/src/graph.rs b/src/graph.rs index c718ce930..e8bef2776 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -850,7 +850,7 @@ impl PyGraph { /// ``(source, target, weight)`` where source and target are integer /// node indices. If the node index is not present in the graph, /// nodes will be added (with a node weight of ``None``) to that index. - #[pyo3(text_signature = "(self, edge_lsit, /)")] + #[pyo3(text_signature = "(self, edge_list, /)")] pub fn extend_from_weighted_edge_list( &mut self, py: Python, From c24f8f836c3068d1d6a88e21230213fbbe1ade2e Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 15:41:47 -0800 Subject: [PATCH 63/71] Make .pyi file names identical to Rust names --- rustworkx/__init__.pyi | 2 +- rustworkx/{pydigraph.pyi => digraph.pyi} | 8 +-- rustworkx/{pygraph.pyi => graph.pyi} | 6 +- ...{custom_return_types.pyi => iterators.pyi} | 62 +++++++++++++------ rustworkx/rustworkx.pyi | 10 +-- 5 files changed, 57 insertions(+), 31 deletions(-) rename rustworkx/{pydigraph.pyi => digraph.pyi} (97%) rename rustworkx/{pygraph.pyi => graph.pyi} (97%) rename rustworkx/{custom_return_types.pyi => iterators.pyi} (81%) diff --git a/rustworkx/__init__.pyi b/rustworkx/__init__.pyi index 7b5d23ebd..979e6df4f 100644 --- a/rustworkx/__init__.pyi +++ b/rustworkx/__init__.pyi @@ -7,7 +7,7 @@ # that they have been altered from the originals. # This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs +# For implementation details, see __init__.py and src/lib.rs from .rustworkx import * from typing import Generic, TypeVar diff --git a/rustworkx/pydigraph.pyi b/rustworkx/digraph.pyi similarity index 97% rename from rustworkx/pydigraph.pyi rename to rustworkx/digraph.pyi index f4f23429c..67cdfdadb 100644 --- a/rustworkx/pydigraph.pyi +++ b/rustworkx/digraph.pyi @@ -7,15 +7,15 @@ # that they have been altered from the originals. # This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs +# For implementation details, see __init__.py and src/digraph.rs import numpy as np -from .custom_return_types import * -from .pygraph import PyGraph +from .iterators import * +from .graph import PyGraph from typing import Any, Callable, Dict, Generic, TypeVar, Optional, List, Tuple, Sequence -__all__ = ['PyDiGraph'] +__all__ = ["PyDiGraph"] S = TypeVar("S") T = TypeVar("T") diff --git a/rustworkx/pygraph.pyi b/rustworkx/graph.pyi similarity index 97% rename from rustworkx/pygraph.pyi rename to rustworkx/graph.pyi index e3fa405b6..e3d54dcc1 100644 --- a/rustworkx/pygraph.pyi +++ b/rustworkx/graph.pyi @@ -7,10 +7,10 @@ # that they have been altered from the originals. # This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs +# For implementation details, see __init__.py and src/graph.rs import numpy as np -from .custom_return_types import * +from .iterators import * from typing import ( Any, @@ -24,7 +24,7 @@ from typing import ( Sequence, ) -__all__ = ['PyGraph'] +__all__ = ["PyGraph"] S = TypeVar("S") T = TypeVar("T") diff --git a/rustworkx/custom_return_types.pyi b/rustworkx/iterators.pyi similarity index 81% rename from rustworkx/custom_return_types.pyi rename to rustworkx/iterators.pyi index 892f5019f..2ed7fc8c5 100644 --- a/rustworkx/custom_return_types.pyi +++ b/rustworkx/iterators.pyi @@ -7,11 +7,24 @@ # that they have been altered from the originals. # This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs +# For implementation details, see __init__.py and src/iterators.rs -from typing import Any, Generic, List, ItemsView, KeysView, ValuesView, Iterator, Mapping, TypeVar, Tuple, overload, final +from typing import ( + Any, + Generic, + List, + ItemsView, + KeysView, + ValuesView, + Iterator, + Mapping, + TypeVar, + Tuple, + overload, + final, +) from abc import ABC -from collections.abc import Sequence +from collections.abc import Sequence from typing_extensions import Self import numpy as np @@ -20,20 +33,20 @@ S = TypeVar("S") T_co = TypeVar("T_co", covariant=True) __all__ = [ - 'NodeIndices', - 'PathLengthMapping', - 'PathMapping', - 'AllPairsPathLengthMapping', - 'AllPairsPathMapping', - 'BFSSuccessors', - 'EdgeIndexMap', - 'EdgeIndices', - 'Chains', - 'EdgeList', - 'NodeMap', - 'NodesCountMapping', - 'Pos2DMapping', - 'WeightedEdgeList', + "NodeIndices", + "PathLengthMapping", + "PathMapping", + "AllPairsPathLengthMapping", + "AllPairsPathMapping", + "BFSSuccessors", + "EdgeIndexMap", + "EdgeIndices", + "Chains", + "EdgeList", + "NodeMap", + "NodesCountMapping", + "Pos2DMapping", + "WeightedEdgeList", ] class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): @@ -49,7 +62,7 @@ class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): def __len__(self) -> int: ... def __ne__(self, other: object) -> bool: ... def __setstate__(self, state: Sequence[T_co]) -> None: ... - def __array__(self, _dt: np.dtype=...) -> np.ndarray: ... + def __array__(self, _dt: np.dtype = ...) -> np.ndarray: ... class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): def __init__(self) -> None: ... @@ -69,29 +82,42 @@ class RustworkxCustomHashMapIter(Generic[S, T_co], Mapping[S, T_co], ABC): @final class NodeIndices(RustworkxCustomVecIter[int]): ... + @final class PathLengthMapping(RustworkxCustomHashMapIter[int, float]): ... + @final class PathMapping(RustworkxCustomHashMapIter[int, NodeIndices]): ... + @final class AllPairsPathLengthMapping(RustworkxCustomHashMapIter[int, PathLengthMapping]): ... + @final class AllPairsPathMapping(RustworkxCustomHashMapIter[int, PathMapping]): ... + @final class BFSSuccessors(Generic[T_co], RustworkxCustomVecIter[Tuple[T_co, List[T_co]]]): ... + @final class EdgeIndexMap(Generic[T_co], RustworkxCustomHashMapIter[int, Tuple[int, int, T_co]]): ... + @final class EdgeIndices(RustworkxCustomVecIter[int]): ... + @final class Chains(RustworkxCustomVecIter[EdgeIndices]): ... + @final class EdgeList(RustworkxCustomVecIter[Tuple[int, int]]): ... + @final class NodeMap(RustworkxCustomHashMapIter[int, int]): ... + @final class NodesCountMapping(RustworkxCustomHashMapIter[int, int]): ... + @final class Pos2DMapping(RustworkxCustomHashMapIter[int, Tuple[float, float]]): ... + @final class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[Tuple[int, int, T_co]]): ... diff --git a/rustworkx/rustworkx.pyi b/rustworkx/rustworkx.pyi index d6ae3006d..d0924ccac 100644 --- a/rustworkx/rustworkx.pyi +++ b/rustworkx/rustworkx.pyi @@ -7,11 +7,11 @@ # that they have been altered from the originals. # This file contains only type annotations for PyO3 functions and classes -# For implementation details, see __init__.py and lib.rs +# For implementation details, see __init__.py and src/lib.rs -from .custom_return_types import * -from .pygraph import PyGraph as PyGraph -from .pydigraph import PyDiGraph as PyDiGraph +from .iterators import * +from .graph import PyGraph as PyGraph +from .digraph import PyDiGraph as PyDiGraph class DAGHasCycle(Exception): ... class DAGWouldCycle(Exception): ... @@ -22,4 +22,4 @@ class NoSuitableNeighbors(Exception): ... class NullGraph(Exception): ... class NegativeCycle(Exception): ... class JSONSerializationError(Exception): ... -class FailedToConverge(Exception): ... \ No newline at end of file +class FailedToConverge(Exception): ... From a441d395ac2a16926e0f1d1ec89028a8651cd415 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:16:25 -0800 Subject: [PATCH 64/71] Make mypy.stubtest happy --- rustworkx/digraph.pyi | 19 ++++++++++++++----- rustworkx/graph.pyi | 25 ++++++++++++++++++++----- rustworkx/iterators.pyi | 21 +++++++++++++++++++++ src/digraph.rs | 4 ++-- src/graph.rs | 2 +- 5 files changed, 58 insertions(+), 13 deletions(-) diff --git a/rustworkx/digraph.pyi b/rustworkx/digraph.pyi index 67cdfdadb..6ac2b5087 100644 --- a/rustworkx/digraph.pyi +++ b/rustworkx/digraph.pyi @@ -66,15 +66,23 @@ class PyDiGraph(Generic[S, T]): /, ) -> None: ... def find_adjacent_node_by_edge(self, node: int, predicate: Callable[[T], bool], /) -> S: ... - def find_node_by_weight(self, obj: Callable[[S], bool]) -> Optional[int]: ... + def find_node_by_weight( + self, + obj: Callable[[S], bool], + /, + ) -> Optional[int]: ... def find_predecessors_by_edge( self, node: int, filter_fn: Callable[[T], bool], / ) -> List[S]: ... def find_successors_by_edge(self, node: int, filter_fn: Callable[[T], bool], /) -> List[S]: ... @staticmethod - def from_adjacency_matrix(matrix: np.ndarray, /) -> PyDiGraph[int, float]: ... + def from_adjacency_matrix( + matrix: np.ndarray, /, null_value: float = ... + ) -> PyDiGraph[int, float]: ... @staticmethod - def from_complex_adjacency_matrix(matrix: np.ndarray, /) -> PyDiGraph[int, complex]: ... + def from_complex_adjacency_matrix( + matrix: np.ndarray, /, null_value: complex = ... + ) -> PyDiGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... @@ -102,6 +110,7 @@ class PyDiGraph(Generic[S, T]): /, comment: Optional[str] = ..., deliminator: Optional[str] = ..., + labels: bool = ..., ) -> PyDiGraph: ... def remove_edge(self, parent: int, child: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... @@ -115,7 +124,7 @@ class PyDiGraph(Generic[S, T]): condition: Optional[Callable[[S, S], bool]] = ..., ) -> None: ... def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... - def subgraph(self, nodes: Sequence[int], /) -> PyDiGraph[S, T]: ... + def subgraph(self, nodes: Sequence[int], /, preserve_attrs: bool = ...) -> PyDiGraph[S, T]: ... def substitute_node_with_subgraph( self, node: int, @@ -141,7 +150,7 @@ class PyDiGraph(Generic[S, T]): multigraph: bool = ..., weight_combo_fn: Optional[Callable[[T, T], T]] = ..., ) -> PyGraph[S, T]: ... - def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge(self, source: int, target: int, edge: T, /,) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... def weighted_edge_list(self) -> WeightedEdgeList[T]: ... def write_edge_list( diff --git a/rustworkx/graph.pyi b/rustworkx/graph.pyi index e3d54dcc1..7277c1eda 100644 --- a/rustworkx/graph.pyi +++ b/rustworkx/graph.pyi @@ -33,7 +33,11 @@ class PyGraph(Generic[S, T]): multigraph: bool = ... def __init__(self, /, multigraph: bool = ...) -> None: ... def add_edge(self, node_a: int, node_b: int, edge: T, /) -> int: ... - def add_edges_from(self, obj_list: Sequence[Tuple[int, int, T]]) -> List[int]: ... + def add_edges_from( + self, + obj_list: Sequence[Tuple[int, int, T]], + /, + ) -> List[int]: ... def add_edges_from_no_data( self: PyGraph[S, Optional[T]], obj_list: Sequence[Tuple[int, int]], / ) -> List[int]: ... @@ -63,9 +67,13 @@ class PyGraph(Generic[S, T]): /, ) -> None: ... @staticmethod - def from_adjacency_matrix(matrix: np.ndarray, /) -> PyGraph[int, float]: ... + def from_adjacency_matrix( + matrix: np.ndarray, /, null_value: float = ... + ) -> PyGraph[int, float]: ... @staticmethod - def from_complex_adjacency_matrix(matrix: np.ndarray, /) -> PyGraph[int, complex]: ... + def from_complex_adjacency_matrix( + matrix: np.ndarray, /, null_value: complex = ... + ) -> PyGraph[int, complex]: ... def get_all_edge_data(self, node_a: int, node_b: int, /) -> List[T]: ... def get_edge_data(self, node_a: int, node_b: int, /) -> T: ... def get_node_data(self, node: int, /) -> S: ... @@ -81,13 +89,14 @@ class PyGraph(Generic[S, T]): /, comment: Optional[str] = ..., deliminator: Optional[str] = ..., + labels: bool = ..., ) -> PyGraph: ... def remove_edge(self, node_a: int, node_b: int, /) -> None: ... def remove_edge_from_index(self, edge: int, /) -> None: ... def remove_edges_from(self, index_list: Sequence[Tuple[int, int]], /) -> None: ... def remove_node(self, node: int, /) -> None: ... def remove_nodes_from(self, index_list: Sequence[int], /) -> None: ... - def subgraph(self, nodes: Sequence[int], /) -> PyGraph[S, T]: ... + def subgraph(self, nodes: Sequence[int], /, preserve_attrs: bool = ...) -> PyGraph[S, T]: ... def to_dot( self, /, @@ -96,7 +105,13 @@ class PyGraph(Generic[S, T]): graph_attr: Optional[Dict[str, str]] = ..., filename: Optional[str] = ..., ) -> Optional[str]: ... - def update_edge(self, source: int, target: int, edge: T, /) -> None: ... + def update_edge( + self, + source: int, + target: int, + edge: T, + /, + ) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... def weighted_edge_list(self) -> WeightedEdgeList[T]: ... def write_edge_list( diff --git a/rustworkx/iterators.pyi b/rustworkx/iterators.pyi index 2ed7fc8c5..81840d84b 100644 --- a/rustworkx/iterators.pyi +++ b/rustworkx/iterators.pyi @@ -13,6 +13,7 @@ from typing import ( Any, Generic, List, + Dict, ItemsView, KeysView, ValuesView, @@ -47,6 +48,11 @@ __all__ = [ "NodesCountMapping", "Pos2DMapping", "WeightedEdgeList", + "CentralityMapping", + "BiconnectedComponents", + "ProductNodeMap", + "MultiplePathMapping", + "AllPairsMultiplePathMapping", ] class RustworkxCustomVecIter(Generic[T_co], Sequence[T_co], ABC): @@ -121,3 +127,18 @@ class Pos2DMapping(RustworkxCustomHashMapIter[int, Tuple[float, float]]): ... @final class WeightedEdgeList(Generic[T_co], RustworkxCustomVecIter[Tuple[int, int, T_co]]): ... + +@final +class CentralityMapping(RustworkxCustomHashMapIter[int, float]): ... + +@final +class BiconnectedComponents(RustworkxCustomHashMapIter[Tuple[int, int], int]): ... + +@final +class ProductNodeMap(RustworkxCustomHashMapIter[Tuple[int, int], int]): ... + +@final +class MultiplePathMapping(RustworkxCustomHashMapIter[int, List[List[int]]]): ... + +@final +class AllPairsMultiplePathMapping(RustworkxCustomHashMapIter[int, MultiplePathMapping]): ... diff --git a/src/digraph.rs b/src/digraph.rs index 7ece57dc9..f02a1ed1d 100644 --- a/src/digraph.rs +++ b/src/digraph.rs @@ -733,7 +733,7 @@ impl PyDiGraph { /// :param int target: The index for the second node /// /// :raises NoEdgeBetweenNodes: When there is no edge between nodes - #[pyo3(text_signature = "(self, source, target, edge /)")] + #[pyo3(text_signature = "(self, source, target, edge, /)")] pub fn update_edge(&mut self, source: usize, target: usize, edge: PyObject) -> PyResult<()> { let index_a = NodeIndex::new(source); let index_b = NodeIndex::new(target); @@ -1271,7 +1271,7 @@ impl PyDiGraph { /// /// :param int u: The source node that is going to be merged /// :param int v: The target node that is going to be the new node - #[pyo3(text_signature = "(self, u, v /)")] + #[pyo3(text_signature = "(self, u, v, /)")] pub fn merge_nodes(&mut self, py: Python, u: usize, v: usize) -> PyResult<()> { let source_node = NodeIndex::new(u); let target_node = NodeIndex::new(v); diff --git a/src/graph.rs b/src/graph.rs index e8bef2776..3b0f2c43a 100644 --- a/src/graph.rs +++ b/src/graph.rs @@ -579,7 +579,7 @@ impl PyGraph { /// :param int target: The index for the second node /// /// :raises NoEdgeBetweenNodes: When there is no edge between nodes - #[pyo3(text_signature = "(self, source, target, edge /)")] + #[pyo3(text_signature = "(self, source, target, edge, /)")] pub fn update_edge(&mut self, source: usize, target: usize, edge: PyObject) -> PyResult<()> { let index_a = NodeIndex::new(source); let index_b = NodeIndex::new(target); From 265fbe9f014eaf4240c12dc86e79e63c9bfaa39b Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:22:08 -0800 Subject: [PATCH 65/71] Use mypy.stubtest on CI --- .github/workflows/main.yml | 2 +- CONTRIBUTING.md | 6 +- tests/stubs/conftest.py | 11 ---- tests/stubs/pydigraph_test.py | 53 --------------- tests/stubs/pygraph_test.py | 53 --------------- tests/stubs/restrict_operations_test.py | 86 ------------------------- tox.ini | 6 +- 7 files changed, 4 insertions(+), 213 deletions(-) delete mode 100644 tests/stubs/conftest.py delete mode 100644 tests/stubs/pydigraph_test.py delete mode 100644 tests/stubs/pygraph_test.py delete mode 100644 tests/stubs/restrict_operations_test.py diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c6ef61990..56909797c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,7 +39,7 @@ jobs: - name: Black Codestyle Format run: black --check --diff retworkx rustworkx retworkx tests - name: Python Lint - run: flake8 --per-file-ignores='retworkx/__init__.py:F405,F403 tests/stubs/*:E501' setup.py retworkx tests rustworkx + run: flake8 --per-file-ignores='retworkx/__init__.py:F405,F403' setup.py retworkx tests rustworkx - name: Check stray release notes run: python tools/find_stray_release_notes.py - name: rustworkx-core Rust Tests diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94e0f70a2..bd6ebdaa7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -281,16 +281,12 @@ They contain annotated signatures for Python functions, stripped of their implem While this step is optional, it is very helpful for end-users. Adding annotations lets users type check their code with [mypy](http://mypy-lang.org/), which can be helpful for finding bugs. -Just like with tests for the code, annotations are also tested via tox. On Linux and Mac OS -machines, the tests can be executed via: +Just like with tests for the code, annotations are also tested via tox. ``` tox -estubs ``` -We also encourage type annotation contributions -to add tests in the `tests/stubs` directory to verify the correctness of the annotations. - ### Release Notes It is important to document any end user facing changes when we release a new diff --git a/tests/stubs/conftest.py b/tests/stubs/conftest.py deleted file mode 100644 index a7b43783a..000000000 --- a/tests/stubs/conftest.py +++ /dev/null @@ -1,11 +0,0 @@ -# Configure Pytest to ignore stub tests in early versions -import sys - -collect_ignore_glob = [] -if sys.version_info < (3, 12): - collect_ignore_glob.append("*.py") - - -def pytest_sessionfinish(session, exitstatus): - if exitstatus == 5: - session.exitstatus = 0 # ignore no tests found, it's intentional diff --git a/tests/stubs/pydigraph_test.py b/tests/stubs/pydigraph_test.py deleted file mode 100644 index 920fc4603..000000000 --- a/tests/stubs/pydigraph_test.py +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from rustworkx import PyDiGraph - -import pytest - - -@pytest.mark.mypy_testing -def test_pydigraph_simple() -> None: - graph: PyDiGraph[str, float] = PyDiGraph() - node_a = graph.add_node("A") - node_b = graph.add_node("B") - edge_ab = graph.add_edge(node_a, node_b, 3.5) - reveal_type(node_a) # R: builtins.int - reveal_type(edge_ab) # R: builtins.int - - -@pytest.mark.mypy_testing -def test_custom_return_types() -> None: - graph: PyDiGraph[str, float] = PyDiGraph() - node_a = graph.add_node("A") - node_b = graph.add_node("B") - graph.add_edge(node_a, node_b, 3.5) - - edges = graph.edge_list() - weighted_edges = graph.weighted_edge_list() - node_indices = graph.node_indexes() - - # fmt: off - reveal_type(edges) # R: rustworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: rustworkx.custom_return_types.WeightedEdgeList[builtins.float] - reveal_type(node_indices) # R: rustworkx.custom_return_types.NodeIndices - # fmt: on - - list_of_edges = list(edges) - list_of_weights = list(weighted_edges) - list_of_nodes = list(node_indices) - - # fmt: off - reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.float]] - reveal_type(list_of_nodes) # R: builtins.list[builtins.int] - # fmt: on diff --git a/tests/stubs/pygraph_test.py b/tests/stubs/pygraph_test.py deleted file mode 100644 index 8d6fbd967..000000000 --- a/tests/stubs/pygraph_test.py +++ /dev/null @@ -1,53 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from rustworkx import PyGraph - -import pytest - - -@pytest.mark.mypy_testing -def test_pygraph_simple() -> None: - graph: PyGraph[str, float] = PyGraph() - node_a = graph.add_node("A") - node_b = graph.add_node("B") - edge_ab = graph.add_edge(node_a, node_b, 3.5) - reveal_type(node_a) # R: builtins.int - reveal_type(edge_ab) # R: builtins.int - - -@pytest.mark.mypy_testing -def test_custom_return_types() -> None: - graph: PyGraph[str, float] = PyGraph() - node_a = graph.add_node("A") - node_b = graph.add_node("B") - graph.add_edge(node_a, node_b, 3.5) - - edges = graph.edge_list() - weighted_edges = graph.weighted_edge_list() - node_indices = graph.node_indexes() - - # fmt: off - reveal_type(edges) # R: rustworkx.custom_return_types.EdgeList - reveal_type(weighted_edges) # R: rustworkx.custom_return_types.WeightedEdgeList[builtins.float] - reveal_type(node_indices) # R: rustworkx.custom_return_types.NodeIndices - # fmt: on - - list_of_edges = list(edges) - list_of_weights = list(weighted_edges) - list_of_nodes = list(node_indices) - - # fmt: off - reveal_type(list_of_edges) # R: builtins.list[Tuple[builtins.int, builtins.int]] - reveal_type(list_of_weights) # R: builtins.list[Tuple[builtins.int, builtins.int, builtins.float]] - reveal_type(list_of_nodes) # R: builtins.list[builtins.int] - # fmt: on diff --git a/tests/stubs/restrict_operations_test.py b/tests/stubs/restrict_operations_test.py deleted file mode 100644 index 13b7e5497..000000000 --- a/tests/stubs/restrict_operations_test.py +++ /dev/null @@ -1,86 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from typing import Optional -from rustworkx import PyGraph, PyDiGraph - -import pytest - - -@pytest.mark.mypy_testing -def test_pygraph_add_edges_from_no_data_illegal() -> None: - graph: PyGraph[str, float] = PyGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - - # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyGraph[S, Optional[T]], Sequence[Tuple[int, int]]], List[int]]" - # fmt: on - - -@pytest.mark.mypy_testing -def test_pygraph_add_edges_from_no_data_legal() -> None: - graph: PyGraph[str, Optional[float]] = PyGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - - graph.add_edges_from_no_data([(node_a, node_b)]) - - -@pytest.mark.mypy_testing -def test_pygraph_extend_from_edge_list_illegal() -> None: - graph: PyGraph[str, float] = PyGraph() - - # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyGraph[Optional[S], Optional[T]], Sequence[Tuple[int, int]]], None]" - # fmt: on - - -@pytest.mark.mypy_testing -def test_pygraph_extend_from_edge_list_legal() -> None: - graph: PyGraph[Optional[str], Optional[float]] = PyGraph() - graph.extend_from_edge_list([(0, 5)]) - - -@pytest.mark.mypy_testing -def test_pydigraph_add_edges_from_no_data_illegal() -> None: - graph: PyDiGraph[str, float] = PyDiGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - - # fmt: off - graph.add_edges_from_no_data([(node_a, node_b)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "add_edges_from_no_data" with type "Callable[[PyDiGraph[S, Optional[T]], Sequence[Tuple[int, int]]], List[int]]" - # fmt: on - - -@pytest.mark.mypy_testing -def test_pydigraph_add_edges_from_no_data_legal() -> None: - graph: PyDiGraph[str, Optional[float]] = PyDiGraph() - node_a: int = graph.add_node("A") - node_b: int = graph.add_node("B") - - graph.add_edges_from_no_data([(node_a, node_b)]) - - -@pytest.mark.mypy_testing -def test_pydigraph_extend_from_edge_list_illegal() -> None: - graph: PyDiGraph[str, float] = PyDiGraph() - - # fmt: off - graph.extend_from_edge_list([(0, 5)]) # E: Invalid self argument "PyDiGraph[str, float]" to attribute function "extend_from_edge_list" with type "Callable[[PyDiGraph[Optional[S], Optional[T]], Sequence[Tuple[int, int]]], None]" - # fmt: on - - -@pytest.mark.mypy_testing -def test_pydigraph_extend_from_edge_list_legal() -> None: - graph: PyDiGraph[Optional[str], Optional[float]] = PyDiGraph() - graph.extend_from_edge_list([(0, 5)]) diff --git a/tox.ini b/tox.ini index 4ebb812ce..ae1b13ba3 100644 --- a/tox.ini +++ b/tox.ini @@ -60,10 +60,8 @@ commands = black {posargs} '../rustworkx' '../tests' '../retworkx' basepython = python3 envdir = .tox/stubs deps = - pytest==7.1.3 - mypy==0.950 - pytest-mypy-testing==0.0.10 -commands = python -m pytest '../tests/stubs' + mypy @ git+https://github.com/python/mypy.git +commands = python -m mypy.stubtest --concise --ignore-missing-stub rustworkx.rustworkx [flake8] # E125 is deliberately excluded. See https://github.com/jcrocholl/pep8/issues/126 From c16ae22c4c3ea5ec550f5371d0c49d86ea54c7bf Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:26:40 -0800 Subject: [PATCH 66/71] Run Black --- rustworkx/digraph.pyi | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rustworkx/digraph.pyi b/rustworkx/digraph.pyi index 6ac2b5087..56b977d98 100644 --- a/rustworkx/digraph.pyi +++ b/rustworkx/digraph.pyi @@ -150,7 +150,13 @@ class PyDiGraph(Generic[S, T]): multigraph: bool = ..., weight_combo_fn: Optional[Callable[[T, T], T]] = ..., ) -> PyGraph[S, T]: ... - def update_edge(self, source: int, target: int, edge: T, /,) -> None: ... + def update_edge( + self, + source: int, + target: int, + edge: T, + /, + ) -> None: ... def update_edge_by_index(self, edge_index: int, edge: T, /) -> None: ... def weighted_edge_list(self) -> WeightedEdgeList[T]: ... def write_edge_list( From 9a21cae22bbc79b0ee1aaec1a9909fe524982013 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:27:52 -0800 Subject: [PATCH 67/71] Remove things that we do not need anymore --- tox.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/tox.ini b/tox.ini index ae1b13ba3..bd069db18 100644 --- a/tox.ini +++ b/tox.ini @@ -75,6 +75,3 @@ max-line-length = 110 ignore = E125,E123,E129,E711 extend-ignore = E203, W503 exclude = .venv,.git,.tox,dist,doc,*egg,build -builtins=reveal_type -per-file-ignores = - tests/stubs/*:E501 \ No newline at end of file From 119cdb31e1c427f771842dc392383ffec2e8686f Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:31:22 -0800 Subject: [PATCH 68/71] More things I forgot to remove --- tox.ini | 2 -- 1 file changed, 2 deletions(-) diff --git a/tox.ini b/tox.ini index bd069db18..84a10f596 100644 --- a/tox.ini +++ b/tox.ini @@ -69,8 +69,6 @@ commands = python -m mypy.stubtest --concise --ignore-missing-stub rustworkx.rus # E129 skipped because it is too limiting when combined with other rules # E711 skipped because sqlalchemy filter() requires using == instead of is # max-line-length, E203, W503 are added for black compatibility -# builtins includes reveal_type because mypy injects it -# pytest-mypy-testing needs reveal_type to be a one-liner hence we ignore lenght warnings max-line-length = 110 ignore = E125,E123,E129,E711 extend-ignore = E203, W503 From fb278837bef86ee06e46317f49ccaf24e911a8b2 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 16:53:19 -0800 Subject: [PATCH 69/71] Skip Python 3.7 for mypy --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56909797c..16c22230f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -92,7 +92,7 @@ jobs: run: tox -epy - name: 'Run stubs-tests' run: tox -estubs - if: runner.os == 'Linux' + if: runner.os == 'Linux' && ${{ matrix.python-version != 3.7 }} tests_retworkx_compat: needs: [build_lint] name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} ${{ matrix.msrv }} From 968f9d3edf54cbe21f6b771660f19f158d7426be Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Wed, 1 Feb 2023 17:52:32 -0800 Subject: [PATCH 70/71] Add test stubs without Python 3.7 --- .github/workflows/main.yml | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 16c22230f..a6c597729 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -90,9 +90,31 @@ jobs: if: runner.os == 'Linux' - name: 'Run tests' run: tox -epy - - name: 'Run stubs-tests' + tests_stubs: + needs: [tests] + name: python-stubs-${{ matrix.python-version }} + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.8, 3.9, "3.10", "3.11"] + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + architecture: x64 + - name: Install Rust toolchain + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: x86_64-unknown-linux-gnu + profile: minimal + default: true + - name: 'Install dependencies' + run: python -m pip install --upgrade 'tox<4' + - name: 'Run rustworkx stub tests' run: tox -estubs - if: runner.os == 'Linux' && ${{ matrix.python-version != 3.7 }} tests_retworkx_compat: needs: [build_lint] name: python${{ matrix.python-version }}-${{ matrix.platform.python-architecture }} ${{ matrix.platform.os }} ${{ matrix.msrv }} From 5ed884bbcfbc77fc293302c50388f42c13ebeec1 Mon Sep 17 00:00:00 2001 From: Ivan Carvalho Date: Tue, 21 Feb 2023 11:30:44 -0800 Subject: [PATCH 71/71] Don't use latest mypy release --- tox.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tox.ini b/tox.ini index 84a10f596..8f5e71656 100644 --- a/tox.ini +++ b/tox.ini @@ -60,7 +60,7 @@ commands = black {posargs} '../rustworkx' '../tests' '../retworkx' basepython = python3 envdir = .tox/stubs deps = - mypy @ git+https://github.com/python/mypy.git + mypy==1.0.1 commands = python -m mypy.stubtest --concise --ignore-missing-stub rustworkx.rustworkx [flake8]