-
-
Notifications
You must be signed in to change notification settings - Fork 34.4k
bpo-39274: Ensure Fraction.__bool__ returns a bool
#18017
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,6 +6,7 @@ | |
| import numbers | ||
| import operator | ||
| import fractions | ||
| import functools | ||
| import sys | ||
| import unittest | ||
| import warnings | ||
|
|
@@ -346,6 +347,42 @@ def testConversions(self): | |
|
|
||
| self.assertTypedEquals(0.1+0j, complex(F(1,10))) | ||
|
|
||
| def testBoolGuarateesBoolReturn(self): | ||
| # Ensure that __bool__ is used on numerator which guarantees a bool | ||
| # return. See also bpo-39274. | ||
| @functools.total_ordering | ||
| class CustomValue: | ||
| denominator = 1 | ||
|
|
||
| def __init__(self, value): | ||
| self.value = value | ||
|
|
||
| def __bool__(self): | ||
| return bool(self.value) | ||
|
||
|
|
||
| @property | ||
| def numerator(self): | ||
| # required to preserve `self` during instantiation | ||
| return self | ||
|
||
|
|
||
| def __eq__(self, other): | ||
| raise AssertionError("Avoid comparisons in Fraction.__bool__") | ||
|
|
||
| __lt__ = __eq__ | ||
|
|
||
| # We did not implement all abstract methods, so register: | ||
| numbers.Rational.register(CustomValue) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may fail if you run the test with reference leak test: ./python -m test -R 3:3 test_fractions Can you check that it does not leak? I would prefer to avoid .register() if it does leak. ... This test is getting more and more complex... Maybe we should just ignore the test and just merge the fix. What do you think @mdickinson?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmmm, seems to work: I have not used the python refcount checker, so not sure if it clears ABCs are not.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The fix itself looks good to me; I think we should merge as is. |
||
|
|
||
| numerator = CustomValue(1) | ||
| r = F(numerator) | ||
|
||
| # ensure the numerator was not lost during instantiation: | ||
| self.assertIs(r.numerator, numerator) | ||
| self.assertIs(bool(r), True) | ||
|
|
||
| numerator = CustomValue(0) | ||
| r = F(numerator) | ||
| self.assertIs(bool(r), False) | ||
|
|
||
| def testRound(self): | ||
| self.assertTypedEquals(F(-200), round(F(-150), -2)) | ||
| self.assertTypedEquals(F(-200), round(F(-250), -2)) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ``bool(fraction.Fraction)`` now returns a boolean even if (numerator != 0) does not return a boolean (ex: numpy number). |
Uh oh!
There was an error while loading. Please reload this page.