Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/easyscience/variable/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ def _update(self) -> None:
if self._desired_unit is not None:
self._convert_unit(self._desired_unit)

if self._callback.fset is not None:
self._callback.fset(self._scalar.value)

self._notify_observers()
else:
global_object.log.getLogger('variable').warning(
Expand Down
58 changes: 58 additions & 0 deletions tests/unit/variable/test_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,64 @@ def test_make_dependent_on(self, normal_parameter: Parameter):
normal_parameter.value == 4
self.compare_parameters(normal_parameter, 2 * independent_parameter)

def test_dependent_parameter_update_pushes_value_to_callback(self, parameter: Parameter):
# When # Simulate a calculator bound to the parameter via the callback (issue #281)
calculator = {'value': parameter._scalar.value}
self.mock_callback.fget.side_effect = lambda: calculator['value']
self.mock_callback.fset.side_effect = lambda value: calculator.update(value=value)
independent_parameter = Parameter(
name='independent', value=1, unit='m', variance=0.01, min=0, max=10
)

# Then
parameter.make_dependent_on(
dependency_expression='2*a', dependency_map={'a': independent_parameter}
)

# Expect # Making the parameter dependent pushes the computed value to the calculator
assert calculator['value'] == 2.0
self.mock_callback.fset.assert_called_with(2.0)
assert self.mock_callback.fset.call_count == 1

# Then
independent_parameter.value = 3

# Expect # The change of the independent parameter propagates to the calculator
assert calculator['value'] == 6.0
self.mock_callback.fset.assert_called_with(6.0)
assert self.mock_callback.fset.call_count == 2
# Reading the value must not return a stale calculator value
assert parameter.value == 6.0

def test_dependent_parameter_update_pushes_value_to_callback_with_desired_unit(
self, parameter: Parameter
):
# When # Simulate a calculator bound to the parameter via the callback (issue #281)
calculator = {'value': parameter._scalar.value}
self.mock_callback.fget.side_effect = lambda: calculator['value']
self.mock_callback.fset.side_effect = lambda value: calculator.update(value=value)
independent_parameter = Parameter(
name='independent', value=1, unit='m', variance=0.01, min=0, max=10
)

# Then
parameter.make_dependent_on(
dependency_expression='2*a',
dependency_map={'a': independent_parameter},
desired_unit='cm',
)

# Expect # The calculator receives the value converted to the desired unit
assert calculator['value'] == 200.0
self.mock_callback.fset.assert_called_with(200.0)

# Then
independent_parameter.value = 2

# Expect
assert calculator['value'] == 400.0
assert parameter.value == 400.0

def test_dependent_parameter_make_dependent_on_with_desired_unit(
self, normal_parameter: Parameter
):
Expand Down