summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJarrod Millman <jarrod.millman@gmail.com>2021-10-23 15:37:48 -0700
committerGitHub <noreply@github.com>2021-10-23 15:37:48 -0700
commit0c503e31ba0062dc9a4ed47c380481aa8d6978c8 (patch)
treeef389b7ba52dec39941978824c7e0e833f17ab9e
parent27d362b9a752adf38d7db1828a48f50bb41c84bd (diff)
downloadnetworkx-0c503e31ba0062dc9a4ed47c380481aa8d6978c8.tar.gz
Drop Py37 (#5143)
* Drop Py37 * XML serialization issue * Use math.comb Co-authored-by: Simone Gasperini <simone.gasperini2@studio.unibo.it> * Run pyupgrade --py38-plus * Run black * More documentation * Deprecate euclidean Co-authored-by: Simone Gasperini <simone.gasperini2@studio.unibo.it>
-rw-r--r--.github/workflows/lint.yml2
-rw-r--r--.github/workflows/test.yml8
-rw-r--r--INSTALL.rst2
-rw-r--r--doc/developer/deprecations.rst1
-rw-r--r--doc/release/release_dev.rst6
-rw-r--r--examples/drawing/plot_degree.py2
-rw-r--r--networkx/algorithms/assortativity/correlation.py8
-rw-r--r--networkx/algorithms/centrality/katz.py2
-rw-r--r--networkx/algorithms/clique.py6
-rw-r--r--networkx/algorithms/coloring/equitable_coloring.py2
-rw-r--r--networkx/algorithms/coloring/tests/test_coloring.py2
-rw-r--r--networkx/algorithms/community/lukes.py6
-rw-r--r--networkx/algorithms/community/modularity_max.py2
-rw-r--r--networkx/algorithms/components/tests/test_biconnected.py4
-rw-r--r--networkx/algorithms/connectivity/tests/test_edge_augmentation.py2
-rw-r--r--networkx/algorithms/dag.py8
-rw-r--r--networkx/algorithms/distance_regular.py2
-rw-r--r--networkx/algorithms/euler.py2
-rw-r--r--networkx/algorithms/isomorphism/matchhelpers.py4
-rw-r--r--networkx/algorithms/isomorphism/tree_isomorphism.py8
-rw-r--r--networkx/algorithms/link_analysis/hits_alg.py2
-rw-r--r--networkx/algorithms/link_analysis/pagerank_alg.py2
-rw-r--r--networkx/algorithms/matching.py2
-rw-r--r--networkx/algorithms/operators/all.py2
-rw-r--r--networkx/algorithms/shortest_paths/generic.py2
-rw-r--r--networkx/algorithms/similarity.py44
-rw-r--r--networkx/algorithms/smetric.py2
-rw-r--r--networkx/algorithms/summarization.py4
-rw-r--r--networkx/algorithms/tests/test_core.py10
-rw-r--r--networkx/algorithms/tests/test_similarity.py13
-rw-r--r--networkx/algorithms/tests/test_simple_paths.py4
-rw-r--r--networkx/algorithms/tests/test_summarization.py56
-rw-r--r--networkx/algorithms/tests/test_threshold.py6
-rw-r--r--networkx/algorithms/threshold.py2
-rw-r--r--networkx/classes/function.py2
-rw-r--r--networkx/classes/ordered.py8
-rw-r--r--networkx/classes/tests/historical_tests.py2
-rw-r--r--networkx/classes/tests/test_digraph_historical.py2
-rw-r--r--networkx/convert_matrix.py2
-rw-r--r--networkx/drawing/tests/test_pydot.py10
-rw-r--r--networkx/generators/directed.py6
-rw-r--r--networkx/generators/geometric.py15
-rw-r--r--networkx/generators/tests/test_geometric.py54
-rw-r--r--networkx/generators/tests/test_random_graphs.py4
-rw-r--r--networkx/linalg/attrmatrix.py4
-rw-r--r--networkx/linalg/bethehessianmatrix.py5
-rw-r--r--networkx/readwrite/nx_shp.py2
-rw-r--r--networkx/readwrite/tests/test_gexf.py113
-rw-r--r--networkx/readwrite/tests/test_graphml.py8
-rw-r--r--networkx/utils/decorators.py2
-rw-r--r--setup.py7
51 files changed, 147 insertions, 329 deletions
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index f4f8fb08..20ae7d49 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -7,7 +7,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- python-version: [3.7]
+ python-version: [3.8]
steps:
- uses: actions/checkout@v2
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index e6c2812d..a9198f31 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -9,7 +9,7 @@ jobs:
strategy:
matrix:
os: [ubuntu, macos, windows]
- python-version: [3.7, 3.8, 3.9]
+ python-version: [3.8, 3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -33,7 +33,7 @@ jobs:
strategy:
matrix:
os: [ubuntu, macos]
- python-version: [pypy-3.7]
+ python-version: [pypy-3.8]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -57,7 +57,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-20.04, macos-latest, windows-latest]
- python-version: [3.7, 3.8, 3.9]
+ python-version: [3.8, 3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
@@ -109,7 +109,7 @@ jobs:
strategy:
matrix:
os: [ubuntu, macos]
- python-version: [3.7, 3.8, 3.9]
+ python-version: [3.8, 3.9]
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
diff --git a/INSTALL.rst b/INSTALL.rst
index 99cf907e..6a8b6f78 100644
--- a/INSTALL.rst
+++ b/INSTALL.rst
@@ -1,7 +1,7 @@
Install
=======
-NetworkX requires Python 3.7, 3.8, or 3.9. If you do not already
+NetworkX requires Python 3.8 or 3.9. If you do not already
have a Python environment configured on your computer, please see the
instructions for installing the full `scientific Python stack
<https://scipy.org/install.html>`_.
diff --git a/doc/developer/deprecations.rst b/doc/developer/deprecations.rst
index be4b7be5..616217a5 100644
--- a/doc/developer/deprecations.rst
+++ b/doc/developer/deprecations.rst
@@ -92,3 +92,4 @@ Version 3.0
* In ``algorithms/assortativity/connectivity.py`` remove ``k_nearest_neighbors``.
* In ``utils/decorators.py`` remove ``random_state``.
* In ``algorithms/operators/binary.py`` remove ``name`` kwarg from ``union`` and docstring.
+* In ``networkx/generators/geometric.py`` remove ``euclidean`` and tests.
diff --git a/doc/release/release_dev.rst b/doc/release/release_dev.rst
index a779ab16..5101f209 100644
--- a/doc/release/release_dev.rst
+++ b/doc/release/release_dev.rst
@@ -3,7 +3,7 @@ Next Release
Release date: TBD
-Supports Python ...
+Supports Python 3.8, 3.9, and ...
NetworkX is a Python package for the creation, manipulation, and study of the
structure, dynamics, and functions of complex networks.
@@ -31,6 +31,8 @@ X contributors. Highlights include:
.. _gh-4946: https://github.com/networkx/networkx/pull/4946#issuecomment-914623654
+- Dropped support for Python 3.7.
+
Improvements
------------
@@ -50,6 +52,8 @@ Deprecations
Deprecate the ``random_state`` alias in favor of ``np_random_state``
- [`#5114 <https://github.com/networkx/networkx/pull/5114>`_]
Deprecate the ``name`` kwarg from ``union`` as it isn't used.
+- [`#5143 <https://github.com/networkx/networkx/pull/5143>`_]
+ Deprecate ``euclidean`` in favor of ``math.dist``.
Merged PRs
diff --git a/examples/drawing/plot_degree.py b/examples/drawing/plot_degree.py
index 6fc5994b..9d7abe4a 100644
--- a/examples/drawing/plot_degree.py
+++ b/examples/drawing/plot_degree.py
@@ -19,7 +19,7 @@ import matplotlib.pyplot as plt
G = nx.gnp_random_graph(100, 0.02, seed=10374196)
-degree_sequence = sorted([d for n, d in G.degree()], reverse=True)
+degree_sequence = sorted((d for n, d in G.degree()), reverse=True)
dmax = max(degree_sequence)
fig = plt.figure("Degree of a random graph", figsize=(8, 8))
diff --git a/networkx/algorithms/assortativity/correlation.py b/networkx/algorithms/assortativity/correlation.py
index 3036ff8b..39ac2fab 100644
--- a/networkx/algorithms/assortativity/correlation.py
+++ b/networkx/algorithms/assortativity/correlation.py
@@ -80,18 +80,18 @@ def degree_assortativity_coefficient(G, x="out", y="in", weight=None, nodes=None
if G.is_directed():
indeg = (
- set([d for _, d in G.in_degree(nodes, weight=weight)])
+ {d for _, d in G.in_degree(nodes, weight=weight)}
if "in" in (x, y)
else set()
)
outdeg = (
- set([d for _, d in G.out_degree(nodes, weight=weight)])
+ {d for _, d in G.out_degree(nodes, weight=weight)}
if "out" in (x, y)
else set()
)
degrees = set.union(indeg, outdeg)
else:
- degrees = set([d for _, d in G.degree(nodes, weight=weight)])
+ degrees = {d for _, d in G.degree(nodes, weight=weight)}
mapping = {d: i for i, d, in enumerate(degrees)}
M = degree_mixing_matrix(G, x=x, y=y, nodes=nodes, weight=weight, mapping=mapping)
@@ -247,7 +247,7 @@ def numeric_assortativity_coefficient(G, attribute, nodes=None):
"""
if nodes is None:
nodes = G.nodes
- vals = set(G.nodes[n][attribute] for n in nodes)
+ vals = {G.nodes[n][attribute] for n in nodes}
mapping = {d: i for i, d, in enumerate(vals)}
M = attribute_mixing_matrix(G, attribute, nodes, mapping)
return numeric_ac(M, mapping)
diff --git a/networkx/algorithms/centrality/katz.py b/networkx/algorithms/centrality/katz.py
index 87c2df07..33fcf096 100644
--- a/networkx/algorithms/centrality/katz.py
+++ b/networkx/algorithms/centrality/katz.py
@@ -176,7 +176,7 @@ def katz_centrality(
x[n] = alpha * x[n] + b[n]
# check convergence
- err = sum([abs(x[n] - xlast[n]) for n in x])
+ err = sum(abs(x[n] - xlast[n]) for n in x)
if err < nnodes * tol:
if normalized:
# normalize vector
diff --git a/networkx/algorithms/clique.py b/networkx/algorithms/clique.py
index 803507b8..d636a842 100644
--- a/networkx/algorithms/clique.py
+++ b/networkx/algorithms/clique.py
@@ -485,11 +485,11 @@ def node_clique_number(G, nodes=None, cliques=None):
if not isinstance(nodes, list): # check for a list
v = nodes
# assume it is a single value
- d = max([len(c) for c in cliques if v in c])
+ d = max(len(c) for c in cliques if v in c)
else:
d = {}
for v in nodes:
- d[v] = max([len(c) for c in cliques if v in c])
+ d[v] = max(len(c) for c in cliques if v in c)
return d
# if nodes is None: # none, use entire graph
@@ -554,7 +554,7 @@ def cliques_containing_node(G, nodes=None, cliques=None):
return vcliques
-class MaxWeightClique(object):
+class MaxWeightClique:
"""A class for the maximum weight clique algorithm.
This class is a helper for the `max_weight_clique` function. The class
diff --git a/networkx/algorithms/coloring/equitable_coloring.py b/networkx/algorithms/coloring/equitable_coloring.py
index f07cc541..1a2c99fe 100644
--- a/networkx/algorithms/coloring/equitable_coloring.py
+++ b/networkx/algorithms/coloring/equitable_coloring.py
@@ -447,7 +447,7 @@ def equitable_color(G, num_colors):
# Basic graph statistics and sanity check.
if len(G.nodes) > 0:
- r_ = max([G.degree(node) for node in G.nodes])
+ r_ = max(G.degree(node) for node in G.nodes)
else:
r_ = 0
diff --git a/networkx/algorithms/coloring/tests/test_coloring.py b/networkx/algorithms/coloring/tests/test_coloring.py
index 5d2cb82f..274abff5 100644
--- a/networkx/algorithms/coloring/tests/test_coloring.py
+++ b/networkx/algorithms/coloring/tests/test_coloring.py
@@ -775,7 +775,7 @@ def check_state(L, N, H, F, C):
def max_degree(G):
"""Get the maximum degree of any node in G."""
- return max([G.degree(node) for node in G.nodes]) if len(G.nodes) > 0 else 0
+ return max(G.degree(node) for node in G.nodes) if len(G.nodes) > 0 else 0
def make_params_from_graph(G, F):
diff --git a/networkx/algorithms/community/lukes.py b/networkx/algorithms/community/lukes.py
index 29ade800..6fe1d0de 100644
--- a/networkx/algorithms/community/lukes.py
+++ b/networkx/algorithms/community/lukes.py
@@ -132,14 +132,14 @@ def lukes_partitioning(G, max_size: int, node_weight=None, edge_weight=None) ->
@lru_cache(CLUSTER_EVAL_CACHE_SIZE)
def _value_of_cluster(cluster: frozenset):
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])
+ return sum(safe_G.edges[e][edge_weight] for e in valid_edges)
def _value_of_partition(partition: list):
- return sum([_value_of_cluster(frozenset(c)) for c in partition])
+ return sum(_value_of_cluster(frozenset(c)) for c in partition)
@lru_cache(CLUSTER_EVAL_CACHE_SIZE)
def _weight_of_cluster(cluster: frozenset):
- return sum([safe_G.nodes[n][node_weight] for n in cluster])
+ return sum(safe_G.nodes[n][node_weight] for n in cluster)
def _pivot(partition: list, node):
ccx = [c for c in partition if node in c]
diff --git a/networkx/algorithms/community/modularity_max.py b/networkx/algorithms/community/modularity_max.py
index 10d42e7f..19810531 100644
--- a/networkx/algorithms/community/modularity_max.py
+++ b/networkx/algorithms/community/modularity_max.py
@@ -282,7 +282,7 @@ def naive_greedy_modularity_communities(G, resolution=1):
modularity
"""
# First create one community for each node
- communities = list([frozenset([u]) for u in G.nodes()])
+ communities = list(frozenset([u]) for u in G.nodes())
# Track merges
merges = []
# Greedily merge communities until no improvement is possible
diff --git a/networkx/algorithms/components/tests/test_biconnected.py b/networkx/algorithms/components/tests/test_biconnected.py
index 80faea0e..6c7574dc 100644
--- a/networkx/algorithms/components/tests/test_biconnected.py
+++ b/networkx/algorithms/components/tests/test_biconnected.py
@@ -4,8 +4,8 @@ from networkx import NetworkXNotImplemented
def assert_components_edges_equal(x, y):
- sx = {frozenset([frozenset(e) for e in c]) for c in x}
- sy = {frozenset([frozenset(e) for e in c]) for c in y}
+ sx = {frozenset(frozenset(e) for e in c) for c in x}
+ sy = {frozenset(frozenset(e) for e in c) for c in y}
assert sx == sy
diff --git a/networkx/algorithms/connectivity/tests/test_edge_augmentation.py b/networkx/algorithms/connectivity/tests/test_edge_augmentation.py
index 600ab13e..a1bbf5a5 100644
--- a/networkx/algorithms/connectivity/tests/test_edge_augmentation.py
+++ b/networkx/algorithms/connectivity/tests/test_edge_augmentation.py
@@ -351,7 +351,7 @@ def _augment_and_check(
# Find the weight of the augmentation
num_edges = len(aug_edges)
if avail is not None:
- total_weight = sum([avail_dict[e] for e in aug_edges])
+ total_weight = sum(avail_dict[e] for e in aug_edges)
else:
total_weight = num_edges
diff --git a/networkx/algorithms/dag.py b/networkx/algorithms/dag.py
index e6a408e0..5a4881ff 100644
--- a/networkx/algorithms/dag.py
+++ b/networkx/algorithms/dag.py
@@ -681,15 +681,13 @@ def transitive_closure(G, reflexive=False):
for v in G:
if reflexive is None:
- TC.add_edges_from(((v, u) for u in nx.descendants(G, v) if u not in TC[v]))
+ TC.add_edges_from((v, u) for u in nx.descendants(G, v) if u not in TC[v])
elif reflexive is True:
TC.add_edges_from(
- ((v, u) for u in nx.descendants(G, v) | {v} if u not in TC[v])
+ (v, u) for u in nx.descendants(G, v) | {v} if u not in TC[v]
)
elif reflexive is False:
- TC.add_edges_from(
- ((v, e[1]) for e in nx.edge_bfs(G, v) if e[1] not in TC[v])
- )
+ TC.add_edges_from((v, e[1]) for e in nx.edge_bfs(G, v) if e[1] not in TC[v])
return TC
diff --git a/networkx/algorithms/distance_regular.py b/networkx/algorithms/distance_regular.py
index cd2ab793..3813aa73 100644
--- a/networkx/algorithms/distance_regular.py
+++ b/networkx/algorithms/distance_regular.py
@@ -151,7 +151,7 @@ def intersection_array(G):
raise nx.NetworkXError("Graph is not distance regular.")
k = knext
path_length = dict(nx.all_pairs_shortest_path_length(G))
- diameter = max([max(path_length[n].values()) for n in path_length])
+ diameter = max(max(path_length[n].values()) for n in path_length)
bint = {} # 'b' intersection array
cint = {} # 'c' intersection array
for u in G:
diff --git a/networkx/algorithms/euler.py b/networkx/algorithms/euler.py
index 5fd8dce4..6d433c0a 100644
--- a/networkx/algorithms/euler.py
+++ b/networkx/algorithms/euler.py
@@ -74,7 +74,7 @@ def _find_path_start(G):
return arbitrary_element(G)
if G.is_directed():
- v1, v2 = [v for v in G if G.in_degree(v) != G.out_degree(v)]
+ v1, v2 = (v for v in G if G.in_degree(v) != G.out_degree(v))
# Determines which is the 'start' node (as opposed to the 'end')
if G.out_degree(v1) > G.in_degree(v1):
return v1
diff --git a/networkx/algorithms/isomorphism/matchhelpers.py b/networkx/algorithms/isomorphism/matchhelpers.py
index 5daaff69..c2f02778 100644
--- a/networkx/algorithms/isomorphism/matchhelpers.py
+++ b/networkx/algorithms/isomorphism/matchhelpers.py
@@ -198,8 +198,8 @@ def numerical_multiedge_match(attr, default, rtol=1.0000000000000001e-05, atol=1
if isinstance(attr, str):
def match(datasets1, datasets2):
- values1 = sorted([data.get(attr, default) for data in datasets1.values()])
- values2 = sorted([data.get(attr, default) for data in datasets2.values()])
+ values1 = sorted(data.get(attr, default) for data in datasets1.values())
+ values2 = sorted(data.get(attr, default) for data in datasets2.values())
return allclose(values1, values2, rtol=rtol, atol=atol)
else:
diff --git a/networkx/algorithms/isomorphism/tree_isomorphism.py b/networkx/algorithms/isomorphism/tree_isomorphism.py
index 94ef6cd4..7e13d027 100644
--- a/networkx/algorithms/isomorphism/tree_isomorphism.py
+++ b/networkx/algorithms/isomorphism/tree_isomorphism.py
@@ -175,7 +175,7 @@ def rooted_tree_isomorphism(t1, root1, t2, root2):
if dT.out_degree(v) > 0:
# get all the pairs of labels and nodes of children
# and sort by labels
- s = sorted([(label[u], u) for u in dT.successors(v)])
+ s = sorted((label[u], u) for u in dT.successors(v))
# invert to give a list of two tuples
# the sorted labels, and the corresponding children
@@ -183,7 +183,7 @@ def rooted_tree_isomorphism(t1, root1, t2, root2):
# now collect and sort the sorted ordered_labels
# for all nodes in L[i], carrying along the node
- forlabel = sorted([(ordered_labels[v], v) for v in L[i]])
+ forlabel = sorted((ordered_labels[v], v) for v in L[i])
# now assign labels to these nodes, according to the sorted order
# starting from 0, where idential ordered_labels get the same label
@@ -249,8 +249,8 @@ def tree_isomorphism(t1, t2):
return []
# Another shortcut is that the sorted degree sequences need to be the same.
- degree_sequence1 = sorted([d for (n, d) in t1.degree()])
- degree_sequence2 = sorted([d for (n, d) in t2.degree()])
+ degree_sequence1 = sorted(d for (n, d) in t1.degree())
+ degree_sequence2 = sorted(d for (n, d) in t2.degree())
if degree_sequence1 != degree_sequence2:
return []
diff --git a/networkx/algorithms/link_analysis/hits_alg.py b/networkx/algorithms/link_analysis/hits_alg.py
index 281ebad2..491214d9 100644
--- a/networkx/algorithms/link_analysis/hits_alg.py
+++ b/networkx/algorithms/link_analysis/hits_alg.py
@@ -129,7 +129,7 @@ def _hits_python(G, max_iter=100, tol=1.0e-8, nstart=None, normalized=True):
for n in a:
a[n] *= s
# check convergence, l1 norm
- err = sum([abs(h[n] - hlast[n]) for n in h])
+ err = sum(abs(h[n] - hlast[n]) for n in h)
if err < tol:
break
else:
diff --git a/networkx/algorithms/link_analysis/pagerank_alg.py b/networkx/algorithms/link_analysis/pagerank_alg.py
index f564b910..718ddb51 100644
--- a/networkx/algorithms/link_analysis/pagerank_alg.py
+++ b/networkx/algorithms/link_analysis/pagerank_alg.py
@@ -166,7 +166,7 @@ def _pagerank_python(
x[nbr] += alpha * xlast[n] * wt
x[n] += danglesum * dangling_weights.get(n, 0) + (1.0 - alpha) * p.get(n, 0)
# check convergence, l1 norm
- err = sum([abs(x[n] - xlast[n]) for n in x])
+ err = sum(abs(x[n] - xlast[n]) for n in x)
if err < N * tol:
return x
raise nx.PowerIterationFailedConvergence(max_iter)
diff --git a/networkx/algorithms/matching.py b/networkx/algorithms/matching.py
index cbafe8fa..0c874f40 100644
--- a/networkx/algorithms/matching.py
+++ b/networkx/algorithms/matching.py
@@ -217,7 +217,7 @@ def min_weight_matching(G, maxcardinality=False, weight="weight"):
if len(G.edges) == 0:
return max_weight_matching(G, maxcardinality, weight)
G_edges = G.edges(data=weight, default=1)
- min_weight = min([w for _, _, w in G_edges])
+ min_weight = min(w for _, _, w in G_edges)
InvG = nx.Graph()
edges = ((u, v, 1 / (1 + w - min_weight)) for u, v, w in G_edges)
InvG.add_weighted_edges_from(edges, weight=weight)
diff --git a/networkx/algorithms/operators/all.py b/networkx/algorithms/operators/all.py
index 92df582d..0ff17094 100644
--- a/networkx/algorithms/operators/all.py
+++ b/networkx/algorithms/operators/all.py
@@ -71,7 +71,7 @@ def union_all(graphs, rename=(None,)):
graphs = [add_prefix(G, name) for G, name in zip_longest(graphs, rename)]
- if sum([len(G) for G in graphs]) != len(set().union(*graphs)):
+ if sum(len(G) for G in graphs) != len(set().union(*graphs)):
raise nx.NetworkXError(
"The node sets of the graphs are not disjoint.",
"Use appropriate rename"
diff --git a/networkx/algorithms/shortest_paths/generic.py b/networkx/algorithms/shortest_paths/generic.py
index e5a691e2..2c11eb5d 100644
--- a/networkx/algorithms/shortest_paths/generic.py
+++ b/networkx/algorithms/shortest_paths/generic.py
@@ -403,7 +403,7 @@ def average_shortest_path_length(G, weight=None, method=None):
else:
if method == "floyd-warshall":
all_pairs = nx.floyd_warshall(G, weight=weight)
- s = sum([sum(t.values()) for t in all_pairs.values()])
+ s = sum(sum(t.values()) for t in all_pairs.values())
elif method == "floyd-warshall-numpy":
s = nx.floyd_warshall_numpy(G, weight=weight).sum()
return s / (n * (n - 1))
diff --git a/networkx/algorithms/similarity.py b/networkx/algorithms/similarity.py
index c56eb55e..9966d76a 100644
--- a/networkx/algorithms/similarity.py
+++ b/networkx/algorithms/similarity.py
@@ -1515,48 +1515,6 @@ def simrank_similarity_numpy(
)
-# TODO replace w/ math.comb(n, k) for Python 3.8+
-def _n_choose_k(n, k):
- """Pure Python implementation of the binomial coefficient
-
- The general equation is n! / (k! * (n - k)!). The below
- implementation is a more efficient version.
-
- Note: this will be removed in favor of Python 3.8's ``math.comb(n, k)``.
-
- Parameters
- ----------
- n : int
- Set of ``n`` elements
- k : int
- Unordered chosen subset of length ``k``
-
- Returns
- -------
- binomial_coeff : int
- The number of ways (disregarding order) that k objects
- can be chosen from among n objects.
-
- Examples
- --------
- >>> _n_choose_k(5, 2)
- 10
- >>> _n_choose_k(5, 4)
- 5
- >>> _n_choose_k(100, 100)
- 1
-
- """
- if k > n:
- return 0
- if n == k:
- return 1
- elif k < n - k:
- return reduce(mul, range(n - k + 1, n + 1)) // math.factorial(k)
- else:
- return reduce(mul, range(k + 1, n + 1)) // math.factorial(n - k)
-
-
def panther_similarity(G, source, k=5, path_length=5, c=0.5, delta=0.1, eps=None):
r"""Returns the Panther similarity of nodes in the graph `G` to node ``v``.
@@ -1623,7 +1581,7 @@ def panther_similarity(G, source, k=5, path_length=5, c=0.5, delta=0.1, eps=None
# Calculate the sample size ``R`` for how many paths
# to randomly generate
- t_choose_2 = _n_choose_k(path_length, 2)
+ t_choose_2 = math.comb(path_length, 2)
sample_size = int((c / eps ** 2) * (np.log2(t_choose_2) + 1 + np.log(1 / delta)))
index_map = {}
_ = list(
diff --git a/networkx/algorithms/smetric.py b/networkx/algorithms/smetric.py
index e33f6702..b851e1ee 100644
--- a/networkx/algorithms/smetric.py
+++ b/networkx/algorithms/smetric.py
@@ -35,4 +35,4 @@ def s_metric(G, normalized=True):
# Gmax = li_smax_graph(list(G.degree().values()))
# return s_metric(G,normalized=False)/s_metric(Gmax,normalized=False)
# else:
- return float(sum([G.degree(u) * G.degree(v) for (u, v) in G.edges()]))
+ return float(sum(G.degree(u) * G.degree(v) for (u, v) in G.edges()))
diff --git a/networkx/algorithms/summarization.py b/networkx/algorithms/summarization.py
index b26639d7..a572a832 100644
--- a/networkx/algorithms/summarization.py
+++ b/networkx/algorithms/summarization.py
@@ -174,7 +174,7 @@ def dedensify(G, threshold, prefix=None, copy=True):
degrees = G.in_degree if G.is_directed() else G.degree
# Group nodes based on degree threshold
- high_degree_nodes = set([n for n, d in degrees if d > threshold])
+ high_degree_nodes = {n for n, d in degrees if d > threshold}
low_degree_nodes = G.nodes() - high_degree_nodes
auxillary = {}
@@ -262,7 +262,7 @@ def _snap_build_graph(
node_label_lookup = dict()
for index, group_id in enumerate(groups):
group_set = groups[group_id]
- supernode = "%s%s" % (prefix, index)
+ supernode = f"{prefix}{index}"
node_label_lookup[group_id] = supernode
supernode_attributes = {
attr: G.nodes[next(iter(group_set))][attr] for attr in node_attributes
diff --git a/networkx/algorithms/tests/test_core.py b/networkx/algorithms/tests/test_core.py
index 9caabfc1..ae546a38 100644
--- a/networkx/algorithms/tests/test_core.py
+++ b/networkx/algorithms/tests/test_core.py
@@ -54,9 +54,7 @@ class TestCore:
def test_find_cores(self):
core = nx.find_cores(self.G)
- nodes_by_core = [
- sorted([n for n in core if core[n] == val]) for val in range(4)
- ]
+ nodes_by_core = [sorted(n for n in core if core[n] == val) for val in range(4)]
assert nodes_equal(nodes_by_core[0], [21])
assert nodes_equal(nodes_by_core[1], [17, 18, 19, 20])
assert nodes_equal(nodes_by_core[2], [9, 10, 11, 12, 13, 14, 15, 16])
@@ -68,9 +66,7 @@ class TestCore:
def test_find_cores2(self):
core = nx.find_cores(self.H)
- nodes_by_core = [
- sorted([n for n in core if core[n] == val]) for val in range(3)
- ]
+ nodes_by_core = [sorted(n for n in core if core[n] == val) for val in range(3)]
assert nodes_equal(nodes_by_core[0], [0])
assert nodes_equal(nodes_by_core[1], [1, 3])
assert nodes_equal(nodes_by_core[2], [2, 4, 5, 6])
@@ -169,7 +165,7 @@ class TestCore:
def test_onion_layers(self):
layers = nx.onion_layers(self.G)
nodes_by_layer = [
- sorted([n for n in layers if layers[n] == val]) for val in range(1, 7)
+ sorted(n for n in layers if layers[n] == val) for val in range(1, 7)
]
assert nodes_equal(nodes_by_layer[0], [21])
assert nodes_equal(nodes_by_layer[1], [17, 18, 19, 20])
diff --git a/networkx/algorithms/tests/test_similarity.py b/networkx/algorithms/tests/test_similarity.py
index 8c9b5422..c4fd17f1 100644
--- a/networkx/algorithms/tests/test_similarity.py
+++ b/networkx/algorithms/tests/test_similarity.py
@@ -5,7 +5,6 @@ from networkx.algorithms.similarity import (
graph_edit_distance,
optimal_edit_paths,
optimize_graph_edit_distance,
- _n_choose_k,
)
from networkx.generators.classic import (
circular_ladder_graph,
@@ -791,18 +790,6 @@ class TestSimilarity:
actual = nx.similarity._simrank_similarity_numpy(G, source=0, target=0)
np.testing.assert_allclose(expected, actual, atol=1e-7)
- def test_n_choose_k_small_k(self):
- assert _n_choose_k(10, 4) == 210
-
- def test_n_choose_k_big_k(self):
- assert _n_choose_k(10, 8) == 45
-
- def test_n_choose_k_same(self):
- assert _n_choose_k(10, 10) == 1
-
- def test_n_choose_k_k_bigger_than_n(self):
- assert _n_choose_k(5, 10) == 0
-
def test_panther_similarity_unweighted(self):
np.random.seed(42)
diff --git a/networkx/algorithms/tests/test_simple_paths.py b/networkx/algorithms/tests/test_simple_paths.py
index aaf9a051..3e83c5d0 100644
--- a/networkx/algorithms/tests/test_simple_paths.py
+++ b/networkx/algorithms/tests/test_simple_paths.py
@@ -449,7 +449,7 @@ def test_shortest_simple_paths():
assert next(paths) == [1, 2, 3, 4, 8, 12]
assert next(paths) == [1, 5, 6, 7, 8, 12]
assert [len(path) for path in nx.shortest_simple_paths(G, 1, 12)] == sorted(
- [len(path) for path in nx.all_simple_paths(G, 1, 12)]
+ len(path) for path in nx.all_simple_paths(G, 1, 12)
)
@@ -469,7 +469,7 @@ def test_shortest_simple_paths_directed_with_weight_fucntion():
assert next(paths) == [1, 5, 6, 7, 8, 12]
assert [
len(path) for path in nx.shortest_simple_paths(G, 1, 12, weight=cost)
- ] == sorted([len(path) for path in nx.all_simple_paths(G, 1, 12)])
+ ] == sorted(len(path) for path in nx.all_simple_paths(G, 1, 12))
def test_shortest_simple_paths_with_weight_fucntion():
diff --git a/networkx/algorithms/tests/test_summarization.py b/networkx/algorithms/tests/test_summarization.py
index d633f825..2106f615 100644
--- a/networkx/algorithms/tests/test_summarization.py
+++ b/networkx/algorithms/tests/test_summarization.py
@@ -340,12 +340,12 @@ class TestSNAPNoEdgeTypes(AbstractSNAP):
G.add_edge(source, target)
supernodes = {
- "Supernode-0": set(["A", "B"]),
- "Supernode-1": set(["C", "D"]),
- "Supernode-2": set(["E", "F"]),
- "Supernode-3": set(["G", "H"]),
- "Supernode-4": set(["I", "J"]),
- "Supernode-5": set(["K", "L"]),
+ "Supernode-0": {"A", "B"},
+ "Supernode-1": {"C", "D"},
+ "Supernode-2": {"E", "F"},
+ "Supernode-3": {"G", "H"},
+ "Supernode-4": {"I", "J"},
+ "Supernode-5": {"K", "L"},
}
nx.set_node_attributes(G, supernodes, "group")
return G
@@ -418,12 +418,12 @@ class TestSNAPUndirected(AbstractSNAP):
G.add_edge(source, target, types=[dict(type=type)])
supernodes = {
- "Supernode-0": set(["A", "B"]),
- "Supernode-1": set(["C", "D"]),
- "Supernode-2": set(["E", "F"]),
- "Supernode-3": set(["G", "H"]),
- "Supernode-4": set(["I", "J"]),
- "Supernode-5": set(["K", "L"]),
+ "Supernode-0": {"A", "B"},
+ "Supernode-1": {"C", "D"},
+ "Supernode-2": {"E", "F"},
+ "Supernode-3": {"G", "H"},
+ "Supernode-4": {"I", "J"},
+ "Supernode-5": {"K", "L"},
}
nx.set_node_attributes(G, supernodes, "group")
return G
@@ -488,12 +488,12 @@ class TestSNAPDirected(AbstractSNAP):
G.add_edge(source, target, types=types)
supernodes = {
- "Supernode-0": set(["A", "B"]),
- "Supernode-1": set(["C", "D"]),
- "Supernode-2": set(["E", "F"]),
- "Supernode-3": set(["G", "H"]),
- "Supernode-4": set(["I", "J"]),
- "Supernode-5": set(["K", "L"]),
+ "Supernode-0": {"A", "B"},
+ "Supernode-1": {"C", "D"},
+ "Supernode-2": {"E", "F"},
+ "Supernode-3": {"G", "H"},
+ "Supernode-4": {"I", "J"},
+ "Supernode-5": {"K", "L"},
}
nx.set_node_attributes(G, supernodes, "group")
return G
@@ -559,12 +559,12 @@ class TestSNAPUndirectedMulti(AbstractSNAP):
G.add_edge(source, target, type=type)
supernodes = {
- "Supernode-0": set(["A", "B"]),
- "Supernode-1": set(["C", "D"]),
- "Supernode-2": set(["E", "F"]),
- "Supernode-3": set(["G", "H"]),
- "Supernode-4": set(["I", "J"]),
- "Supernode-5": set(["K", "L"]),
+ "Supernode-0": {"A", "B"},
+ "Supernode-1": {"C", "D"},
+ "Supernode-2": {"E", "F"},
+ "Supernode-3": {"G", "H"},
+ "Supernode-4": {"I", "J"},
+ "Supernode-5": {"K", "L"},
}
nx.set_node_attributes(G, supernodes, "group")
return G
@@ -631,10 +631,10 @@ class TestSNAPDirectedMulti(AbstractSNAP):
G.add_edge(source, target, type=type)
supernodes = {
- "Supernode-0": set(["A", "B"]),
- "Supernode-1": set(["C", "D"]),
- "Supernode-2": set(["E", "F"]),
- "Supernode-3": set(["G", "H"]),
+ "Supernode-0": {"A", "B"},
+ "Supernode-1": {"C", "D"},
+ "Supernode-2": {"E", "F"},
+ "Supernode-3": {"G", "H"},
}
nx.set_node_attributes(G, supernodes, "group")
return G
diff --git a/networkx/algorithms/tests/test_threshold.py b/networkx/algorithms/tests/test_threshold.py
index fdd03c19..9467e8de 100644
--- a/networkx/algorithms/tests/test_threshold.py
+++ b/networkx/algorithms/tests/test_threshold.py
@@ -190,7 +190,7 @@ class TestGeneratorThreshold:
wseq = nxt.creation_sequence_to_weights("ddidiiidididid")
ws = [s / float(12) for s in [6, 6, 5, 7, 4, 4, 4, 8, 3, 9, 2, 10, 1, 11]]
- assert sum([abs(c - d) for c, d in zip(wseq, ws)]) < 1e-14
+ assert sum(abs(c - d) for c, d in zip(wseq, ws)) < 1e-14
def test_finding_routines(self):
G = nx.Graph({1: [2], 2: [3], 3: [4], 4: [5], 5: [6]})
@@ -223,11 +223,11 @@ class TestGeneratorThreshold:
c1 = nxt.cluster_sequence(cs)
c2 = list(nx.clustering(G).values())
- assert sum([abs(c - d) for c, d in zip(c1, c2)]) == pytest.approx(0, abs=1e-7)
+ assert sum(abs(c - d) for c, d in zip(c1, c2)) == pytest.approx(0, abs=1e-7)
b1 = nx.betweenness_centrality(G).values()
b2 = nxt.betweenness_sequence(cs)
- assert sum([abs(c - d) for c, d in zip(b1, b2)]) < 1e-14
+ assert sum(abs(c - d) for c, d in zip(b1, b2)) < 1e-14
assert nxt.eigenvalues(cs) == [0, 1, 3, 3, 5, 7, 7, 8]
diff --git a/networkx/algorithms/threshold.py b/networkx/algorithms/threshold.py
index 57677725..aa9b13db 100644
--- a/networkx/algorithms/threshold.py
+++ b/networkx/algorithms/threshold.py
@@ -772,7 +772,7 @@ def spectral_projection(u, eigenpairs):
coeff = []
evect = eigenpairs[1]
for ev in evect:
- c = sum([evv * uv for (evv, uv) in zip(ev, u)])
+ c = sum(evv * uv for (evv, uv) in zip(ev, u))
coeff.append(c)
return coeff
diff --git a/networkx/classes/function.py b/networkx/classes/function.py
index fdc6f69f..6830e59a 100644
--- a/networkx/classes/function.py
+++ b/networkx/classes/function.py
@@ -1295,7 +1295,7 @@ def path_weight(G, path, weight):
raise nx.NetworkXNoPath("path does not exist")
for node, nbr in nx.utils.pairwise(path):
if multigraph:
- cost += min([v[weight] for v in G[node][nbr].values()])
+ cost += min(v[weight] for v in G[node][nbr].values())
else:
cost += G[node][nbr][weight]
return cost
diff --git a/networkx/classes/ordered.py b/networkx/classes/ordered.py
index 67021e5a..778ed14c 100644
--- a/networkx/classes/ordered.py
+++ b/networkx/classes/ordered.py
@@ -73,7 +73,7 @@ class OrderedGraph(Graph):
DeprecationWarning,
stacklevel=2,
)
- super(OrderedGraph, self).__init__(incoming_graph_data, **attr)
+ super().__init__(incoming_graph_data, **attr)
class OrderedDiGraph(DiGraph):
@@ -101,7 +101,7 @@ class OrderedDiGraph(DiGraph):
DeprecationWarning,
stacklevel=2,
)
- super(OrderedDiGraph, self).__init__(incoming_graph_data, **attr)
+ super().__init__(incoming_graph_data, **attr)
class OrderedMultiGraph(MultiGraph):
@@ -130,7 +130,7 @@ class OrderedMultiGraph(MultiGraph):
DeprecationWarning,
stacklevel=2,
)
- super(OrderedMultiGraph, self).__init__(incoming_graph_data, **attr)
+ super().__init__(incoming_graph_data, **attr)
class OrderedMultiDiGraph(MultiDiGraph):
@@ -159,4 +159,4 @@ class OrderedMultiDiGraph(MultiDiGraph):
DeprecationWarning,
stacklevel=2,
)
- super(OrderedMultiDiGraph, self).__init__(incoming_graph_data, **attr)
+ super().__init__(incoming_graph_data, **attr)
diff --git a/networkx/classes/tests/historical_tests.py b/networkx/classes/tests/historical_tests.py
index daa5dbaf..612d55f4 100644
--- a/networkx/classes/tests/historical_tests.py
+++ b/networkx/classes/tests/historical_tests.py
@@ -404,7 +404,7 @@ class HistoricalTests:
G.edges(), [("A", "B"), ("A", "C"), ("B", "D"), ("C", "B"), ("C", "D")]
)
- assert sorted([v for k, v in G.degree()]) == [0, 0, 0, 2, 2, 3, 3]
+ assert sorted(v for k, v in G.degree()) == [0, 0, 0, 2, 2, 3, 3]
assert sorted(G.degree(), key=str) == [
("A", 2),
("B", 3),
diff --git a/networkx/classes/tests/test_digraph_historical.py b/networkx/classes/tests/test_digraph_historical.py
index 7047bbf3..403051fa 100644
--- a/networkx/classes/tests/test_digraph_historical.py
+++ b/networkx/classes/tests/test_digraph_historical.py
@@ -32,7 +32,7 @@ class TestDiGraphHistorical(HistoricalTests):
G = self.G()
G.add_nodes_from("GJK")
G.add_edges_from([("A", "B"), ("A", "C"), ("B", "D"), ("B", "C"), ("C", "D")])
- assert sorted([v for k, v in G.in_degree()]) == [0, 0, 0, 0, 1, 2, 2]
+ assert sorted(v for k, v in G.in_degree()) == [0, 0, 0, 0, 1, 2, 2]
assert dict(G.out_degree()) == {
"A": 2,
"C": 1,
diff --git a/networkx/convert_matrix.py b/networkx/convert_matrix.py
index b691eebd..e1697a23 100644
--- a/networkx/convert_matrix.py
+++ b/networkx/convert_matrix.py
@@ -760,7 +760,7 @@ def to_numpy_recarray(G, nodelist=None, dtype=None, order=None):
for u, v, attrs in G.edges(data=True):
if (u in nodeset) and (v in nodeset):
i, j = index[u], index[v]
- values = tuple([attrs[n] for n in names])
+ values = tuple(attrs[n] for n in names)
M[i, j] = values
if undirected:
M[j, i] = M[i, j]
diff --git a/networkx/drawing/tests/test_pydot.py b/networkx/drawing/tests/test_pydot.py
index 39371880..ba1e9733 100644
--- a/networkx/drawing/tests/test_pydot.py
+++ b/networkx/drawing/tests/test_pydot.py
@@ -53,21 +53,19 @@ class TestPydot:
Pin = Pin_list[0]
# Sorted list of all nodes in the original "pydot.Dot" instance.
- n1 = sorted([p.get_name() for p in P.get_node_list()])
+ n1 = sorted(p.get_name() for p in P.get_node_list())
# Sorted list of all nodes in the deserialized "pydot.Dot" instance.
- n2 = sorted([p.get_name() for p in Pin.get_node_list()])
+ n2 = sorted(p.get_name() for p in Pin.get_node_list())
# Validate these instances to contain the same nodes.
assert n1 == n2
# Sorted list of all edges in the original "pydot.Dot" instance.
- e1 = sorted([(e.get_source(), e.get_destination()) for e in P.get_edge_list()])
+ e1 = sorted((e.get_source(), e.get_destination()) for e in P.get_edge_list())
# Sorted list of all edges in the original "pydot.Dot" instance.
- e2 = sorted(
- [(e.get_source(), e.get_destination()) for e in Pin.get_edge_list()]
- )
+ e2 = sorted((e.get_source(), e.get_destination()) for e in Pin.get_edge_list())
# Validate these instances to contain the same edges.
assert e1 == e2
diff --git a/networkx/generators/directed.py b/networkx/generators/directed.py
index 9382e47b..d76e79ef 100644
--- a/networkx/generators/directed.py
+++ b/networkx/generators/directed.py
@@ -271,8 +271,8 @@ def scale_free_graph(
raise ValueError("delta_out must be >= 0.")
# pre-populate degree states
- vs = sum([count * [idx] for idx, count in G.out_degree()], [])
- ws = sum([count * [idx] for idx, count in G.in_degree()], [])
+ vs = sum((count * [idx] for idx, count in G.out_degree()), [])
+ ws = sum((count * [idx] for idx, count in G.in_degree()), [])
# pre-populate node state
node_list = list(G.nodes())
@@ -281,7 +281,7 @@ def scale_free_graph(
numeric_nodes = [n for n in node_list if isinstance(n, numbers.Number)]
if len(numeric_nodes) > 0:
# set cursor for new nodes appropriately
- cursor = max([int(n.real) for n in numeric_nodes]) + 1
+ cursor = max(int(n.real) for n in numeric_nodes) + 1
else:
# or start at zero
cursor = 0
diff --git a/networkx/generators/geometric.py b/networkx/generators/geometric.py
index d843a9df..9888a6ae 100644
--- a/networkx/generators/geometric.py
+++ b/networkx/generators/geometric.py
@@ -3,7 +3,6 @@
from bisect import bisect_left
from itertools import accumulate, combinations, product
-from math import sqrt
import math
import networkx as nx
@@ -26,8 +25,16 @@ def euclidean(x, y):
Each of ``x`` and ``y`` can be any iterable of numbers. The
iterables must be of the same length.
+ .. deprecated:: 2.7
"""
- return sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
+ import warnings
+
+ msg = (
+ "euclidean is deprecated and will be removed in 3.0."
+ "Use math.dist(x, y) instead."
+ )
+ warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ return math.dist(x, y)
def geometric_edges(G, radius, p):
@@ -450,7 +457,7 @@ def geographical_threshold_graph(
pos = {v: [seed.random() for i in range(dim)] for v in nodes}
# If no distance metric is provided, use Euclidean distance.
if metric is None:
- metric = euclidean
+ metric = math.dist
nx.set_node_attributes(G, weight, "weight")
nx.set_node_attributes(G, pos, "pos")
@@ -571,7 +578,7 @@ def waxman_graph(
nx.set_node_attributes(G, pos, "pos")
# If no distance metric is provided, use Euclidean distance.
if metric is None:
- metric = euclidean
+ metric = math.dist
# If the maximum distance L is not specified (that is, we are in the
# Waxman-1 model), then find the maximum distance between any pair
# of nodes.
diff --git a/networkx/generators/tests/test_geometric.py b/networkx/generators/tests/test_geometric.py
index 87dadafe..ea83d6f1 100644
--- a/networkx/generators/tests/test_geometric.py
+++ b/networkx/generators/tests/test_geometric.py
@@ -1,10 +1,8 @@
from itertools import combinations
-from math import sqrt
+import math
import random
-
import networkx as nx
-from networkx.generators.geometric import euclidean
def l1dist(x, y):
@@ -30,15 +28,14 @@ class TestRandomGeometricGraph:
"""
# Use the Euclidean metric, the default according to the
# documentation.
- dist = euclidean
G = nx.random_geometric_graph(50, 0.25)
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
# Nonadjacent vertices must be at greater distance.
else:
- assert not dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_p(self):
"""Tests for providing an alternate distance metric to the
@@ -46,15 +43,14 @@ class TestRandomGeometricGraph:
"""
# Use the L1 metric.
- dist = l1dist
G = nx.random_geometric_graph(50, 0.25, p=1)
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
# Nonadjacent vertices must be at greater distance.
else:
- assert not dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert not l1dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_node_names(self):
"""Tests using values other than sequential numbers as node IDs."""
@@ -64,14 +60,13 @@ class TestRandomGeometricGraph:
G = nx.random_geometric_graph(nodes, 0.25)
assert len(G) == len(nodes)
- dist = euclidean
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
# Nonadjacent vertices must be at greater distance.
else:
- assert not dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert not math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
class TestSoftRandomGeometricGraph:
@@ -93,14 +88,11 @@ class TestSoftRandomGeometricGraph:
"""
# Use the Euclidean metric, the default according to the
# documentation.
- def dist(x, y):
- return sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
-
G = nx.soft_random_geometric_graph(50, 0.25)
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_p(self):
"""Tests for providing an alternate distance metric to the
@@ -125,13 +117,10 @@ class TestSoftRandomGeometricGraph:
G = nx.soft_random_geometric_graph(nodes, 0.25)
assert len(G) == len(nodes)
- def dist(x, y):
- return sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
-
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_p_dist_default(self):
"""Tests default p_dict = 0.5 returns graph with edge count <= RGG with
@@ -192,15 +181,14 @@ class TestGeographicalThresholdGraph:
"""
# Use the Euclidean metric and alpha = -2
# the default according to the documentation.
- dist = euclidean
G = nx.geographical_threshold_graph(50, 10)
for u, v in combinations(G, 2):
# Adjacent vertices must exceed the threshold.
if v in G[u]:
- assert join(G, u, v, 10, -2, dist)
+ assert join(G, u, v, 10, -2, math.dist)
# Nonadjacent vertices must not exceed the threshold.
else:
- assert not join(G, u, v, 10, -2, dist)
+ assert not join(G, u, v, 10, -2, math.dist)
def test_metric(self):
"""Tests for providing an alternate distance metric to the
@@ -208,15 +196,14 @@ class TestGeographicalThresholdGraph:
"""
# Use the L1 metric.
- dist = l1dist
- G = nx.geographical_threshold_graph(50, 10, metric=dist)
+ G = nx.geographical_threshold_graph(50, 10, metric=l1dist)
for u, v in combinations(G, 2):
# Adjacent vertices must exceed the threshold.
if v in G[u]:
- assert join(G, u, v, 10, -2, dist)
+ assert join(G, u, v, 10, -2, l1dist)
# Nonadjacent vertices must not exceed the threshold.
else:
- assert not join(G, u, v, 10, -2, dist)
+ assert not join(G, u, v, 10, -2, l1dist)
def test_p_dist_zero(self):
"""Tests if p_dict = 0 returns disconencted graph with 0 edges"""
@@ -249,8 +236,7 @@ class TestWaxmanGraph:
"""
# Use the L1 metric.
- dist = l1dist
- G = nx.waxman_graph(50, 0.5, 0.1, metric=dist)
+ G = nx.waxman_graph(50, 0.5, 0.1, metric=l1dist)
assert len(G) == 50
@@ -288,14 +274,11 @@ class TestThresholdedRandomGeometricGraph:
"""
# Use the Euclidean metric, the default according to the
# documentation.
- def dist(x, y):
- return sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
-
G = nx.thresholded_random_geometric_graph(50, 0.25, 0.1)
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_p(self):
"""Tests for providing an alternate distance metric to the
@@ -320,13 +303,10 @@ class TestThresholdedRandomGeometricGraph:
G = nx.thresholded_random_geometric_graph(nodes, 0.25, 0.1)
assert len(G) == len(nodes)
- def dist(x, y):
- return sqrt(sum((a - b) ** 2 for a, b in zip(x, y)))
-
for u, v in combinations(G, 2):
# Adjacent vertices must be within the given distance.
if v in G[u]:
- assert dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
+ assert math.dist(G.nodes[u]["pos"], G.nodes[v]["pos"]) <= 0.25
def test_theta(self):
"""Tests that pairs of vertices adjacent if and only if their sum
diff --git a/networkx/generators/tests/test_random_graphs.py b/networkx/generators/tests/test_random_graphs.py
index 8d47b960..bcc8aa2b 100644
--- a/networkx/generators/tests/test_random_graphs.py
+++ b/networkx/generators/tests/test_random_graphs.py
@@ -50,7 +50,7 @@ def test_gnp_generators_for_p_close_to_1(generator):
"""If the edge probability `p` is close to 1, the resulting graph should have all edges."""
runs = 100
edges = sum(
- [generator(10, 0.99999, directed=True).number_of_edges() for _ in range(runs)]
+ generator(10, 0.99999, directed=True).number_of_edges() for _ in range(runs)
)
assert abs(edges / float(runs) - 90) <= runs * 2.0 / 100
@@ -180,7 +180,7 @@ class TestGeneratorsRandom:
return is_caterpillar(g.subgraph(non_leafs))
G = nx.random_lobster(10, 0.1, 0.5, seed)
- assert max([G.degree(n) for n in G.nodes()]) > 3
+ assert max(G.degree(n) for n in G.nodes()) > 3
assert is_lobster(G)
pytest.raises(nx.NetworkXError, nx.random_lobster, 10, 0.1, 1, seed)
pytest.raises(nx.NetworkXError, nx.random_lobster, 10, 1, 1, seed)
diff --git a/networkx/linalg/attrmatrix.py b/networkx/linalg/attrmatrix.py
index 6d9eab6d..97fc8b1e 100644
--- a/networkx/linalg/attrmatrix.py
+++ b/networkx/linalg/attrmatrix.py
@@ -102,7 +102,7 @@ def _edge_value(G, edge_attr):
if G.is_multigraph():
def value(u, v):
- return sum([d.get(edge_attr, 1) for d in G[u][v].values()])
+ return sum(d.get(edge_attr, 1) for d in G[u][v].values())
else:
@@ -114,7 +114,7 @@ def _edge_value(G, edge_attr):
if G.is_multigraph():
def value(u, v):
- return sum([d[edge_attr] for d in G[u][v].values()])
+ return sum(d[edge_attr] for d in G[u][v].values())
else:
diff --git a/networkx/linalg/bethehessianmatrix.py b/networkx/linalg/bethehessianmatrix.py
index a38ca86e..b189dacf 100644
--- a/networkx/linalg/bethehessianmatrix.py
+++ b/networkx/linalg/bethehessianmatrix.py
@@ -67,10 +67,7 @@ def bethe_hessian_matrix(G, r=None, nodelist=None):
if nodelist is None:
nodelist = list(G)
if r is None:
- r = (
- sum([d ** 2 for v, d in nx.degree(G)]) / sum([d for v, d in nx.degree(G)])
- - 1
- )
+ r = sum(d ** 2 for v, d in nx.degree(G)) / sum(d for v, d in nx.degree(G)) - 1
A = nx.to_scipy_sparse_matrix(G, nodelist=nodelist, format="csr")
n, m = A.shape
diags = A.sum(axis=1)
diff --git a/networkx/readwrite/nx_shp.py b/networkx/readwrite/nx_shp.py
index 3908d48e..4dd01be5 100644
--- a/networkx/readwrite/nx_shp.py
+++ b/networkx/readwrite/nx_shp.py
@@ -116,7 +116,7 @@ def read_shp(path, simplify=True, geom_attrs=True, strict=True):
else:
if strict:
raise nx.NetworkXError(
- "GeometryType {} not supported".format(g.GetGeometryType())
+ f"GeometryType {g.GetGeometryType()} not supported"
)
return net
diff --git a/networkx/readwrite/tests/test_gexf.py b/networkx/readwrite/tests/test_gexf.py
index abdfa64d..6dcc85fa 100644
--- a/networkx/readwrite/tests/test_gexf.py
+++ b/networkx/readwrite/tests/test_gexf.py
@@ -1,5 +1,4 @@
import io
-import sys
import time
import pytest
@@ -274,18 +273,6 @@ org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gexf.net/\
assert list(H) == [7]
assert H.nodes[7]["label"] == "77"
- # FIXME: We should test xml without caring about their order This is causing a
- # problem b/c of a change in Python 3.8
- #
- # "Prior to Python 3.8, the serialisation order of the XML attributes of
- # elements was artificially made predictable by sorting the attributes by their
- # name. Based on the now guaranteed ordering of dicts, this arbitrary
- # reordering was removed in Python 3.8 to preserve the order in which
- # attributes were originally parsed or created by user code."
- #
- # https://docs.python.org/3.8/library/xml.etree.elementtree.html
- # https://bugs.python.org/issue34160
-
def test_write_with_node_attributes(self):
# Addresses #673.
G = nx.OrderedGraph()
@@ -297,30 +284,7 @@ org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.gexf.net/\
G.nodes[i]["start"] = i
G.nodes[i]["end"] = i + 1
- if sys.version_info < (3, 8):
- expected = f"""<gexf version="1.2" xmlns="http://www.gexf.net/1.2\
-draft" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:\
-schemaLocation="http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/\
-gexf.xsd">
- <meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
- <creator>NetworkX {nx.__version__}</creator>
- </meta>
- <graph defaultedgetype="undirected" mode="dynamic" name="" timeformat="long">
- <nodes>
- <node end="1" id="0" label="0" pid="0" start="0" />
- <node end="2" id="1" label="1" pid="1" start="1" />
- <node end="3" id="2" label="2" pid="2" start="2" />
- <node end="4" id="3" label="3" pid="3" start="3" />
- </nodes>
- <edges>
- <edge id="0" source="0" target="1" />
- <edge id="1" source="1" target="2" />
- <edge id="2" source="2" target="3" />
- </edges>
- </graph>
-</gexf>"""
- else:
- expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
+ expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=\
"http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/\
gexf.xsd" version="1.2">
@@ -348,30 +312,7 @@ gexf.xsd" version="1.2">
G = nx.Graph()
G.add_edges_from([(0, 1, {"id": 0}), (1, 2, {"id": 2}), (2, 3)])
- if sys.version_info < (3, 8):
- expected = f"""<gexf version="1.2" xmlns="http://www.gexf.net/\
-1.2draft" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:\
-schemaLocation="http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/\
-gexf.xsd">
- <meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
- <creator>NetworkX {nx.__version__}</creator>
- </meta>
- <graph defaultedgetype="undirected" mode="static" name="">
- <nodes>
- <node id="0" label="0" />
- <node id="1" label="1" />
- <node id="2" label="2" />
- <node id="3" label="3" />
- </nodes>
- <edges>
- <edge id="0" source="0" target="1" />
- <edge id="2" source="1" target="2" />
- <edge id="1" source="2" target="3" />
- </edges>
- </graph>
-</gexf>"""
- else:
- expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
+ expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft" xmlns:xsi\
="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.\
gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd" version="1.2">
<meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
@@ -401,55 +342,7 @@ gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd" version="1.2">
nx.set_node_attributes(G, {n: n for n in np.arange(4)}, "number")
G[0][1]["edge-number"] = np.float64(1.1)
- if sys.version_info < (3, 8):
- expected = f"""<gexf version="1.2" xmlns="http://www.gexf.net/1.2draft"\
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation\
-="http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd">
- <meta lastmodifieddate="{time.strftime('%Y-%m-%d')}">
- <creator>NetworkX {nx.__version__}</creator>
- </meta>
- <graph defaultedgetype="undirected" mode="static" name="">
- <attributes class="edge" mode="static">
- <attribute id="1" title="edge-number" type="float" />
- </attributes>
- <attributes class="node" mode="static">
- <attribute id="0" title="number" type="int" />
- </attributes>
- <nodes>
- <node id="0" label="0">
- <attvalues>
- <attvalue for="0" value="0" />
- </attvalues>
- </node>
- <node id="1" label="1">
- <attvalues>
- <attvalue for="0" value="1" />
- </attvalues>
- </node>
- <node id="2" label="2">
- <attvalues>
- <attvalue for="0" value="2" />
- </attvalues>
- </node>
- <node id="3" label="3">
- <attvalues>
- <attvalue for="0" value="3" />
- </attvalues>
- </node>
- </nodes>
- <edges>
- <edge id="0" source="0" target="1">
- <attvalues>
- <attvalue for="1" value="1.1" />
- </attvalues>
- </edge>
- <edge id="1" source="1" target="2" />
- <edge id="2" source="2" target="3" />
- </edges>
- </graph>
-</gexf>"""
- else:
- expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft"\
+ expected = f"""<gexf xmlns="http://www.gexf.net/1.2draft"\
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation\
="http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd"\
version="1.2">
diff --git a/networkx/readwrite/tests/test_graphml.py b/networkx/readwrite/tests/test_graphml.py
index c97d07cc..c26220c8 100644
--- a/networkx/readwrite/tests/test_graphml.py
+++ b/networkx/readwrite/tests/test_graphml.py
@@ -1385,11 +1385,11 @@ class TestWriteGraphML(BaseGraphML):
assert nodes_equal(G.nodes(), H.nodes())
assert edges_equal(G.edges(), H.edges())
- assert sorted([data.get("eid") for u, v, data in H.edges(data=True)]) == sorted(
+ assert sorted(data.get("eid") for u, v, data in H.edges(data=True)) == sorted(
edge_attributes.values()
)
# NetworkX uses edge_ids as keys in multigraphs if no key
- assert sorted([key for u, v, key in H.edges(keys=True)]) == sorted(
+ assert sorted(key for u, v, key in H.edges(keys=True)) == sorted(
edge_attributes.values()
)
@@ -1412,11 +1412,11 @@ class TestWriteGraphML(BaseGraphML):
assert nodes_equal(G.nodes(), J.nodes())
assert edges_equal(G.edges(), J.edges())
- assert sorted([data.get("eid") for u, v, data in J.edges(data=True)]) == sorted(
+ assert sorted(data.get("eid") for u, v, data in J.edges(data=True)) == sorted(
edge_attributes.values()
)
# NetworkX uses edge_ids as keys in multigraphs if no key
- assert sorted([key for u, v, key in J.edges(keys=True)]) == sorted(
+ assert sorted(key for u, v, key in J.edges(keys=True)) == sorted(
edge_attributes.values()
)
diff --git a/networkx/utils/decorators.py b/networkx/utils/decorators.py
index 555117c3..14bac852 100644
--- a/networkx/utils/decorators.py
+++ b/networkx/utils/decorators.py
@@ -1080,7 +1080,7 @@ class argmap:
@classmethod
def signature(cls, f):
- """Construct a Signature object describing `f`
+ r"""Construct a Signature object describing `f`
Compute a Signature so that we can write a function wrapping f with
the same signature and call-type.
diff --git a/setup.py b/setup.py
index e08b1036..cd15dd81 100644
--- a/setup.py
+++ b/setup.py
@@ -3,9 +3,9 @@ import os
import sys
from setuptools import setup
-if sys.version_info[:2] < (3, 7):
+if sys.version_info[:2] < (3, 8):
error = (
- "NetworkX 2.6+ requires Python 3.7 or later (%d.%d detected). \n"
+ "NetworkX 2.7+ requires Python 3.8 or later (%d.%d detected). \n"
"For Python 2.7, please install version 2.2 using: \n"
"$ pip install 'networkx==2.2'" % sys.version_info[:2]
)
@@ -45,7 +45,6 @@ classifiers = [
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3 :: Only",
@@ -192,6 +191,6 @@ if __name__ == "__main__":
package_data=package_data,
install_requires=install_requires,
extras_require=extras_require,
- python_requires=">=3.7",
+ python_requires=">=3.8",
zip_safe=False,
)