napari-plugin-manager 0.1.6__py3-none-any.whl → 0.1.8__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- napari_plugin_manager/_tests/conftest.py +10 -10
- napari_plugin_manager/_tests/test_installer_process.py +123 -82
- napari_plugin_manager/_tests/test_npe2api.py +12 -11
- napari_plugin_manager/_tests/test_qt_plugin_dialog.py +91 -93
- napari_plugin_manager/_tests/test_utils.py +7 -7
- napari_plugin_manager/_version.py +16 -3
- napari_plugin_manager/base_qt_package_installer.py +144 -68
- napari_plugin_manager/base_qt_plugin_dialog.py +176 -157
- napari_plugin_manager/npe2api.py +3 -3
- napari_plugin_manager/qt_package_installer.py +44 -16
- napari_plugin_manager/qt_plugin_dialog.py +40 -30
- napari_plugin_manager/qt_warning_dialog.py +5 -3
- napari_plugin_manager/qt_widgets.py +3 -3
- napari_plugin_manager/styles.qss +30 -13
- napari_plugin_manager/utils.py +3 -3
- {napari_plugin_manager-0.1.6.dist-info → napari_plugin_manager-0.1.8.dist-info}/METADATA +8 -35
- napari_plugin_manager-0.1.8.dist-info/RECORD +23 -0
- {napari_plugin_manager-0.1.6.dist-info → napari_plugin_manager-0.1.8.dist-info}/WHEEL +1 -1
- napari_plugin_manager-0.1.6.dist-info/RECORD +0 -23
- {napari_plugin_manager-0.1.6.dist-info → napari_plugin_manager-0.1.8.dist-info}/licenses/LICENSE +0 -0
- {napari_plugin_manager-0.1.6.dist-info → napari_plugin_manager-0.1.8.dist-info}/top_level.txt +0 -0
|
@@ -10,17 +10,17 @@ from napari_plugin_manager.qt_package_installer import CondaInstallerTool
|
|
|
10
10
|
@pytest.fixture(autouse=True)
|
|
11
11
|
def _block_message_box(monkeypatch, request):
|
|
12
12
|
def raise_on_call(*_, **__):
|
|
13
|
-
raise RuntimeError(
|
|
14
|
-
|
|
15
|
-
monkeypatch.setattr(QMessageBox,
|
|
16
|
-
monkeypatch.setattr(QMessageBox,
|
|
17
|
-
monkeypatch.setattr(QMessageBox,
|
|
18
|
-
monkeypatch.setattr(QMessageBox,
|
|
19
|
-
monkeypatch.setattr(QMessageBox,
|
|
20
|
-
monkeypatch.setattr(QInputDialog,
|
|
13
|
+
raise RuntimeError('exec_ call') # pragma: no cover
|
|
14
|
+
|
|
15
|
+
monkeypatch.setattr(QMessageBox, 'exec_', raise_on_call)
|
|
16
|
+
monkeypatch.setattr(QMessageBox, 'critical', raise_on_call)
|
|
17
|
+
monkeypatch.setattr(QMessageBox, 'information', raise_on_call)
|
|
18
|
+
monkeypatch.setattr(QMessageBox, 'question', raise_on_call)
|
|
19
|
+
monkeypatch.setattr(QMessageBox, 'warning', raise_on_call)
|
|
20
|
+
monkeypatch.setattr(QInputDialog, 'getText', raise_on_call)
|
|
21
21
|
# QDialogs can be allowed via a marker; only raise if not decorated
|
|
22
|
-
if
|
|
23
|
-
monkeypatch.setattr(QDialog,
|
|
22
|
+
if 'enabledialog' not in request.keywords:
|
|
23
|
+
monkeypatch.setattr(QDialog, 'exec_', raise_on_call)
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
if TYPE_CHECKING:
|
|
@@ -19,6 +19,7 @@ from napari_plugin_manager.qt_package_installer import (
|
|
|
19
19
|
NapariCondaInstallerTool,
|
|
20
20
|
NapariInstallerQueue,
|
|
21
21
|
NapariPipInstallerTool,
|
|
22
|
+
NapariUvInstallerTool,
|
|
22
23
|
)
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
@@ -34,7 +35,7 @@ def _assert_exit_code_not_zero(
|
|
|
34
35
|
if error is not None:
|
|
35
36
|
errors.append("- 'error' should have been None!")
|
|
36
37
|
if errors:
|
|
37
|
-
raise AssertionError(
|
|
38
|
+
raise AssertionError('\n'.join(errors))
|
|
38
39
|
return self._on_process_done_original(exit_code, exit_status, error)
|
|
39
40
|
|
|
40
41
|
|
|
@@ -45,13 +46,13 @@ def _assert_error_used(self, exit_code=None, exit_status=None, error=None):
|
|
|
45
46
|
if exit_code is not None:
|
|
46
47
|
errors.append("- 'exit_code' should not have been populated!")
|
|
47
48
|
if errors:
|
|
48
|
-
raise AssertionError(
|
|
49
|
+
raise AssertionError('\n'.join(errors))
|
|
49
50
|
return self._on_process_done_original(exit_code, exit_status, error)
|
|
50
51
|
|
|
51
52
|
|
|
52
53
|
class _NonExistingTool(AbstractInstallerTool):
|
|
53
54
|
def executable(self):
|
|
54
|
-
return f
|
|
55
|
+
return f'this-tool-does-not-exist-{hash(time.time())}'
|
|
55
56
|
|
|
56
57
|
def arguments(self):
|
|
57
58
|
return ()
|
|
@@ -60,32 +61,52 @@ class _NonExistingTool(AbstractInstallerTool):
|
|
|
60
61
|
return QProcessEnvironment.systemEnvironment()
|
|
61
62
|
|
|
62
63
|
|
|
64
|
+
@pytest.fixture
|
|
65
|
+
def patch_tool_executable(request):
|
|
66
|
+
mp = request.getfixturevalue('monkeypatch')
|
|
67
|
+
venv = request.getfixturevalue('tmp_virtualenv')
|
|
68
|
+
tool = request.getfixturevalue('tool')
|
|
69
|
+
mp.setattr(
|
|
70
|
+
tool,
|
|
71
|
+
'executable'
|
|
72
|
+
if tool == NapariPipInstallerTool
|
|
73
|
+
else '_python_executable',
|
|
74
|
+
lambda *a: venv.creator.exe,
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@pytest.mark.parametrize(
|
|
79
|
+
'tool', [NapariPipInstallerTool, NapariUvInstallerTool]
|
|
80
|
+
)
|
|
63
81
|
def test_pip_installer_tasks(
|
|
64
|
-
qtbot,
|
|
82
|
+
qtbot,
|
|
83
|
+
tool,
|
|
84
|
+
tmp_virtualenv: 'Session',
|
|
85
|
+
monkeypatch,
|
|
86
|
+
caplog,
|
|
87
|
+
patch_tool_executable,
|
|
65
88
|
):
|
|
66
89
|
caplog.set_level(logging.DEBUG, logger=bqpi.__name__)
|
|
67
|
-
installer = NapariInstallerQueue()
|
|
68
90
|
monkeypatch.setattr(
|
|
69
|
-
|
|
70
|
-
"executable",
|
|
71
|
-
lambda *a: tmp_virtualenv.creator.exe,
|
|
91
|
+
NapariInstallerQueue, 'PYPI_INSTALLER_TOOL_CLASS', tool
|
|
72
92
|
)
|
|
93
|
+
installer = NapariInstallerQueue()
|
|
73
94
|
monkeypatch.setattr(
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
(
|
|
95
|
+
tool,
|
|
96
|
+
'origins',
|
|
97
|
+
('https://pypi.org/simple',),
|
|
77
98
|
)
|
|
78
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
99
|
+
with qtbot.waitSignal(installer.allFinished, timeout=30_000):
|
|
79
100
|
installer.install(
|
|
80
|
-
tool=InstallerTools.
|
|
101
|
+
tool=InstallerTools.PYPI,
|
|
81
102
|
pkgs=['pip-install-test'],
|
|
82
103
|
)
|
|
83
104
|
installer.install(
|
|
84
|
-
tool=InstallerTools.
|
|
105
|
+
tool=InstallerTools.PYPI,
|
|
85
106
|
pkgs=['typing-extensions'],
|
|
86
107
|
)
|
|
87
108
|
job_id = installer.install(
|
|
88
|
-
tool=InstallerTools.
|
|
109
|
+
tool=InstallerTools.PYPI,
|
|
89
110
|
pkgs=['requests'],
|
|
90
111
|
)
|
|
91
112
|
assert isinstance(job_id, int)
|
|
@@ -104,74 +125,82 @@ def test_pip_installer_tasks(
|
|
|
104
125
|
|
|
105
126
|
assert pkgs >= 2, 'package was not installed'
|
|
106
127
|
|
|
107
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
128
|
+
with qtbot.waitSignal(installer.allFinished, timeout=30_000):
|
|
108
129
|
job_id = installer.uninstall(
|
|
109
|
-
tool=InstallerTools.
|
|
130
|
+
tool=InstallerTools.PYPI,
|
|
110
131
|
pkgs=['pip-install-test'],
|
|
111
132
|
)
|
|
112
133
|
|
|
113
134
|
for pth in tmp_virtualenv.creator.libs:
|
|
114
|
-
assert not (
|
|
115
|
-
|
|
116
|
-
)
|
|
135
|
+
assert not (pth / 'pip_install_test').exists(), (
|
|
136
|
+
'pip_install_test still installed'
|
|
137
|
+
)
|
|
117
138
|
assert not installer.hasJobs()
|
|
118
139
|
|
|
119
140
|
# Test new signals
|
|
120
|
-
with qtbot.waitSignal(
|
|
141
|
+
with qtbot.waitSignal(
|
|
142
|
+
installer.processFinished, timeout=30_000
|
|
143
|
+
) as blocker:
|
|
121
144
|
installer.install(
|
|
122
|
-
tool=InstallerTools.
|
|
145
|
+
tool=InstallerTools.PYPI,
|
|
123
146
|
pkgs=['pydantic'],
|
|
124
147
|
)
|
|
125
148
|
process_finished_data = blocker.args[0]
|
|
126
149
|
assert process_finished_data['action'] == InstallerActions.INSTALL
|
|
127
|
-
assert process_finished_data['pkgs'] ==
|
|
150
|
+
assert process_finished_data['pkgs'] == ('pydantic',)
|
|
128
151
|
|
|
129
152
|
# Test upgrade
|
|
130
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
153
|
+
with qtbot.waitSignal(installer.allFinished, timeout=30_000):
|
|
131
154
|
installer.install(
|
|
132
|
-
tool=InstallerTools.
|
|
155
|
+
tool=InstallerTools.PYPI,
|
|
133
156
|
pkgs=['requests==2.30.0'],
|
|
134
157
|
)
|
|
135
158
|
installer.upgrade(
|
|
136
|
-
tool=InstallerTools.
|
|
159
|
+
tool=InstallerTools.PYPI,
|
|
137
160
|
pkgs=['requests'],
|
|
138
161
|
)
|
|
139
162
|
|
|
140
163
|
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
@pytest.mark.parametrize(
|
|
165
|
+
'tool', [NapariPipInstallerTool, NapariUvInstallerTool]
|
|
166
|
+
)
|
|
167
|
+
def test_pip_installer_invalid_action(
|
|
168
|
+
tool, tmp_virtualenv: 'Session', monkeypatch, patch_tool_executable
|
|
169
|
+
):
|
|
143
170
|
monkeypatch.setattr(
|
|
144
|
-
|
|
145
|
-
"executable",
|
|
146
|
-
lambda *a: tmp_virtualenv.creator.exe,
|
|
171
|
+
NapariInstallerQueue, 'PYPI_INSTALLER_TOOL_CLASS', tool
|
|
147
172
|
)
|
|
173
|
+
installer = NapariInstallerQueue()
|
|
148
174
|
invalid_action = 'Invalid Action'
|
|
175
|
+
item = installer._build_queue_item(
|
|
176
|
+
tool=InstallerTools.PYPI,
|
|
177
|
+
action=invalid_action,
|
|
178
|
+
pkgs=['pip-install-test'],
|
|
179
|
+
prefix=None,
|
|
180
|
+
origins=(),
|
|
181
|
+
process=installer._create_process(),
|
|
182
|
+
)
|
|
149
183
|
with pytest.raises(
|
|
150
184
|
ValueError, match=f"Action '{invalid_action}' not supported!"
|
|
151
185
|
):
|
|
152
|
-
item = installer._build_queue_item(
|
|
153
|
-
tool=InstallerTools.PIP,
|
|
154
|
-
action=invalid_action,
|
|
155
|
-
pkgs=['pip-install-test'],
|
|
156
|
-
prefix=None,
|
|
157
|
-
origins=(),
|
|
158
|
-
process=installer._create_process(),
|
|
159
|
-
)
|
|
160
186
|
installer._queue_item(item)
|
|
161
187
|
|
|
162
188
|
|
|
163
|
-
|
|
164
|
-
|
|
189
|
+
@pytest.mark.parametrize(
|
|
190
|
+
'tool', [NapariPipInstallerTool, NapariUvInstallerTool]
|
|
191
|
+
)
|
|
192
|
+
def test_installer_failures(
|
|
193
|
+
tool, qtbot, tmp_virtualenv: 'Session', monkeypatch, patch_tool_executable
|
|
194
|
+
):
|
|
165
195
|
monkeypatch.setattr(
|
|
166
|
-
|
|
167
|
-
"executable",
|
|
168
|
-
lambda *a: tmp_virtualenv.creator.exe,
|
|
196
|
+
NapariInstallerQueue, 'PYPI_INSTALLER_TOOL_CLASS', tool
|
|
169
197
|
)
|
|
198
|
+
installer = NapariInstallerQueue()
|
|
170
199
|
|
|
171
200
|
# CHECK 1) Errors should trigger finished and allFinished too
|
|
172
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
201
|
+
with qtbot.waitSignal(installer.allFinished, timeout=10_000):
|
|
173
202
|
installer.install(
|
|
174
|
-
tool=InstallerTools.
|
|
203
|
+
tool=InstallerTools.PYPI,
|
|
175
204
|
pkgs=[f'this-package-does-not-exist-{hash(time.time())}'],
|
|
176
205
|
)
|
|
177
206
|
|
|
@@ -181,51 +210,57 @@ def test_installer_failures(qtbot, tmp_virtualenv: 'Session', monkeypatch):
|
|
|
181
210
|
# CHECK 2) Non-existing packages should return non-zero
|
|
182
211
|
monkeypatch.setattr(
|
|
183
212
|
installer,
|
|
184
|
-
|
|
213
|
+
'_on_process_done',
|
|
185
214
|
MethodType(_assert_exit_code_not_zero, installer),
|
|
186
215
|
)
|
|
187
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
216
|
+
with qtbot.waitSignal(installer.allFinished, timeout=10_000):
|
|
188
217
|
installer.install(
|
|
189
|
-
tool=InstallerTools.
|
|
218
|
+
tool=InstallerTools.PYPI,
|
|
190
219
|
pkgs=[f'this-package-does-not-exist-{hash(time.time())}'],
|
|
191
220
|
)
|
|
192
221
|
|
|
193
222
|
# CHECK 3) Non-existing tools should fail to start
|
|
194
223
|
monkeypatch.setattr(
|
|
195
224
|
installer,
|
|
196
|
-
|
|
225
|
+
'_on_process_done',
|
|
197
226
|
MethodType(_assert_error_used, installer),
|
|
198
227
|
)
|
|
199
|
-
monkeypatch.setattr(installer,
|
|
200
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
228
|
+
monkeypatch.setattr(installer, '_get_tool', lambda *a: _NonExistingTool)
|
|
229
|
+
with qtbot.waitSignal(installer.allFinished, timeout=10_000):
|
|
201
230
|
installer.install(
|
|
202
231
|
tool=_NonExistingTool,
|
|
203
232
|
pkgs=[f'this-package-does-not-exist-{hash(time.time())}'],
|
|
204
233
|
)
|
|
205
234
|
|
|
206
235
|
|
|
207
|
-
|
|
236
|
+
@pytest.mark.parametrize(
|
|
237
|
+
'tool', [NapariPipInstallerTool, NapariUvInstallerTool]
|
|
238
|
+
)
|
|
239
|
+
def test_cancel_incorrect_job_id(tool, qtbot, monkeypatch):
|
|
240
|
+
monkeypatch.setattr(
|
|
241
|
+
NapariInstallerQueue, 'PYPI_INSTALLER_TOOL_CLASS', tool
|
|
242
|
+
)
|
|
208
243
|
installer = NapariInstallerQueue()
|
|
209
|
-
with qtbot.waitSignal(installer.allFinished, timeout=
|
|
244
|
+
with qtbot.waitSignal(installer.allFinished, timeout=30_000):
|
|
210
245
|
job_id = installer.install(
|
|
211
|
-
tool=InstallerTools.
|
|
246
|
+
tool=InstallerTools.PYPI,
|
|
212
247
|
pkgs=['requests'],
|
|
213
248
|
)
|
|
214
|
-
with pytest.raises(ValueError):
|
|
249
|
+
with pytest.raises(ValueError, match=f'No job with id {job_id + 1}.'):
|
|
215
250
|
installer.cancel(job_id + 1)
|
|
216
251
|
|
|
217
252
|
|
|
218
253
|
@pytest.mark.skipif(
|
|
219
|
-
not NapariCondaInstallerTool.available(), reason=
|
|
254
|
+
not NapariCondaInstallerTool.available(), reason='Conda is not available.'
|
|
220
255
|
)
|
|
221
256
|
def test_conda_installer(qtbot, caplog, monkeypatch, tmp_conda_env: Path):
|
|
222
|
-
if sys.platform ==
|
|
257
|
+
if sys.platform == 'darwin':
|
|
223
258
|
# check handled for `PYTHONEXECUTABLE` env definition on macOS
|
|
224
|
-
monkeypatch.setenv(
|
|
259
|
+
monkeypatch.setenv('PYTHONEXECUTABLE', sys.executable)
|
|
225
260
|
caplog.set_level(logging.DEBUG, logger=bqpi.__name__)
|
|
226
|
-
conda_meta = tmp_conda_env /
|
|
227
|
-
glob_pat =
|
|
228
|
-
glob_pat_2 =
|
|
261
|
+
conda_meta = tmp_conda_env / 'conda-meta'
|
|
262
|
+
glob_pat = 'typing-extensions-*.json'
|
|
263
|
+
glob_pat_2 = 'packaging-*.json'
|
|
229
264
|
installer = NapariInstallerQueue()
|
|
230
265
|
|
|
231
266
|
with qtbot.waitSignal(installer.allFinished, timeout=600_000):
|
|
@@ -257,7 +292,7 @@ def test_conda_installer(qtbot, caplog, monkeypatch, tmp_conda_env: Path):
|
|
|
257
292
|
)
|
|
258
293
|
installer.install(
|
|
259
294
|
tool=InstallerTools.CONDA,
|
|
260
|
-
pkgs=['
|
|
295
|
+
pkgs=['packaging'],
|
|
261
296
|
prefix=tmp_conda_env,
|
|
262
297
|
)
|
|
263
298
|
assert installer.currentJobs() == 2
|
|
@@ -276,7 +311,7 @@ def test_conda_installer(qtbot, caplog, monkeypatch, tmp_conda_env: Path):
|
|
|
276
311
|
)
|
|
277
312
|
job_id_2 = installer.install(
|
|
278
313
|
tool=InstallerTools.CONDA,
|
|
279
|
-
pkgs=['
|
|
314
|
+
pkgs=['packaging'],
|
|
280
315
|
prefix=tmp_conda_env,
|
|
281
316
|
)
|
|
282
317
|
assert installer.currentJobs() == 2
|
|
@@ -294,7 +329,7 @@ def test_conda_installer(qtbot, caplog, monkeypatch, tmp_conda_env: Path):
|
|
|
294
329
|
)
|
|
295
330
|
job_id_2 = installer.install(
|
|
296
331
|
tool=InstallerTools.CONDA,
|
|
297
|
-
pkgs=['
|
|
332
|
+
pkgs=['packaging'],
|
|
298
333
|
prefix=tmp_conda_env,
|
|
299
334
|
)
|
|
300
335
|
assert installer.currentJobs() == 2
|
|
@@ -304,22 +339,24 @@ def test_conda_installer(qtbot, caplog, monkeypatch, tmp_conda_env: Path):
|
|
|
304
339
|
assert not installer.hasJobs()
|
|
305
340
|
|
|
306
341
|
|
|
307
|
-
|
|
308
|
-
|
|
342
|
+
@pytest.mark.parametrize(
|
|
343
|
+
'tool', [NapariPipInstallerTool, NapariUvInstallerTool]
|
|
344
|
+
)
|
|
345
|
+
def test_installer_error(qtbot, tool, monkeypatch):
|
|
309
346
|
monkeypatch.setattr(
|
|
310
|
-
|
|
311
|
-
"executable",
|
|
312
|
-
lambda *a: 'not-a-real-executable',
|
|
347
|
+
NapariInstallerQueue, 'PYPI_INSTALLER_TOOL_CLASS', tool
|
|
313
348
|
)
|
|
349
|
+
installer = NapariInstallerQueue()
|
|
350
|
+
monkeypatch.setattr(tool, 'executable', lambda *a: 'not-a-real-executable')
|
|
314
351
|
with qtbot.waitSignal(installer.allFinished, timeout=600_000):
|
|
315
352
|
installer.install(
|
|
316
|
-
tool=InstallerTools.
|
|
353
|
+
tool=InstallerTools.PYPI,
|
|
317
354
|
pkgs=['some-package-that-does-not-exist'],
|
|
318
355
|
)
|
|
319
356
|
|
|
320
357
|
|
|
321
358
|
@pytest.mark.skipif(
|
|
322
|
-
not NapariCondaInstallerTool.available(), reason=
|
|
359
|
+
not NapariCondaInstallerTool.available(), reason='Conda is not available.'
|
|
323
360
|
)
|
|
324
361
|
def test_conda_installer_wait_for_finished(qtbot, tmp_conda_env: Path):
|
|
325
362
|
installer = NapariInstallerQueue()
|
|
@@ -332,37 +369,41 @@ def test_conda_installer_wait_for_finished(qtbot, tmp_conda_env: Path):
|
|
|
332
369
|
)
|
|
333
370
|
installer.install(
|
|
334
371
|
tool=InstallerTools.CONDA,
|
|
335
|
-
pkgs=['
|
|
372
|
+
pkgs=['packaging'],
|
|
336
373
|
prefix=tmp_conda_env,
|
|
337
374
|
)
|
|
338
|
-
installer.waitForFinished(
|
|
375
|
+
installer.waitForFinished(30_000)
|
|
339
376
|
|
|
340
377
|
|
|
341
378
|
def test_constraints_are_in_sync():
|
|
342
379
|
conda_constraints = sorted(NapariCondaInstallerTool.constraints())
|
|
343
|
-
|
|
380
|
+
pypi_constraints = sorted(NapariPipInstallerTool.constraints())
|
|
344
381
|
|
|
345
|
-
assert len(conda_constraints) == len(
|
|
382
|
+
assert len(conda_constraints) == len(pypi_constraints)
|
|
346
383
|
|
|
347
|
-
name_re = re.compile(r
|
|
348
|
-
for conda_constraint,
|
|
349
|
-
conda_constraints,
|
|
384
|
+
name_re = re.compile(r'([a-z0-9_\-]+).*')
|
|
385
|
+
for conda_constraint, pypi_constraint in zip(
|
|
386
|
+
conda_constraints, pypi_constraints, strict=False
|
|
350
387
|
):
|
|
351
388
|
conda_name = name_re.match(conda_constraint).group(1)
|
|
352
|
-
|
|
353
|
-
assert conda_name ==
|
|
389
|
+
pypi_name = name_re.match(pypi_constraint).group(1)
|
|
390
|
+
assert conda_name == pypi_name
|
|
354
391
|
|
|
355
392
|
|
|
356
393
|
def test_executables():
|
|
357
394
|
assert NapariCondaInstallerTool.executable()
|
|
358
395
|
assert NapariPipInstallerTool.executable()
|
|
396
|
+
assert NapariUvInstallerTool.executable()
|
|
359
397
|
|
|
360
398
|
|
|
361
399
|
def test_available():
|
|
362
400
|
assert str(NapariCondaInstallerTool.available())
|
|
363
401
|
assert NapariPipInstallerTool.available()
|
|
402
|
+
assert NapariUvInstallerTool.available()
|
|
364
403
|
|
|
365
404
|
|
|
366
405
|
def test_unrecognized_tool():
|
|
367
|
-
with pytest.raises(
|
|
406
|
+
with pytest.raises(
|
|
407
|
+
ValueError, match='InstallerTool shrug not recognized!'
|
|
408
|
+
):
|
|
368
409
|
NapariInstallerQueue().install(tool='shrug', pkgs=[])
|
|
@@ -18,16 +18,17 @@ def test_user_agent():
|
|
|
18
18
|
@flaky(max_runs=4, min_passes=2)
|
|
19
19
|
def test_plugin_summaries():
|
|
20
20
|
keys = [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
21
|
+
'name',
|
|
22
|
+
'normalized_name',
|
|
23
|
+
'version',
|
|
24
|
+
'display_name',
|
|
25
|
+
'summary',
|
|
26
|
+
'author',
|
|
27
|
+
'license',
|
|
28
|
+
'home_page',
|
|
29
|
+
'pypi_versions',
|
|
30
|
+
'conda_versions',
|
|
31
|
+
'project_url',
|
|
31
32
|
]
|
|
32
33
|
try:
|
|
33
34
|
data = plugin_summaries()
|
|
@@ -42,7 +43,7 @@ def test_plugin_summaries():
|
|
|
42
43
|
|
|
43
44
|
|
|
44
45
|
def test_conda_map():
|
|
45
|
-
pkgs = [
|
|
46
|
+
pkgs = ['napari-svg']
|
|
46
47
|
try:
|
|
47
48
|
data = conda_map()
|
|
48
49
|
for pkg in pkgs:
|