From 5b465707dda13d4291e406949545215f316ca30d Mon Sep 17 00:00:00 2001 From: Talley Lambert Date: Sun, 12 Jun 2022 08:58:08 -0400 Subject: [PATCH] Fix writer order preference (#172) * fixes #129 * remove docstring * fix test * use _writer key --- npe2/_plugin_manager.py | 21 ++++++--------------- tests/test_contributions.py | 19 ++++++++++++++++++- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/npe2/_plugin_manager.py b/npe2/_plugin_manager.py index 5e8881aa..ae728aa7 100644 --- a/npe2/_plugin_manager.py +++ b/npe2/_plugin_manager.py @@ -153,32 +153,23 @@ def _get_candidates(lt: LayerType) -> Set[WriterContribution]: if layer == lt and (min_ <= counts[lt] < max_) } - candidates = {w for _, _, _, w in self._writers} + # keep ordered without duplicates + candidates = list({w: None for _, _, _, w in self._writers}) for lt in LayerType: if candidates: - candidates &= _get_candidates(lt) + candidates = [i for i in candidates if i in _get_candidates(lt)] else: break - def _writer_key(writer: WriterContribution) -> Tuple[bool, int, int, List[str]]: + def _writer_key(writer: WriterContribution) -> Tuple[bool, int]: # 1. writers with no file extensions (like directory writers) go last no_ext = len(writer.filename_extensions) == 0 # 2. more "specific" writers first nbounds = sum(not c.is_zero() for c in writer.layer_type_constraints()) + return (no_ext, nbounds) - # 3. then sort by the number of listed extensions - # (empty set of extensions goes last) - ext_len = len(writer.filename_extensions) - - # 4. finally group related extensions together - exts = writer.filename_extensions - return (no_ext, nbounds, ext_len, exts) - - yield from sorted( - candidates, - key=_writer_key, - ) + yield from sorted(candidates, key=_writer_key) class PluginManagerEvents(SignalGroup): diff --git a/tests/test_contributions.py b/tests/test_contributions.py index 6ff29b48..0a9e8ad4 100644 --- a/tests/test_contributions.py +++ b/tests/test_contributions.py @@ -3,7 +3,7 @@ import pytest -from npe2 import PluginManager, PluginManifest +from npe2 import DynamicPlugin, PluginManager, PluginManifest from npe2.manifest.contributions import ( CommandContribution, SampleDataGenerator, @@ -41,6 +41,23 @@ def test_writer_ranges(param, uses_sample_plugin, plugin_manager: PluginManager) assert nwriters == expected_count +def test_writer_priority(): + """Contributions listed earlier in the manifest should be preferred.""" + pm = PluginManager() + with DynamicPlugin(name="my_plugin", plugin_manager=pm) as plg: + + @plg.contribute.writer(filename_extensions=["*.tif"], layer_types=["image"]) + def my_writer1(path, data): + ... + + @plg.contribute.writer(filename_extensions=["*.abc"], layer_types=["image"]) + def my_writer2(path, data): + ... + + writers = list(pm.iter_compatible_writers(["image"])) + assert writers[0].command == "my_plugin.my_writer1" + + @pytest.mark.parametrize( "expr", ["vectors", "vectors+", "vectors*", "vectors?", "vectors{3}", "vectors{3,8}"],