-
Notifications
You must be signed in to change notification settings - Fork 2
Added desired units and tests #188
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #188 +/- ##
===========================================
+ Coverage 81.15% 81.22% +0.07%
===========================================
Files 52 52
Lines 4267 4283 +16
Branches 740 744 +4
===========================================
+ Hits 3463 3479 +16
Misses 624 624
Partials 180 180
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This pull request does not contain a valid label. Please add one of the following labels: ['[scope] bug', '[scope] enhancement', '[scope] documentation', '[scope] significant', '[scope] maintenance']
| try: | ||
| self._convert_unit(self._desired_unit) | ||
| except Exception as e: | ||
| raise UnitError(f'Failed to convert unit from {temporary_parameter.unit} to {self._desired_unit}: {e}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we completely bail out on bad unit conversion? Maybe return the original value with the original unit and warn users of the failure of the unit conversion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, good question. I tend to think yes, since something must have gone wrong if the user expects a unit that is incompatible with the calculated unit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this check down to the make_dependent_on method and do a _revert_dependency if it fails.
Like with all our other checks. The update method should have no checks.
The dependency_result can be converted to try it out.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I moved the check. Update only checks if self._desired_unit is not None
damskii9992
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't simply call this argument "unit", it is too vague and can be understood as it can be anything. Maybe "unit_format"? Or something similar.
|
|
||
| if self._independent: | ||
| raise AttributeError('This is an independent parameter, desired unit can only be set for dependent parameters.') | ||
| self._desired_unit = unit_str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is missing a check on the type of unit_str
| try: | ||
| self._convert_unit(self._desired_unit) | ||
| except Exception as e: | ||
| raise UnitError(f'Failed to convert unit from {temporary_parameter.unit} to {self._desired_unit}: {e}') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would move this check down to the make_dependent_on method and do a _revert_dependency if it fails.
Like with all our other checks. The update method should have no checks.
The dependency_result can be converted to try it out.
The argument 'unit' is already used at least in tests, e.g. the following, so I'm hesitant to change it. Thoughts? |
Why does it matter that it is already used in tests? O.o That would literally be the case for any name changes we do XD |
Well it might not matter, it's just that that implies that people might rely on this behavior. But maybe we shouldn't allow a unit in Edit: the point is that |
Ahh, in this case it is simply the test that is wrong. The "unit" is a kwarg passed to the Parameter constructor, but it gets overwritten so it is a redundant argument. |
rozyczko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few issues noted.
|
|
||
| if self._desired_unit is not None: | ||
| try: | ||
| dependency_result._convert_unit(self._desired_unit) | ||
| except Exception as e: | ||
| raise UnitError(f'Failed to convert unit from {dependency_result.unit} to {self._desired_unit}: {e}') | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When the unit conversion fails, the code raises a UnitError but does not call _revert_dependency() first, leaving the parameter in an inconsistent state if unit conversion fails.
This is inconsistent with all other validation checks in make_dependent_on() that properly revert the dependency state before raising.
| def set_desired_unit(self, unit_str: str) -> None: | ||
| """ | ||
| Set the desired unit for a dependent Parameter. This will convert the parameter to the desired unit. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make_dependent_on and from_dependency methods accept unit: str | sc.Unit | None but this only takes str - is this expected?
| self, dependency_expression: str, dependency_map: Optional[dict] = None, unit: str | sc.Unit | None = None | ||
| ) -> None: | ||
| """ | ||
| Make this parameter dependent on another parameter. This will overwrite the current value, unit, variance, min and max. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no validation on unit type. A user can pass unit=1234 and this will get accepted.
| '_dependency_string': self._dependency_string, | ||
| '_dependency_map': self._dependency_map, | ||
| '_dependency_interpreter': self._dependency_interpreter, | ||
| '_clean_dependency_string': self._clean_dependency_string, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You forgot to add _desired_unit to previous dependency
| self._convert_unit(self._desired_unit) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_convert_unit doesn't catch any exceptions and we aren't checking anything here. Maybe add some exception handling so it doesn't bubble up potentially leaving the parameter in a weird state?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is on purpose. To keep the _update method as fast as possible, all the checks are made in the make_dependent_on method. If this method succeeds, then the _update will also always succeed.
This is also how we did it for the other updates :)
| normal_parameter.value == 4 | ||
| self.compare_parameters(normal_parameter, 2*independent_parameter) | ||
|
|
||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no test verifying that _desired_unit is properly handled when calling make_dependent_on on an already-dependent parameter (i.e., overwriting an existing dependency).
Added desired units for the dependent parameter constructors, and a method to change it later:
set_desired_unit