diff options
author | Jarrod Millman <jarrod.millman@gmail.com> | 2021-10-23 15:37:48 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-23 15:37:48 -0700 |
commit | 0c503e31ba0062dc9a4ed47c380481aa8d6978c8 (patch) | |
tree | ef389b7ba52dec39941978824c7e0e833f17ab9e | |
parent | 27d362b9a752adf38d7db1828a48f50bb41c84bd (diff) | |
download | networkx-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>
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. @@ -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, ) |