We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
npe2 plugins need to be added to `napari --info` 
## 🐛 Bug
currently, `napari --info` doesn't include npe2 plugins

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `napari/utils/info.py`
Content:
```
1 import os
2 import platform
3 import subprocess
4 import sys
5 
6 import napari
7 
8 OS_RELEASE_PATH = "/etc/os-release"
9 
10 
11 def _linux_sys_name():
12     """
13     Try to discover linux system name base on /etc/os-release file or lsb_release command output
14     https://www.freedesktop.org/software/systemd/man/os-release.html
15     """
16     if os.path.exists(OS_RELEASE_PATH):
17         with open(OS_RELEASE_PATH) as f_p:
18             data = {}
19             for line in f_p:
20                 field, value = line.split("=")
21                 data[field.strip()] = value.strip().strip('"')
22         if "PRETTY_NAME" in data:
23             return data["PRETTY_NAME"]
24         if "NAME" in data:
25             if "VERSION" in data:
26                 return f'{data["NAME"]} {data["VERSION"]}'
27             if "VERSION_ID" in data:
28                 return f'{data["NAME"]} {data["VERSION_ID"]}'
29             return f'{data["NAME"]} (no version)'
30 
31     try:
32         res = subprocess.run(
33             ["lsb_release", "-d", "-r"], check=True, capture_output=True
34         )
35         text = res.stdout.decode()
36         data = {}
37         for line in text.split("\n"):
38             key, val = line.split(":")
39             data[key.strip()] = val.strip()
40         version_str = data["Description"]
41         if not version_str.endswith(data["Release"]):
42             version_str += " " + data["Release"]
43         return version_str
44     except subprocess.CalledProcessError:
45         pass
46     return ""
47 
48 
49 def _sys_name():
50     """
51     Discover MacOS or Linux Human readable information. For Linux provide information about distribution.
52     """
53     try:
54         if sys.platform == "linux":
55             return _linux_sys_name()
56         if sys.platform == "darwin":
57             try:
58                 res = subprocess.run(
59                     ["sw_vers", "-productVersion"],
60                     check=True,
61                     capture_output=True,
62                 )
63                 return f"MacOS {res.stdout.decode().strip()}"
64             except subprocess.CalledProcessError:
65                 pass
66     except Exception:
67         pass
68     return ""
69 
70 
71 def sys_info(as_html=False):
72     """Gathers relevant module versions for troubleshooting purposes.
73 
74     Parameters
75     ----------
76     as_html : bool
77         if True, info will be returned as HTML, suitable for a QTextEdit widget
78     """
79     from napari.plugins import plugin_manager
80 
81     sys_version = sys.version.replace('\n', ' ')
82     text = (
83         f"<b>napari</b>: {napari.__version__}<br>"
84         f"<b>Platform</b>: {platform.platform()}<br>"
85     )
86 
87     __sys_name = _sys_name()
88     if __sys_name:
89         text += f"<b>System</b>: {__sys_name}<br>"
90 
91     text += f"<b>Python</b>: {sys_version}<br>"
92 
93     try:
94         from qtpy import API_NAME, PYQT_VERSION, PYSIDE_VERSION, QtCore
95 
96         if API_NAME == 'PySide2':
97             API_VERSION = PYSIDE_VERSION
98         elif API_NAME == 'PyQt5':
99             API_VERSION = PYQT_VERSION
100         else:
101             API_VERSION = ''
102 
103         text += (
104             f"<b>Qt</b>: {QtCore.__version__}<br>"
105             f"<b>{API_NAME}</b>: {API_VERSION}<br>"
106         )
107 
108     except Exception as e:
109         text += f"<b>Qt</b>: Import failed ({e})<br>"
110 
111     modules = (
112         ('numpy', 'NumPy'),
113         ('scipy', 'SciPy'),
114         ('dask', 'Dask'),
115         ('vispy', 'VisPy'),
116     )
117 
118     loaded = {}
119     for module, name in modules:
120         try:
121             loaded[module] = __import__(module)
122             text += f"<b>{name}</b>: {loaded[module].__version__}<br>"
123         except Exception as e:
124             text += f"<b>{name}</b>: Import failed ({e})<br>"
125 
126     text += "<br><b>OpenGL:</b><br>"
127 
128     if loaded.get('vispy', False):
129         sys_info_text = (
130             "<br>".join(
131                 [
132                     loaded['vispy'].sys_info().split("\n")[index]
133                     for index in [-4, -3]
134                 ]
135             )
136             .replace("'", "")
137             .replace("<br>", "<br>  - ")
138         )
139         text += f'  - {sys_info_text}<br>'
140     else:
141         text += "  - failed to load vispy"
142 
143     text += "<br><b>Screens:</b><br>"
144 
145     try:
146         from qtpy.QtGui import QGuiApplication
147 
148         screen_list = QGuiApplication.screens()
149         for i, screen in enumerate(screen_list, start=1):
150             text += f"  - screen {i}: resolution {screen.geometry().width()}x{screen.geometry().height()}, scale {screen.devicePixelRatio()}<br>"
151     except Exception as e:
152         text += f"  - failed to load screen information {e}"
153 
154     plugin_manager.discover()
155     plugin_strings = []
156     for meta in plugin_manager.list_plugin_metadata():
157         plugin_name = meta.get('plugin_name')
158         if plugin_name == 'builtins':
159             continue
160         version = meta.get('version')
161         version_string = f": {version}" if version else ""
162         plugin_strings.append(f"  - {plugin_name}{version_string}")
163     text += '<br><b>Plugins</b>:'
164     text += (
165         ("<br>" + "<br>".join(sorted(plugin_strings)))
166         if plugin_strings
167         else '  None'
168     )
169 
170     if not as_html:
171         text = (
172             text.replace("<br>", "\n").replace("<b>", "").replace("</b>", "")
173         )
174     return text
175 
176 
177 citation_text = (
178     'napari contributors (2019). napari: a '
179     'multi-dimensional image viewer for python. '
180     'doi:10.5281/zenodo.3555620'
181 )
182
```
--- 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()

```

diff --git a/napari/utils/info.py b/napari/utils/info.py
--- a/napari/utils/info.py
+++ b/napari/utils/info.py
@@ -76,6 +76,8 @@
     as_html : bool
         if True, info will be returned as HTML, suitable for a QTextEdit widget
     """
+    from npe2 import PluginManager as Npe2PluginManager
+
     from napari.plugins import plugin_manager
 
     sys_version = sys.version.replace('\n', ' ')
@@ -152,17 +154,27 @@
         text += f"  - failed to load screen information {e}"
 
     plugin_manager.discover()
-    plugin_strings = []
+    plugin_strings = {}
     for meta in plugin_manager.list_plugin_metadata():
         plugin_name = meta.get('plugin_name')
         if plugin_name == 'builtins':
             continue
         version = meta.get('version')
         version_string = f": {version}" if version else ""
-        plugin_strings.append(f"  - {plugin_name}{version_string}")
+        plugin_strings[plugin_name] = f"  - {plugin_name}{version_string}"
+
+    npe2_plugin_manager = Npe2PluginManager.instance()
+    for manifest in npe2_plugin_manager.iter_manifests():
+        plugin_name = manifest.name
+        if plugin_name in ("napari", "builtins"):
+            continue
+        version = manifest.package_version
+        version_string = f": {version}" if version else ""
+        plugin_strings[plugin_name] = f"  - {plugin_name}{version_string}"
+
     text += '<br><b>Plugins</b>:'
     text += (
-        ("<br>" + "<br>".join(sorted(plugin_strings)))
+        ("<br>" + "<br>".join(sorted(plugin_strings.values())))
         if plugin_strings
         else '  None'
     )

{"golden_diff": "diff --git a/napari/utils/info.py b/napari/utils/info.py\n--- a/napari/utils/info.py\n+++ b/napari/utils/info.py\n@@ -76,6 +76,8 @@\n     as_html : bool\n         if True, info will be returned as HTML, suitable for a QTextEdit widget\n     \"\"\"\n+    from npe2 import PluginManager as Npe2PluginManager\n+\n     from napari.plugins import plugin_manager\n \n     sys_version = sys.version.replace('\\n', ' ')\n@@ -152,17 +154,27 @@\n         text += f\"  - failed to load screen information {e}\"\n \n     plugin_manager.discover()\n-    plugin_strings = []\n+    plugin_strings = {}\n     for meta in plugin_manager.list_plugin_metadata():\n         plugin_name = meta.get('plugin_name')\n         if plugin_name == 'builtins':\n             continue\n         version = meta.get('version')\n         version_string = f\": {version}\" if version else \"\"\n-        plugin_strings.append(f\"  - {plugin_name}{version_string}\")\n+        plugin_strings[plugin_name] = f\"  - {plugin_name}{version_string}\"\n+\n+    npe2_plugin_manager = Npe2PluginManager.instance()\n+    for manifest in npe2_plugin_manager.iter_manifests():\n+        plugin_name = manifest.name\n+        if plugin_name in (\"napari\", \"builtins\"):\n+            continue\n+        version = manifest.package_version\n+        version_string = f\": {version}\" if version else \"\"\n+        plugin_strings[plugin_name] = f\"  - {plugin_name}{version_string}\"\n+\n     text += '<br><b>Plugins</b>:'\n     text += (\n-        (\"<br>\" + \"<br>\".join(sorted(plugin_strings)))\n+        (\"<br>\" + \"<br>\".join(sorted(plugin_strings.values())))\n         if plugin_strings\n         else '  None'\n     )\n", "issue": "npe2 plugins need to be added to `napari --info` \n## \ud83d\udc1b Bug\r\ncurrently, `napari --info` doesn't include npe2 plugins\n", "before_files": [{"content": "import os\nimport platform\nimport subprocess\nimport sys\n\nimport napari\n\nOS_RELEASE_PATH = \"/etc/os-release\"\n\n\ndef _linux_sys_name():\n    \"\"\"\n    Try to discover linux system name base on /etc/os-release file or lsb_release command output\n    https://www.freedesktop.org/software/systemd/man/os-release.html\n    \"\"\"\n    if os.path.exists(OS_RELEASE_PATH):\n        with open(OS_RELEASE_PATH) as f_p:\n            data = {}\n            for line in f_p:\n                field, value = line.split(\"=\")\n                data[field.strip()] = value.strip().strip('\"')\n        if \"PRETTY_NAME\" in data:\n            return data[\"PRETTY_NAME\"]\n        if \"NAME\" in data:\n            if \"VERSION\" in data:\n                return f'{data[\"NAME\"]} {data[\"VERSION\"]}'\n            if \"VERSION_ID\" in data:\n                return f'{data[\"NAME\"]} {data[\"VERSION_ID\"]}'\n            return f'{data[\"NAME\"]} (no version)'\n\n    try:\n        res = subprocess.run(\n            [\"lsb_release\", \"-d\", \"-r\"], check=True, capture_output=True\n        )\n        text = res.stdout.decode()\n        data = {}\n        for line in text.split(\"\\n\"):\n            key, val = line.split(\":\")\n            data[key.strip()] = val.strip()\n        version_str = data[\"Description\"]\n        if not version_str.endswith(data[\"Release\"]):\n            version_str += \" \" + data[\"Release\"]\n        return version_str\n    except subprocess.CalledProcessError:\n        pass\n    return \"\"\n\n\ndef _sys_name():\n    \"\"\"\n    Discover MacOS or Linux Human readable information. For Linux provide information about distribution.\n    \"\"\"\n    try:\n        if sys.platform == \"linux\":\n            return _linux_sys_name()\n        if sys.platform == \"darwin\":\n            try:\n                res = subprocess.run(\n                    [\"sw_vers\", \"-productVersion\"],\n                    check=True,\n                    capture_output=True,\n                )\n                return f\"MacOS {res.stdout.decode().strip()}\"\n            except subprocess.CalledProcessError:\n                pass\n    except Exception:\n        pass\n    return \"\"\n\n\ndef sys_info(as_html=False):\n    \"\"\"Gathers relevant module versions for troubleshooting purposes.\n\n    Parameters\n    ----------\n    as_html : bool\n        if True, info will be returned as HTML, suitable for a QTextEdit widget\n    \"\"\"\n    from napari.plugins import plugin_manager\n\n    sys_version = sys.version.replace('\\n', ' ')\n    text = (\n        f\"<b>napari</b>: {napari.__version__}<br>\"\n        f\"<b>Platform</b>: {platform.platform()}<br>\"\n    )\n\n    __sys_name = _sys_name()\n    if __sys_name:\n        text += f\"<b>System</b>: {__sys_name}<br>\"\n\n    text += f\"<b>Python</b>: {sys_version}<br>\"\n\n    try:\n        from qtpy import API_NAME, PYQT_VERSION, PYSIDE_VERSION, QtCore\n\n        if API_NAME == 'PySide2':\n            API_VERSION = PYSIDE_VERSION\n        elif API_NAME == 'PyQt5':\n            API_VERSION = PYQT_VERSION\n        else:\n            API_VERSION = ''\n\n        text += (\n            f\"<b>Qt</b>: {QtCore.__version__}<br>\"\n            f\"<b>{API_NAME}</b>: {API_VERSION}<br>\"\n        )\n\n    except Exception as e:\n        text += f\"<b>Qt</b>: Import failed ({e})<br>\"\n\n    modules = (\n        ('numpy', 'NumPy'),\n        ('scipy', 'SciPy'),\n        ('dask', 'Dask'),\n        ('vispy', 'VisPy'),\n    )\n\n    loaded = {}\n    for module, name in modules:\n        try:\n            loaded[module] = __import__(module)\n            text += f\"<b>{name}</b>: {loaded[module].__version__}<br>\"\n        except Exception as e:\n            text += f\"<b>{name}</b>: Import failed ({e})<br>\"\n\n    text += \"<br><b>OpenGL:</b><br>\"\n\n    if loaded.get('vispy', False):\n        sys_info_text = (\n            \"<br>\".join(\n                [\n                    loaded['vispy'].sys_info().split(\"\\n\")[index]\n                    for index in [-4, -3]\n                ]\n            )\n            .replace(\"'\", \"\")\n            .replace(\"<br>\", \"<br>  - \")\n        )\n        text += f'  - {sys_info_text}<br>'\n    else:\n        text += \"  - failed to load vispy\"\n\n    text += \"<br><b>Screens:</b><br>\"\n\n    try:\n        from qtpy.QtGui import QGuiApplication\n\n        screen_list = QGuiApplication.screens()\n        for i, screen in enumerate(screen_list, start=1):\n            text += f\"  - screen {i}: resolution {screen.geometry().width()}x{screen.geometry().height()}, scale {screen.devicePixelRatio()}<br>\"\n    except Exception as e:\n        text += f\"  - failed to load screen information {e}\"\n\n    plugin_manager.discover()\n    plugin_strings = []\n    for meta in plugin_manager.list_plugin_metadata():\n        plugin_name = meta.get('plugin_name')\n        if plugin_name == 'builtins':\n            continue\n        version = meta.get('version')\n        version_string = f\": {version}\" if version else \"\"\n        plugin_strings.append(f\"  - {plugin_name}{version_string}\")\n    text += '<br><b>Plugins</b>:'\n    text += (\n        (\"<br>\" + \"<br>\".join(sorted(plugin_strings)))\n        if plugin_strings\n        else '  None'\n    )\n\n    if not as_html:\n        text = (\n            text.replace(\"<br>\", \"\\n\").replace(\"<b>\", \"\").replace(\"</b>\", \"\")\n        )\n    return text\n\n\ncitation_text = (\n    'napari contributors (2019). napari: a '\n    'multi-dimensional image viewer for python. '\n    'doi:10.5281/zenodo.3555620'\n)\n", "path": "napari/utils/info.py"}], "after_files": [{"content": "import os\nimport platform\nimport subprocess\nimport sys\n\nimport napari\n\nOS_RELEASE_PATH = \"/etc/os-release\"\n\n\ndef _linux_sys_name():\n    \"\"\"\n    Try to discover linux system name base on /etc/os-release file or lsb_release command output\n    https://www.freedesktop.org/software/systemd/man/os-release.html\n    \"\"\"\n    if os.path.exists(OS_RELEASE_PATH):\n        with open(OS_RELEASE_PATH) as f_p:\n            data = {}\n            for line in f_p:\n                field, value = line.split(\"=\")\n                data[field.strip()] = value.strip().strip('\"')\n        if \"PRETTY_NAME\" in data:\n            return data[\"PRETTY_NAME\"]\n        if \"NAME\" in data:\n            if \"VERSION\" in data:\n                return f'{data[\"NAME\"]} {data[\"VERSION\"]}'\n            if \"VERSION_ID\" in data:\n                return f'{data[\"NAME\"]} {data[\"VERSION_ID\"]}'\n            return f'{data[\"NAME\"]} (no version)'\n\n    try:\n        res = subprocess.run(\n            [\"lsb_release\", \"-d\", \"-r\"], check=True, capture_output=True\n        )\n        text = res.stdout.decode()\n        data = {}\n        for line in text.split(\"\\n\"):\n            key, val = line.split(\":\")\n            data[key.strip()] = val.strip()\n        version_str = data[\"Description\"]\n        if not version_str.endswith(data[\"Release\"]):\n            version_str += \" \" + data[\"Release\"]\n        return version_str\n    except subprocess.CalledProcessError:\n        pass\n    return \"\"\n\n\ndef _sys_name():\n    \"\"\"\n    Discover MacOS or Linux Human readable information. For Linux provide information about distribution.\n    \"\"\"\n    try:\n        if sys.platform == \"linux\":\n            return _linux_sys_name()\n        if sys.platform == \"darwin\":\n            try:\n                res = subprocess.run(\n                    [\"sw_vers\", \"-productVersion\"],\n                    check=True,\n                    capture_output=True,\n                )\n                return f\"MacOS {res.stdout.decode().strip()}\"\n            except subprocess.CalledProcessError:\n                pass\n    except Exception:\n        pass\n    return \"\"\n\n\ndef sys_info(as_html=False):\n    \"\"\"Gathers relevant module versions for troubleshooting purposes.\n\n    Parameters\n    ----------\n    as_html : bool\n        if True, info will be returned as HTML, suitable for a QTextEdit widget\n    \"\"\"\n    from npe2 import PluginManager as Npe2PluginManager\n\n    from napari.plugins import plugin_manager\n\n    sys_version = sys.version.replace('\\n', ' ')\n    text = (\n        f\"<b>napari</b>: {napari.__version__}<br>\"\n        f\"<b>Platform</b>: {platform.platform()}<br>\"\n    )\n\n    __sys_name = _sys_name()\n    if __sys_name:\n        text += f\"<b>System</b>: {__sys_name}<br>\"\n\n    text += f\"<b>Python</b>: {sys_version}<br>\"\n\n    try:\n        from qtpy import API_NAME, PYQT_VERSION, PYSIDE_VERSION, QtCore\n\n        if API_NAME == 'PySide2':\n            API_VERSION = PYSIDE_VERSION\n        elif API_NAME == 'PyQt5':\n            API_VERSION = PYQT_VERSION\n        else:\n            API_VERSION = ''\n\n        text += (\n            f\"<b>Qt</b>: {QtCore.__version__}<br>\"\n            f\"<b>{API_NAME}</b>: {API_VERSION}<br>\"\n        )\n\n    except Exception as e:\n        text += f\"<b>Qt</b>: Import failed ({e})<br>\"\n\n    modules = (\n        ('numpy', 'NumPy'),\n        ('scipy', 'SciPy'),\n        ('dask', 'Dask'),\n        ('vispy', 'VisPy'),\n    )\n\n    loaded = {}\n    for module, name in modules:\n        try:\n            loaded[module] = __import__(module)\n            text += f\"<b>{name}</b>: {loaded[module].__version__}<br>\"\n        except Exception as e:\n            text += f\"<b>{name}</b>: Import failed ({e})<br>\"\n\n    text += \"<br><b>OpenGL:</b><br>\"\n\n    if loaded.get('vispy', False):\n        sys_info_text = (\n            \"<br>\".join(\n                [\n                    loaded['vispy'].sys_info().split(\"\\n\")[index]\n                    for index in [-4, -3]\n                ]\n            )\n            .replace(\"'\", \"\")\n            .replace(\"<br>\", \"<br>  - \")\n        )\n        text += f'  - {sys_info_text}<br>'\n    else:\n        text += \"  - failed to load vispy\"\n\n    text += \"<br><b>Screens:</b><br>\"\n\n    try:\n        from qtpy.QtGui import QGuiApplication\n\n        screen_list = QGuiApplication.screens()\n        for i, screen in enumerate(screen_list, start=1):\n            text += f\"  - screen {i}: resolution {screen.geometry().width()}x{screen.geometry().height()}, scale {screen.devicePixelRatio()}<br>\"\n    except Exception as e:\n        text += f\"  - failed to load screen information {e}\"\n\n    plugin_manager.discover()\n    plugin_strings = {}\n    for meta in plugin_manager.list_plugin_metadata():\n        plugin_name = meta.get('plugin_name')\n        if plugin_name == 'builtins':\n            continue\n        version = meta.get('version')\n        version_string = f\": {version}\" if version else \"\"\n        plugin_strings[plugin_name] = f\"  - {plugin_name}{version_string}\"\n\n    npe2_plugin_manager = Npe2PluginManager.instance()\n    for manifest in npe2_plugin_manager.iter_manifests():\n        plugin_name = manifest.name\n        if plugin_name in (\"napari\", \"builtins\"):\n            continue\n        version = manifest.package_version\n        version_string = f\": {version}\" if version else \"\"\n        plugin_strings[plugin_name] = f\"  - {plugin_name}{version_string}\"\n\n    text += '<br><b>Plugins</b>:'\n    text += (\n        (\"<br>\" + \"<br>\".join(sorted(plugin_strings.values())))\n        if plugin_strings\n        else '  None'\n    )\n\n    if not as_html:\n        text = (\n            text.replace(\"<br>\", \"\\n\").replace(\"<b>\", \"\").replace(\"</b>\", \"\")\n        )\n    return text\n\n\ncitation_text = (\n    'napari contributors (2019). napari: a '\n    'multi-dimensional image viewer for python. '\n    'doi:10.5281/zenodo.3555620'\n)\n", "path": "napari/utils/info.py"}]}