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
4 changes: 3 additions & 1 deletion Lib/fractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,9 @@ def __ge__(a, b):

def __bool__(a):
"""a != 0"""
return a._numerator != 0
# bpo-39274: Use bool() because (a._numerator != 0) can return an
# object which is not a bool.
return bool(a._numerator)

# support for pickling, copy, and deepcopy

Expand Down
37 changes: 37 additions & 0 deletions Lib/test/test_fractions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import numbers
import operator
import fractions
import functools
import sys
import unittest
import warnings
Expand Down Expand Up @@ -335,6 +336,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)

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))
Expand Down
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).