Repository: networkx/networkx

Issue:
Unify documentation README with contributor guide
It was pointed out in #6766 that we have a README in the `doc/` folder that describes how to build the documentation. I think the go-to reference for this information is the contributor guide, and these two documents are not necessarily in sync. However, contributors have also indicated that having a README in the doc folder is nice. Therefore I would propose the following:

1. Reformat `doc/README.md` to .rst, then
2. `.. include` `doc/README` in the `Documentation` section of `CONTRIBUTING.rst`

This should check all boxes: it preserves the README in the `doc/` folder, de-duplicates the source of info (preventing divergence of the README from the contributor guide), and guarantees that the info from the README shows up in the html version of the contributor guide.

Comments:

Patch:
diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst
index 2ab68ed29..e92e9373a 100644
--- a/CONTRIBUTING.rst
+++ b/CONTRIBUTING.rst
@@ -403,7 +403,7 @@ Then create a baseline image to compare against later::
 
     $ pytest -k test_barbell --mpl-generate-path=networkx/drawing/tests/baseline
 
-.. note: In order to keep the size of the repository from becoming too large, we
+.. note:: In order to keep the size of the repository from becoming too large, we
    prefer to limit the size and number of baseline images we include.
 
 And test::
@@ -413,27 +413,7 @@ And test::
 Documentation
 -------------
 
-Building the documentation locally requires that the additional dependencies
-specified in ``requirements/doc.txt`` be installed in your development
-environment.
-
-The documentation is built with ``sphinx``. To build the documentation locally,
-navigate to the ``doc/`` directory and::
-
-    make html
-
-This will generate both the reference documentation as well as the example
-gallery. If you want to build the documentation *without* building the
-gallery examples use::
-
-    make html-noplot
-
-The build products are stored in ``doc/build/`` and can be viewed directly.
-For example, to view the built html, open ``build/html/index.html``
-in your preferred web browser.
-
-.. note: ``sphinx`` supports many other output formats. Type ``make`` without
-   any arguments to see all the built-in options.
+.. include:: ../README.rst
 
 Adding examples
 ~~~~~~~~~~~~~~~
diff --git a/doc/README.md b/doc/README.rst
similarity index 57%
rename from doc/README.md
rename to doc/README.rst
index c806ffca2..09a0f8278 100644
--- a/doc/README.md
+++ b/doc/README.rst
@@ -1,5 +1,3 @@
-# Building docs
-
 We use Sphinx for generating the API and reference documentation.
 
 Pre-built versions can be found at
@@ -8,33 +6,37 @@ Pre-built versions can be found at
 
 for both the stable and the latest (i.e., development) releases.
 
-## Instructions
+Instructions
+~~~~~~~~~~~~
 
 After installing NetworkX and its dependencies, install the Python
 packages needed to build the documentation by entering the root
-directory and executing:
+directory and executing::
 
     pip install -r requirements/doc.txt
 
 Building the example gallery additionally requires the dependencies
-listed in `requirements/extra.txt` and `requirements/example.txt`:
+listed in ``requirements/extra.txt`` and ``requirements/example.txt``::
 
     pip install -r requirements/extra.txt
     pip install -r requirements/example.txt
 
-To build the HTML documentation, enter `doc/` and execute:
+To build the HTML documentation, enter ``doc/`` and execute::
 
     make html
 
-This will generate a `build/html` subdirectory containing the built
-documentation. If the dependencies in `extra.txt` and `example.txt`
+This will generate a ``build/html`` subdirectory containing the built
+documentation. If the dependencies in ``extra.txt`` and ``example.txt``
 are **not** installed, build the HTML documentation without generating
-figures by using:
+figures by using::
 
     make html-noplot
 
-To build the PDF documentation, enter:
+To build the PDF documentation, enter::
 
     make latexpdf
 
 You will need to have LaTeX installed for this.
+
+.. note:: ``sphinx`` supports many other output formats. Type ``make`` without
+   any arguments to see all the built-in options.
diff --git a/doc/developer/deprecations.rst b/doc/developer/deprecations.rst
index c6339b550..5dd39577c 100644
--- a/doc/developer/deprecations.rst
+++ b/doc/developer/deprecations.rst
@@ -66,8 +66,6 @@ Version 3.2
 * In ``generators/directed.py`` remove the ``create_using`` keyword argument
   for the ``scale_free_graph`` function.
 * Remove pydot functionality ``drawing/nx_pydot.py``, if pydot is still not being maintained. See #5723
-* In ``readwrite/json_graph/node_link.py`` remove the ``attrs` keyword code 
-  and docstring in ``node_link_data`` and ``node_link_graph``. Also the associated tests.
 * Remove renamed function ``join()`` in ``algorithms/tree/operations.py`` and
   in ``doc/reference/algorithms/trees.rst``
 
diff --git a/networkx/algorithms/graphical.py b/networkx/algorithms/graphical.py
index da27e5f1f..20e9ced75 100644
--- a/networkx/algorithms/graphical.py
+++ b/networkx/algorithms/graphical.py
@@ -104,6 +104,13 @@ def is_valid_degree_sequence_havel_hakimi(deg_sequence):
     valid : bool
         True if deg_sequence is graphical and False if not.
 
+    Examples
+    --------
+    >>> G = nx.Graph([(1, 2), (1, 3), (2, 3), (3, 4), (4, 2), (5, 1), (5, 4)])
+    >>> sequence = (d for _, d in G.degree())
+    >>> nx.is_valid_degree_sequence_havel_hakimi(sequence)
+    True
+
     Notes
     -----
     The ZZ condition says that for the sequence d if
@@ -177,6 +184,13 @@ def is_valid_degree_sequence_erdos_gallai(deg_sequence):
     valid : bool
         True if deg_sequence is graphical and False if not.
 
+    Examples
+    --------
+    >>> G = nx.Graph([(1, 2), (1, 3), (2, 3), (3, 4), (4, 2), (5, 1), (5, 4)])
+    >>> sequence = (d for _, d in G.degree())
+    >>> nx.is_valid_degree_sequence_erdos_gallai(sequence)
+    True
+
     Notes
     -----
 
@@ -252,6 +266,13 @@ def is_multigraphical(sequence):
     valid : bool
         True if deg_sequence is a multigraphic degree sequence and False if not.
 
+    Examples
+    --------
+    >>> G = nx.MultiGraph([(1, 2), (1, 3), (2, 3), (3, 4), (4, 2), (5, 1), (5, 4)])
+    >>> sequence = (d for _, d in G.degree())
+    >>> nx.is_multigraphical(sequence)
+    True
+
     Notes
     -----
     The worst-case run time is $O(n)$ where $n$ is the length of the sequence.
@@ -292,6 +313,13 @@ def is_pseudographical(sequence):
     valid : bool
       True if the sequence is a pseudographic degree sequence and False if not.
 
+    Examples
+    --------
+    >>> G = nx.Graph([(1, 2), (1, 3), (2, 3), (3, 4), (4, 2), (5, 1), (5, 4)])
+    >>> sequence = (d for _, d in G.degree())
+    >>> nx.is_pseudographical(sequence)
+    True
+
     Notes
     -----
     The worst-case run time is $O(n)$ where n is the length of the sequence.
@@ -326,6 +354,14 @@ def is_digraphical(in_sequence, out_sequence):
     valid : bool
       True if in and out-sequences are digraphic False if not.
 
+    Examples
+    --------
+    >>> G = nx.DiGraph([(1, 2), (1, 3), (2, 3), (3, 4), (4, 2), (5, 1), (5, 4)])
+    >>> in_seq = (d for n, d in G.in_degree())
+    >>> out_seq = (d for n, d in G.out_degree())
+    >>> nx.is_digraphical(in_seq, out_seq)
+    True
+
     Notes
     -----
     This algorithm is from Kleitman and Wang [1]_.
diff --git a/networkx/classes/reportviews.py b/networkx/classes/reportviews.py
index 4503566e7..59a16243f 100644
--- a/networkx/classes/reportviews.py
+++ b/networkx/classes/reportviews.py
@@ -757,7 +757,7 @@ class OutEdgeDataView:
     def __setstate__(self, state):
         self.__init__(**state)
 
-    def __init__(self, viewer, nbunch=None, data=False, default=None):
+    def __init__(self, viewer, nbunch=None, data=False, *, default=None):
         self._viewer = viewer
         adjdict = self._adjdict = viewer._adjdict
         if nbunch is None:
@@ -902,7 +902,7 @@ class OutMultiEdgeDataView(OutEdgeDataView):
     def __setstate__(self, state):
         self.__init__(**state)
 
-    def __init__(self, viewer, nbunch=None, data=False, keys=False, default=None):
+    def __init__(self, viewer, nbunch=None, data=False, *, default=None, keys=False):
         self._viewer = viewer
         adjdict = self._adjdict = viewer._adjdict
         self.keys = keys
@@ -1085,10 +1085,10 @@ class OutEdgeView(Set, Mapping):
         return self._adjdict[u][v]
 
     # EdgeDataView methods
-    def __call__(self, nbunch=None, data=False, default=None):
+    def __call__(self, nbunch=None, data=False, *, default=None):
         if nbunch is None and data is False:
             return self
-        return self.dataview(self, nbunch, data, default)
+        return self.dataview(self, nbunch, data, default=default)
 
     def data(self, data=True, default=None, nbunch=None):
         """
@@ -1166,7 +1166,7 @@ class OutEdgeView(Set, Mapping):
         """
         if nbunch is None and data is False:
             return self
-        return self.dataview(self, nbunch, data, default)
+        return self.dataview(self, nbunch, data, default=default)
 
     # String Methods
     def __str__(self):
@@ -1352,15 +1352,15 @@ class OutMultiEdgeView(OutEdgeView):
         u, v, k = e
         return self._adjdict[u][v][k]
 
-    def __call__(self, nbunch=None, data=False, keys=False, default=None):
+    def __call__(self, nbunch=None, data=False, *, default=None, keys=False):
         if nbunch is None and data is False and keys is True:
             return self
-        return self.dataview(self, nbunch, data, keys, default)
+        return self.dataview(self, nbunch, data, default=default, keys=keys)
 
-    def data(self, data=True, keys=False, default=None, nbunch=None):
+    def data(self, data=True, default=None, nbunch=None, keys=False):
         if nbunch is None and data is False and keys is True:
             return self
-        return self.dataview(self, nbunch, data, keys, default)
+        return self.dataview(self, nbunch, data, default=default, keys=keys)
 
 
 class MultiEdgeView(OutMultiEdgeView):
diff --git a/networkx/generators/atlas.py b/networkx/generators/atlas.py
index a5c7f492c..6f4388d2b 100644
--- a/networkx/generators/atlas.py
+++ b/networkx/generators/atlas.py
@@ -2,6 +2,7 @@
 Generators for the small graph atlas.
 """
 import gzip
+import importlib.resources
 import os
 import os.path
 from itertools import islice
@@ -16,9 +17,6 @@ __all__ = ["graph_atlas", "graph_atlas_g"]
 #: including) this number.
 NUM_GRAPHS = 1253
 
-#: The absolute path representing the directory containing this file.
-THIS_DIR = os.path.dirname(os.path.abspath(__file__))
-
 #: The path to the data file containing the graph edge lists.
 #:
 #: This is the absolute path of the gzipped text file containing the
@@ -51,7 +49,9 @@ THIS_DIR = os.path.dirname(os.path.abspath(__file__))
 #:             f.write(bytes(f'NODES {len(G)}\n', encoding='utf-8'))
 #:             write_edgelist(G, f, data=False)
 #:
-ATLAS_FILE = os.path.join(THIS_DIR, "atlas.dat.gz")
+
+# Path to the atlas file
+ATLAS_FILE = importlib.resources.files("networkx.generators") / "atlas.dat.gz"
 
 
 def _generate_graphs():
diff --git a/networkx/readwrite/json_graph/node_link.py b/networkx/readwrite/json_graph/node_link.py
index 65bcf4d63..98979c301 100644
--- a/networkx/readwrite/json_graph/node_link.py
+++ b/networkx/readwrite/json_graph/node_link.py
@@ -33,7 +33,6 @@ def _to_tuple(x):
 
 def node_link_data(
     G,
-    attrs=None,
     *,
     source="source",
     target="target",
@@ -47,29 +46,6 @@ def node_link_data(
     Parameters
     ----------
     G : NetworkX graph
-
-    attrs : dict
-        A dictionary that contains five keys 'source', 'target', 'name',
-        'key' and 'link'.  The corresponding values provide the attribute
-        names for storing NetworkX-internal graph data.  The values should
-        be unique.  Default value::
-
-            dict(source='source', target='target', name='id',
-                 key='key', link='links')
-
-        If some user-defined graph data use these attribute names as data keys,
-        they may be silently dropped.
-
-        .. deprecated:: 2.8.6
-
-           The `attrs` keyword argument will be replaced with `source`, `target`, `name`,
-           `key` and `link`. in networkx 3.2
-
-           If the `attrs` keyword and the new keywords are both used in a single function call (not recommended)
-           the `attrs` keyword argument will take precedence.
-
-           The values of the keywords must be unique.
-
     source : string
         A string that provides the 'source' attribute name for storing NetworkX-internal graph data.
     target : string
@@ -134,31 +110,6 @@ def node_link_data(
     --------
     node_link_graph, adjacency_data, tree_data
     """
-    # ------ TODO: Remove between the lines after signature change is complete ----- #
-    if attrs is not None:
-        import warnings
-
-        msg = (
-            "\n\nThe `attrs` keyword argument of node_link_data is deprecated\n"
-            "and will be removed in networkx 3.2. It is replaced with explicit\n"
-            "keyword arguments: `source`, `target`, `name`, `key` and `link`.\n"
-            "To make this warning go away, and ensure usage is forward\n"
-            "compatible, replace `attrs` with the keywords. "
-            "For example:\n\n"
-            "   >>> node_link_data(G, attrs={'target': 'foo', 'name': 'bar'})\n\n"
-            "should instead be written as\n\n"
-            "   >>> node_link_data(G, target='foo', name='bar')\n\n"
-            "in networkx 3.2.\n"
-            "The default values of the keywords will not change.\n"
-        )
-        warnings.warn(msg, DeprecationWarning, stacklevel=2)
-
-        source = attrs.get("source", "source")
-        target = attrs.get("target", "target")
-        name = attrs.get("name", "name")
-        key = attrs.get("key", "key")
-        link = attrs.get("link", "links")
-    # -------------------------------------------------- #
     multigraph = G.is_multigraph()
 
     # Allow 'key' to be omitted from attrs if the graph is not a multigraph.
@@ -185,7 +136,6 @@ def node_link_graph(
     data,
     directed=False,
     multigraph=True,
-    attrs=None,
     *,
     source="source",
     target="target",
@@ -207,24 +157,6 @@ def node_link_graph(
     multigraph : bool
         If True, and multigraph not specified in data, return a multigraph.
 
-    attrs : dict
-        A dictionary that contains five keys 'source', 'target', 'name',
-        'key' and 'link'.  The corresponding values provide the attribute
-        names for storing NetworkX-internal graph data.  Default value:
-
-            dict(source='source', target='target', name='id',
-                key='key', link='links')
-
-        .. deprecated:: 2.8.6
-
-           The `attrs` keyword argument will be replaced with the individual keywords: `source`, `target`, `name`,
-           `key` and `link`. in networkx 3.2.
-
-           If the `attrs` keyword and the new keywords are both used in a single function call (not recommended)
-           the `attrs` keyword argument will take precedence.
-
-           The values of the keywords must be unique.
-
     source : string
         A string that provides the 'source' attribute name for storing NetworkX-internal graph data.
     target : string
@@ -277,31 +209,6 @@ def node_link_graph(
     --------
     node_link_data, adjacency_data, tree_data
     """
-    # ------ TODO: Remove between the lines after signature change is complete ----- #
-    if attrs is not None:
-        import warnings
-
-        msg = (
-            "\n\nThe `attrs` keyword argument of node_link_graph is deprecated\n"
-            "and will be removed in networkx 3.2. It is replaced with explicit\n"
-            "keyword arguments: `source`, `target`, `name`, `key` and `link`.\n"
-            "To make this warning go away, and ensure usage is forward\n"
-            "compatible, replace `attrs` with the keywords. "
-            "For example:\n\n"
-            "   >>> node_link_graph(data, attrs={'target': 'foo', 'name': 'bar'})\n\n"
-            "should instead be written as\n\n"
-            "   >>> node_link_graph(data, target='foo', name='bar')\n\n"
-            "in networkx 3.2.\n"
-            "The default values of the keywords will not change.\n"
-        )
-        warnings.warn(msg, DeprecationWarning, stacklevel=2)
-
-        source = attrs.get("source", "source")
-        target = attrs.get("target", "target")
-        name = attrs.get("name", "name")
-        key = attrs.get("key", "key")
-        link = attrs.get("link", "links")
-    # -------------------------------------------------- #
     multigraph = data.get("multigraph", multigraph)
     directed = data.get("directed", directed)
     if multigraph:


Test patch:
diff --git a/networkx/algorithms/flow/tests/test_maxflow_large_graph.py b/networkx/algorithms/flow/tests/test_maxflow_large_graph.py
index fd36c1153..7b4859c8a 100644
--- a/networkx/algorithms/flow/tests/test_maxflow_large_graph.py
+++ b/networkx/algorithms/flow/tests/test_maxflow_large_graph.py
@@ -2,6 +2,7 @@
 """
 
 import bz2
+import importlib.resources
 import os
 import pickle
 
@@ -48,8 +49,11 @@ def gen_pyramid(N):
 
 
 def read_graph(name):
-    dirname = os.path.dirname(__file__)
-    fname = os.path.join(dirname, name + ".gpickle.bz2")
+    fname = (
+        importlib.resources.files("networkx.algorithms.flow.tests")
+        / f"{name}.gpickle.bz2"
+    )
+
     with bz2.BZ2File(fname, "rb") as f:
         G = pickle.load(f)
     return G
diff --git a/networkx/algorithms/flow/tests/test_mincost.py b/networkx/algorithms/flow/tests/test_mincost.py
index 65603d3c1..5b1794b15 100644
--- a/networkx/algorithms/flow/tests/test_mincost.py
+++ b/networkx/algorithms/flow/tests/test_mincost.py
@@ -1,4 +1,5 @@
 import bz2
+import importlib.resources
 import os
 import pickle
 
@@ -461,7 +462,10 @@ class TestMinCostFlow:
         # pytest.raises(nx.NetworkXUnfeasible, nx.capacity_scaling, G)
 
     def test_large(self):
-        fname = os.path.join(os.path.dirname(__file__), "netgen-2.gpickle.bz2")
+        fname = (
+            importlib.resources.files("networkx.algorithms.flow.tests")
+            / "netgen-2.gpickle.bz2"
+        )
         with bz2.BZ2File(fname, "rb") as f:
             G = pickle.load(f)
         flowCost, flowDict = nx.network_simplex(G)
diff --git a/networkx/algorithms/flow/tests/test_networksimplex.py b/networkx/algorithms/flow/tests/test_networksimplex.py
index 40c4bf080..5b3b5f6dd 100644
--- a/networkx/algorithms/flow/tests/test_networksimplex.py
+++ b/networkx/algorithms/flow/tests/test_networksimplex.py
@@ -1,4 +1,5 @@
 import bz2
+import importlib.resources
 import os
 import pickle
 
@@ -141,7 +142,11 @@ def test_google_or_tools_example2():
 
 
 def test_large():
-    fname = os.path.join(os.path.dirname(__file__), "netgen-2.gpickle.bz2")
+    fname = (
+        importlib.resources.files("networkx.algorithms.flow.tests")
+        / "netgen-2.gpickle.bz2"
+    )
+
     with bz2.BZ2File(fname, "rb") as f:
         G = pickle.load(f)
     flowCost, flowDict = nx.network_simplex(G)
diff --git a/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py b/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py
index 31f670a32..f658bcae4 100644
--- a/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py
+++ b/networkx/algorithms/isomorphism/tests/test_isomorphvf2.py
@@ -2,6 +2,7 @@
     Tests for VF2 isomorphism algorithm.
 """
 
+import importlib.resources
 import os
 import random
 import struct
@@ -118,18 +119,18 @@ class TestVF2GraphDB:
         return graph
 
     def test_graph(self):
-        head, tail = os.path.split(__file__)
-        g1 = self.create_graph(os.path.join(head, "iso_r01_s80.A99"))
-        g2 = self.create_graph(os.path.join(head, "iso_r01_s80.B99"))
+        head = importlib.resources.files("networkx.algorithms.isomorphism.tests")
+        g1 = self.create_graph(head / "iso_r01_s80.A99")
+        g2 = self.create_graph(head / "iso_r01_s80.B99")
         gm = iso.GraphMatcher(g1, g2)
         assert gm.is_isomorphic()
 
     def test_subgraph(self):
         # A is the subgraph
         # B is the full graph
-        head, tail = os.path.split(__file__)
-        subgraph = self.create_graph(os.path.join(head, "si2_b06_m200.A99"))
-        graph = self.create_graph(os.path.join(head, "si2_b06_m200.B99"))
+        head = importlib.resources.files("networkx.algorithms.isomorphism.tests")
+        subgraph = self.create_graph(head / "si2_b06_m200.A99")
+        graph = self.create_graph(head / "si2_b06_m200.B99")
         gm = iso.GraphMatcher(graph, subgraph)
         assert gm.subgraph_is_isomorphic()
         # Just testing some cases
diff --git a/networkx/classes/tests/test_reportviews.py b/networkx/classes/tests/test_reportviews.py
index 48148c240..a68d6eb82 100644
--- a/networkx/classes/tests/test_reportviews.py
+++ b/networkx/classes/tests/test_reportviews.py
@@ -872,8 +872,12 @@ class TestMultiEdgeView(TestEdgeView):
             assert len(e) == 3
         elist = sorted([(i, i + 1, 0) for i in range(8)] + [(1, 2, 3)])
         assert sorted(ev) == elist
-        # test order of arguments:graph, nbunch, data, keys, default
-        ev = evr((1, 2), "foo", True, 1)
+        # test that the keyword arguments are passed correctly
+        ev = evr((1, 2), "foo", keys=True, default=1)
+        with pytest.raises(TypeError):
+            evr((1, 2), "foo", True, 1)
+        with pytest.raises(TypeError):
+            evr((1, 2), "foo", True, default=1)
         for e in ev:
             if set(e[:2]) == {1, 2}:
                 assert e[2] in {0, 3}
diff --git a/networkx/conftest.py b/networkx/conftest.py
index a2b63a3b2..682a91a5d 100644
--- a/networkx/conftest.py
+++ b/networkx/conftest.py
@@ -101,11 +101,6 @@ def set_warnings():
     warnings.filterwarnings(
         "ignore", category=DeprecationWarning, message="nx.nx_pydot"
     )
-    warnings.filterwarnings(
-        "ignore",
-        category=DeprecationWarning,
-        message="\n\nThe `attrs` keyword argument of node_link",
-    )
     warnings.filterwarnings(
         "ignore",
         category=DeprecationWarning,
diff --git a/networkx/readwrite/json_graph/tests/test_node_link.py b/networkx/readwrite/json_graph/tests/test_node_link.py
index 54078c471..a432666b6 100644
--- a/networkx/readwrite/json_graph/tests/test_node_link.py
+++ b/networkx/readwrite/json_graph/tests/test_node_link.py
@@ -6,31 +6,6 @@ import networkx as nx
 from networkx.readwrite.json_graph import node_link_data, node_link_graph
 
 
-# TODO: To be removed when signature change complete
-def test_attrs_deprecation(recwarn):
-    G = nx.path_graph(3)
-
-    # No warnings when `attrs` kwarg not used
-    data = node_link_data(G)
-    H = node_link_graph(data)
-    assert len(recwarn) == 0
-
-    # Future warning raised with `attrs` kwarg
-    attrs = {
-        "source": "source",
-        "target": "target",
-        "name": "id",
-        "key": "key",
-        "link": "links",
-    }
-    data = node_link_data(G, attrs=attrs)
-    assert len(recwarn) == 1
-
-    recwarn.clear()
-    H = node_link_graph(data, attrs=attrs)
-    assert len(recwarn) == 1
-
-
 class TestNodeLink:
     # TODO: To be removed when signature change complete
     def test_custom_attrs_dep(self):
@@ -48,9 +23,7 @@ class TestNodeLink:
             "link": "c_links",
         }
 
-        H = node_link_graph(
-            node_link_data(G, attrs=attrs), multigraph=False, attrs=attrs
-        )
+        H = node_link_graph(node_link_data(G, **attrs), multigraph=False, **attrs)
         assert nx.is_isomorphic(G, H)
         assert H.graph["foo"] == "bar"
         assert H.nodes[1]["color"] == "red"
@@ -63,20 +36,16 @@ class TestNodeLink:
             "source": "c_source",
             "target": "c_target",
         }
-        H = node_link_graph(
-            node_link_data(G, attrs=attrs), multigraph=False, attrs=attrs
-        )
+        H = node_link_graph(node_link_data(G, **attrs), multigraph=False, **attrs)
         assert nx.is_isomorphic(G, H)
         assert H.graph["foo"] == "bar"
         assert H.nodes[1]["color"] == "red"
         assert H[1][2]["width"] == 7
 
-    # TODO: To be removed when signature change complete
     def test_exception_dep(self):
         with pytest.raises(nx.NetworkXError):
             G = nx.MultiDiGraph()
-            attrs = {"name": "node", "source": "node", "target": "node", "key": "node"}
-            node_link_data(G, attrs)
+            node_link_data(G, name="node", source="node", target="node", key="node")
 
     def test_graph(self):
         G = nx.path_graph(4)