Repository: napari/napari

Issue:
Plugin Errors not work in develop 
## 🐛 Bug

<!-- A clear and concise description of what the bug is. -->

$ NAPARI_CATCH_ERRORS=0 python -m napari
16:11:17 ERROR Unhandled exception:
Traceback (most recent call last):
  File "/home/czaki/Dokumenty/projekty/napari/napari/_qt/qt_main_window.py", line 300, in _show_plugin_err_reporter
    plugin_sorter = QtPluginErrReporter(parent=self._qt_window)
  File "/home/czaki/Dokumenty/projekty/napari/napari/_qt/dialogs/qt_plugin_report.py", line 62, in __init__
    from ..plugins import plugin_manager as _pm
ModuleNotFoundError: No module named 'napari._qt.plugins'


## To Reproduce

Steps to reproduce the behavior:

1. install last napari from github
2. try open "Plugin Errors" dialog


<!-- If you have a code sample, error messages, stack traces, please provide it here as well -->

## Expected behavior

<!-- A clear and concise description of what you expected to happen. -->

## Environment

 - Please copy and paste the information at napari info option in help menubar here:

napari: 0.3.7.dev30+gf101ef7
Platform: Linux-4.15.0-112-generic-x86_64-with-debian-buster-sid
Python: 3.7.6 (default, Feb 20 2020, 10:04:45) [GCC 7.4.0]
Qt: 5.14.2
PyQt5: 5.14.2
NumPy: 1.18.5
SciPy: 1.4.1
Dask: 2.17.2
VisPy: 0.6.4

GL version: 4.6.0 NVIDIA 440.100
MAX_TEXTURE_SIZE: 32768

Plugins:
- napari-plugin-engine: 0.1.5
- svg: 0.1.3

 - Any other relevant information:

## Additional context

<!-- Add any other context about the problem here. -->
@sofroniewn @jni 


Discussion:
Looks like this relates to a reorg of the qt files in #1431 and some additional nesting. Should be an easy fix to `from ...plugins import plugin_manager as _pm` but I'd want to check first. A PR with a test would be very welcome @Czaki, sorry about the bug! 
I found it by accident. I'm not sure if I found time for PR before Monday. And You have plan to create next release in short time, where such bug should not appear. 

So If no one fix it earlier I will probably fix in in next week. 
> I found it by accident. I'm not sure if I found time for PR before Monday. And You have plan to create next release in short time, where such bug should not appear.
>
> So If no one fix it earlier I will probably fix in in next week.

Sounds good, thanks for letting me know!! I may quickly fix it before release. If it's still there next week, then PR welcome :-)

Resolving patch:
diff --git a/napari/_qt/dialogs/qt_plugin_report.py b/napari/_qt/dialogs/qt_plugin_report.py
--- a/napari/_qt/dialogs/qt_plugin_report.py
+++ b/napari/_qt/dialogs/qt_plugin_report.py
@@ -59,7 +59,7 @@ def __init__(
     ) -> None:
         super().__init__(parent)
         if not plugin_manager:
-            from ..plugins import plugin_manager as _pm
+            from ...plugins import plugin_manager as _pm
 
             self.plugin_manager = _pm
         else:
diff --git a/napari/_qt/dialogs/qt_plugin_table.py b/napari/_qt/dialogs/qt_plugin_table.py
--- a/napari/_qt/dialogs/qt_plugin_table.py
+++ b/napari/_qt/dialogs/qt_plugin_table.py
@@ -8,7 +8,7 @@ class QtPluginTable(QDialog):
     def __init__(self, parent, plugin_manager=None):
         super().__init__(parent)
         if not plugin_manager:
-            from ..plugins import plugin_manager
+            from ...plugins import plugin_manager
 
         self.setMaximumHeight(800)
         self.setMaximumWidth(1280)


Test patch:
diff --git a/napari/_qt/_tests/test_exception_handler.py b/napari/_qt/_tests/test_exception_handler.py
--- a/napari/_qt/_tests/test_exception_handler.py
+++ b/napari/_qt/_tests/test_exception_handler.py
@@ -1,4 +1,5 @@
 import logging
+
 import pytest
 
 from napari._qt.exceptions import ExceptionHandler
diff --git a/napari/_qt/dialogs/_tests/test_qt_plugin_list.py b/napari/_qt/dialogs/_tests/test_qt_plugin_list.py
--- a/napari/_qt/dialogs/_tests/test_qt_plugin_list.py
+++ b/napari/_qt/dialogs/_tests/test_qt_plugin_list.py
@@ -34,16 +34,24 @@ def entrypoint_plugin(tmp_path):
 
 
 # test_plugin_manager fixture is provided by napari_plugin_engine._testsupport
-def test_qt_plugin_list(test_plugin_manager, entrypoint_plugin):
+def test_qt_plugin_list(test_plugin_manager, entrypoint_plugin, qtbot):
     """Make sure the plugin list viewer works and has the test plugins."""
 
     with temp_path_additions(entrypoint_plugin):
         test_plugin_manager.discover(entry_point='app.plugin')
         assert 'a_plugin' in test_plugin_manager.plugins
         dialog = QtPluginTable(None, test_plugin_manager)
+        qtbot.addWidget(dialog)
         assert dialog.table.rowCount() > 0
         plugins = {
             dialog.table.item(i, 0).text()
             for i in range(dialog.table.rowCount())
         }
         assert 'a_plugin' in plugins
+
+
+def test_dialog_create(qtbot):
+    dialog = QtPluginTable(None)
+    qtbot.addWidget(dialog)
+    assert dialog.table.rowCount() >= 2
+    assert dialog.table.columnCount() == 6
diff --git a/napari/_qt/dialogs/_tests/test_qt_plugin_report.py b/napari/_qt/dialogs/_tests/test_qt_plugin_report.py
--- a/napari/_qt/dialogs/_tests/test_qt_plugin_report.py
+++ b/napari/_qt/dialogs/_tests/test_qt_plugin_report.py
@@ -55,3 +55,8 @@ def mock_webbrowser_open(url, new=0):
 
     report_widget.set_plugin(None)
     assert not report_widget.text_area.toPlainText()
+
+
+def test_dialog_create(qtbot):
+    dialog = qt_plugin_report.QtPluginErrReporter()
+    qtbot.addWidget(dialog)