auto-options-python 0.1.6__tar.gz → 1.0.8__tar.gz
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.
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/PKG-INFO +3 -5
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/pyproject.toml +3 -4
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/PKG-INFO +3 -5
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/SOURCES.txt +5 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/requires.txt +0 -1
- auto_options_python-1.0.8/src/autooptions/_tests/test_layouts.py +80 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_options.py +2 -1
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_qtutil.py +39 -75
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_widget.py +59 -41
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_version.py +3 -3
- auto_options_python-1.0.8/src/autooptions/layouts/__init__.py +29 -0
- auto_options_python-1.0.8/src/autooptions/layouts/base_layout.py +81 -0
- auto_options_python-1.0.8/src/autooptions/layouts/grid_layout.py +46 -0
- auto_options_python-1.0.8/src/autooptions/layouts/vertical_layout.py +46 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/options.py +250 -89
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/qtutil.py +130 -64
- auto_options_python-1.0.8/src/autooptions/widget.py +427 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/scratch/options.py +9 -3
- auto_options_python-0.1.6/src/autooptions/widget.py +0 -382
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/.github/workflows/create_doc.yml +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/.github/workflows/test_and_deploy.yml +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/.gitignore +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/LICENSE +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/README.md +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/Makefile +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/make.bat +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/auto-options-python.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/autooptions.array_util.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/autooptions.napari_util.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/autooptions.options.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/autooptions.qtutil.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/autooptions.widget.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/conf.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/index.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/modules.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/user/installation.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/user/introduction.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/docs/source/user/user_documentation.rst +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/setup.cfg +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/dependency_links.txt +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/top_level.txt +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/__init__.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/__init__.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_array_util.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_napari_util.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/array_util.py +0 -0
- {auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/napari_util.py +0 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: auto-options-python
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
Author: Volker Baecker
|
|
6
|
-
Author-email: volker.baecker@mri.cnrs.fr
|
|
3
|
+
Version: 1.0.8
|
|
4
|
+
Summary: Manage command options in Python and create QWidgets for them.
|
|
5
|
+
Author-email: Volker Baecker <volker.baecker@mri.cnrs.fr>, Clément Benedetti <clement.benedetti@mri.cnrs.fr>
|
|
7
6
|
License: MIT License
|
|
8
7
|
|
|
9
8
|
Copyright (c) 2025 Montpellier Ressources Imagerie
|
|
@@ -47,7 +46,6 @@ Requires-Python: >=3.10
|
|
|
47
46
|
Description-Content-Type: text/markdown
|
|
48
47
|
License-File: LICENSE
|
|
49
48
|
Requires-Dist: appdirs
|
|
50
|
-
Requires-Dist: pyqt5
|
|
51
49
|
Requires-Dist: qtpy
|
|
52
50
|
Requires-Dist: napari
|
|
53
51
|
Requires-Dist: pyperclip
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "auto-options-python"
|
|
3
3
|
dynamic = ["version"]
|
|
4
|
-
description = "
|
|
4
|
+
description = "Manage command options in Python and create QWidgets for them."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {file = "LICENSE"}
|
|
7
7
|
authors = [
|
|
8
|
-
{name = "Volker Baecker"},
|
|
9
|
-
{email = "
|
|
8
|
+
{name = "Volker Baecker", email = "volker.baecker@mri.cnrs.fr"},
|
|
9
|
+
{name = "Clément Benedetti", email = "clement.benedetti@mri.cnrs.fr"}
|
|
10
10
|
]
|
|
11
11
|
classifiers = [
|
|
12
12
|
"Development Status :: 4 - Beta",
|
|
@@ -30,7 +30,6 @@ requires-python = ">=3.10"
|
|
|
30
30
|
# See best practices: https://napari.org/stable/plugins/building_a_plugin/best_practices.html
|
|
31
31
|
dependencies = [
|
|
32
32
|
"appdirs",
|
|
33
|
-
"pyqt5",
|
|
34
33
|
"qtpy",
|
|
35
34
|
"napari",
|
|
36
35
|
"pyperclip",
|
{auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/PKG-INFO
RENAMED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: auto-options-python
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
Author: Volker Baecker
|
|
6
|
-
Author-email: volker.baecker@mri.cnrs.fr
|
|
3
|
+
Version: 1.0.8
|
|
4
|
+
Summary: Manage command options in Python and create QWidgets for them.
|
|
5
|
+
Author-email: Volker Baecker <volker.baecker@mri.cnrs.fr>, Clément Benedetti <clement.benedetti@mri.cnrs.fr>
|
|
7
6
|
License: MIT License
|
|
8
7
|
|
|
9
8
|
Copyright (c) 2025 Montpellier Ressources Imagerie
|
|
@@ -47,7 +46,6 @@ Requires-Python: >=3.10
|
|
|
47
46
|
Description-Content-Type: text/markdown
|
|
48
47
|
License-File: LICENSE
|
|
49
48
|
Requires-Dist: appdirs
|
|
50
|
-
Requires-Dist: pyqt5
|
|
51
49
|
Requires-Dist: qtpy
|
|
52
50
|
Requires-Dist: napari
|
|
53
51
|
Requires-Dist: pyperclip
|
{auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/auto_options_python.egg-info/SOURCES.txt
RENAMED
|
@@ -32,8 +32,13 @@ src/autooptions/qtutil.py
|
|
|
32
32
|
src/autooptions/widget.py
|
|
33
33
|
src/autooptions/_tests/__init__.py
|
|
34
34
|
src/autooptions/_tests/test_array_util.py
|
|
35
|
+
src/autooptions/_tests/test_layouts.py
|
|
35
36
|
src/autooptions/_tests/test_napari_util.py
|
|
36
37
|
src/autooptions/_tests/test_options.py
|
|
37
38
|
src/autooptions/_tests/test_qtutil.py
|
|
38
39
|
src/autooptions/_tests/test_widget.py
|
|
40
|
+
src/autooptions/layouts/__init__.py
|
|
41
|
+
src/autooptions/layouts/base_layout.py
|
|
42
|
+
src/autooptions/layouts/grid_layout.py
|
|
43
|
+
src/autooptions/layouts/vertical_layout.py
|
|
39
44
|
src/scratch/options.py
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
import os
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
from autooptions.widget import OptionsWidget
|
|
6
|
+
from autooptions.options import Options
|
|
7
|
+
from autooptions.layouts import LayoutFactory
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestLayoutUtils:
|
|
11
|
+
|
|
12
|
+
@staticmethod
|
|
13
|
+
def getLayoutsList():
|
|
14
|
+
return list(LayoutFactory.availableLayouts.keys())
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TestLayouts:
|
|
18
|
+
|
|
19
|
+
def onSomethingHappened(self, value):
|
|
20
|
+
self.lastValue = value
|
|
21
|
+
|
|
22
|
+
@pytest.fixture()
|
|
23
|
+
def options(self):
|
|
24
|
+
options = Options("Autooptions Test", "Layouts Test")
|
|
25
|
+
options.addImage("image", value=None, transient=True, optional=(True, False))
|
|
26
|
+
options.addLabels("labels", value="labels_layer", transient=True)
|
|
27
|
+
options.addPoints("points", value="points_layer", transient=True)
|
|
28
|
+
options.addFFT("fft", value=None, transient=True)
|
|
29
|
+
options.addStr("group", value="lps", optional=(True, True))
|
|
30
|
+
options.addInt("size xy", value=3)
|
|
31
|
+
options.addInt("size z", value=1)
|
|
32
|
+
options.addChoice(
|
|
33
|
+
"footprint",
|
|
34
|
+
choices=["none", "cube", "ball", "octahedron"],
|
|
35
|
+
callback=self.onSomethingHappened,
|
|
36
|
+
)
|
|
37
|
+
options.addFloat("sigma", value=1.34)
|
|
38
|
+
options.addBool("do it", value=True)
|
|
39
|
+
yield options
|
|
40
|
+
|
|
41
|
+
@pytest.mark.parametrize("layout_type", TestLayoutUtils.getLayoutsList())
|
|
42
|
+
def testLayoutInstanciation(self, options, make_napari_viewer_proxy, layout_type):
|
|
43
|
+
viewer = make_napari_viewer_proxy()
|
|
44
|
+
widget = OptionsWidget(viewer, options, layout_type=layout_type, client=self)
|
|
45
|
+
assert widget.options is options
|
|
46
|
+
assert widget.viewer is viewer
|
|
47
|
+
assert widget.client is self
|
|
48
|
+
assert type(widget.layout()) is LayoutFactory.availableLayouts[layout_type]
|
|
49
|
+
|
|
50
|
+
@pytest.mark.parametrize("layout_type", TestLayoutUtils.getLayoutsList())
|
|
51
|
+
@pytest.mark.parametrize("same_row", [None, [], ["labels", "points"], ["size z"]])
|
|
52
|
+
def testLayoutLength(
|
|
53
|
+
self, options, make_napari_viewer_proxy, layout_type, same_row
|
|
54
|
+
):
|
|
55
|
+
viewer = make_napari_viewer_proxy()
|
|
56
|
+
widget = OptionsWidget(
|
|
57
|
+
viewer, options, layout_type=layout_type, sameRowSet=same_row, client=self
|
|
58
|
+
)
|
|
59
|
+
n_widgets = len(options)
|
|
60
|
+
expected = n_widgets - (len(same_row) if same_row else 0)
|
|
61
|
+
assert widget.layout().size() == expected
|
|
62
|
+
|
|
63
|
+
@pytest.mark.parametrize("field_width", [50, 300])
|
|
64
|
+
def testLayoutSizingFixed(self, options, make_napari_viewer_proxy, field_width):
|
|
65
|
+
viewer = make_napari_viewer_proxy()
|
|
66
|
+
args = {"name": "vertical", "max_width": field_width}
|
|
67
|
+
widget = OptionsWidget(viewer, options, layout_type=args, client=self)
|
|
68
|
+
for _, w in widget.widgets.values():
|
|
69
|
+
assert w.maximumWidth() == field_width
|
|
70
|
+
|
|
71
|
+
@pytest.mark.parametrize("layout_type", TestLayoutUtils.getLayoutsList())
|
|
72
|
+
def testWidgetsHierarchy(self, options, make_napari_viewer_proxy, layout_type):
|
|
73
|
+
viewer = make_napari_viewer_proxy()
|
|
74
|
+
widget = OptionsWidget(viewer, options, layout_type=layout_type, client=self)
|
|
75
|
+
for cb, w in widget.widgets.values():
|
|
76
|
+
assert w.parent() is widget
|
|
77
|
+
assert w in widget.children()
|
|
78
|
+
if cb is not None:
|
|
79
|
+
assert cb.parent() is widget
|
|
80
|
+
assert cb in widget.children()
|
{auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_options.py
RENAMED
|
@@ -157,11 +157,12 @@ class TestOptions:
|
|
|
157
157
|
|
|
158
158
|
|
|
159
159
|
def testGetBaseOption(self, options):
|
|
160
|
-
option = options.
|
|
160
|
+
option = options._getBaseOption(7, True, None, self.onSomething, [True, False])
|
|
161
161
|
assert option["value"] == 7
|
|
162
162
|
assert option["transient"] == True
|
|
163
163
|
assert option["position"] == 6
|
|
164
164
|
assert option["callback"] == "onSomething"
|
|
165
|
+
assert option["optional"] == [True, False]
|
|
165
166
|
|
|
166
167
|
|
|
167
168
|
def test_GetPosition(self, options):
|
{auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_qtutil.py
RENAMED
|
@@ -7,21 +7,16 @@ from autooptions.qtutil import WidgetTool
|
|
|
7
7
|
from autooptions.qtutil import TableView
|
|
8
8
|
from autooptions.qtutil import PlotWidget
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
10
|
COUNTER_TEXT_CHANGED = 0
|
|
13
11
|
|
|
14
12
|
|
|
15
|
-
|
|
16
13
|
class ParentWidget(QWidget):
|
|
17
14
|
|
|
18
|
-
|
|
19
15
|
def __init__(self):
|
|
20
16
|
super().__init__()
|
|
21
17
|
self.setWindowTitle("Test")
|
|
22
18
|
|
|
23
19
|
|
|
24
|
-
|
|
25
20
|
def handleTextChanged(text):
|
|
26
21
|
global COUNTER_TEXT_CHANGED
|
|
27
22
|
COUNTER_TEXT_CHANGED = COUNTER_TEXT_CHANGED + 1
|
|
@@ -29,57 +24,38 @@ def handleTextChanged(text):
|
|
|
29
24
|
|
|
30
25
|
def testGetLineInput(make_napari_viewer_proxy):
|
|
31
26
|
make_napari_viewer_proxy()
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
10,
|
|
36
|
-
50,
|
|
37
|
-
handleTextChanged)
|
|
38
|
-
assert label in parent.children()
|
|
39
|
-
assert inputWidget in parent.children()
|
|
40
|
-
assert label.parent() == parent
|
|
41
|
-
assert inputWidget.parent() == parent
|
|
27
|
+
label, inputWidget, cbActive = WidgetTool.getLineInput(
|
|
28
|
+
"your guess", 10, callback=handleTextChanged
|
|
29
|
+
)
|
|
42
30
|
assert label.text() == "your guess"
|
|
43
31
|
counter = COUNTER_TEXT_CHANGED
|
|
44
32
|
assert inputWidget.text() == str(10)
|
|
45
33
|
inputWidget.setText("20")
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
assert
|
|
34
|
+
# Editing in the interface -> sends the signal
|
|
35
|
+
# Programmatically changing the value -> does not send the signal
|
|
36
|
+
assert COUNTER_TEXT_CHANGED == counter
|
|
37
|
+
assert cbActive is None
|
|
49
38
|
|
|
50
39
|
|
|
51
40
|
def testGetLineInputNoCallback(make_napari_viewer_proxy):
|
|
52
41
|
make_napari_viewer_proxy()
|
|
53
|
-
|
|
54
|
-
label, inputWidget = WidgetTool.getLineInput(parent,
|
|
55
|
-
"your guess",
|
|
56
|
-
10,
|
|
57
|
-
50,
|
|
58
|
-
None)
|
|
59
|
-
assert label in parent.children()
|
|
60
|
-
assert inputWidget in parent.children()
|
|
61
|
-
assert label.parent() == parent
|
|
62
|
-
assert inputWidget.parent() == parent
|
|
42
|
+
label, inputWidget, cbActive = WidgetTool.getLineInput("your guess", 10)
|
|
63
43
|
assert label.text() == "your guess"
|
|
64
44
|
counter = COUNTER_TEXT_CHANGED
|
|
65
45
|
assert inputWidget.text() == str(10)
|
|
66
46
|
inputWidget.setText("20")
|
|
67
|
-
assert inputWidget.maximumWidth() == 50
|
|
68
47
|
assert COUNTER_TEXT_CHANGED == counter
|
|
48
|
+
assert cbActive is None # by default, options are not optional
|
|
69
49
|
|
|
70
50
|
|
|
71
51
|
def testGetComboBox(make_napari_viewer_proxy, mocker):
|
|
72
52
|
make_napari_viewer_proxy()
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
assert label in parent.children()
|
|
80
|
-
assert comboWidget in parent.children()
|
|
81
|
-
assert label.parent() == parent
|
|
82
|
-
assert comboWidget.parent() == parent
|
|
53
|
+
callback = mocker.stub(name="onSelectedFruitChanged")
|
|
54
|
+
label, comboWidget, _ = WidgetTool.getComboInput(
|
|
55
|
+
"fruits",
|
|
56
|
+
["apple", "orange", "banana"],
|
|
57
|
+
callback=callback
|
|
58
|
+
)
|
|
83
59
|
assert label.text() == "fruits"
|
|
84
60
|
allItems = [comboWidget.itemText(i) for i in range(comboWidget.count())]
|
|
85
61
|
assert allItems == ["apple", "orange", "banana"]
|
|
@@ -89,12 +65,12 @@ def testGetComboBox(make_napari_viewer_proxy, mocker):
|
|
|
89
65
|
callback.assert_called_once_with("banana")
|
|
90
66
|
|
|
91
67
|
|
|
92
|
-
def testReplaceItemsInComboBox(make_napari_viewer_proxy
|
|
68
|
+
def testReplaceItemsInComboBox(make_napari_viewer_proxy):
|
|
93
69
|
make_napari_viewer_proxy()
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
70
|
+
_, comboWidget, _ = WidgetTool.getComboInput(
|
|
71
|
+
"fruits",
|
|
72
|
+
["apple", "orange", "banana"]
|
|
73
|
+
)
|
|
98
74
|
WidgetTool.replaceItemsInComboBox(comboWidget, ["lemon", "ananas"])
|
|
99
75
|
allItems = [comboWidget.itemText(i) for i in range(comboWidget.count())]
|
|
100
76
|
assert allItems == ["lemon", "ananas"]
|
|
@@ -108,34 +84,22 @@ def testReplaceItemsInComboBox(make_napari_viewer_proxy, mocker):
|
|
|
108
84
|
|
|
109
85
|
def testGetCheckBox(make_napari_viewer_proxy, mocker):
|
|
110
86
|
make_napari_viewer_proxy()
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
callback)
|
|
118
|
-
assert label in parent.children()
|
|
119
|
-
assert checkbox in parent.children()
|
|
120
|
-
assert checkbox.parent() == parent
|
|
121
|
-
assert label.parent() == parent
|
|
87
|
+
callback = mocker.stub(name="onRemoveBackgroundChanged")
|
|
88
|
+
label, checkbox, _ = WidgetTool.getCheckbox(
|
|
89
|
+
"remove background",
|
|
90
|
+
True,
|
|
91
|
+
callback=callback
|
|
92
|
+
)
|
|
122
93
|
assert label.text() == "remove background"
|
|
123
94
|
assert checkbox.isChecked()
|
|
124
|
-
assert checkbox.maximumWidth() == 50
|
|
125
95
|
checkbox.setChecked(False)
|
|
126
96
|
callback.assert_called_once_with(False)
|
|
127
|
-
|
|
128
|
-
"smooth",
|
|
129
|
-
False,
|
|
130
|
-
50,
|
|
131
|
-
None)
|
|
97
|
+
_, checkbox2, _ = WidgetTool.getCheckbox("smooth", False, callback=None)
|
|
132
98
|
assert not checkbox2.isChecked()
|
|
133
99
|
|
|
134
100
|
|
|
135
|
-
|
|
136
101
|
class TestTableView:
|
|
137
102
|
|
|
138
|
-
|
|
139
103
|
def testConstructor(self, make_napari_viewer_proxy):
|
|
140
104
|
make_napari_viewer_proxy()
|
|
141
105
|
table = {"area": [23.87, 65.28, 12.98], "mean": [19992, 2233, 24553]}
|
|
@@ -144,7 +108,6 @@ class TestTableView:
|
|
|
144
108
|
tableView2 = TableView(None)
|
|
145
109
|
assert not tableView2.data
|
|
146
110
|
|
|
147
|
-
|
|
148
111
|
def testSetData(self, make_napari_viewer_proxy):
|
|
149
112
|
make_napari_viewer_proxy()
|
|
150
113
|
table = {"area": [23.87, 65.28, 12.98], "mean": [19992, 2233, 24553]}
|
|
@@ -153,7 +116,6 @@ class TestTableView:
|
|
|
153
116
|
tableView.setData(table2)
|
|
154
117
|
assert tableView.data == table2
|
|
155
118
|
|
|
156
|
-
|
|
157
119
|
def testResetView(self, make_napari_viewer_proxy):
|
|
158
120
|
make_napari_viewer_proxy()
|
|
159
121
|
table = {"area": [23.87, 65.28, 12.98], "mean": [19992, 2233, 24553]}
|
|
@@ -161,32 +123,39 @@ class TestTableView:
|
|
|
161
123
|
tableView.resetView()
|
|
162
124
|
assert tableView.data == table
|
|
163
125
|
|
|
164
|
-
|
|
165
126
|
def testKeyPressEvent(self, make_napari_viewer_proxy):
|
|
166
127
|
pyperclip.copy("")
|
|
167
128
|
make_napari_viewer_proxy()
|
|
168
129
|
table = {"area": [23.87, 65.28, 12.98], "mean": [19992, 2233, 24553]}
|
|
169
130
|
tableView = TableView(table)
|
|
170
131
|
tableView.selectAll()
|
|
171
|
-
event = QKeyEvent(
|
|
132
|
+
event = QKeyEvent(
|
|
133
|
+
QEvent.Type.KeyPress,
|
|
134
|
+
Qt.Key.Key_C,
|
|
135
|
+
Qt.KeyboardModifier.ControlModifier,
|
|
136
|
+
"copy",
|
|
137
|
+
)
|
|
172
138
|
tableView.keyPressEvent(event)
|
|
173
139
|
text = pyperclip.paste()
|
|
174
140
|
assert "23.87" in text
|
|
175
141
|
assert "24553" in text
|
|
176
142
|
|
|
177
|
-
|
|
178
143
|
def testKeyPressEventNoCopy(self, make_napari_viewer_proxy):
|
|
179
144
|
pyperclip.copy("")
|
|
180
145
|
make_napari_viewer_proxy()
|
|
181
146
|
table = {"area": [23.87, 65.28, 12.98], "mean": [19992, 2233, 24553]}
|
|
182
147
|
tableView = TableView(table)
|
|
183
148
|
tableView.selectAll()
|
|
184
|
-
event = QKeyEvent(
|
|
149
|
+
event = QKeyEvent(
|
|
150
|
+
QEvent.Type.KeyPress,
|
|
151
|
+
Qt.Key.Key_C,
|
|
152
|
+
Qt.KeyboardModifier.ShiftModifier,
|
|
153
|
+
"copy",
|
|
154
|
+
)
|
|
185
155
|
tableView.keyPressEvent(event)
|
|
186
156
|
text = pyperclip.paste()
|
|
187
157
|
assert text == ""
|
|
188
158
|
|
|
189
|
-
|
|
190
159
|
def testCopyDataToClipboard(self, make_napari_viewer_proxy):
|
|
191
160
|
pyperclip.copy("")
|
|
192
161
|
make_napari_viewer_proxy()
|
|
@@ -204,7 +173,6 @@ class TestTableView:
|
|
|
204
173
|
|
|
205
174
|
class TestPlotWidget:
|
|
206
175
|
|
|
207
|
-
|
|
208
176
|
def testConstructor(self, make_napari_viewer_proxy):
|
|
209
177
|
viewer = make_napari_viewer_proxy()
|
|
210
178
|
plot = PlotWidget(viewer)
|
|
@@ -212,7 +180,6 @@ class TestPlotWidget:
|
|
|
212
180
|
assert plot.X == []
|
|
213
181
|
assert plot.Y == []
|
|
214
182
|
|
|
215
|
-
|
|
216
183
|
def testAddData(self, make_napari_viewer_proxy):
|
|
217
184
|
viewer = make_napari_viewer_proxy()
|
|
218
185
|
plot = PlotWidget(viewer)
|
|
@@ -221,7 +188,6 @@ class TestPlotWidget:
|
|
|
221
188
|
assert [1, 4, 9] in plot.Y
|
|
222
189
|
assert "r+" in plot.formatStrings
|
|
223
190
|
|
|
224
|
-
|
|
225
191
|
def testClearData(self, make_napari_viewer_proxy):
|
|
226
192
|
viewer = make_napari_viewer_proxy()
|
|
227
193
|
plot = PlotWidget(viewer)
|
|
@@ -229,7 +195,6 @@ class TestPlotWidget:
|
|
|
229
195
|
plot.clear()
|
|
230
196
|
assert True
|
|
231
197
|
|
|
232
|
-
|
|
233
198
|
def testDisplay(self, make_napari_viewer_proxy):
|
|
234
199
|
viewer = make_napari_viewer_proxy()
|
|
235
200
|
plot = PlotWidget(viewer)
|
|
@@ -242,4 +207,3 @@ class TestPlotWidget:
|
|
|
242
207
|
plot2.display()
|
|
243
208
|
assert plot2.ax.get_xlabel() == plot2.xLabel
|
|
244
209
|
assert plot2.ax.get_ylabel() == plot2.yLabel
|
|
245
|
-
|
{auto_options_python-0.1.6 → auto_options_python-1.0.8}/src/autooptions/_tests/test_widget.py
RENAMED
|
@@ -4,129 +4,147 @@ import numpy as np
|
|
|
4
4
|
from autooptions.widget import OptionsWidget
|
|
5
5
|
from autooptions.options import Options
|
|
6
6
|
|
|
7
|
+
|
|
7
8
|
class FakeEvent:
|
|
8
9
|
modifiers = {}
|
|
9
10
|
|
|
10
11
|
|
|
11
12
|
class TestOptionsWidget:
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
14
|
def onSomethingHappened(self, value):
|
|
16
15
|
self.lastValue = value
|
|
17
16
|
|
|
18
|
-
|
|
19
17
|
@pytest.fixture()
|
|
20
18
|
def options(self):
|
|
21
19
|
options = Options("Autooptions Test", "Widget Test")
|
|
22
|
-
options.addImage(
|
|
23
|
-
options.addLabels(
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
options.addImage("image", value=None, transient=True, optional=(True, False))
|
|
21
|
+
options.addLabels(
|
|
22
|
+
"labels",
|
|
23
|
+
value="labels_layer",
|
|
24
|
+
transient=True,
|
|
25
|
+
optional=(True, True)
|
|
26
|
+
)
|
|
27
|
+
options.addPoints(
|
|
28
|
+
"points",
|
|
29
|
+
value="points_layer",
|
|
30
|
+
transient=True,
|
|
31
|
+
optional=(False, False)
|
|
32
|
+
)
|
|
33
|
+
options.addFFT(
|
|
34
|
+
"fft",
|
|
35
|
+
value=None,
|
|
36
|
+
transient=True,
|
|
37
|
+
optional=(False, True)
|
|
38
|
+
)
|
|
26
39
|
options.addStr("group", value="lps")
|
|
27
|
-
options.addInt(
|
|
28
|
-
options.addInt(
|
|
29
|
-
options.addChoice(
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
options.addInt("size xy", value=3)
|
|
41
|
+
options.addInt("size z", value=1)
|
|
42
|
+
options.addChoice(
|
|
43
|
+
"footprint",
|
|
44
|
+
choices=["none", "cube", "ball", "octahedron"],
|
|
45
|
+
callback=self.onSomethingHappened,
|
|
46
|
+
)
|
|
47
|
+
options.addFloat("sigma", value=1.34)
|
|
48
|
+
options.addBool("do it", value=True)
|
|
32
49
|
yield options
|
|
33
50
|
|
|
51
|
+
def testOptionsCheckboxes(self, options, make_napari_viewer_proxy):
|
|
52
|
+
viewer = make_napari_viewer_proxy()
|
|
53
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
54
|
+
viewer.window.add_dock_widget(widget, name=options.optionsName)
|
|
55
|
+
for name, (cb, _) in widget.widgets.items():
|
|
56
|
+
if options.isOptional(name):
|
|
57
|
+
assert cb is not None
|
|
58
|
+
else:
|
|
59
|
+
assert cb is None
|
|
34
60
|
|
|
35
61
|
def testConstructor(self, options, make_napari_viewer_proxy):
|
|
36
62
|
viewer = make_napari_viewer_proxy()
|
|
37
|
-
widget = OptionsWidget(viewer, options, self)
|
|
63
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
38
64
|
assert widget.options is options
|
|
39
65
|
assert widget.viewer is viewer
|
|
40
66
|
assert widget.client is self
|
|
41
67
|
|
|
42
|
-
|
|
43
68
|
def testAddApplyButton(self, options, make_napari_viewer_proxy, mocker):
|
|
44
69
|
viewer = make_napari_viewer_proxy()
|
|
45
|
-
widget = OptionsWidget(viewer, options, self)
|
|
70
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
46
71
|
assert widget.getApplyButton() is None
|
|
47
|
-
callback = mocker.stub(name=
|
|
72
|
+
callback = mocker.stub(name="onApplyButtonPressed")
|
|
48
73
|
widget.addApplyButton(callback)
|
|
49
74
|
assert not widget.getApplyButton() is None
|
|
50
75
|
assert callback.call_count == 0
|
|
51
76
|
|
|
52
|
-
|
|
53
77
|
def testAddOKButton(self, options, make_napari_viewer_proxy, mocker):
|
|
54
78
|
viewer = make_napari_viewer_proxy()
|
|
55
|
-
widget = OptionsWidget(viewer, options, self)
|
|
79
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
56
80
|
assert widget.getOKButton() is None
|
|
57
|
-
callback = mocker.stub(name=
|
|
81
|
+
callback = mocker.stub(name="onOKButtonPressed")
|
|
58
82
|
widget.addOKButton(callback)
|
|
59
83
|
assert not widget.getOKButton() is None
|
|
60
84
|
assert callback.call_count == 0
|
|
61
85
|
|
|
62
|
-
|
|
63
86
|
def testAddCancelButton(self, options, make_napari_viewer_proxy, mocker):
|
|
64
87
|
viewer = make_napari_viewer_proxy()
|
|
65
|
-
widget = OptionsWidget(viewer, options, self)
|
|
88
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
66
89
|
assert widget.getCancelButton() is None
|
|
67
|
-
callback = mocker.stub(name=
|
|
90
|
+
callback = mocker.stub(name="onCancelButtonPressed")
|
|
68
91
|
widget.addCancelButton(callback)
|
|
69
92
|
assert not widget.getCancelButton() is None
|
|
70
93
|
assert callback.call_count == 0
|
|
71
94
|
|
|
72
|
-
|
|
73
95
|
def test_OnApplyButtonClicked(self, options, make_napari_viewer_proxy, mocker):
|
|
74
96
|
viewer = make_napari_viewer_proxy()
|
|
75
|
-
widget = OptionsWidget(viewer, options, self)
|
|
76
|
-
callback = mocker.stub(name=
|
|
97
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
98
|
+
callback = mocker.stub(name="self.apply")
|
|
77
99
|
widget.addApplyButton(callback)
|
|
78
|
-
options.setValue(
|
|
100
|
+
options.setValue("group", "xps")
|
|
79
101
|
if os.path.exists(options.optionsPath):
|
|
80
102
|
os.remove(options.optionsPath)
|
|
81
103
|
widget._onApplyButtonClicked()
|
|
82
104
|
assert os.path.exists(options.optionsPath)
|
|
83
105
|
assert options.value("group") == "lps"
|
|
84
106
|
|
|
85
|
-
|
|
86
107
|
def test_OnOKButtonClicked(self, options, make_napari_viewer_proxy, mocker):
|
|
87
108
|
viewer = make_napari_viewer_proxy()
|
|
88
|
-
widget = OptionsWidget(viewer, options, self)
|
|
89
|
-
callback = mocker.stub(name=
|
|
109
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
110
|
+
callback = mocker.stub(name="self.ok")
|
|
90
111
|
widget.addOKButton(callback)
|
|
91
112
|
viewer.window.add_dock_widget(widget, name=options.optionsName)
|
|
92
|
-
options.setValue(
|
|
113
|
+
options.setValue("group", "xps")
|
|
93
114
|
if os.path.exists(options.optionsPath):
|
|
94
115
|
os.remove(options.optionsPath)
|
|
95
116
|
widget._onOKButtonClicked()
|
|
96
117
|
assert os.path.exists(options.optionsPath)
|
|
97
118
|
assert options.value("group") == "lps"
|
|
98
119
|
|
|
99
|
-
|
|
100
120
|
def test_OnCancelButtonClicked(self, options, make_napari_viewer_proxy, mocker):
|
|
101
121
|
viewer = make_napari_viewer_proxy()
|
|
102
|
-
widget = OptionsWidget(viewer, options, self)
|
|
103
|
-
callback = mocker.stub(name=
|
|
122
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
123
|
+
callback = mocker.stub(name="self.cancel")
|
|
104
124
|
widget.addCancelButton(callback)
|
|
105
125
|
viewer.window.add_dock_widget(widget, name=options.optionsName)
|
|
106
|
-
options.setValue(
|
|
126
|
+
options.setValue("group", "xps")
|
|
107
127
|
if os.path.exists(options.optionsPath):
|
|
108
128
|
os.remove(options.optionsPath)
|
|
109
129
|
widget._onCancelButtonClicked()
|
|
110
130
|
assert not os.path.exists(options.optionsPath)
|
|
111
131
|
assert options.value("group") == "xps"
|
|
112
132
|
|
|
113
|
-
|
|
114
133
|
def test_OnLayerAddedOrRemoved(self, options, make_napari_viewer_proxy):
|
|
115
134
|
viewer = make_napari_viewer_proxy()
|
|
116
|
-
widget = OptionsWidget(viewer, options, self)
|
|
135
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
117
136
|
viewer.window.add_dock_widget(widget, name=options.optionsName)
|
|
118
137
|
data = np.random.rand(12, 12)
|
|
119
|
-
viewer.add_image(data=data, name=
|
|
138
|
+
viewer.add_image(data=data, name="data")
|
|
120
139
|
assert True
|
|
121
140
|
|
|
122
|
-
|
|
123
141
|
def testGetImageLayer(self, options, make_napari_viewer_proxy):
|
|
124
142
|
viewer = make_napari_viewer_proxy()
|
|
125
|
-
widget = OptionsWidget(viewer, options, self)
|
|
143
|
+
widget = OptionsWidget(viewer, options, client=self)
|
|
126
144
|
viewer.window.add_dock_widget(widget, name=options.optionsName)
|
|
127
145
|
data = np.random.rand(12, 12)
|
|
128
|
-
viewer.add_image(data=data, name=
|
|
146
|
+
viewer.add_image(data=data, name="labels_layer")
|
|
129
147
|
layer = widget.getImageLayer("labels")
|
|
130
148
|
assert layer is not None
|
|
131
149
|
assert layer.name == "labels_layer"
|
|
132
|
-
assert layer.data.shape == (12, 12)
|
|
150
|
+
assert layer.data.shape == (12, 12)
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.
|
|
22
|
-
__version_tuple__ = version_tuple = (
|
|
21
|
+
__version__ = version = '1.0.8'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 8)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g8b8e2d997'
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from autooptions.layouts.grid_layout import GridLayout
|
|
2
|
+
from autooptions.layouts.vertical_layout import VerticalLayout
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class LayoutFactory(object):
|
|
6
|
+
|
|
7
|
+
availableLayouts = {"grid": GridLayout, "vertical": VerticalLayout}
|
|
8
|
+
|
|
9
|
+
defaultLayout = GridLayout
|
|
10
|
+
|
|
11
|
+
def get(self, layout_type):
|
|
12
|
+
return self.availableLayouts.get(layout_type, self.defaultLayout)
|
|
13
|
+
|
|
14
|
+
@staticmethod
|
|
15
|
+
def createLayout(layout_type, same_row_set=None, parent=None):
|
|
16
|
+
if type(layout_type) is str:
|
|
17
|
+
layout_name = layout_type.lower()
|
|
18
|
+
layout_args = {}
|
|
19
|
+
elif type(layout_type) is dict:
|
|
20
|
+
layout_name = layout_type.get("name", "vertical").lower()
|
|
21
|
+
layout_args = {k: v for k, v in layout_type.items() if k != "name"}
|
|
22
|
+
else:
|
|
23
|
+
raise ValueError(f"Invalid layout_type: {layout_type}")
|
|
24
|
+
layoutConstructor = LayoutFactory.availableLayouts.get(
|
|
25
|
+
layout_name, LayoutFactory.defaultLayout
|
|
26
|
+
)
|
|
27
|
+
return layoutConstructor(
|
|
28
|
+
same_row_set=same_row_set, parent=parent, **layout_args
|
|
29
|
+
)
|