Skip to content

Commit 09cdf92

Browse files
committed
Add FuncPropMulti operator property and update tests for complex dependencies
1 parent 48f2a42 commit 09cdf92

4 files changed

Lines changed: 66 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44

55
💥 New features:
66

7+
* New operator property `FuncPropMulti` for handling multiple properties:
8+
* This property allows you to apply a function to multiple item properties at once.
9+
* It can be used to create more complex dependencies between items in a dataset.
10+
* See the `guidata.tests.dataset.test_activable_items` module for an example of usage.
11+
712
* New script `gbuild` for building the package:
813
* This script is a wrapper around the `guidata.utils.securebuild` module, which ensures that the build process is secure and reproducible.
914
* It checks that the `pyproject.toml` file is present in the root of the repository, and that it is committed to Git.

guidata/dataset/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
EndTabGroup,
4848
FormatProp,
4949
FuncProp,
50+
FuncPropMulti,
5051
GetAttrProp,
5152
GroupItem,
5253
ItemProperty,

guidata/dataset/datatypes.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@
5353
5454
.. autoclass:: guidata.dataset.FuncProp
5555
:members:
56+
57+
.. autoclass:: guidata.dataset.FuncPropMulti
58+
:members:
5659
"""
5760

5861
# pylint: disable-msg=W0622
@@ -249,6 +252,42 @@ def set(self, instance: DataSet, item: DataItem, value: Any) -> None:
249252
self.property.set(instance, item, self.inverse_function(value))
250253

251254

255+
class FuncPropMulti(ItemProperty):
256+
"""An 'operator property' for multiple properties
257+
258+
Args:
259+
props (list[ItemProperty]): properties to apply function to
260+
func (function): function to apply
261+
invfunc (function): inverse function (default: func)
262+
"""
263+
264+
def __init__(
265+
self,
266+
props: list[ItemProperty],
267+
func: Callable,
268+
invfunc: Callable | None = None,
269+
) -> None:
270+
self.properties = props
271+
self.function = func
272+
if invfunc is None:
273+
invfunc = func
274+
self.inverse_function = invfunc
275+
276+
def __call__(self, instance: DataSet, item: DataItem, value: Any) -> Any:
277+
return self.function(*[prop(instance, item, value) for prop in self.properties])
278+
279+
def set(self, instance: DataSet, item: DataItem, value: Any) -> None:
280+
"""Sets the value of the property given an instance, item and value
281+
282+
Args:
283+
instance (DataSet): instance of the DataSet
284+
item (Any): item to set the value of
285+
value (Any): value to set
286+
"""
287+
for prop in self.properties:
288+
prop.set(instance, item, self.inverse_function(value))
289+
290+
252291
class DataItem(ABC):
253292
"""DataSet data item
254293

guidata/tests/dataset/test_activable_items.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,29 +10,35 @@
1010

1111
# guitest: show
1212

13-
from guidata.dataset import (
14-
BoolItem,
15-
ChoiceItem,
16-
DataSet,
17-
FloatItem,
18-
FuncProp,
19-
GetAttrProp,
20-
)
13+
import guidata.dataset as gds
2114
from guidata.env import execenv
2215
from guidata.qthelpers import qt_app_context
2316

2417
choices = (("A", "Choice #1: A"), ("B", "Choice #2: B"), ("C", "Choice #3: C"))
2518

2619

27-
class Parameters(DataSet):
20+
class Parameters(gds.DataSet):
2821
"""Example dataset"""
2922

30-
_prop = GetAttrProp("choice")
31-
choice = ChoiceItem("Choice", choices).set_prop("display", store=_prop)
32-
x1 = FloatItem("x1")
33-
x2 = FloatItem("x2").set_prop("display", active=FuncProp(_prop, lambda x: x == "B"))
34-
x3 = FloatItem("x3").set_prop("display", active=FuncProp(_prop, lambda x: x == "C"))
35-
b1 = BoolItem("b1").set_prop("display", active=FuncProp(_prop, lambda x: x == "C"))
23+
_prop1 = gds.GetAttrProp("choice1")
24+
choice1 = gds.ChoiceItem("Choice 1", choices).set_prop("display", store=_prop1)
25+
_prop2 = gds.GetAttrProp("choice2")
26+
choice2 = gds.ChoiceItem("Choice 2", choices).set_prop("display", store=_prop2)
27+
x1 = gds.FloatItem("x1")
28+
x2 = gds.FloatItem("x2").set_prop(
29+
"display", active=gds.FuncProp(_prop1, lambda x: x == "B")
30+
)
31+
x3 = gds.FloatItem("x3").set_prop(
32+
"display", active=gds.FuncProp(_prop1, lambda x: x == "C")
33+
)
34+
b1 = gds.BoolItem("A and C").set_prop(
35+
"display",
36+
active=gds.FuncPropMulti([_prop1, _prop2], lambda x, y: x == "A" and y == "C"),
37+
)
38+
b2 = gds.BoolItem("A or B").set_prop(
39+
"display",
40+
active=gds.FuncPropMulti([_prop1, _prop2], lambda x, y: x == "A" or y == "B"),
41+
)
3642

3743

3844
def test_activable_items():

0 commit comments

Comments
 (0)