Repository: napari/napari

Issue:
`ValueError: WindowsPath('.') has an empty name` raised when interacting with the file extension readers preference line edit
## 🐛 Bug

A `ValueError` exception raises when interacting with the file extension patterns line edit at least on Windows (`Preferences > Plugins > File extension readers > Start typing filename pattern... line edit`):

![pref_error](https://github.com/napari/napari/assets/16781833/7bc1d65a-25f0-412f-88e3-dcf4019f18fa)

## To Reproduce

Steps to reproduce the behavior:

1. Open preferences dialog
2. Go to the `Plugins` config
3. Write in the line edit widget to add a filename pattern under `File extension readers`
4. Remove the text that was wrote.

### Traceback

<details>

```python-traceback
ValueError                                Traceback (most recent call last)
E:\Acer\Documentos\Quansight\Napari\napari\napari\_qt\widgets\qt_extension2reader.py in _filter_compatible_readers(self=<napari._vendor.qt_json_builder.qt_jsonschema_form.widgets.Extension2ReaderWidget object>, new_pattern='')
    171         readers = self._npe2_readers.copy()
    172         to_delete = []
--> 173         compatible_readers = get_potential_readers(new_pattern)
        compatible_readers = undefined
        global get_potential_readers = <function get_potential_readers at 0x000002B4CF38A320>
        new_pattern = ''
    174         for plugin_name in readers:
    175             if plugin_name not in compatible_readers:

E:\Acer\Documentos\Quansight\Napari\napari\napari\plugins\utils.py in get_potential_readers(filename='')
    132     # lower case file extension
    133     ext = str(Path(filename).suffix).lower()
--> 134     filename = str(Path(filename).with_suffix(ext))
        filename = ''
        global str = undefined
        global Path = <class 'pathlib.Path'>
        filename.with_suffix = undefined
        ext = ''
    135     for impl in hook_caller.get_hookimpls():
    136         reader = hook_caller._call_plugin(impl.plugin_name, path=filename)

~\anaconda3\envs\napari-dev\lib\pathlib.py in with_suffix(self=WindowsPath('.'), suffix='')
    780         name = self.name
    781         if not name:
--> 782             raise ValueError("%r has an empty name" % (self,))
        global ValueError = undefined
        self = WindowsPath('.')
    783         old_suffix = self.suffix
    784         if not old_suffix:

ValueError: WindowsPath('.') has an empty name
```

</details>

## Expected behavior

No error/traceback to happen

## Environment

<details>

```
napari: 0.5.0a2.dev231+g7689d09a
Platform: Windows-10-10.0.19045-SP0
Python: 3.10.9 | packaged by conda-forge | (main, Jan 11 2023, 15:15:40) [MSC v.1916 64 bit (AMD64)]
Qt: 5.15.2
PyQt5: 5.15.9
NumPy: 1.24.3
SciPy: 1.9.3
Dask: 2022.10.2
VisPy: 0.12.1
magicgui: 0.6.0
superqt: unknown
in-n-out: 0.1.5
app-model: 0.1.4
npe2: 0.7.0

OpenGL:
- GL version: 4.5.0 - Build 25.20.100.6444
- MAX_TEXTURE_SIZE: 16384

Screens:
- screen 1: resolution 1366x768, scale 1.0
- screen 2: resolution 1600x900, scale 1.0

Settings path:
- C:\Users\dalth\AppData\Local\napari\napari-dev_4454fdbf170edefe23827a4bf512389a6806af69\settings.yaml
```

</details>


## Additional context

Issue found while checking #5977



Discussion:

Resolving patch:
diff --git a/napari/_qt/widgets/qt_extension2reader.py b/napari/_qt/widgets/qt_extension2reader.py
--- a/napari/_qt/widgets/qt_extension2reader.py
+++ b/napari/_qt/widgets/qt_extension2reader.py
@@ -170,7 +170,12 @@ def _filter_compatible_readers(self, new_pattern):
 
         readers = self._npe2_readers.copy()
         to_delete = []
-        compatible_readers = get_potential_readers(new_pattern)
+        try:
+            compatible_readers = get_potential_readers(new_pattern)
+        except ValueError as e:
+            if "empty name" not in str(e):
+                raise
+            compatible_readers = {}
         for plugin_name in readers:
             if plugin_name not in compatible_readers:
                 to_delete.append(plugin_name)
@@ -180,13 +185,12 @@ def _filter_compatible_readers(self, new_pattern):
 
         readers.update(self._npe1_readers)
 
-        if not readers:
+        for i, (plugin_name, display_name) in enumerate(
+            sorted(readers.items())
+        ):
+            self._add_reader_choice(i, plugin_name, display_name)
+        if self._new_reader_dropdown.count() == 0:
             self._new_reader_dropdown.addItem(trans._("None available"))
-        else:
-            for i, (plugin_name, display_name) in enumerate(
-                sorted(readers.items())
-            ):
-                self._add_reader_choice(i, plugin_name, display_name)
 
     def _save_new_preference(self, event):
         """Save current preference to settings and show in table"""


Test patch:
diff --git a/napari/_qt/widgets/_tests/test_qt_extension2reader.py b/napari/_qt/widgets/_tests/test_qt_extension2reader.py
--- a/napari/_qt/widgets/_tests/test_qt_extension2reader.py
+++ b/napari/_qt/widgets/_tests/test_qt_extension2reader.py
@@ -151,6 +151,18 @@ def test_filtering_readers(
     )
 
 
+@pytest.mark.parametrize("pattern", [".", "", "/"])
+def test_filtering_readers_problematic_patterns(
+    extension2reader_widget, builtins, tif_reader, npy_reader, pattern
+):
+    widget = extension2reader_widget(
+        npe1_readers={builtins.display_name: builtins.display_name}
+    )
+    widget._filter_compatible_readers(pattern)
+    assert widget._new_reader_dropdown.count() == 1
+    assert widget._new_reader_dropdown.itemText(0) == "None available"
+
+
 def test_filtering_readers_complex_pattern(
     extension2reader_widget, npy_reader, tif_reader
 ):