Beispiel #1
0
def test_cli_retains_viewer_ref(mock_run, monkeypatch, make_napari_viewer):
    """Test that napari.__main__ is retaining a reference to the viewer."""
    v = make_napari_viewer()  # our mock view_path will return this object
    ref_count = None  # counter that will be updated before __main__._run()

    def _check_refs(**kwargs):
        # when run() is called in napari.__main__, we will call this function
        # it forces garbage collection, and then makes sure that at least one
        # additional reference to our viewer exists.
        gc.collect()
        if sys.getrefcount(v) <= ref_count:
            raise AssertionError(
                "Reference to napari.viewer has been lost by "
                "the time the event loop started in napari.__main__"
            )

    mock_run.side_effect = _check_refs
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['napari', 'path/to/file.tif'])
        # return our local v
        with mock.patch('napari.Viewer', return_value=v) as mock_viewer:
            ref_count = sys.getrefcount(v)  # count current references
            # mock gui open so we're not opening dialogs/throwing errors on fake path
            with mock.patch(
                'napari._qt.qt_viewer.QtViewer._qt_open', return_value=None
            ) as mock_viewer_open:
                __main__._run()
            mock_viewer.assert_called_once()
            mock_viewer_open.assert_called_once()
Beispiel #2
0
def test_cli_shows_plugins(napari_plugin_manager, monkeypatch, capsys):
    """Test the cli --info runs and shows plugins"""
    monkeypatch.setattr(sys, 'argv', ['napari', '--info'])
    with pytest.raises(SystemExit):
        __main__._run()
    # this is because sckit-image is OUR builtin providing sample_data
    assert 'scikit-image' in str(capsys.readouterr())
Beispiel #3
0
def test_cli_retains_viewer_ref(mock_run, monkeypatch):
    """Test that napari.__main__ is retaining a reference to the viewer."""
    v = napari.Viewer(show=False)  # our mock view_path will return this object
    ref_count = None  # counter that will be updated before __main__._run()

    def _check_refs(**kwargs):
        # when run() is called in napari.__main__, we will call this function
        # it forces garbage collection, and then makes sure that at least one
        # additional reference to our viewer exists.
        gc.collect()
        if not sys.getrefcount(v) > ref_count:
            raise AssertionError(
                "Reference to napari.viewer has been lost by "
                "the time the event loop started in napari.__main__")

    mock_run.side_effect = _check_refs
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['napari', 'path/to/file.tif'])
        with mock.patch(
                'napari.__main__.view_path',
                return_value=v  # return our local v
        ) as mock_vp:
            ref_count = sys.getrefcount(v)  # count current references
            __main__._run()
            mock_vp.assert_called_once()
Beispiel #4
0
def test_cli_shows_plugins(monkeypatch, capsys):
    """Test the cli --info runs and shows plugins"""
    monkeypatch.setattr(napari.plugins, 'dock_widgets', dict())
    monkeypatch.setattr(napari.plugins, 'function_widgets', dict())
    monkeypatch.setattr(sys, 'argv', ['napari', '--info'])
    with pytest.raises(SystemExit):
        __main__._run()
    assert 'svg' in str(capsys.readouterr())
Beispiel #5
0
def test_cli_runscript(run_path, monkeypatch, tmp_path):
    """Test that running napari script.py runs a script"""
    script = tmp_path / 'test.py'
    script.write_text('import napari; v = napari.Viewer(show=False)')

    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['napari', str(script)])
        __main__._run()

    run_path.assert_called_once_with(str(script))
Beispiel #6
0
def test_cli_raises(monkeypatch):
    """test that unknown kwargs raise the correct errors."""
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['napari', 'path/to/file', '--nonsense'])
        with pytest.raises(SystemExit) as e:
            __main__._run()
        assert str(e.value) == 'error: unrecognized arguments: --nonsense'

    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['napari', 'path/to/file', '--gamma'])
        with pytest.raises(SystemExit) as e:
            __main__._run()
        assert str(e.value) == 'error: argument --gamma expected one argument'
Beispiel #7
0
def test_cli_parses_unknowns(mock_run, monkeypatch, make_napari_viewer):
    """test that we can parse layer keyword arg variants"""
    v = make_napari_viewer()  # our mock view_path will return this object

    def assert_kwargs(*args, **kwargs):
        assert ["file"] in args
        assert kwargs['contrast_limits'] == (0, 1)

    # testing all the variants of literal_evals
    with mock.patch('napari.Viewer', return_value=v):
        monkeypatch.setattr(
            napari.components.viewer_model.ViewerModel, 'open', assert_kwargs
        )
        with monkeypatch.context() as m:
            m.setattr(
                sys, 'argv', ['n', 'file', '--contrast-limits', '(0, 1)']
            )
            __main__._run()
        with monkeypatch.context() as m:
            m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits', '(0,1)'])
            __main__._run()
        with monkeypatch.context() as m:
            m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits=(0, 1)'])
            __main__._run()
        with monkeypatch.context() as m:
            m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits=(0,1)'])
            __main__._run()
Beispiel #8
0
def test_cli_passes_kwargs(view_path, mock_run, monkeypatch):
    """test that we can parse layer keyword arg variants"""

    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['n', 'file', '--name', 'some name'])
        __main__._run()

    view_path.assert_called_once_with(
        ['file'],
        stack=False,
        plugin=None,
        layer_type=None,
        name='some name',
    )
    mock_run.assert_called_once_with(gui_exceptions=True)
Beispiel #9
0
def test_cli_passes_kwargs(qt_open, mock_run, monkeypatch, make_napari_viewer):
    """test that we can parse layer keyword arg variants"""
    v = make_napari_viewer()

    with mock.patch('napari.Viewer', return_value=v):
        with monkeypatch.context() as m:
            m.setattr(sys, 'argv', ['n', 'file', '--name', 'some name'])
            __main__._run()

    qt_open.assert_called_once_with(
        ['file'],
        stack=False,
        plugin=None,
        layer_type=None,
        name='some name',
    )
    mock_run.assert_called_once_with(gui_exceptions=True)
Beispiel #10
0
def test_cli_parses_unknowns(mock_run, monkeypatch):
    """test that we can parse layer keyword arg variants"""
    def assert_kwargs(*args, **kwargs):
        assert args == (["file"], )
        assert kwargs['contrast_limits'] == (0, 1)

    # testing all the variants of literal_evals
    monkeypatch.setattr(napari, 'view_path', assert_kwargs)
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits', '(0, 1)'])
        __main__._run()
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits', '(0,1)'])
        __main__._run()
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits=(0, 1)'])
        __main__._run()
    with monkeypatch.context() as m:
        m.setattr(sys, 'argv', ['n', 'file', '--contrast-limits=(0,1)'])
        __main__._run()
Beispiel #11
0
def test_cli_shows_plugins(monkeypatch, capsys, tmp_plugin):
    """Test the cli --info runs and shows plugins"""
    monkeypatch.setattr(sys, 'argv', ['napari', '--info'])
    with pytest.raises(SystemExit):
        __main__._run()
    assert tmp_plugin.name in str(capsys.readouterr())
Beispiel #12
0
def test_cli_works(monkeypatch, capsys):
    """Test the cli runs and shows help"""
    monkeypatch.setattr(sys, 'argv', ['napari', '-h'])
    with pytest.raises(SystemExit):
        __main__._run()
    assert 'napari command line viewer.' in str(capsys.readouterr())
Beispiel #13
0
#!/usr/bin/env python3
import re
import sys
from napari.__main__ import _run

if __name__ == '__main__':
    print(sys.argv[0])
    # sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
    sys.exit(_run())
Beispiel #14
0
def run_napari(dataset_name, usage=False):
    def none():
        return napari.Viewer()

    def num():
        images = [create_text_array(x) for x in range(20)]
        data = np.stack(images, axis=0)
        return napari.view_image(data, rgb=True, name='numbered slices')

    def num_tiled():
        size = (1000, 1030)
        images = [create_tiled_text_array(x, 16, 16, size) for x in range(5)]
        data = np.stack(images, axis=0)
        return napari.view_image(data, rgb=True, name='numbered slices')

    def num_tiled_1():
        size = (1024, 1024)
        images = [create_tiled_test_1(x, 16, 1, size) for x in range(5)]
        data = np.stack(images, axis=0)
        return napari.view_image(data, rgb=True, name='numbered slices')

    def num_tiny():
        images = [create_text_array(x, size=(16, 16)) for x in range(20)]
        data = np.stack(images, axis=0)
        return napari.view_image(data, rgb=True, name='numbered slices')

    def num_16():
        num_slices = 25
        data = create_grid_stack(4, 4, num_slices)
        names = [f"layer {n}" for n in range(num_slices)]
        return napari.view_image(data, name=names, channel_axis=0)

    def num_16_0():
        num_slices = 25
        data = create_grid_stack(4, 4, num_slices, 0)
        names = [f"layer {n}" for n in range(num_slices)]
        return napari.view_image(data, name=names, channel_axis=0)

    def num_4():
        num_slices = 25
        data = create_grid_stack(2, 2, num_slices)
        names = [f"layer {n}" for n in range(num_slices)]
        return napari.view_image(data, name=names, channel_axis=0)

    def num_1():
        num_slices = 25
        data = create_grid_stack(1, 1, num_slices)
        names = [f"layer {n}" for n in range(num_slices)]
        return napari.view_image(data, name=names, channel_axis=0)

    def num_delayed():
        data = create_stack(20, 1)
        return napari.view_image(data, name='delayed (1 second)')

    def num_delayed0():
        data = create_stack(20, 0)
        return napari.view_image(data, name='zero delay')

    def num_mixed():
        data = create_stack_mixed(20)
        return napari.view_image(data, name='zero delay')

    def num_2():
        data = add_delay(create_text_array("one"), 1)
        return napari.view_image(data, name='numbered slices', channel_axis=0)

    def async_3d():
        data = da.random.random((200, 512, 512, 512),
                                chunks=(1, 512, 512, 512))
        return napari.view_image(data, name='async_3d', channel_axis=0)

    def async_3d_small():
        data = da.random.random((5, 512, 512, 512), chunks=(1, 512, 512, 512))
        return napari.view_image(data, name='async_3d_small', channel_axis=0)

    def invisible():
        return napari.view_image(
            np.random.random((5, 1024, 1024)),
            name='five 1k images',
            visible=False,
        )

    def noise():
        return napari.view_image(np.random.random((5, 1024, 1024)),
                                 name='five 1k images')

    def big8():
        return napari.view_image(np.random.random((2, 8192, 8192)),
                                 name='two 8k 2d images')

    def big16():
        return napari.view_image(np.random.random((2, 16384, 16384)),
                                 name='two 16k 2d images')

    def big2d():
        return napari.view_image(np.random.random((21, 8192, 8192)),
                                 name='big 2D timeseries')

    def big3d():
        return napari.view_image(
            np.random.random((6, 256, 512, 512)),
            ndisplay=3,
            name='big 3D timeseries',
        )

    def small3d():
        return napari.view_image(
            np.random.random((3, 64, 64, 64)),
            ndisplay=3,
            name='small 3D timeseries',
        )

    def labels():
        return napari.view_labels(
            np.random.randint(10, size=(20, 2048, 2048)),
            name='big labels timeseries',
        )

    def multi_rand():
        shapes = [
            (167424, 79360),
            (83712, 39680),
            (41856, 19840),
            (20928, 9920),
            (10464, 4960),
            (5232, 2480),
            (2616, 1240),
            (1308, 620),
            (654, 310),
            (327, 155),
            (163, 77),
        ]
        pyramid = [da.random.random(s) for s in shapes]
        return napari.view_image(pyramid)

    def multi_zarr():
        path = 'https://s3.embassy.ebi.ac.uk/idr/zarr/v0.1/9822151.zarr'
        resolutions = [
            da.from_zarr(path, component=str(i))[0, 0, 0]
            for i in list(range(11))
        ]
        return napari.view_image(resolutions)

    def astronaut():
        from skimage import data

        return napari.view_image(data.astronaut(), rgb=True)

    REMOTE_SMALL_URL = (
        "https://s3.embassy.ebi.ac.uk/idr/zarr/v0.1/6001240.zarr")
    DATASETS = {
        "none": none,
        "num": num,
        "num_tiled": num_tiled,
        "num_tiny": num_tiny,
        "num_16": num_16,
        "num_16_0": num_16_0,
        "num_4": num_4,
        "num_2": num_2,
        "num_1": num_1,
        "num_delayed": num_delayed,
        "num_delayed0": num_delayed0,
        "num_mixed": num_mixed,
        "async_3d": async_3d,
        "async_3d_small": async_3d_small,
        "invisible": invisible,
        "noise": noise,
        "big8": big8,
        "big16": big16,
        "big2pd": big2d,
        "big3d": big3d,
        "small3d": small3d,
        "labels": labels,
        "remote": "https://s3.embassy.ebi.ac.uk/idr/zarr/v0.1/4495402.zarr",
        "remote-small": REMOTE_SMALL_URL,
        "big": "/data-ext/4495402.zarr",
        "small": "/Users/pbw/data/6001240.zarr",
        "multi_zarr": multi_zarr,
        "multi_rand": multi_rand,
        "astronaut": astronaut,
    }

    if usage:
        print('\n'.join(DATASETS.keys()))
        return 2

    if dataset_name is None:
        import napari
        from napari.__main__ import _run

        sys.argv = sys.argv[:1]

        with napari.gui_qt():
            _run()
    else:
        data_set = DATASETS[dataset_name]

        if isinstance(data_set, str):
            # Import late so it sees our env vars.
            from napari.__main__ import main as napari_main

            print(f"LOADING {dataset_name}: {data_set}")

            sys.argv[1] = data_set
            sys.exit(napari_main())

        else:
            # Import late so it sees our env vars.
            import napari

            # The DATASET is factory that creates a viewer.
            viewer_factory = data_set

            print(f"Starting napari with: {dataset_name}")

            # It's a callable function
            with napari.gui_qt():
                viewer = viewer_factory()
                print(viewer._title)