From 2fecf7a933f10f240aaa7f9758d7759a5535c41f Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 24 May 2023 23:30:58 +0200 Subject: [PATCH 01/12] fix converting of editable package --- src/npe2/__main__.py | 4 ++++ src/npe2/_inspection/_from_npe1.py | 9 ++++++++- src/npe2/cli.py | 2 ++ 3 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 src/npe2/__main__.py diff --git a/src/npe2/__main__.py b/src/npe2/__main__.py new file mode 100644 index 00000000..7aaff027 --- /dev/null +++ b/src/npe2/__main__.py @@ -0,0 +1,4 @@ +from npe2.cli import main + +if __name__ == "__main__": + main() diff --git a/src/npe2/_inspection/_from_npe1.py b/src/npe2/_inspection/_from_npe1.py index 48622824..0d96ef65 100644 --- a/src/npe2/_inspection/_from_npe1.py +++ b/src/npe2/_inspection/_from_npe1.py @@ -507,6 +507,7 @@ def _camel_to_spaces(val): def get_top_module_path(package_name, top_module: Optional[str] = None) -> Path: dist = metadata.distribution(package_name) + # import pdb; pdb.set_trace() if not top_module: top_mods = (dist.read_text("top_level.txt") or "").strip().splitlines() if not top_mods: @@ -517,7 +518,13 @@ def get_top_module_path(package_name, top_module: Optional[str] = None) -> Path: top_module = top_mods[0] path = Path(dist.locate_file(top_module)) - assert path.is_dir() + if not path.is_dir(): + for f_path in dist.files: + if "__editable__" in f_path.name: + path = Path(f_path.read_text().strip()) / top_module + break + + assert path.is_dir(), f"Could not find top level module {top_module} using {path}" return path diff --git a/src/npe2/cli.py b/src/npe2/cli.py index fc4e2479..38484a2a 100644 --- a/src/npe2/cli.py +++ b/src/npe2/cli.py @@ -4,6 +4,7 @@ from enum import Enum from pathlib import Path from typing import TYPE_CHECKING, Iterator, List, Optional, Sequence +from traceback import print_exc import typer @@ -429,6 +430,7 @@ def convert( typer.echo() except Exception as e: + print_exc() msg = f"Conversion failed:\n{type(e).__name__}: {e}" typer.secho(msg, fg=typer.colors.RED, bold=True) raise typer.Exit(1) from e From e3aecf50b3b073c1bbe0fc4aebc1cfa71e9ba60a Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 24 May 2023 23:33:21 +0200 Subject: [PATCH 02/12] remove debug --- src/npe2/_inspection/_from_npe1.py | 1 - src/npe2/cli.py | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/npe2/_inspection/_from_npe1.py b/src/npe2/_inspection/_from_npe1.py index 0d96ef65..94a3f02a 100644 --- a/src/npe2/_inspection/_from_npe1.py +++ b/src/npe2/_inspection/_from_npe1.py @@ -507,7 +507,6 @@ def _camel_to_spaces(val): def get_top_module_path(package_name, top_module: Optional[str] = None) -> Path: dist = metadata.distribution(package_name) - # import pdb; pdb.set_trace() if not top_module: top_mods = (dist.read_text("top_level.txt") or "").strip().splitlines() if not top_mods: diff --git a/src/npe2/cli.py b/src/npe2/cli.py index 38484a2a..fc4e2479 100644 --- a/src/npe2/cli.py +++ b/src/npe2/cli.py @@ -4,7 +4,6 @@ from enum import Enum from pathlib import Path from typing import TYPE_CHECKING, Iterator, List, Optional, Sequence -from traceback import print_exc import typer @@ -430,7 +429,6 @@ def convert( typer.echo() except Exception as e: - print_exc() msg = f"Conversion failed:\n{type(e).__name__}: {e}" typer.secho(msg, fg=typer.colors.RED, bold=True) raise typer.Exit(1) from e From 39e52670aa56bcda3e2a10103de7922fb6c97a08 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Wed, 24 May 2023 23:55:44 +0200 Subject: [PATCH 03/12] fix handling None files for dist --- src/npe2/_inspection/_from_npe1.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/npe2/_inspection/_from_npe1.py b/src/npe2/_inspection/_from_npe1.py index 94a3f02a..8a83a9d0 100644 --- a/src/npe2/_inspection/_from_npe1.py +++ b/src/npe2/_inspection/_from_npe1.py @@ -517,7 +517,7 @@ def get_top_module_path(package_name, top_module: Optional[str] = None) -> Path: top_module = top_mods[0] path = Path(dist.locate_file(top_module)) - if not path.is_dir(): + if not path.is_dir() and dist.files: for f_path in dist.files: if "__editable__" in f_path.name: path = Path(f_path.read_text().strip()) / top_module From 60511dcddaa1511aab1b9374d93b608a9bf1efc2 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 1 Jun 2023 16:53:40 +0200 Subject: [PATCH 04/12] add test --- tests/conftest.py | 37 +++++++ tests/npe1-plugin-src/setup.cfg | 10 ++ .../src/npe1-plugin1-0.0.1.dist-info/METADATA | 3 + .../entry_points.txt | 2 + .../top_level.txt | 1 + .../src/npe1_module1/__init__.py | 97 +++++++++++++++++++ tests/test_conversion.py | 15 +++ 7 files changed, 165 insertions(+) create mode 100644 tests/npe1-plugin-src/setup.cfg create mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA create mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt create mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt create mode 100644 tests/npe1-plugin-src/src/npe1_module1/__init__.py diff --git a/tests/conftest.py b/tests/conftest.py index d7c7991b..8e2b97a7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -68,6 +68,11 @@ def npe1_repo(): return Path(__file__).parent / "npe1-plugin" +@pytest.fixture +def npe1_repo1(): + return Path(__file__).parent / "npe1-plugin-src" + + @pytest.fixture def uses_npe1_plugin(npe1_repo): import site @@ -170,6 +175,38 @@ def _from_name(name): if (npe1_repo / "setup.py").exists(): (npe1_repo / "setup.py").unlink() +@pytest.fixture +def mock_npe1_src_pm_with_plugin(npe1_repo1, npe1_plugin_module): + """Mocks a fully installed local repository""" + from npe2._inspection._from_npe1 import plugin_packages + + mock_dist = metadata.PathDistribution(npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info") + assert (npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info").exists() + + def _dists(): + return [mock_dist] + + def _from_name(name): + if name == "npe1-plugin1": + return mock_dist + raise metadata.PackageNotFoundError(name) + + setup_cfg = npe1_repo1 / "setup.cfg" + new_manifest = npe1_repo1 / "src" / "npe1_module1" / "napari.yaml" + with patch.object(metadata, "distributions", new=_dists): + with patch.object(metadata.Distribution, "from_name", new=_from_name): + cfg = setup_cfg.read_text() + plugin_packages.cache_clear() + try: + yield mock_npe1_pm + finally: + plugin_packages.cache_clear() + setup_cfg.write_text(cfg) + if new_manifest.exists(): + new_manifest.unlink() + if (npe1_repo1 / "setup.py").exists(): + (npe1_repo1 / "setup.py").unlink() + @pytest.fixture(autouse=True) def mock_cache(tmp_path, monkeypatch): diff --git a/tests/npe1-plugin-src/setup.cfg b/tests/npe1-plugin-src/setup.cfg new file mode 100644 index 00000000..3b78f20d --- /dev/null +++ b/tests/npe1-plugin-src/setup.cfg @@ -0,0 +1,10 @@ +[metadata] +name = npe1-plugin1 +version = 0.1.0 + +[options.entry_points] +napari.plugin = + npe1-plugin1 = npe1_module1 + +[options.packages.find] +where = src \ No newline at end of file diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA new file mode 100644 index 00000000..d5950713 --- /dev/null +++ b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA @@ -0,0 +1,3 @@ +Metadata-Version: 2.1 +Name: npe1-plugin1 +Version: 0.1.0 diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt new file mode 100644 index 00000000..58596f9a --- /dev/null +++ b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt @@ -0,0 +1,2 @@ +[napari.plugin] +npe1-plugin1 = npe1_module1 diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt new file mode 100644 index 00000000..2b7d59af --- /dev/null +++ b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt @@ -0,0 +1 @@ +npe1_module1 diff --git a/tests/npe1-plugin-src/src/npe1_module1/__init__.py b/tests/npe1-plugin-src/src/npe1_module1/__init__.py new file mode 100644 index 00000000..2dfe0fe4 --- /dev/null +++ b/tests/npe1-plugin-src/src/npe1_module1/__init__.py @@ -0,0 +1,97 @@ +from functools import partial + +import numpy as np +from magicgui import magic_factory +from napari_plugin_engine import napari_hook_implementation + + +class MyWidget: + ... + + +def some_function(x: int): + ... + + +def gen_data(): + ... + + +@napari_hook_implementation +def napari_get_reader(path): + ... + + +@napari_hook_implementation +def napari_write_image(path, data, meta): + ... + + +@napari_hook_implementation +def napari_write_labels(path, data, meta): + ... + + +@napari_hook_implementation +def napari_provide_sample_data(): + return { + "random data": gen_data, + "local data": partial(np.ones, (4, 4)), + "random image": "https://picsum.photos/1024", + "sample_key": { + "display_name": "Some Random Data (512 x 512)", + "data": gen_data, + }, + "local_ones": { + "display_name": "Some local ones", + "data": partial(np.ones, (4, 4)), + }, + } + + +@napari_hook_implementation +def napari_experimental_provide_theme(): + return { + "super_dark": { + "name": "super_dark", + "background": "rgb(12, 12, 12)", + "foreground": "rgb(65, 72, 81)", + "primary": "rgb(90, 98, 108)", + "secondary": "rgb(134, 142, 147)", + "highlight": "rgb(106, 115, 128)", + "text": "rgb(240, 241, 242)", + "icon": "rgb(209, 210, 212)", + "warning": "rgb(153, 18, 31)", + "current": "rgb(0, 122, 204)", + "syntax_style": "native", + "console": "rgb(0, 0, 0)", + "canvas": "black", + }, + "pretty_light": { + "background": "rgb(192, 223, 139)", + }, + } + + +factory = magic_factory(some_function) + + +@napari_hook_implementation +def napari_experimental_provide_dock_widget(): + @magic_factory + def local_widget(y: str): + ... + + return [ + MyWidget, + (factory, {"name": "My Other Widget"}), + (local_widget, {"name": "Local Widget"}), + ] + + +@napari_hook_implementation +def napari_experimental_provide_function(): + def local_function(x: int): + ... + + return [some_function, local_function] diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 499c1f6f..9eb3bbd0 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -68,6 +68,21 @@ def test_conversion_from_package(npe1_repo, mock_npe1_pm_with_plugin): assert "Is this package already converted?" in str(e.value) +@pytest.mark.filterwarnings("ignore:Failed to convert napari_provide_sample_data") +@pytest.mark.filterwarnings("ignore:Error converting function") +@pytest.mark.filterwarnings("ignore:Error converting dock widget") +def test_conversion_from_package(npe1_repo1, mock_npe1_src_pm_with_plugin): + setup_cfg = npe1_repo1 / "setup.cfg" + before = setup_cfg.read_text() + convert_repository(npe1_repo1, dry_run=True) + assert setup_cfg.read_text() == before + assert not (npe1_repo1 / "src" / "npe1_module1" / "napari.yaml").exists() + convert_repository(npe1_repo1, dry_run=False) + new_setup = setup_cfg.read_text() + assert new_setup != before + assert (npe1_repo1 / "src" / "npe1_module1" / "napari.yaml").exists() + + def _assert_expected_errors(record: pytest.WarningsRecorder): assert len(record) == 4 msg = str(record[0].message) From be807564b099985bad784d82d580c382b8af9dc3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 1 Jun 2023 14:53:59 +0000 Subject: [PATCH 05/12] style: [pre-commit.ci] auto fixes [...] --- tests/conftest.py | 5 ++++- tests/npe1-plugin-src/setup.cfg | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8e2b97a7..f74dd2f9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -175,12 +175,15 @@ def _from_name(name): if (npe1_repo / "setup.py").exists(): (npe1_repo / "setup.py").unlink() + @pytest.fixture def mock_npe1_src_pm_with_plugin(npe1_repo1, npe1_plugin_module): """Mocks a fully installed local repository""" from npe2._inspection._from_npe1 import plugin_packages - mock_dist = metadata.PathDistribution(npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info") + mock_dist = metadata.PathDistribution( + npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info" + ) assert (npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info").exists() def _dists(): diff --git a/tests/npe1-plugin-src/setup.cfg b/tests/npe1-plugin-src/setup.cfg index 3b78f20d..85dd3821 100644 --- a/tests/npe1-plugin-src/setup.cfg +++ b/tests/npe1-plugin-src/setup.cfg @@ -7,4 +7,4 @@ napari.plugin = npe1-plugin1 = npe1_module1 [options.packages.find] -where = src \ No newline at end of file +where = src From cdc72205aa2925a4e8227d0a7ac382cbc2f7adf2 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 1 Jun 2023 16:55:52 +0200 Subject: [PATCH 06/12] rename test function --- tests/test_conversion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 9eb3bbd0..d5b50af9 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -71,7 +71,7 @@ def test_conversion_from_package(npe1_repo, mock_npe1_pm_with_plugin): @pytest.mark.filterwarnings("ignore:Failed to convert napari_provide_sample_data") @pytest.mark.filterwarnings("ignore:Error converting function") @pytest.mark.filterwarnings("ignore:Error converting dock widget") -def test_conversion_from_package(npe1_repo1, mock_npe1_src_pm_with_plugin): +def test_conversion_from_package_src(npe1_repo1, mock_npe1_src_pm_with_plugin): setup_cfg = npe1_repo1 / "setup.cfg" before = setup_cfg.read_text() convert_repository(npe1_repo1, dry_run=True) From 4d613c1fd7999d2b42cd8d8fe203073433a4f5ab Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 1 Jun 2023 20:47:47 +0200 Subject: [PATCH 07/12] fix test --- tests/conftest.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index f74dd2f9..a138addd 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -114,6 +114,23 @@ def npe1_plugin_module(npe1_repo): del sys.modules[spec.name] +@pytest.fixture +def npe1_plugin_src_module(npe1_repo1): + import sys + from importlib.util import module_from_spec, spec_from_file_location + + npe1_module_path = npe1_repo1 / "src" / "npe1_module1" / "__init__.py" + spec = spec_from_file_location("npe1_module1", npe1_module_path) + assert spec + module = module_from_spec(spec) + sys.modules[spec.name] = module + spec.loader.exec_module(module) # type: ignore + try: + yield module + finally: + del sys.modules[spec.name] + + @pytest.fixture def mock_npe1_pm(): from napari_plugin_engine import PluginManager, napari_hook_specification @@ -177,7 +194,7 @@ def _from_name(name): @pytest.fixture -def mock_npe1_src_pm_with_plugin(npe1_repo1, npe1_plugin_module): +def mock_npe1_src_pm_with_plugin(npe1_repo1, npe1_plugin_src_module): """Mocks a fully installed local repository""" from npe2._inspection._from_npe1 import plugin_packages From 746f7ae8e1deb98e2fa62e2e81f87ec35f0e7675 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 1 Jun 2023 23:36:48 +0200 Subject: [PATCH 08/12] remove wrong tests --- tests/conftest.py | 57 ---------------------------------------- tests/test_conversion.py | 15 ----------- 2 files changed, 72 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index a138addd..d7c7991b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -68,11 +68,6 @@ def npe1_repo(): return Path(__file__).parent / "npe1-plugin" -@pytest.fixture -def npe1_repo1(): - return Path(__file__).parent / "npe1-plugin-src" - - @pytest.fixture def uses_npe1_plugin(npe1_repo): import site @@ -114,23 +109,6 @@ def npe1_plugin_module(npe1_repo): del sys.modules[spec.name] -@pytest.fixture -def npe1_plugin_src_module(npe1_repo1): - import sys - from importlib.util import module_from_spec, spec_from_file_location - - npe1_module_path = npe1_repo1 / "src" / "npe1_module1" / "__init__.py" - spec = spec_from_file_location("npe1_module1", npe1_module_path) - assert spec - module = module_from_spec(spec) - sys.modules[spec.name] = module - spec.loader.exec_module(module) # type: ignore - try: - yield module - finally: - del sys.modules[spec.name] - - @pytest.fixture def mock_npe1_pm(): from napari_plugin_engine import PluginManager, napari_hook_specification @@ -193,41 +171,6 @@ def _from_name(name): (npe1_repo / "setup.py").unlink() -@pytest.fixture -def mock_npe1_src_pm_with_plugin(npe1_repo1, npe1_plugin_src_module): - """Mocks a fully installed local repository""" - from npe2._inspection._from_npe1 import plugin_packages - - mock_dist = metadata.PathDistribution( - npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info" - ) - assert (npe1_repo1 / "src" / "npe1-plugin1-0.0.1.dist-info").exists() - - def _dists(): - return [mock_dist] - - def _from_name(name): - if name == "npe1-plugin1": - return mock_dist - raise metadata.PackageNotFoundError(name) - - setup_cfg = npe1_repo1 / "setup.cfg" - new_manifest = npe1_repo1 / "src" / "npe1_module1" / "napari.yaml" - with patch.object(metadata, "distributions", new=_dists): - with patch.object(metadata.Distribution, "from_name", new=_from_name): - cfg = setup_cfg.read_text() - plugin_packages.cache_clear() - try: - yield mock_npe1_pm - finally: - plugin_packages.cache_clear() - setup_cfg.write_text(cfg) - if new_manifest.exists(): - new_manifest.unlink() - if (npe1_repo1 / "setup.py").exists(): - (npe1_repo1 / "setup.py").unlink() - - @pytest.fixture(autouse=True) def mock_cache(tmp_path, monkeypatch): with monkeypatch.context() as m: diff --git a/tests/test_conversion.py b/tests/test_conversion.py index d5b50af9..499c1f6f 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -68,21 +68,6 @@ def test_conversion_from_package(npe1_repo, mock_npe1_pm_with_plugin): assert "Is this package already converted?" in str(e.value) -@pytest.mark.filterwarnings("ignore:Failed to convert napari_provide_sample_data") -@pytest.mark.filterwarnings("ignore:Error converting function") -@pytest.mark.filterwarnings("ignore:Error converting dock widget") -def test_conversion_from_package_src(npe1_repo1, mock_npe1_src_pm_with_plugin): - setup_cfg = npe1_repo1 / "setup.cfg" - before = setup_cfg.read_text() - convert_repository(npe1_repo1, dry_run=True) - assert setup_cfg.read_text() == before - assert not (npe1_repo1 / "src" / "npe1_module1" / "napari.yaml").exists() - convert_repository(npe1_repo1, dry_run=False) - new_setup = setup_cfg.read_text() - assert new_setup != before - assert (npe1_repo1 / "src" / "npe1_module1" / "napari.yaml").exists() - - def _assert_expected_errors(record: pytest.WarningsRecorder): assert len(record) == 4 msg = str(record[0].message) From 575eea072735ec30f0bdd5810dab22d37dc061d7 Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Thu, 1 Jun 2023 23:39:26 +0200 Subject: [PATCH 09/12] remove wrong tests2 --- tests/npe1-plugin-src/setup.cfg | 10 -- .../src/npe1-plugin1-0.0.1.dist-info/METADATA | 3 - .../entry_points.txt | 2 - .../top_level.txt | 1 - .../src/npe1_module1/__init__.py | 97 ------------------- 5 files changed, 113 deletions(-) delete mode 100644 tests/npe1-plugin-src/setup.cfg delete mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA delete mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt delete mode 100644 tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt delete mode 100644 tests/npe1-plugin-src/src/npe1_module1/__init__.py diff --git a/tests/npe1-plugin-src/setup.cfg b/tests/npe1-plugin-src/setup.cfg deleted file mode 100644 index 85dd3821..00000000 --- a/tests/npe1-plugin-src/setup.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[metadata] -name = npe1-plugin1 -version = 0.1.0 - -[options.entry_points] -napari.plugin = - npe1-plugin1 = npe1_module1 - -[options.packages.find] -where = src diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA deleted file mode 100644 index d5950713..00000000 --- a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/METADATA +++ /dev/null @@ -1,3 +0,0 @@ -Metadata-Version: 2.1 -Name: npe1-plugin1 -Version: 0.1.0 diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt deleted file mode 100644 index 58596f9a..00000000 --- a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/entry_points.txt +++ /dev/null @@ -1,2 +0,0 @@ -[napari.plugin] -npe1-plugin1 = npe1_module1 diff --git a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt b/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt deleted file mode 100644 index 2b7d59af..00000000 --- a/tests/npe1-plugin-src/src/npe1-plugin1-0.0.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -npe1_module1 diff --git a/tests/npe1-plugin-src/src/npe1_module1/__init__.py b/tests/npe1-plugin-src/src/npe1_module1/__init__.py deleted file mode 100644 index 2dfe0fe4..00000000 --- a/tests/npe1-plugin-src/src/npe1_module1/__init__.py +++ /dev/null @@ -1,97 +0,0 @@ -from functools import partial - -import numpy as np -from magicgui import magic_factory -from napari_plugin_engine import napari_hook_implementation - - -class MyWidget: - ... - - -def some_function(x: int): - ... - - -def gen_data(): - ... - - -@napari_hook_implementation -def napari_get_reader(path): - ... - - -@napari_hook_implementation -def napari_write_image(path, data, meta): - ... - - -@napari_hook_implementation -def napari_write_labels(path, data, meta): - ... - - -@napari_hook_implementation -def napari_provide_sample_data(): - return { - "random data": gen_data, - "local data": partial(np.ones, (4, 4)), - "random image": "https://picsum.photos/1024", - "sample_key": { - "display_name": "Some Random Data (512 x 512)", - "data": gen_data, - }, - "local_ones": { - "display_name": "Some local ones", - "data": partial(np.ones, (4, 4)), - }, - } - - -@napari_hook_implementation -def napari_experimental_provide_theme(): - return { - "super_dark": { - "name": "super_dark", - "background": "rgb(12, 12, 12)", - "foreground": "rgb(65, 72, 81)", - "primary": "rgb(90, 98, 108)", - "secondary": "rgb(134, 142, 147)", - "highlight": "rgb(106, 115, 128)", - "text": "rgb(240, 241, 242)", - "icon": "rgb(209, 210, 212)", - "warning": "rgb(153, 18, 31)", - "current": "rgb(0, 122, 204)", - "syntax_style": "native", - "console": "rgb(0, 0, 0)", - "canvas": "black", - }, - "pretty_light": { - "background": "rgb(192, 223, 139)", - }, - } - - -factory = magic_factory(some_function) - - -@napari_hook_implementation -def napari_experimental_provide_dock_widget(): - @magic_factory - def local_widget(y: str): - ... - - return [ - MyWidget, - (factory, {"name": "My Other Widget"}), - (local_widget, {"name": "Local Widget"}), - ] - - -@napari_hook_implementation -def napari_experimental_provide_function(): - def local_function(x: int): - ... - - return [some_function, local_function] From bb7fadc14f63090a0fc37a673ba47eee4b60685f Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 2 Jun 2023 09:18:55 +0200 Subject: [PATCH 10/12] add test for editable --- tests/conftest.py | 50 +++++++++++++++++++ .../npe1-plugin-0.0.1.dist-info/RECORD | 5 ++ tests/test_conversion.py | 24 +++++++++ 3 files changed, 79 insertions(+) create mode 100644 tests/npe1-plugin/npe1-plugin-0.0.1.dist-info/RECORD diff --git a/tests/conftest.py b/tests/conftest.py index d7c7991b..b4eed5de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,5 +1,6 @@ import shutil import sys +import shutil from importlib import abc, metadata from pathlib import Path from unittest.mock import patch @@ -171,6 +172,55 @@ def _from_name(name): (npe1_repo / "setup.py").unlink() +@pytest.fixture +def mock_npe1_pm_with_plugin_editable(npe1_repo, npe1_plugin_module, tmp_path): + """Mocks a fully installed local repository""" + from npe2._inspection._from_npe1 import plugin_packages + + dist_path = tmp_path / "npe1-plugin-0.0.1.dist-info" + shutil.copytree(npe1_repo / "npe1-plugin-0.0.1.dist-info", dist_path) + + record_path = dist_path / "RECORD" + + record_content = record_path.read_text().splitlines() + record_content.pop(-1) + record_content.append("__editable__.npe1-plugin-0.0.1.pth") + + with record_path.open("w") as f: + f.write("\n".join(record_content)) + + with open(tmp_path / "__editable__.npe1-plugin-0.0.1.pth", "w") as f: + f.write(str(npe1_repo)) + + + mock_dist = metadata.PathDistribution(dist_path) + + def _dists(): + return [mock_dist] + + def _from_name(name): + if name == "npe1-plugin": + return mock_dist + raise metadata.PackageNotFoundError(name) + + setup_cfg = npe1_repo / "setup.cfg" + new_manifest = npe1_repo / "npe1_module" / "napari.yaml" + with patch.object(metadata, "distributions", new=_dists): + with patch.object(metadata.Distribution, "from_name", new=_from_name): + cfg = setup_cfg.read_text() + plugin_packages.cache_clear() + try: + yield mock_npe1_pm + finally: + plugin_packages.cache_clear() + setup_cfg.write_text(cfg) + if new_manifest.exists(): + new_manifest.unlink() + if (npe1_repo / "setup.py").exists(): + (npe1_repo / "setup.py").unlink() + + + @pytest.fixture(autouse=True) def mock_cache(tmp_path, monkeypatch): with monkeypatch.context() as m: diff --git a/tests/npe1-plugin/npe1-plugin-0.0.1.dist-info/RECORD b/tests/npe1-plugin/npe1-plugin-0.0.1.dist-info/RECORD new file mode 100644 index 00000000..f0f82af7 --- /dev/null +++ b/tests/npe1-plugin/npe1-plugin-0.0.1.dist-info/RECORD @@ -0,0 +1,5 @@ +npe1-plugin-0.0.1.dist-info/RECORD,, +npe1-plugin-0.0.1.dist-info/METADATA,, +npe1-plugin-0.0.1.dist-info/top_level.txt,, +npe1-plugin-0.0.1.dist-info/entry_points.txt,, +../npe1_module/__init__.py,, diff --git a/tests/test_conversion.py b/tests/test_conversion.py index 499c1f6f..4f179dc5 100644 --- a/tests/test_conversion.py +++ b/tests/test_conversion.py @@ -68,6 +68,30 @@ def test_conversion_from_package(npe1_repo, mock_npe1_pm_with_plugin): assert "Is this package already converted?" in str(e.value) +@pytest.mark.filterwarnings("ignore:Failed to convert napari_provide_sample_data") +@pytest.mark.filterwarnings("ignore:Error converting function") +@pytest.mark.filterwarnings("ignore:Error converting dock widget") +def test_conversion_from_package_editable(npe1_repo, mock_npe1_pm_with_plugin_editable): + setup_cfg = npe1_repo / "setup.cfg" + before = setup_cfg.read_text() + convert_repository(npe1_repo, dry_run=True) + assert setup_cfg.read_text() == before + assert not (npe1_repo / "npe1_module" / "napari.yaml").exists() + convert_repository(npe1_repo, dry_run=False) + new_setup = setup_cfg.read_text() + assert new_setup != before + assert ( + "[options.entry_points]\n" + "napari.manifest = \n npe1-plugin = npe1_module:napari.yaml" + ) in new_setup + assert "[options.package_data]\nnpe1_module = napari.yaml" in new_setup + assert (npe1_repo / "npe1_module" / "napari.yaml").is_file() + + with pytest.raises(ValueError) as e: + convert_repository(npe1_repo) + assert "Is this package already converted?" in str(e.value) + + def _assert_expected_errors(record: pytest.WarningsRecorder): assert len(record) == 4 msg = str(record[0].message) From 5f453c6a826d4e3590c4df22295edc90156b3f91 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 2 Jun 2023 07:19:12 +0000 Subject: [PATCH 11/12] style: [pre-commit.ci] auto fixes [...] --- tests/conftest.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index b4eed5de..4708bb24 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,5 @@ import shutil import sys -import shutil from importlib import abc, metadata from pathlib import Path from unittest.mock import patch @@ -188,11 +187,10 @@ def mock_npe1_pm_with_plugin_editable(npe1_repo, npe1_plugin_module, tmp_path): with record_path.open("w") as f: f.write("\n".join(record_content)) - + with open(tmp_path / "__editable__.npe1-plugin-0.0.1.pth", "w") as f: f.write(str(npe1_repo)) - mock_dist = metadata.PathDistribution(dist_path) def _dists(): @@ -220,7 +218,6 @@ def _from_name(name): (npe1_repo / "setup.py").unlink() - @pytest.fixture(autouse=True) def mock_cache(tmp_path, monkeypatch): with monkeypatch.context() as m: From 6482bc74f96cc48bf855e94f72b7170c18b06d6c Mon Sep 17 00:00:00 2001 From: Grzegorz Bokota Date: Fri, 2 Jun 2023 09:45:28 +0200 Subject: [PATCH 12/12] ommit coverage of __main__.py --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 84e21812..2cdd35a0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -148,6 +148,7 @@ source = ["src"] omit = [ "src/npe2/manifest/contributions/_keybindings.py", "src/npe2/manifest/menus.py", + "src/npe2/__main__.py", "src/npe2/manifest/package_metadata.py", # due to all of the isolated sub-environments and sub-processes, # it's really hard to get coverage on the setuptools plugin.