prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Remove warning on import about missing networkx dependency
  Currently, importing vispy (or some submodule) without networkx installed results in a warning about installing networkx, even if the user/downstream library has no intention of using the graph layout. The warning should be delayed and turned into an error, as noted by @djhoese [here](https://github.com/napari/napari/issues/2979#issuecomment-874159877).
  
  xref  napari/napari#2979
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `vispy/visuals/graphs/layouts/networkx_layout.py`
  Content:
  ```
  1 # -*- coding: utf-8 -*-
  2 # Copyright (c) Vispy Development Team. All Rights Reserved.
  3 # Distributed under the (new) BSD License. See LICENSE.txt for more info.#!/usr/bin/env python3
  4 from ..util import _straight_line_vertices, issparse
  5 import numpy as np
  6 try:
  7     import networkx as nx
  8 except ModuleNotFoundError:
  9     import warnings
  10     warnings.warn(
  11         "Networkx not found, please install network to use its layouts")
  12     nx = None
  13 
  14 
  15 class NetworkxCoordinates:
  16     def __init__(self, graph=None, layout=None, **kwargs):
  17         """
  18         Converts :graph: into a layout. Can be used in conjunction with networkx layouts or using raw 2D-numpy arrays.
  19 
  20         Parameters
  21         ----------
  22         graph : a networkx graph.
  23         layout : str or dict or iterable-object of float32, optional
  24         - When :layout: is s string, a lookup will be performed in the networkx avaiable layouts.
  25         - When :layout: is a dict, it will be assumed that it takes the shape (key, value) = (node_id, 2D-coordinate).
  26         - When :layout: is numpy array it is assumed it takes the shape (number_of_nodes, 2).
  27         kwargs: dict, optional
  28         when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx
  29         """
  30         if isinstance(graph, type(None)):
  31             raise ValueError("Requires networkx input")
  32         self.graph = graph
  33         self.positions = np.zeros((len(graph), 2), dtype=np.float32)
  34         # default random positions
  35         if isinstance(layout, type(None)):
  36             self.positions = np.random.rand(*self.positions.shape)
  37 
  38         # check for networkx
  39         elif isinstance(layout, str):
  40             if nx:
  41                 if not layout.endswith("_layout"):
  42                     layout += "_layout"  # append for nx
  43                 layout_function = getattr(nx, layout)
  44                 if layout_function:
  45                     self.positions = np.asarray(
  46                         [i for i in dict(layout_function(graph, **kwargs)).values()])
  47                 else:
  48                     raise ValueError("Check networkx for layouts")
  49             else:
  50                 raise ValueError("networkx not found")
  51         # assume dict from networkx; values are 2-array
  52         elif isinstance(layout, dict):
  53             self.positions = np.asarray([i for i in layout.values()])
  54 
  55         # assume given values
  56         elif isinstance(layout, np.ndarray):
  57             assert layout.ndim == 2
  58             assert layout.shape[0] == len(graph)
  59             self.positions = layout
  60         else:
  61             raise ValueError("Input not understood")
  62 
  63         # normalize coordinates
  64         self.positions = (self.positions - self.positions.min()) / \
  65             (self.positions.max() - self.positions.min())
  66         self.positions = self.positions.astype(np.float32)
  67 
  68     def __call__(self, adjacency_mat, directed=False):
  69         """
  70         Parameters
  71         ----------
  72         adjacency_mat : sparse adjacency matrix.
  73         directed : bool, default False
  74 
  75         Returns
  76         ---------
  77         (node_vertices, line_vertices, arrow_vertices) : tuple
  78         Yields the node and line vertices in a tuple. This layout only yields a
  79         single time, and has no builtin animation
  80         """
  81         if issparse(adjacency_mat):
  82             adjacency_mat = adjacency_mat.tocoo()
  83         line_vertices, arrows = _straight_line_vertices(
  84             adjacency_mat, self.positions, directed)
  85 
  86         yield self.positions, line_vertices, arrows
  87 
  88     @property
  89     def adj(self):
  90         """Convenient storage and holder of the adjacency matrix for the :scene.visuals.Graph: function."""
  91         return nx.adjacency_matrix(self.graph)
  92
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/vispy/visuals/graphs/layouts/networkx_layout.py b/vispy/visuals/graphs/layouts/networkx_layout.py
  --- a/vispy/visuals/graphs/layouts/networkx_layout.py
  +++ b/vispy/visuals/graphs/layouts/networkx_layout.py
  @@ -6,9 +6,6 @@
   try:
       import networkx as nx
   except ModuleNotFoundError:
  -    import warnings
  -    warnings.warn(
  -        "Networkx not found, please install network to use its layouts")
       nx = None
   
   
  @@ -27,6 +24,8 @@
           kwargs: dict, optional
           when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx
           """
  +        if nx is None:
  +            raise ValueError("networkx not found, please install networkx to use its layouts")
           if isinstance(graph, type(None)):
               raise ValueError("Requires networkx input")
           self.graph = graph
  @@ -37,17 +36,14 @@
   
           # check for networkx
           elif isinstance(layout, str):
  -            if nx:
  -                if not layout.endswith("_layout"):
  -                    layout += "_layout"  # append for nx
  -                layout_function = getattr(nx, layout)
  -                if layout_function:
  -                    self.positions = np.asarray(
  -                        [i for i in dict(layout_function(graph, **kwargs)).values()])
  -                else:
  -                    raise ValueError("Check networkx for layouts")
  +            if not layout.endswith("_layout"):
  +                layout += "_layout"  # append for nx
  +            layout_function = getattr(nx, layout)
  +            if layout_function:
  +                self.positions = np.asarray(
  +                    [i for i in dict(layout_function(graph, **kwargs)).values()])
               else:
  -                raise ValueError("networkx not found")
  +                raise ValueError("Check networkx for layouts")
           # assume dict from networkx; values are 2-array
           elif isinstance(layout, dict):
               self.positions = np.asarray([i for i in layout.values()])
  
verification_info: {"golden_diff": "diff --git a/vispy/visuals/graphs/layouts/networkx_layout.py b/vispy/visuals/graphs/layouts/networkx_layout.py\n--- a/vispy/visuals/graphs/layouts/networkx_layout.py\n+++ b/vispy/visuals/graphs/layouts/networkx_layout.py\n@@ -6,9 +6,6 @@\n try:\n     import networkx as nx\n except ModuleNotFoundError:\n-    import warnings\n-    warnings.warn(\n-        \"Networkx not found, please install network to use its layouts\")\n     nx = None\n \n \n@@ -27,6 +24,8 @@\n         kwargs: dict, optional\n         when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx\n         \"\"\"\n+        if nx is None:\n+            raise ValueError(\"networkx not found, please install networkx to use its layouts\")\n         if isinstance(graph, type(None)):\n             raise ValueError(\"Requires networkx input\")\n         self.graph = graph\n@@ -37,17 +36,14 @@\n \n         # check for networkx\n         elif isinstance(layout, str):\n-            if nx:\n-                if not layout.endswith(\"_layout\"):\n-                    layout += \"_layout\"  # append for nx\n-                layout_function = getattr(nx, layout)\n-                if layout_function:\n-                    self.positions = np.asarray(\n-                        [i for i in dict(layout_function(graph, **kwargs)).values()])\n-                else:\n-                    raise ValueError(\"Check networkx for layouts\")\n+            if not layout.endswith(\"_layout\"):\n+                layout += \"_layout\"  # append for nx\n+            layout_function = getattr(nx, layout)\n+            if layout_function:\n+                self.positions = np.asarray(\n+                    [i for i in dict(layout_function(graph, **kwargs)).values()])\n             else:\n-                raise ValueError(\"networkx not found\")\n+                raise ValueError(\"Check networkx for layouts\")\n         # assume dict from networkx; values are 2-array\n         elif isinstance(layout, dict):\n             self.positions = np.asarray([i for i in layout.values()])\n", "issue": "Remove warning on import about missing networkx dependency\nCurrently, importing vispy (or some submodule) without networkx installed results in a warning about installing networkx, even if the user/downstream library has no intention of using the graph layout. The warning should be delayed and turned into an error, as noted by @djhoese [here](https://github.com/napari/napari/issues/2979#issuecomment-874159877).\r\n\r\nxref  napari/napari#2979\n", "before_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) Vispy Development Team. All Rights Reserved.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.#!/usr/bin/env python3\nfrom ..util import _straight_line_vertices, issparse\nimport numpy as np\ntry:\n    import networkx as nx\nexcept ModuleNotFoundError:\n    import warnings\n    warnings.warn(\n        \"Networkx not found, please install network to use its layouts\")\n    nx = None\n\n\nclass NetworkxCoordinates:\n    def __init__(self, graph=None, layout=None, **kwargs):\n        \"\"\"\n        Converts :graph: into a layout. Can be used in conjunction with networkx layouts or using raw 2D-numpy arrays.\n\n        Parameters\n        ----------\n        graph : a networkx graph.\n        layout : str or dict or iterable-object of float32, optional\n        - When :layout: is s string, a lookup will be performed in the networkx avaiable layouts.\n        - When :layout: is a dict, it will be assumed that it takes the shape (key, value) = (node_id, 2D-coordinate).\n        - When :layout: is numpy array it is assumed it takes the shape (number_of_nodes, 2).\n        kwargs: dict, optional\n        when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx\n        \"\"\"\n        if isinstance(graph, type(None)):\n            raise ValueError(\"Requires networkx input\")\n        self.graph = graph\n        self.positions = np.zeros((len(graph), 2), dtype=np.float32)\n        # default random positions\n        if isinstance(layout, type(None)):\n            self.positions = np.random.rand(*self.positions.shape)\n\n        # check for networkx\n        elif isinstance(layout, str):\n            if nx:\n                if not layout.endswith(\"_layout\"):\n                    layout += \"_layout\"  # append for nx\n                layout_function = getattr(nx, layout)\n                if layout_function:\n                    self.positions = np.asarray(\n                        [i for i in dict(layout_function(graph, **kwargs)).values()])\n                else:\n                    raise ValueError(\"Check networkx for layouts\")\n            else:\n                raise ValueError(\"networkx not found\")\n        # assume dict from networkx; values are 2-array\n        elif isinstance(layout, dict):\n            self.positions = np.asarray([i for i in layout.values()])\n\n        # assume given values\n        elif isinstance(layout, np.ndarray):\n            assert layout.ndim == 2\n            assert layout.shape[0] == len(graph)\n            self.positions = layout\n        else:\n            raise ValueError(\"Input not understood\")\n\n        # normalize coordinates\n        self.positions = (self.positions - self.positions.min()) / \\\n            (self.positions.max() - self.positions.min())\n        self.positions = self.positions.astype(np.float32)\n\n    def __call__(self, adjacency_mat, directed=False):\n        \"\"\"\n        Parameters\n        ----------\n        adjacency_mat : sparse adjacency matrix.\n        directed : bool, default False\n\n        Returns\n        ---------\n        (node_vertices, line_vertices, arrow_vertices) : tuple\n        Yields the node and line vertices in a tuple. This layout only yields a\n        single time, and has no builtin animation\n        \"\"\"\n        if issparse(adjacency_mat):\n            adjacency_mat = adjacency_mat.tocoo()\n        line_vertices, arrows = _straight_line_vertices(\n            adjacency_mat, self.positions, directed)\n\n        yield self.positions, line_vertices, arrows\n\n    @property\n    def adj(self):\n        \"\"\"Convenient storage and holder of the adjacency matrix for the :scene.visuals.Graph: function.\"\"\"\n        return nx.adjacency_matrix(self.graph)\n", "path": "vispy/visuals/graphs/layouts/networkx_layout.py"}], "after_files": [{"content": "# -*- coding: utf-8 -*-\n# Copyright (c) Vispy Development Team. All Rights Reserved.\n# Distributed under the (new) BSD License. See LICENSE.txt for more info.#!/usr/bin/env python3\nfrom ..util import _straight_line_vertices, issparse\nimport numpy as np\ntry:\n    import networkx as nx\nexcept ModuleNotFoundError:\n    nx = None\n\n\nclass NetworkxCoordinates:\n    def __init__(self, graph=None, layout=None, **kwargs):\n        \"\"\"\n        Converts :graph: into a layout. Can be used in conjunction with networkx layouts or using raw 2D-numpy arrays.\n\n        Parameters\n        ----------\n        graph : a networkx graph.\n        layout : str or dict or iterable-object of float32, optional\n        - When :layout: is s string, a lookup will be performed in the networkx avaiable layouts.\n        - When :layout: is a dict, it will be assumed that it takes the shape (key, value) = (node_id, 2D-coordinate).\n        - When :layout: is numpy array it is assumed it takes the shape (number_of_nodes, 2).\n        kwargs: dict, optional\n        when layout is :str: :kwargs: will act as a setting dictionary for the layout function of networkx\n        \"\"\"\n        if nx is None:\n            raise ValueError(\"networkx not found, please install networkx to use its layouts\")\n        if isinstance(graph, type(None)):\n            raise ValueError(\"Requires networkx input\")\n        self.graph = graph\n        self.positions = np.zeros((len(graph), 2), dtype=np.float32)\n        # default random positions\n        if isinstance(layout, type(None)):\n            self.positions = np.random.rand(*self.positions.shape)\n\n        # check for networkx\n        elif isinstance(layout, str):\n            if not layout.endswith(\"_layout\"):\n                layout += \"_layout\"  # append for nx\n            layout_function = getattr(nx, layout)\n            if layout_function:\n                self.positions = np.asarray(\n                    [i for i in dict(layout_function(graph, **kwargs)).values()])\n            else:\n                raise ValueError(\"Check networkx for layouts\")\n        # assume dict from networkx; values are 2-array\n        elif isinstance(layout, dict):\n            self.positions = np.asarray([i for i in layout.values()])\n\n        # assume given values\n        elif isinstance(layout, np.ndarray):\n            assert layout.ndim == 2\n            assert layout.shape[0] == len(graph)\n            self.positions = layout\n        else:\n            raise ValueError(\"Input not understood\")\n\n        # normalize coordinates\n        self.positions = (self.positions - self.positions.min()) / \\\n            (self.positions.max() - self.positions.min())\n        self.positions = self.positions.astype(np.float32)\n\n    def __call__(self, adjacency_mat, directed=False):\n        \"\"\"\n        Parameters\n        ----------\n        adjacency_mat : sparse adjacency matrix.\n        directed : bool, default False\n\n        Returns\n        ---------\n        (node_vertices, line_vertices, arrow_vertices) : tuple\n        Yields the node and line vertices in a tuple. This layout only yields a\n        single time, and has no builtin animation\n        \"\"\"\n        if issparse(adjacency_mat):\n            adjacency_mat = adjacency_mat.tocoo()\n        line_vertices, arrows = _straight_line_vertices(\n            adjacency_mat, self.positions, directed)\n\n        yield self.positions, line_vertices, arrows\n\n    @property\n    def adj(self):\n        \"\"\"Convenient storage and holder of the adjacency matrix for the :scene.visuals.Graph: function.\"\"\"\n        return nx.adjacency_matrix(self.graph)\n", "path": "vispy/visuals/graphs/layouts/networkx_layout.py"}]}