-
Notifications
You must be signed in to change notification settings - Fork 64
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
warn about using floor division of durations #58
Conversation
First off, this is definitely an improvement over what the current behavour is, so thanks for that! I think a
This default behavour is at least meaningful - integer division is well-defined on scalars, and has "round to the nearest" semantics. As it is currently implemented on Durations, these semantics are broken.
It's not terrible, but I think it violates d = Duration(...)
f = float(...)
d_divrounded = d // f Can be more clearly written and generically as
There's probably a good argument for a Ultimately I go go either way on this one though,
With this choice, for a Duration |
I think the best answer is just that we should exactly match the behavior of # python 3.5
>>> dt = timedelta(seconds=1, microseconds=500000)
>>> str(dt)
'0:00:01.500000'
>>> str(dt / 2)
'0:00:00.750000'
>>> str(dt // 2)
'0:00:00.750000'
>>> str(dt / 2.0)
'0:00:00.750000'
>>> str(dt // 2.0)
Traceback (most recent call last):
File "<pyshell#48>", line 1, in <module>
str(dt // 2.0)
TypeError: unsupported operand type(s) for //: 'datetime.timedelta' and 'float'
>>> dt // dt
1
>>> dt / dt
1.0 |
3edb2f0
to
f4ca9c7
Compare
I don't think that a We discussed this in our weekly meeting and will go with these warning for Indigo and Jade. For Kinetic the warning will be removed and the logic for integer division will be updated to behave like the float division. This will imply that Python 2 users not using the future import will use floor division (as with any other division). I have also updated the warnings to mention the option to change the divisor to be a float. |
@ros/ros_team @eric-wieser Please review that this can be merged and released as is into Indigo and Jade. I will create the Kinetic branch after that. |
lgtm |
warnings.warn( | ||
'The Duration.__floordiv__(integer) function is ill-defined. ' | ||
'The floor operation is applied independently on the seconds as well as the nanoseconds. ' | ||
'For true division use a float divisor or the operator `/` (which requires `from __future__ import division` in Python 2) or `__truediv__` instead.', |
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.
Using a float divisor here results in rounding to the nearest second, and does not result in "true division". This warning and/or the docstring should mention the round to the nearest second behavior, If you're not going to mention the correct behavior for floats, there's little point keeping __floordiv__
around at all in kinetic
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 have removed the comment about the float divisor from __floordiv__
. That only makes sense for __div__
where using floats actually makes a difference. Good catch.
I was not aware that If you're set on floor division existing at all, then the kinetic migration path sounds good to me. I don't think I'm really qualified to make a judgement on what can and can't be changed in released versions of ROS. Given that you'd prefer not to change it, this patch looks good to me (modulo my line--comment above) |
f4ca9c7
to
40665c0
Compare
warnings.warn( | ||
'The Duration.__floordiv__(integer) function is ill-defined. ' | ||
'The floor operation is applied independently on the seconds as well as the nanoseconds. ' | ||
'For true division use the operator `/` (which requires `from __future__ import division` in Python 2) or `__truediv__` instead.', |
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 seems to advise direct use of __truediv__
- calling magic methods directly is not recommended, as inevitably their semantics don't quite match the operator they implement. operator.truediv
is a better substitute here, because that can correctly deal with NotImplemented
and __rdiv__
.
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 updated it to mention operator.truediv
instead. Thanks.
40665c0
to
39dcc51
Compare
warnings.warn( | ||
'The Duration.__floordiv__(integer) function is ill-defined. ' | ||
'The floor operation is applied independently on the seconds as well as the nanoseconds. ' | ||
'For true division use the operator `/` (which requires `from __future__ import division` in Python 2) or `operator.truediv` instead.', |
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 think there should be a "For division rounding to the nearest second, use a float divisor" here as well, unless you plan to scrap floordiv entirely in kinetic
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 don't understand what the message is aiming for. floor
is not equal to rounding to nearest seconds
?
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.
Nvm. Will updated the PR with another line added to the warning: https://github.com/ros/genpy/pull/58/files#diff-305939312869835e69b57abda55dd404R402
39dcc51
to
795b170
Compare
Looks good to me |
Thank you @eric-wieser for iterating on this. |
And the followup PR for kinetic: #59. |
Fixes #49.
This adds a
RuntimeWarning
for using floor division with integer dividers. Imo it is reasonable to add this warning to all supported distros since it is informing the user that something unexpected is going on. I don't see a use case where this behavior is actually intended. If existing code currently uses this it will result in a warning and the code an easily be updated.Regarding the question if the class should always implement true division (for all or only newer ROS distros): Python has the same situation when doing integer division. Some might call it really bad default behavior but that's how Python does it. And there is a clean way (
from __future__ import division
) to explicitly use true division (which is the same across division operations across various types). Therefore I think it is reasonable to not change the current implementation.A division by float already does a true division. And if the user requests an explicit float division that is what he wants. The fact that is performs the floor on seconds is reasonable imo. Updating the integer version of the function to return a more similar result is not necessary since the recommendation is to not use the function in the first place.
@ros/ros_team @eric-wieser Please review this carefully to be considered for merge and release as mentioned.