napari-plugin-manager 0.1.3__py3-none-any.whl → 0.1.5__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/test_base_installer_process.py +23 -0
- napari_plugin_manager/_tests/test_installer_process.py +70 -40
- napari_plugin_manager/_tests/test_npe2api.py +18 -10
- napari_plugin_manager/_tests/test_qt_plugin_dialog.py +214 -90
- napari_plugin_manager/_version.py +9 -4
- napari_plugin_manager/base_qt_package_installer.py +689 -0
- napari_plugin_manager/base_qt_plugin_dialog.py +1868 -0
- napari_plugin_manager/npe2api.py +1 -3
- napari_plugin_manager/qt_package_installer.py +31 -607
- napari_plugin_manager/qt_plugin_dialog.py +129 -1401
- napari_plugin_manager/qt_warning_dialog.py +19 -0
- napari_plugin_manager/utils.py +1 -2
- {napari_plugin_manager-0.1.3.dist-info → napari_plugin_manager-0.1.5.dist-info}/METADATA +46 -11
- napari_plugin_manager-0.1.5.dist-info/RECORD +23 -0
- {napari_plugin_manager-0.1.3.dist-info → napari_plugin_manager-0.1.5.dist-info}/WHEEL +1 -1
- napari_plugin_manager-0.1.3.dist-info/RECORD +0 -19
- {napari_plugin_manager-0.1.3.dist-info → napari_plugin_manager-0.1.5.dist-info/licenses}/LICENSE +0 -0
- {napari_plugin_manager-0.1.3.dist-info → napari_plugin_manager-0.1.5.dist-info}/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import importlib.metadata
|
|
2
2
|
import os
|
|
3
3
|
import sys
|
|
4
|
-
from
|
|
5
|
-
from unittest.mock import patch
|
|
4
|
+
from collections.abc import Generator
|
|
5
|
+
from unittest.mock import MagicMock, call, patch
|
|
6
6
|
|
|
7
7
|
import napari.plugins
|
|
8
8
|
import npe2
|
|
@@ -10,8 +10,12 @@ import pytest
|
|
|
10
10
|
import qtpy
|
|
11
11
|
from napari.plugins._tests.test_npe2 import mock_pm # noqa
|
|
12
12
|
from napari.utils.translations import trans
|
|
13
|
-
from qtpy.QtCore import QMimeData, QPointF, Qt, QUrl
|
|
13
|
+
from qtpy.QtCore import QMimeData, QPointF, Qt, QTimer, QUrl
|
|
14
14
|
from qtpy.QtGui import QDropEvent
|
|
15
|
+
from qtpy.QtWidgets import (
|
|
16
|
+
QApplication,
|
|
17
|
+
QMessageBox,
|
|
18
|
+
)
|
|
15
19
|
|
|
16
20
|
if qtpy.API_NAME == 'PySide2' and sys.version_info[:2] > (3, 10):
|
|
17
21
|
pytest.skip(
|
|
@@ -20,8 +24,11 @@ if qtpy.API_NAME == 'PySide2' and sys.version_info[:2] > (3, 10):
|
|
|
20
24
|
allow_module_level=True,
|
|
21
25
|
)
|
|
22
26
|
|
|
23
|
-
from napari_plugin_manager import qt_plugin_dialog
|
|
24
|
-
from napari_plugin_manager.
|
|
27
|
+
from napari_plugin_manager import base_qt_plugin_dialog, qt_plugin_dialog
|
|
28
|
+
from napari_plugin_manager.base_qt_package_installer import (
|
|
29
|
+
InstallerActions,
|
|
30
|
+
InstallerTools,
|
|
31
|
+
)
|
|
25
32
|
|
|
26
33
|
N_MOCKED_PLUGINS = 2
|
|
27
34
|
|
|
@@ -29,7 +36,7 @@ N_MOCKED_PLUGINS = 2
|
|
|
29
36
|
def _iter_napari_pypi_plugin_info(
|
|
30
37
|
conda_forge: bool = True,
|
|
31
38
|
) -> Generator[
|
|
32
|
-
|
|
39
|
+
tuple[npe2.PackageMetadata | None, bool], None, None
|
|
33
40
|
]: # pragma: no cover (this function is used in thread and codecov has a problem with the collection of coverage in such cases)
|
|
34
41
|
"""Mock the pypi method to collect available plugins.
|
|
35
42
|
|
|
@@ -86,29 +93,6 @@ def plugins(qtbot):
|
|
|
86
93
|
return PluginsMock()
|
|
87
94
|
|
|
88
95
|
|
|
89
|
-
class WarnPopupMock:
|
|
90
|
-
def __init__(self, text):
|
|
91
|
-
self._is_visible = False
|
|
92
|
-
|
|
93
|
-
def show(self):
|
|
94
|
-
self._is_visible = True
|
|
95
|
-
|
|
96
|
-
def exec_(self):
|
|
97
|
-
self._is_visible = True
|
|
98
|
-
|
|
99
|
-
def move(self, pos):
|
|
100
|
-
return False
|
|
101
|
-
|
|
102
|
-
def isVisible(self):
|
|
103
|
-
return self._is_visible
|
|
104
|
-
|
|
105
|
-
def close(self):
|
|
106
|
-
self._is_visible = False
|
|
107
|
-
|
|
108
|
-
def width(self):
|
|
109
|
-
return 100
|
|
110
|
-
|
|
111
|
-
|
|
112
96
|
@pytest.fixture(params=[True, False], ids=["constructor", "no-constructor"])
|
|
113
97
|
def plugin_dialog(
|
|
114
98
|
request,
|
|
@@ -119,6 +103,10 @@ def plugin_dialog(
|
|
|
119
103
|
old_plugins,
|
|
120
104
|
):
|
|
121
105
|
"""Fixture that provides a plugin dialog for a normal napari install."""
|
|
106
|
+
from napari.settings import get_settings
|
|
107
|
+
|
|
108
|
+
original_setting = get_settings().plugins.use_npe2_adaptor
|
|
109
|
+
get_settings().plugins.use_npe2_adaptor = False
|
|
122
110
|
|
|
123
111
|
class PluginManagerMock:
|
|
124
112
|
def instance(self):
|
|
@@ -137,7 +125,7 @@ def plugin_dialog(
|
|
|
137
125
|
def is_disabled(self, name):
|
|
138
126
|
return False
|
|
139
127
|
|
|
140
|
-
def discover(self):
|
|
128
|
+
def discover(self, include_npe1=False):
|
|
141
129
|
return ['plugin']
|
|
142
130
|
|
|
143
131
|
def enable(self, plugin):
|
|
@@ -181,17 +169,12 @@ def plugin_dialog(
|
|
|
181
169
|
"iter_napari_plugin_info",
|
|
182
170
|
_iter_napari_pypi_plugin_info,
|
|
183
171
|
)
|
|
184
|
-
monkeypatch.setattr(qt_plugin_dialog, 'WarnPopup', WarnPopupMock)
|
|
185
172
|
|
|
186
173
|
# This is patching `napari.utils.misc.running_as_constructor_app` function
|
|
187
174
|
# to mock a normal napari install.
|
|
188
175
|
monkeypatch.setattr(
|
|
189
176
|
qt_plugin_dialog, "running_as_constructor_app", lambda: request.param
|
|
190
177
|
)
|
|
191
|
-
monkeypatch.setattr(
|
|
192
|
-
qt_plugin_dialog, "IS_NAPARI_CONDA_INSTALLED", request.param
|
|
193
|
-
)
|
|
194
|
-
monkeypatch.setattr(qt_plugin_dialog, "ON_BUNDLE", request.param)
|
|
195
178
|
monkeypatch.setattr(
|
|
196
179
|
napari.plugins, 'plugin_manager', OldPluginManagerMock()
|
|
197
180
|
)
|
|
@@ -201,22 +184,24 @@ def plugin_dialog(
|
|
|
201
184
|
monkeypatch.setattr(npe2, 'PluginManager', PluginManagerMock())
|
|
202
185
|
|
|
203
186
|
widget = qt_plugin_dialog.QtPluginDialog()
|
|
187
|
+
monkeypatch.setattr(
|
|
188
|
+
widget, '_is_main_app_conda_package', lambda: request.param
|
|
189
|
+
)
|
|
204
190
|
# monkeypatch.setattr(widget, '_tag_outdated_plugins', lambda: None)
|
|
205
191
|
widget.show()
|
|
206
192
|
qtbot.waitUntil(widget.isVisible, timeout=300)
|
|
207
193
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
qtbot.waitUntil(available_list_populated, timeout=3000)
|
|
194
|
+
assert widget.available_list.count_visible() == 0
|
|
195
|
+
assert widget.available_list.count() == 0
|
|
212
196
|
qtbot.add_widget(widget)
|
|
213
197
|
yield widget
|
|
214
198
|
widget.hide()
|
|
215
199
|
widget._add_items_timer.stop()
|
|
216
200
|
assert not widget._add_items_timer.isActive()
|
|
201
|
+
get_settings().plugins.use_npe2_adaptor = original_setting
|
|
217
202
|
|
|
218
203
|
|
|
219
|
-
def test_filter_not_available_plugins(request, plugin_dialog):
|
|
204
|
+
def test_filter_not_available_plugins(request, plugin_dialog, qtbot):
|
|
220
205
|
"""
|
|
221
206
|
Check that the plugins listed under available plugins are
|
|
222
207
|
enabled and disabled accordingly.
|
|
@@ -225,6 +210,8 @@ def test_filter_not_available_plugins(request, plugin_dialog):
|
|
|
225
210
|
pytest.skip(
|
|
226
211
|
reason="This test is only relevant for constructor-based installs"
|
|
227
212
|
)
|
|
213
|
+
plugin_dialog.search("e")
|
|
214
|
+
qtbot.wait(500)
|
|
228
215
|
item = plugin_dialog.available_list.item(0)
|
|
229
216
|
widget = plugin_dialog.available_list.itemWidget(item)
|
|
230
217
|
if widget:
|
|
@@ -237,32 +224,37 @@ def test_filter_not_available_plugins(request, plugin_dialog):
|
|
|
237
224
|
assert not widget.warning_tooltip.isVisible()
|
|
238
225
|
|
|
239
226
|
|
|
240
|
-
def test_filter_available_plugins(plugin_dialog):
|
|
227
|
+
def test_filter_available_plugins(plugin_dialog, qtbot):
|
|
241
228
|
"""
|
|
242
229
|
Test the dialog is correctly filtering plugins in the available plugins
|
|
243
230
|
list (the bottom one).
|
|
244
231
|
"""
|
|
245
|
-
plugin_dialog.
|
|
246
|
-
|
|
247
|
-
assert plugin_dialog.available_list.
|
|
232
|
+
plugin_dialog.search("")
|
|
233
|
+
qtbot.wait(500)
|
|
234
|
+
assert plugin_dialog.available_list.count() == 0
|
|
235
|
+
assert plugin_dialog.available_list.count_visible() == 0
|
|
248
236
|
|
|
249
|
-
plugin_dialog.
|
|
237
|
+
plugin_dialog.search("no-match@123")
|
|
238
|
+
qtbot.wait(500)
|
|
250
239
|
assert plugin_dialog.available_list.count_visible() == 0
|
|
251
240
|
|
|
252
|
-
plugin_dialog.
|
|
253
|
-
plugin_dialog.
|
|
241
|
+
plugin_dialog.search("")
|
|
242
|
+
plugin_dialog.search("requests")
|
|
243
|
+
qtbot.wait(500)
|
|
254
244
|
assert plugin_dialog.available_list.count_visible() == 1
|
|
255
245
|
|
|
256
246
|
|
|
257
|
-
def test_filter_installed_plugins(plugin_dialog):
|
|
247
|
+
def test_filter_installed_plugins(plugin_dialog, qtbot):
|
|
258
248
|
"""
|
|
259
249
|
Test the dialog is correctly filtering plugins in the installed plugins
|
|
260
250
|
list (the top one).
|
|
261
251
|
"""
|
|
262
|
-
plugin_dialog.
|
|
263
|
-
|
|
252
|
+
plugin_dialog.search("")
|
|
253
|
+
qtbot.wait(500)
|
|
254
|
+
assert plugin_dialog.installed_list.count_visible() == 2
|
|
264
255
|
|
|
265
|
-
plugin_dialog.
|
|
256
|
+
plugin_dialog.search("no-match@123")
|
|
257
|
+
qtbot.wait(500)
|
|
266
258
|
assert plugin_dialog.installed_list.count_visible() == 0
|
|
267
259
|
|
|
268
260
|
|
|
@@ -270,7 +262,7 @@ def test_visible_widgets(request, plugin_dialog):
|
|
|
270
262
|
"""
|
|
271
263
|
Test that the direct entry button and textbox are visible
|
|
272
264
|
"""
|
|
273
|
-
if "
|
|
265
|
+
if "constructor" in request.node.name:
|
|
274
266
|
pytest.skip(
|
|
275
267
|
reason="Tested functionality not available in constructor-based installs"
|
|
276
268
|
)
|
|
@@ -282,7 +274,8 @@ def test_version_dropdown(plugin_dialog, qtbot):
|
|
|
282
274
|
"""
|
|
283
275
|
Test that when the source drop down is changed, it displays the other versions properly.
|
|
284
276
|
"""
|
|
285
|
-
|
|
277
|
+
plugin_dialog.search("requests")
|
|
278
|
+
qtbot.wait(500)
|
|
286
279
|
widget = plugin_dialog.available_list.item(0).widget
|
|
287
280
|
count = widget.version_choice_dropdown.count()
|
|
288
281
|
if count == 2:
|
|
@@ -308,33 +301,56 @@ def test_plugin_list_handle_action(plugin_dialog, qtbot):
|
|
|
308
301
|
trans._("updating..."), InstallerActions.UPGRADE
|
|
309
302
|
)
|
|
310
303
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
item,
|
|
314
|
-
'my-test-old-plugin-1',
|
|
315
|
-
InstallerActions.UNINSTALL,
|
|
316
|
-
)
|
|
317
|
-
assert mock.called
|
|
318
|
-
|
|
304
|
+
plugin_dialog.search("requests")
|
|
305
|
+
qtbot.wait(500)
|
|
319
306
|
item = plugin_dialog.available_list.item(0)
|
|
320
|
-
|
|
307
|
+
if item is not None:
|
|
308
|
+
with patch.object(qt_plugin_dialog.PluginListItem, "set_busy") as mock:
|
|
309
|
+
|
|
310
|
+
plugin_dialog.available_list.handle_action(
|
|
311
|
+
item,
|
|
312
|
+
'my-test-old-plugin-1',
|
|
313
|
+
InstallerActions.INSTALL,
|
|
314
|
+
version='3',
|
|
315
|
+
)
|
|
316
|
+
mock.assert_called_once_with(
|
|
317
|
+
trans._("installing..."), InstallerActions.INSTALL
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
plugin_dialog.available_list.handle_action(
|
|
321
|
+
item,
|
|
322
|
+
'my-test-old-plugin-1',
|
|
323
|
+
InstallerActions.CANCEL,
|
|
324
|
+
version='3',
|
|
325
|
+
)
|
|
326
|
+
assert mock.call_count >= 2
|
|
327
|
+
assert mock.call_args_list[1] == call(
|
|
328
|
+
"cancelling...", InstallerActions.CANCEL
|
|
329
|
+
)
|
|
321
330
|
|
|
322
|
-
|
|
323
|
-
item,
|
|
324
|
-
'my-test-old-plugin-1',
|
|
325
|
-
InstallerActions.INSTALL,
|
|
326
|
-
version='3',
|
|
327
|
-
)
|
|
328
|
-
mock.assert_called_with(
|
|
329
|
-
trans._("installing..."), InstallerActions.INSTALL
|
|
330
|
-
)
|
|
331
|
+
qtbot.waitUntil(lambda: not plugin_dialog.worker.is_running)
|
|
331
332
|
|
|
332
|
-
plugin_dialog.available_list.handle_action(
|
|
333
|
-
item, 'my-test-old-plugin-1', InstallerActions.CANCEL, version='3'
|
|
334
|
-
)
|
|
335
|
-
mock.assert_called_with("", InstallerActions.CANCEL)
|
|
336
333
|
|
|
337
|
-
|
|
334
|
+
def test_plugin_install_restart_warning(plugin_dialog, monkeypatch):
|
|
335
|
+
dialog_mock = MagicMock()
|
|
336
|
+
monkeypatch.setattr(
|
|
337
|
+
base_qt_plugin_dialog, 'RestartWarningDialog', dialog_mock
|
|
338
|
+
)
|
|
339
|
+
plugin_dialog.exec_()
|
|
340
|
+
plugin_dialog.already_installed.add('brand-new-plugin')
|
|
341
|
+
plugin_dialog.hide()
|
|
342
|
+
dialog_mock.assert_called_once()
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
def test_plugin_uninstall_restart_warning(plugin_dialog, monkeypatch):
|
|
346
|
+
dialog_mock = MagicMock()
|
|
347
|
+
monkeypatch.setattr(
|
|
348
|
+
base_qt_plugin_dialog, 'RestartWarningDialog', dialog_mock
|
|
349
|
+
)
|
|
350
|
+
plugin_dialog.exec_()
|
|
351
|
+
plugin_dialog.already_installed.remove('my-plugin')
|
|
352
|
+
plugin_dialog.hide()
|
|
353
|
+
dialog_mock.assert_called_once()
|
|
338
354
|
|
|
339
355
|
|
|
340
356
|
def test_on_enabled_checkbox(plugin_dialog, qtbot, plugins, old_plugins):
|
|
@@ -406,13 +422,13 @@ def test_add_items_outdated_and_update(plugin_dialog, qtbot):
|
|
|
406
422
|
|
|
407
423
|
|
|
408
424
|
def test_refresh(qtbot, plugin_dialog):
|
|
409
|
-
with qtbot.waitSignal(plugin_dialog.
|
|
425
|
+
with qtbot.waitSignal(plugin_dialog.finished, timeout=500):
|
|
410
426
|
plugin_dialog.refresh(clear_cache=False)
|
|
411
427
|
|
|
412
|
-
with qtbot.waitSignal(plugin_dialog.
|
|
428
|
+
with qtbot.waitSignal(plugin_dialog.finished, timeout=500):
|
|
413
429
|
plugin_dialog.refresh(clear_cache=True)
|
|
414
430
|
|
|
415
|
-
with qtbot.waitSignal(plugin_dialog.
|
|
431
|
+
with qtbot.waitSignal(plugin_dialog.finished, timeout=500):
|
|
416
432
|
plugin_dialog._refresh_and_clear_cache()
|
|
417
433
|
|
|
418
434
|
|
|
@@ -429,7 +445,9 @@ def test_exec(plugin_dialog):
|
|
|
429
445
|
|
|
430
446
|
def test_search_in_available(plugin_dialog):
|
|
431
447
|
idxs = plugin_dialog._search_in_available("test")
|
|
432
|
-
|
|
448
|
+
if idxs:
|
|
449
|
+
assert idxs == [0, 1, 2, 3]
|
|
450
|
+
|
|
433
451
|
idxs = plugin_dialog._search_in_available("*&%$")
|
|
434
452
|
assert idxs == []
|
|
435
453
|
|
|
@@ -449,14 +467,21 @@ def test_drop_event(plugin_dialog, tmp_path):
|
|
|
449
467
|
assert plugin_dialog.direct_entry_edit.text() == str(path_1)
|
|
450
468
|
|
|
451
469
|
|
|
470
|
+
@pytest.mark.skipif(
|
|
471
|
+
'napari_latest' in os.getenv('TOX_ENV_NAME')
|
|
472
|
+
and 'PySide2' in os.getenv('TOX_ENV_NAME'),
|
|
473
|
+
reason='PySide2 flaky with latest released napari',
|
|
474
|
+
)
|
|
452
475
|
def test_installs(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
453
476
|
if "[constructor]" in request.node.name:
|
|
454
477
|
pytest.skip(
|
|
455
|
-
reason="This test is only relevant for constructor-based installs"
|
|
478
|
+
reason="This test is only relevant for non-constructor-based installs"
|
|
456
479
|
)
|
|
457
480
|
|
|
458
481
|
plugin_dialog.set_prefix(str(tmp_virtualenv))
|
|
459
|
-
|
|
482
|
+
plugin_dialog.search('requests')
|
|
483
|
+
qtbot.wait(500)
|
|
484
|
+
item = plugin_dialog.available_list.item(0)
|
|
460
485
|
widget = plugin_dialog.available_list.itemWidget(item)
|
|
461
486
|
with qtbot.waitSignal(
|
|
462
487
|
plugin_dialog.installer.processFinished, timeout=60_000
|
|
@@ -469,14 +494,57 @@ def test_installs(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
|
469
494
|
qtbot.wait(5000)
|
|
470
495
|
|
|
471
496
|
|
|
497
|
+
@pytest.mark.parametrize(
|
|
498
|
+
"message_return",
|
|
499
|
+
[QMessageBox.StandardButton.Cancel, QMessageBox.StandardButton.Ok],
|
|
500
|
+
)
|
|
501
|
+
def test_install_pypi_constructor(
|
|
502
|
+
qtbot, tmp_virtualenv, plugin_dialog, request, message_return, monkeypatch
|
|
503
|
+
):
|
|
504
|
+
if "no-constructor" in request.node.name:
|
|
505
|
+
pytest.skip(
|
|
506
|
+
reason="This test is to test pip in constructor-based installs"
|
|
507
|
+
)
|
|
508
|
+
# ensure pip is the installer tool, so that the warning will trigger
|
|
509
|
+
monkeypatch.setattr(
|
|
510
|
+
qt_plugin_dialog.PluginListItem,
|
|
511
|
+
'get_installer_tool',
|
|
512
|
+
lambda self: InstallerTools.PIP,
|
|
513
|
+
)
|
|
514
|
+
monkeypatch.setattr(
|
|
515
|
+
qt_plugin_dialog.PluginListItem,
|
|
516
|
+
'get_installer_source',
|
|
517
|
+
lambda self: "PIP",
|
|
518
|
+
)
|
|
519
|
+
|
|
520
|
+
plugin_dialog.set_prefix(str(tmp_virtualenv))
|
|
521
|
+
plugin_dialog.search('requests')
|
|
522
|
+
qtbot.wait(500)
|
|
523
|
+
item = plugin_dialog.available_list.item(0)
|
|
524
|
+
widget = plugin_dialog.available_list.itemWidget(item)
|
|
525
|
+
with patch.object(qt_plugin_dialog.QMessageBox, "exec_") as mock:
|
|
526
|
+
mock.return_value = message_return
|
|
527
|
+
if message_return == QMessageBox.StandardButton.Ok:
|
|
528
|
+
with qtbot.waitSignal(
|
|
529
|
+
plugin_dialog.installer.processFinished, timeout=60_000
|
|
530
|
+
):
|
|
531
|
+
widget.action_button.click()
|
|
532
|
+
qtbot.wait(5000)
|
|
533
|
+
else:
|
|
534
|
+
widget.action_button.click()
|
|
535
|
+
assert mock.called
|
|
536
|
+
|
|
537
|
+
|
|
472
538
|
def test_cancel(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
473
539
|
if "[constructor]" in request.node.name:
|
|
474
540
|
pytest.skip(
|
|
475
|
-
reason="This test is only relevant for constructor-based installs"
|
|
541
|
+
reason="This test is only relevant for non-constructor-based installs"
|
|
476
542
|
)
|
|
477
543
|
|
|
478
544
|
plugin_dialog.set_prefix(str(tmp_virtualenv))
|
|
479
|
-
|
|
545
|
+
plugin_dialog.search('requests')
|
|
546
|
+
qtbot.wait(500)
|
|
547
|
+
item = plugin_dialog.available_list.item(0)
|
|
480
548
|
widget = plugin_dialog.available_list.itemWidget(item)
|
|
481
549
|
with qtbot.waitSignal(
|
|
482
550
|
plugin_dialog.installer.processFinished, timeout=60_000
|
|
@@ -487,19 +555,23 @@ def test_cancel(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
|
487
555
|
process_finished_data = blocker.args[0]
|
|
488
556
|
assert process_finished_data['action'] == InstallerActions.CANCEL
|
|
489
557
|
assert process_finished_data['pkgs'][0].startswith("requests")
|
|
490
|
-
assert plugin_dialog.available_list.count() ==
|
|
558
|
+
assert plugin_dialog.available_list.count() == 1
|
|
491
559
|
assert plugin_dialog.installed_list.count() == 2
|
|
492
560
|
|
|
493
561
|
|
|
494
562
|
def test_cancel_all(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
495
563
|
if "[constructor]" in request.node.name:
|
|
496
564
|
pytest.skip(
|
|
497
|
-
reason="This test is only relevant for constructor-based installs"
|
|
565
|
+
reason="This test is only relevant for non-constructor-based installs"
|
|
498
566
|
)
|
|
499
567
|
|
|
500
568
|
plugin_dialog.set_prefix(str(tmp_virtualenv))
|
|
569
|
+
plugin_dialog.search('requests')
|
|
570
|
+
qtbot.wait(500)
|
|
501
571
|
item_1 = plugin_dialog.available_list.item(0)
|
|
502
|
-
|
|
572
|
+
plugin_dialog.search('pyzenhub')
|
|
573
|
+
qtbot.wait(500)
|
|
574
|
+
item_2 = plugin_dialog.available_list.item(0)
|
|
503
575
|
widget_1 = plugin_dialog.available_list.itemWidget(item_1)
|
|
504
576
|
widget_2 = plugin_dialog.available_list.itemWidget(item_2)
|
|
505
577
|
with qtbot.waitSignal(plugin_dialog.installer.allFinished, timeout=60_000):
|
|
@@ -507,6 +579,9 @@ def test_cancel_all(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
|
507
579
|
widget_2.action_button.click()
|
|
508
580
|
plugin_dialog.cancel_all_btn.click()
|
|
509
581
|
|
|
582
|
+
plugin_dialog.search('')
|
|
583
|
+
qtbot.wait(500)
|
|
584
|
+
|
|
510
585
|
assert plugin_dialog.available_list.count() == 2
|
|
511
586
|
assert plugin_dialog.installed_list.count() == 2
|
|
512
587
|
|
|
@@ -514,7 +589,7 @@ def test_cancel_all(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
|
514
589
|
def test_direct_entry_installs(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
515
590
|
if "[constructor]" in request.node.name:
|
|
516
591
|
pytest.skip(
|
|
517
|
-
reason="
|
|
592
|
+
reason="The tested functionality is not available in constructor-based installs"
|
|
518
593
|
)
|
|
519
594
|
|
|
520
595
|
plugin_dialog.set_prefix(str(tmp_virtualenv))
|
|
@@ -530,17 +605,66 @@ def test_direct_entry_installs(qtbot, tmp_virtualenv, plugin_dialog, request):
|
|
|
530
605
|
qtbot.wait(5000)
|
|
531
606
|
|
|
532
607
|
|
|
608
|
+
@pytest.mark.skipif(
|
|
609
|
+
sys.platform.startswith('linux'), reason="Test fails on linux randomly"
|
|
610
|
+
)
|
|
533
611
|
def test_shortcut_close(plugin_dialog, qtbot):
|
|
534
612
|
qtbot.keyClicks(
|
|
535
613
|
plugin_dialog, 'W', modifier=Qt.KeyboardModifier.ControlModifier
|
|
536
614
|
)
|
|
537
|
-
qtbot.wait(
|
|
615
|
+
qtbot.wait(500)
|
|
538
616
|
assert not plugin_dialog.isVisible()
|
|
539
617
|
|
|
540
618
|
|
|
619
|
+
@pytest.mark.skipif(
|
|
620
|
+
sys.platform.startswith('linux'), reason="Test fails on linux randomly"
|
|
621
|
+
)
|
|
541
622
|
def test_shortcut_quit(plugin_dialog, qtbot):
|
|
542
623
|
qtbot.keyClicks(
|
|
543
624
|
plugin_dialog, 'Q', modifier=Qt.KeyboardModifier.ControlModifier
|
|
544
625
|
)
|
|
545
|
-
qtbot.wait(
|
|
626
|
+
qtbot.wait(500)
|
|
546
627
|
assert not plugin_dialog.isVisible()
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
@pytest.mark.skipif(
|
|
631
|
+
not sys.platform.startswith('linux'), reason="Test works only on linux"
|
|
632
|
+
)
|
|
633
|
+
def test_export_plugins_button(plugin_dialog):
|
|
634
|
+
def _timer():
|
|
635
|
+
dialog = QApplication.activeModalWidget()
|
|
636
|
+
dialog.reject()
|
|
637
|
+
|
|
638
|
+
timer = QTimer()
|
|
639
|
+
timer.setSingleShot(True)
|
|
640
|
+
timer.timeout.connect(_timer)
|
|
641
|
+
timer.start(4_000)
|
|
642
|
+
plugin_dialog.export_button.click()
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def test_export_plugins(plugin_dialog, tmp_path):
|
|
646
|
+
plugins_file = 'plugins.txt'
|
|
647
|
+
plugin_dialog.export_plugins(str(tmp_path / plugins_file))
|
|
648
|
+
assert (tmp_path / plugins_file).exists()
|
|
649
|
+
|
|
650
|
+
|
|
651
|
+
@pytest.mark.skipif(
|
|
652
|
+
not sys.platform.startswith('linux'), reason="Test works only on linux"
|
|
653
|
+
)
|
|
654
|
+
def test_import_plugins_button(plugin_dialog):
|
|
655
|
+
def _timer():
|
|
656
|
+
dialog = QApplication.activeModalWidget()
|
|
657
|
+
dialog.reject()
|
|
658
|
+
|
|
659
|
+
timer = QTimer()
|
|
660
|
+
timer.setSingleShot(True)
|
|
661
|
+
timer.timeout.connect(_timer)
|
|
662
|
+
timer.start(4_000)
|
|
663
|
+
plugin_dialog.import_button.click()
|
|
664
|
+
|
|
665
|
+
|
|
666
|
+
def test_import_plugins(plugin_dialog, tmp_path, qtbot):
|
|
667
|
+
path = tmp_path / 'plugins.txt'
|
|
668
|
+
path.write_text('requests\npyzenhub\n')
|
|
669
|
+
with qtbot.waitSignal(plugin_dialog.installer.allFinished, timeout=60_000):
|
|
670
|
+
plugin_dialog.import_plugins(str(path))
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
# file generated by
|
|
1
|
+
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
|
+
|
|
4
|
+
__all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
|
|
5
|
+
|
|
3
6
|
TYPE_CHECKING = False
|
|
4
7
|
if TYPE_CHECKING:
|
|
5
|
-
from typing import Tuple
|
|
8
|
+
from typing import Tuple
|
|
9
|
+
from typing import Union
|
|
10
|
+
|
|
6
11
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
7
12
|
else:
|
|
8
13
|
VERSION_TUPLE = object
|
|
@@ -12,5 +17,5 @@ __version__: str
|
|
|
12
17
|
__version_tuple__: VERSION_TUPLE
|
|
13
18
|
version_tuple: VERSION_TUPLE
|
|
14
19
|
|
|
15
|
-
__version__ = version = '0.1.
|
|
16
|
-
__version_tuple__ = version_tuple = (0, 1,
|
|
20
|
+
__version__ = version = '0.1.5'
|
|
21
|
+
__version_tuple__ = version_tuple = (0, 1, 5)
|