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()
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())
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()
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())
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))
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'
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()
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)
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)
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()
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())
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())
#!/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())
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)