summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoss Barnowski <rossbar@berkeley.edu>2021-11-17 21:12:56 -0800
committerGitHub <noreply@github.com>2021-11-17 21:12:56 -0800
commit00c261f951ae6734001e0419d2bc754eef6dd1b2 (patch)
tree54e6ce86c89f3de9f2d960f4726025487216d3c8
parent4ebdb5e2ca6c6a1f9fb3bf8c2279f9b857c6d8a7 (diff)
downloadnetworkx-00c261f951ae6734001e0419d2bc754eef6dd1b2.tar.gz
Add Mypy type checking infrastructure (#5127)
* Add minimal mypy configuration file. * Add mypy workflow to GH. * Properly import sentinels from traversal.edgedfs. * mypy doesn't like variables named \"e\". * Rm annotations from single function. * Fix name collisions in test suite. Make sure all tests have unique names. * Rm unused random seed in test setup. * Rm redundant __all__ specification. * Silence mypy error from sum(). Mypy bug? * Fix tsp test instantiation nit. * \"type: ignore\" to suppress conditional fn sigature errors. * Remaining \"type: ignore\" to appease mypy. * Configure mypy to ignore inheritance issues. * Update exclude conf for CI. - Add yaml - Reformat regex containing reportviews * Rm partial annotations from lukes.py. Fixes mypy errors due to unannotated code. * Reorg defaultdict to reduce type: ignore cruft. * Homogenize signatures for fns defined in conditionals. * err as varname only in exception catching. * Fix name collision in Bellman-Ford test suite.
-rw-r--r--.github/workflows/mypy.yml30
-rw-r--r--.mypy.ini3
-rw-r--r--networkx/algorithms/approximation/kcomponents.py2
-rw-r--r--networkx/algorithms/approximation/tests/test_traveling_salesman.py162
-rw-r--r--networkx/algorithms/bipartite/edgelist.py10
-rw-r--r--networkx/algorithms/centrality/katz.py4
-rw-r--r--networkx/algorithms/community/lukes.py14
-rw-r--r--networkx/algorithms/connectivity/__init__.py15
-rw-r--r--networkx/algorithms/d_separation.py2
-rw-r--r--networkx/algorithms/flow/tests/test_maxflow.py2
-rw-r--r--networkx/algorithms/shortest_paths/tests/test_weighted.py2
-rw-r--r--networkx/algorithms/tests/test_cycles.py4
-rw-r--r--networkx/algorithms/tests/test_graph_hashing.py2
-rw-r--r--networkx/algorithms/tests/test_smallworld.py1
-rw-r--r--networkx/algorithms/traversal/tests/test_edgebfs.py38
-rw-r--r--networkx/algorithms/traversal/tests/test_edgedfs.py7
-rw-r--r--networkx/classes/graphviews.py4
-rw-r--r--networkx/classes/tests/test_multigraph.py2
-rw-r--r--networkx/drawing/layout.py6
-rw-r--r--networkx/generators/line.py4
-rw-r--r--networkx/readwrite/graphml.py4
-rw-r--r--networkx/readwrite/nx_shp.py8
-rw-r--r--networkx/readwrite/tests/test_gml.py2
-rw-r--r--networkx/utils/decorators.py10
-rw-r--r--requirements/developer.txt1
25 files changed, 173 insertions, 166 deletions
diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml
new file mode 100644
index 00000000..4fb47ba8
--- /dev/null
+++ b/.github/workflows/mypy.yml
@@ -0,0 +1,30 @@
+name: Mypy
+
+on: [push, pull_request]
+
+jobs:
+ type-check:
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ python-version: [3.9]
+
+ steps:
+ - uses: actions/checkout@v2
+
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: actions/setup-python@v2
+ with:
+ python-version: ${{ matrix.python-version }}
+
+ - name: Install packages
+ run: |
+ pip install --upgrade pip wheel setuptools
+ pip install -r requirements/developer.txt
+ # Rm below when yaml no longer a dep
+ pip install types-PyYAML
+ pip install -e .
+ pip list
+
+ - name: run mypy
+ run: mypy -p networkx
diff --git a/.mypy.ini b/.mypy.ini
new file mode 100644
index 00000000..f10a25b3
--- /dev/null
+++ b/.mypy.ini
@@ -0,0 +1,3 @@
+[mypy]
+ignore_missing_imports = True
+exclude = yaml|subgraphviews|reportviews*
diff --git a/networkx/algorithms/approximation/kcomponents.py b/networkx/algorithms/approximation/kcomponents.py
index 12048da1..518a0274 100644
--- a/networkx/algorithms/approximation/kcomponents.py
+++ b/networkx/algorithms/approximation/kcomponents.py
@@ -213,7 +213,7 @@ class _AntiGraph(nx.Graph):
def single_edge_dict(self):
return self.all_edge_dict
- edge_attr_dict_factory = single_edge_dict
+ edge_attr_dict_factory = single_edge_dict # type: ignore
def __getitem__(self, n):
"""Returns a dict of neighbors of node n in the dense graph.
diff --git a/networkx/algorithms/approximation/tests/test_traveling_salesman.py b/networkx/algorithms/approximation/tests/test_traveling_salesman.py
index 56574f63..50d02b6c 100644
--- a/networkx/algorithms/approximation/tests/test_traveling_salesman.py
+++ b/networkx/algorithms/approximation/tests/test_traveling_salesman.py
@@ -39,83 +39,84 @@ def test_christofides_ignore_selfloops():
# set up graphs for other tests
-@classmethod
-def _setup_class(cls):
- cls.DG = nx.DiGraph()
- cls.DG.add_weighted_edges_from(
- {
- ("A", "B", 3),
- ("A", "C", 17),
- ("A", "D", 14),
- ("B", "A", 3),
- ("B", "C", 12),
- ("B", "D", 16),
- ("C", "A", 13),
- ("C", "B", 12),
- ("C", "D", 4),
- ("D", "A", 14),
- ("D", "B", 15),
- ("D", "C", 2),
- }
- )
- cls.DG_cycle = ["D", "C", "B", "A", "D"]
- cls.DG_cost = 31.0
-
- cls.DG2 = nx.DiGraph()
- cls.DG2.add_weighted_edges_from(
- {
- ("A", "B", 3),
- ("A", "C", 17),
- ("A", "D", 14),
- ("B", "A", 30),
- ("B", "C", 2),
- ("B", "D", 16),
- ("C", "A", 33),
- ("C", "B", 32),
- ("C", "D", 34),
- ("D", "A", 14),
- ("D", "B", 15),
- ("D", "C", 2),
- }
- )
- cls.DG2_cycle = ["D", "A", "B", "C", "D"]
- cls.DG2_cost = 53.0
-
- cls.unweightedUG = nx.complete_graph(5, nx.Graph())
- cls.unweightedDG = nx.complete_graph(5, nx.DiGraph())
-
- cls.incompleteUG = nx.Graph()
- cls.incompleteUG.add_weighted_edges_from({(0, 1, 1), (1, 2, 3)})
- cls.incompleteDG = nx.DiGraph()
- cls.incompleteDG.add_weighted_edges_from({(0, 1, 1), (1, 2, 3)})
-
- cls.UG = nx.Graph()
- cls.UG.add_weighted_edges_from(
- {
- ("A", "B", 3),
- ("A", "C", 17),
- ("A", "D", 14),
- ("B", "C", 12),
- ("B", "D", 16),
- ("C", "D", 4),
- }
- )
- cls.UG_cycle = ["D", "C", "B", "A", "D"]
- cls.UG_cost = 33.0
-
- cls.UG2 = nx.Graph()
- cls.UG2.add_weighted_edges_from(
- {
- ("A", "B", 1),
- ("A", "C", 15),
- ("A", "D", 5),
- ("B", "C", 16),
- ("B", "D", 8),
- ("C", "D", 3),
- }
- )
- cls.UG2_cycle = ["D", "C", "B", "A", "D"]
- cls.UG2_cost = 25.0
+class TestBase:
+ @classmethod
+ def setup_class(cls):
+ cls.DG = nx.DiGraph()
+ cls.DG.add_weighted_edges_from(
+ {
+ ("A", "B", 3),
+ ("A", "C", 17),
+ ("A", "D", 14),
+ ("B", "A", 3),
+ ("B", "C", 12),
+ ("B", "D", 16),
+ ("C", "A", 13),
+ ("C", "B", 12),
+ ("C", "D", 4),
+ ("D", "A", 14),
+ ("D", "B", 15),
+ ("D", "C", 2),
+ }
+ )
+ cls.DG_cycle = ["D", "C", "B", "A", "D"]
+ cls.DG_cost = 31.0
+
+ cls.DG2 = nx.DiGraph()
+ cls.DG2.add_weighted_edges_from(
+ {
+ ("A", "B", 3),
+ ("A", "C", 17),
+ ("A", "D", 14),
+ ("B", "A", 30),
+ ("B", "C", 2),
+ ("B", "D", 16),
+ ("C", "A", 33),
+ ("C", "B", 32),
+ ("C", "D", 34),
+ ("D", "A", 14),
+ ("D", "B", 15),
+ ("D", "C", 2),
+ }
+ )
+ cls.DG2_cycle = ["D", "A", "B", "C", "D"]
+ cls.DG2_cost = 53.0
+
+ cls.unweightedUG = nx.complete_graph(5, nx.Graph())
+ cls.unweightedDG = nx.complete_graph(5, nx.DiGraph())
+
+ cls.incompleteUG = nx.Graph()
+ cls.incompleteUG.add_weighted_edges_from({(0, 1, 1), (1, 2, 3)})
+ cls.incompleteDG = nx.DiGraph()
+ cls.incompleteDG.add_weighted_edges_from({(0, 1, 1), (1, 2, 3)})
+
+ cls.UG = nx.Graph()
+ cls.UG.add_weighted_edges_from(
+ {
+ ("A", "B", 3),
+ ("A", "C", 17),
+ ("A", "D", 14),
+ ("B", "C", 12),
+ ("B", "D", 16),
+ ("C", "D", 4),
+ }
+ )
+ cls.UG_cycle = ["D", "C", "B", "A", "D"]
+ cls.UG_cost = 33.0
+
+ cls.UG2 = nx.Graph()
+ cls.UG2.add_weighted_edges_from(
+ {
+ ("A", "B", 1),
+ ("A", "C", 15),
+ ("A", "D", 5),
+ ("B", "C", 16),
+ ("B", "D", 8),
+ ("C", "D", 3),
+ }
+ )
+ cls.UG2_cycle = ["D", "C", "B", "A", "D"]
+ cls.UG2_cost = 25.0
def validate_solution(soln, cost, exp_soln, exp_cost):
@@ -128,9 +129,7 @@ def validate_symmetric_solution(soln, cost, exp_soln, exp_cost):
assert cost == exp_cost
-class TestGreedyTSP:
- setup_class = _setup_class
-
+class TestGreedyTSP(TestBase):
def test_greedy(self):
cycle = nx_app.greedy_tsp(self.DG, source="D")
cost = sum(self.DG[n][nbr]["weight"] for n, nbr in pairwise(cycle))
@@ -170,8 +169,7 @@ class TestGreedyTSP:
assert len(cycle) - 1 == len(G) == len(set(cycle))
-class TestSimulatedAnnealingTSP:
- setup_class = _setup_class
+class TestSimulatedAnnealingTSP(TestBase):
tsp = staticmethod(nx_app.simulated_annealing_tsp)
def test_simulated_annealing_directed(self):
diff --git a/networkx/algorithms/bipartite/edgelist.py b/networkx/algorithms/bipartite/edgelist.py
index 77645d20..356f4ab7 100644
--- a/networkx/algorithms/bipartite/edgelist.py
+++ b/networkx/algorithms/bipartite/edgelist.py
@@ -133,17 +133,17 @@ def generate_edgelist(G, delimiter=" ", data=True):
raise AttributeError("Missing node attribute `bipartite`") from err
if data is True or data is False:
for n in part0:
- for e in G.edges(n, data=data):
- yield delimiter.join(map(str, e))
+ for edge in G.edges(n, data=data):
+ yield delimiter.join(map(str, edge))
else:
for n in part0:
for u, v, d in G.edges(n, data=True):
- e = [u, v]
+ edge = [u, v]
try:
- e.extend(d[k] for k in data)
+ edge.extend(d[k] for k in data)
except KeyError:
pass # missing data for this edge, should warn?
- yield delimiter.join(map(str, e))
+ yield delimiter.join(map(str, edge))
def parse_edgelist(
diff --git a/networkx/algorithms/centrality/katz.py b/networkx/algorithms/centrality/katz.py
index 523dce04..236f2c61 100644
--- a/networkx/algorithms/centrality/katz.py
+++ b/networkx/algorithms/centrality/katz.py
@@ -176,8 +176,8 @@ def katz_centrality(
x[n] = alpha * x[n] + b[n]
# check convergence
- err = sum(abs(x[n] - xlast[n]) for n in x)
- if err < nnodes * tol:
+ error = sum(abs(x[n] - xlast[n]) for n in x)
+ if error < nnodes * tol:
if normalized:
# normalize vector
try:
diff --git a/networkx/algorithms/community/lukes.py b/networkx/algorithms/community/lukes.py
index 6fe1d0de..b34077a2 100644
--- a/networkx/algorithms/community/lukes.py
+++ b/networkx/algorithms/community/lukes.py
@@ -17,7 +17,7 @@ PKEY = "partitions"
CLUSTER_EVAL_CACHE_SIZE = 2048
-def _split_n_from(n: int, min_size_of_first_part: int):
+def _split_n_from(n, min_size_of_first_part):
# splits j in two parts of which the first is at least
# the second argument
assert n >= min_size_of_first_part
@@ -25,7 +25,7 @@ def _split_n_from(n: int, min_size_of_first_part: int):
yield p1, n - p1
-def lukes_partitioning(G, max_size: int, node_weight=None, edge_weight=None) -> list:
+def lukes_partitioning(G, max_size, node_weight=None, edge_weight=None):
"""Optimal partitioning of a weighted tree using the Lukes algorithm.
@@ -130,23 +130,23 @@ def lukes_partitioning(G, max_size: int, node_weight=None, edge_weight=None) ->
return n
@lru_cache(CLUSTER_EVAL_CACHE_SIZE)
- def _value_of_cluster(cluster: frozenset):
+ def _value_of_cluster(cluster):
valid_edges = [e for e in safe_G.edges if e[0] in cluster and e[1] in cluster]
return sum(safe_G.edges[e][edge_weight] for e in valid_edges)
- def _value_of_partition(partition: list):
+ def _value_of_partition(partition):
return sum(_value_of_cluster(frozenset(c)) for c in partition)
@lru_cache(CLUSTER_EVAL_CACHE_SIZE)
- def _weight_of_cluster(cluster: frozenset):
+ def _weight_of_cluster(cluster):
return sum(safe_G.nodes[n][node_weight] for n in cluster)
- def _pivot(partition: list, node):
+ def _pivot(partition, node):
ccx = [c for c in partition if node in c]
assert len(ccx) == 1
return ccx[0]
- def _concatenate_or_merge(partition_1: list, partition_2: list, x, i, ref_weigth):
+ def _concatenate_or_merge(partition_1, partition_2, x, i, ref_weigth):
ccx = _pivot(partition_1, x)
cci = _pivot(partition_2, i)
diff --git a/networkx/algorithms/connectivity/__init__.py b/networkx/algorithms/connectivity/__init__.py
index 65490c00..15bc5abe 100644
--- a/networkx/algorithms/connectivity/__init__.py
+++ b/networkx/algorithms/connectivity/__init__.py
@@ -9,18 +9,3 @@ from .kcomponents import *
from .kcutsets import *
from .stoerwagner import *
from .utils import *
-
-__all__ = sum(
- [
- connectivity.__all__,
- cuts.__all__,
- edge_augmentation.__all__,
- edge_kcomponents.__all__,
- disjoint_paths.__all__,
- kcomponents.__all__,
- kcutsets.__all__,
- stoerwagner.__all__,
- utils.__all__,
- ],
- [],
-)
diff --git a/networkx/algorithms/d_separation.py b/networkx/algorithms/d_separation.py
index 9d41e2d8..29f1b7cd 100644
--- a/networkx/algorithms/d_separation.py
+++ b/networkx/algorithms/d_separation.py
@@ -67,7 +67,7 @@ __all__ = ["d_separated"]
@not_implemented_for("undirected")
-def d_separated(G: nx.DiGraph, x: AbstractSet, y: AbstractSet, z: AbstractSet) -> bool:
+def d_separated(G, x, y, z):
"""
Return whether node sets ``x`` and ``y`` are d-separated by ``z``.
diff --git a/networkx/algorithms/flow/tests/test_maxflow.py b/networkx/algorithms/flow/tests/test_maxflow.py
index 17b82b4d..9bb69198 100644
--- a/networkx/algorithms/flow/tests/test_maxflow.py
+++ b/networkx/algorithms/flow/tests/test_maxflow.py
@@ -19,7 +19,7 @@ flow_funcs = [
]
max_min_funcs = [nx.maximum_flow, nx.minimum_cut]
flow_value_funcs = [nx.maximum_flow_value, nx.minimum_cut_value]
-interface_funcs = sum([max_min_funcs, flow_value_funcs], [])
+interface_funcs = max_min_funcs + flow_value_funcs
all_funcs = sum([flow_funcs, interface_funcs], [])
diff --git a/networkx/algorithms/shortest_paths/tests/test_weighted.py b/networkx/algorithms/shortest_paths/tests/test_weighted.py
index 032b189d..15a219ee 100644
--- a/networkx/algorithms/shortest_paths/tests/test_weighted.py
+++ b/networkx/algorithms/shortest_paths/tests/test_weighted.py
@@ -838,7 +838,7 @@ class TestBellmanFordAndGoldbergRadzik(WeightedTestBase):
assert pred[3] == 0
assert dist == {0: 0, 1: 1, 2: 2, 3: 1}
- def test_negative_weight(self):
+ def test_negative_weight_bf_path(self):
G = nx.DiGraph()
G.add_nodes_from("abcd")
G.add_edge("a", "d", weight=0)
diff --git a/networkx/algorithms/tests/test_cycles.py b/networkx/algorithms/tests/test_cycles.py
index d509e41c..737d29f4 100644
--- a/networkx/algorithms/tests/test_cycles.py
+++ b/networkx/algorithms/tests/test_cycles.py
@@ -4,9 +4,7 @@ import networkx as nx
from networkx.algorithms import find_cycle
from networkx.algorithms import minimum_cycle_basis
-
-FORWARD = nx.algorithms.edgedfs.FORWARD
-REVERSE = nx.algorithms.edgedfs.REVERSE
+from networkx.algorithms.traversal.edgedfs import FORWARD, REVERSE
class TestCycles:
diff --git a/networkx/algorithms/tests/test_graph_hashing.py b/networkx/algorithms/tests/test_graph_hashing.py
index 70130b39..c76a66e1 100644
--- a/networkx/algorithms/tests/test_graph_hashing.py
+++ b/networkx/algorithms/tests/test_graph_hashing.py
@@ -455,7 +455,7 @@ def test_missing_node_attr_subgraph_hash():
)
-def test_isomorphic_edge_attr_and_node_attr():
+def test_isomorphic_edge_attr_and_node_attr_subgraph_hash():
"""
Isomorphic graphs with differing node attributes should yield different subgraph
hashes if the 'node_attr' and 'edge_attr' argument is supplied and populated in
diff --git a/networkx/algorithms/tests/test_smallworld.py b/networkx/algorithms/tests/test_smallworld.py
index b6219133..e56f9a6a 100644
--- a/networkx/algorithms/tests/test_smallworld.py
+++ b/networkx/algorithms/tests/test_smallworld.py
@@ -7,7 +7,6 @@ import random
from networkx import random_reference, lattice_reference, sigma, omega
import networkx as nx
-rng = random.Random(0)
rng = 42
diff --git a/networkx/algorithms/traversal/tests/test_edgebfs.py b/networkx/algorithms/traversal/tests/test_edgebfs.py
index 170be25c..1bf3fae0 100644
--- a/networkx/algorithms/traversal/tests/test_edgebfs.py
+++ b/networkx/algorithms/traversal/tests/test_edgebfs.py
@@ -1,11 +1,7 @@
import pytest
import networkx as nx
-
-edge_bfs = nx.edge_bfs
-
-FORWARD = nx.algorithms.edgedfs.FORWARD
-REVERSE = nx.algorithms.edgedfs.REVERSE
+from networkx.algorithms.traversal.edgedfs import FORWARD, REVERSE
class TestEdgeBFS:
@@ -16,42 +12,42 @@ class TestEdgeBFS:
def test_empty(self):
G = nx.Graph()
- edges = list(edge_bfs(G))
+ edges = list(nx.edge_bfs(G))
assert edges == []
def test_graph_single_source(self):
G = nx.Graph(self.edges)
G.add_edge(4, 5)
- x = list(edge_bfs(G, [0]))
+ x = list(nx.edge_bfs(G, [0]))
x_ = [(0, 1), (0, 2), (1, 2), (1, 3)]
assert x == x_
def test_graph(self):
G = nx.Graph(self.edges)
- x = list(edge_bfs(G, self.nodes))
+ x = list(nx.edge_bfs(G, self.nodes))
x_ = [(0, 1), (0, 2), (1, 2), (1, 3)]
assert x == x_
def test_digraph(self):
G = nx.DiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes))
+ x = list(nx.edge_bfs(G, self.nodes))
x_ = [(0, 1), (1, 0), (2, 0), (2, 1), (3, 1)]
assert x == x_
def test_digraph_orientation_invalid(self):
G = nx.DiGraph(self.edges)
- edge_iterator = edge_bfs(G, self.nodes, orientation="hello")
+ edge_iterator = nx.edge_bfs(G, self.nodes, orientation="hello")
pytest.raises(nx.NetworkXError, list, edge_iterator)
def test_digraph_orientation_none(self):
G = nx.DiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation=None))
+ x = list(nx.edge_bfs(G, self.nodes, orientation=None))
x_ = [(0, 1), (1, 0), (2, 0), (2, 1), (3, 1)]
assert x == x_
def test_digraph_orientation_original(self):
G = nx.DiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation="original"))
+ x = list(nx.edge_bfs(G, self.nodes, orientation="original"))
x_ = [
(0, 1, FORWARD),
(1, 0, FORWARD),
@@ -64,13 +60,13 @@ class TestEdgeBFS:
def test_digraph2(self):
G = nx.DiGraph()
nx.add_path(G, range(4))
- x = list(edge_bfs(G, [0]))
+ x = list(nx.edge_bfs(G, [0]))
x_ = [(0, 1), (1, 2), (2, 3)]
assert x == x_
def test_digraph_rev(self):
G = nx.DiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation="reverse"))
+ x = list(nx.edge_bfs(G, self.nodes, orientation="reverse"))
x_ = [
(1, 0, REVERSE),
(2, 0, REVERSE),
@@ -83,13 +79,13 @@ class TestEdgeBFS:
def test_digraph_rev2(self):
G = nx.DiGraph()
nx.add_path(G, range(4))
- x = list(edge_bfs(G, [3], orientation="reverse"))
+ x = list(nx.edge_bfs(G, [3], orientation="reverse"))
x_ = [(2, 3, REVERSE), (1, 2, REVERSE), (0, 1, REVERSE)]
assert x == x_
def test_multigraph(self):
G = nx.MultiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes))
+ x = list(nx.edge_bfs(G, self.nodes))
x_ = [(0, 1, 0), (0, 1, 1), (0, 1, 2), (0, 2, 0), (1, 2, 0), (1, 3, 0)]
# This is an example of where hash randomization can break.
# There are 3! * 2 alternative outputs, such as:
@@ -101,13 +97,13 @@ class TestEdgeBFS:
def test_multidigraph(self):
G = nx.MultiDiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes))
+ x = list(nx.edge_bfs(G, self.nodes))
x_ = [(0, 1, 0), (1, 0, 0), (1, 0, 1), (2, 0, 0), (2, 1, 0), (3, 1, 0)]
assert x == x_
def test_multidigraph_rev(self):
G = nx.MultiDiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation="reverse"))
+ x = list(nx.edge_bfs(G, self.nodes, orientation="reverse"))
x_ = [
(1, 0, 0, REVERSE),
(1, 0, 1, REVERSE),
@@ -120,7 +116,7 @@ class TestEdgeBFS:
def test_digraph_ignore(self):
G = nx.DiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation="ignore"))
+ x = list(nx.edge_bfs(G, self.nodes, orientation="ignore"))
x_ = [
(0, 1, FORWARD),
(1, 0, REVERSE),
@@ -133,13 +129,13 @@ class TestEdgeBFS:
def test_digraph_ignore2(self):
G = nx.DiGraph()
nx.add_path(G, range(4))
- x = list(edge_bfs(G, [0], orientation="ignore"))
+ x = list(nx.edge_bfs(G, [0], orientation="ignore"))
x_ = [(0, 1, FORWARD), (1, 2, FORWARD), (2, 3, FORWARD)]
assert x == x_
def test_multidigraph_ignore(self):
G = nx.MultiDiGraph(self.edges)
- x = list(edge_bfs(G, self.nodes, orientation="ignore"))
+ x = list(nx.edge_bfs(G, self.nodes, orientation="ignore"))
x_ = [
(0, 1, 0, FORWARD),
(1, 0, 0, REVERSE),
diff --git a/networkx/algorithms/traversal/tests/test_edgedfs.py b/networkx/algorithms/traversal/tests/test_edgedfs.py
index 6c12ae21..7c1967cc 100644
--- a/networkx/algorithms/traversal/tests/test_edgedfs.py
+++ b/networkx/algorithms/traversal/tests/test_edgedfs.py
@@ -1,11 +1,8 @@
import pytest
import networkx as nx
-
-edge_dfs = nx.algorithms.edge_dfs
-
-FORWARD = nx.algorithms.edgedfs.FORWARD
-REVERSE = nx.algorithms.edgedfs.REVERSE
+from networkx.algorithms import edge_dfs
+from networkx.algorithms.traversal.edgedfs import FORWARD, REVERSE
# These tests can fail with hash randomization. The easiest and clearest way
# to write these unit tests is for the edges to be output in an expected total
diff --git a/networkx/classes/graphviews.py b/networkx/classes/graphviews.py
index 4b276292..fb5dd63b 100644
--- a/networkx/classes/graphviews.py
+++ b/networkx/classes/graphviews.py
@@ -153,13 +153,13 @@ def subgraph_view(G, filter_node=no_filter, filter_edge=no_filter):
if G.is_multigraph():
Adj = FilterMultiAdjacency
- def reverse_edge(u, v, k):
+ def reverse_edge(u, v, k=None):
return filter_edge(v, u, k)
else:
Adj = FilterAdjacency
- def reverse_edge(u, v):
+ def reverse_edge(u, v, k=None):
return filter_edge(v, u)
if G.is_directed():
diff --git a/networkx/classes/tests/test_multigraph.py b/networkx/classes/tests/test_multigraph.py
index f83378a6..ad9d6fd2 100644
--- a/networkx/classes/tests/test_multigraph.py
+++ b/networkx/classes/tests/test_multigraph.py
@@ -217,7 +217,7 @@ class TestMultiGraph(BaseMultiGraphTester, _TestGraph):
dol = {"a": ["b"]}
multiple_edge = [("a", "b", "traits", etraits), ("a", "b", "graphics", egraphics)]
- single_edge = [("a", "b", 0, {})]
+ single_edge = [("a", "b", 0, {})] # type: ignore
single_edge1 = [("a", "b", 0, edata)]
single_edge2 = [("a", "b", 0, etraits)]
single_edge3 = [("a", "b", 0, {"traits": etraits, "s": "foo"})]
diff --git a/networkx/drawing/layout.py b/networkx/drawing/layout.py
index c16446e2..73e52bee 100644
--- a/networkx/drawing/layout.py
+++ b/networkx/drawing/layout.py
@@ -556,8 +556,7 @@ def _fruchterman_reingold(
pos += delta_pos
# cool temperature
t -= dt
- err = np.linalg.norm(delta_pos) / nnodes
- if err < threshold:
+ if (np.linalg.norm(delta_pos) / nnodes) < threshold:
break
return pos
@@ -631,8 +630,7 @@ def _sparse_fruchterman_reingold(
pos += delta_pos
# cool temperature
t -= dt
- err = np.linalg.norm(delta_pos) / nnodes
- if err < threshold:
+ if (np.linalg.norm(delta_pos) / nnodes) < threshold:
break
return pos
diff --git a/networkx/generators/line.py b/networkx/generators/line.py
index 55954c74..466691f6 100644
--- a/networkx/generators/line.py
+++ b/networkx/generators/line.py
@@ -114,12 +114,12 @@ def _node_func(G):
"""
if G.is_multigraph():
- def sorted_node(u, v, key):
+ def sorted_node(u, v, key=None):
return (u, v, key) if u <= v else (v, u, key)
else:
- def sorted_node(u, v):
+ def sorted_node(u, v, key=None):
return (u, v) if u <= v else (v, u)
return sorted_node
diff --git a/networkx/readwrite/graphml.py b/networkx/readwrite/graphml.py
index a1ed7ad1..2e98373c 100644
--- a/networkx/readwrite/graphml.py
+++ b/networkx/readwrite/graphml.py
@@ -999,14 +999,14 @@ class GraphMLReader(GraphML):
data["label"] = node_label.text
# check all the different types of edges avaivable in yEd.
- for e in [
+ for edge_type in [
"PolyLineEdge",
"SplineEdge",
"QuadCurveEdge",
"BezierEdge",
"ArcEdge",
]:
- pref = f"{{{self.NS_Y}}}{e}/{{{self.NS_Y}}}"
+ pref = f"{{{self.NS_Y}}}{edge_type}/{{{self.NS_Y}}}"
edge_label = data_element.find(f"{pref}EdgeLabel")
if edge_label is not None:
break
diff --git a/networkx/readwrite/nx_shp.py b/networkx/readwrite/nx_shp.py
index 4dd01be5..74bc0595 100644
--- a/networkx/readwrite/nx_shp.py
+++ b/networkx/readwrite/nx_shp.py
@@ -327,10 +327,10 @@ def write_shp(G, outdir):
# New edge attribute write support merged into edge loop
edge_fields = {} # storage for field names and their data types
- for e in G.edges(data=True):
- data = G.get_edge_data(*e)
- g = netgeometry(e, data)
- attributes, edges = create_attributes(e[2], edge_fields, edges)
+ for edge in G.edges(data=True):
+ data = G.get_edge_data(*edge)
+ g = netgeometry(edge, data)
+ attributes, edges = create_attributes(edge[2], edge_fields, edges)
create_feature(g, edges, attributes)
nodes, edges = None, None
diff --git a/networkx/readwrite/tests/test_gml.py b/networkx/readwrite/tests/test_gml.py
index 51c08c4f..50facec5 100644
--- a/networkx/readwrite/tests/test_gml.py
+++ b/networkx/readwrite/tests/test_gml.py
@@ -288,7 +288,7 @@ graph
]"""
assert data == answer
- def test_float_label(self):
+ def test_special_float_label(self):
special_floats = [float("nan"), float("+inf"), float("-inf")]
try:
import numpy as np
diff --git a/networkx/utils/decorators.py b/networkx/utils/decorators.py
index 14bac852..e8e4bff5 100644
--- a/networkx/utils/decorators.py
+++ b/networkx/utils/decorators.py
@@ -92,10 +92,12 @@ def not_implemented_for(*graph_types):
# To handle new extensions, define a function accepting a `path` and `mode`.
# Then add the extension to _dispatch_dict.
-_dispatch_dict = defaultdict(lambda: open)
-_dispatch_dict[".gz"] = gzip.open
-_dispatch_dict[".bz2"] = bz2.BZ2File
-_dispatch_dict[".gzip"] = gzip.open
+fopeners = {
+ ".gz": gzip.open,
+ ".gzip": gzip.open,
+ ".bz2": bz2.BZ2File,
+}
+_dispatch_dict = defaultdict(lambda: open, **fopeners) # type: ignore
def open_file(path_arg, mode="r"):
diff --git a/requirements/developer.txt b/requirements/developer.txt
index 0fea0d07..cacc7020 100644
--- a/requirements/developer.txt
+++ b/requirements/developer.txt
@@ -1,3 +1,4 @@
black==21.9b0
pyupgrade>=2.29.0
pre-commit>=2.15
+mypy>=0.910