diff --git a/src/easyscience/variable/descriptor_number.py b/src/easyscience/variable/descriptor_number.py index 7d35ca0..38b233f 100644 --- a/src/easyscience/variable/descriptor_number.py +++ b/src/easyscience/variable/descriptor_number.py @@ -423,16 +423,13 @@ def __rmul__(self, other: numbers.Number) -> DescriptorNumber: def __truediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> DescriptorNumber: if isinstance(other, numbers.Number): - original_other = other if other == 0: raise ZeroDivisionError('Cannot divide by zero') new_value = self.full_value / other elif type(other) is DescriptorNumber: - original_other = other.value - if original_other == 0: + if other.value == 0: raise ZeroDivisionError('Cannot divide by zero') new_value = self.full_value / other.full_value - other.value = original_other else: return NotImplemented descriptor_number = DescriptorNumber.from_scipp(name=self.name, full_value=new_value) diff --git a/src/easyscience/variable/parameter.py b/src/easyscience/variable/parameter.py index 55787ad..ca00732 100644 --- a/src/easyscience/variable/parameter.py +++ b/src/easyscience/variable/parameter.py @@ -877,7 +877,6 @@ def __truediv__(self, other: Union[DescriptorNumber, Parameter, numbers.Number]) combinations = [self.min / other.min, self.max / other.max, self.min / other.max, self.max / other.min] else: combinations = [self.min / other.value, self.max / other.value] - other.value = other_value else: return NotImplemented min_value = min(combinations) @@ -926,7 +925,6 @@ def __rtruediv__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parame parameter = Parameter.from_scipp(name=self.name, full_value=new_full_value, min=min_value, max=max_value) parameter._convert_unit(parameter._base_unit()) parameter.name = parameter.unique_name - self.value = original_self return parameter def __pow__(self, other: Union[DescriptorNumber, numbers.Number]) -> Parameter: diff --git a/tests/unit_tests/variable/test_parameter.py b/tests/unit_tests/variable/test_parameter.py index 0ca8f85..738497c 100644 --- a/tests/unit_tests/variable/test_parameter.py +++ b/tests/unit_tests/variable/test_parameter.py @@ -388,6 +388,51 @@ def test_dependent_parameter_return_is_descriptor_number(self): assert dependent_parameter.min == 2*descriptor_number.value assert dependent_parameter.max == 2*descriptor_number.value + def test_dependent_parameter_division_expression_order(self): + """Test that division expressions work regardless of operand order. + + This is a regression test for https://github.com/easyscience/corelib/issues/190 + where 'a / b' would fail with an observer notification error while '1/b * a' + would work correctly. + """ + # When + angstrom = DescriptorNumber("angstrom", 1e-10, unit="m") + jump_length = Parameter( + name="jump_length", + value=float(1.0), + fixed=False, + unit="angstrom", + ) + + expression = "jump_length / angstrom" + dependency_map = { + "jump_length": jump_length, + "angstrom": angstrom, + } + + # Calculate the expected result from direct division + expected_result = jump_length / angstrom + expected_value = expected_result.value + + # Then - This should not raise an error + dependent_param = Parameter(name='a', value=1.0) + dependent_param.make_dependent_on( + dependency_expression=expression, + dependency_map=dependency_map, + ) + + # Expect - The dependent parameter should have the same value as the direct division + assert dependent_param.value == pytest.approx(expected_value) + + # Also test the alternative expression that previously worked + expression_alt = "1/angstrom * jump_length" + dependent_param_alt = Parameter(name='b', value=1.0) + dependent_param_alt.make_dependent_on( + dependency_expression=expression_alt, + dependency_map=dependency_map, + ) + assert dependent_param_alt.value == pytest.approx(expected_value) + def test_dependent_parameter_overwrite_dependency(self, normal_parameter: Parameter): # When dependent_parameter = Parameter.from_dependency( @@ -1221,4 +1266,4 @@ def test_abs(self, test, expected): assert result.unit == expected.unit assert result.variance == expected.variance assert result.min == expected.min - assert result.max == expected.max \ No newline at end of file + assert result.max == expected.max