summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKirill Podoprigora <kirill.bast9@mail.ru>2024-02-10 14:37:19 (GMT)
committerGitHub <noreply@github.com>2024-02-10 14:37:19 (GMT)
commit5319c66550a6d6c6698dea75c0a0ee005873ce61 (patch)
tree6aab2c3b999e17a9e625157f81d226838c307927
parent597fad07f7bf709ac7084ac20aa3647995759b01 (diff)
downloadcpython-5319c66550a6d6c6698dea75c0a0ee005873ce61.zip
cpython-5319c66550a6d6c6698dea75c0a0ee005873ce61.tar.gz
cpython-5319c66550a6d6c6698dea75c0a0ee005873ce61.tar.bz2
gh-102840: Fix confused traceback when floordiv or mod operations happens between Fraction and complex objects (GH-102842)
-rw-r--r--Lib/fractions.py13
-rw-r--r--Lib/test/test_fractions.py27
-rw-r--r--Misc/NEWS.d/next/Library/2024-02-10-15-24-20.gh-issue-102840.4mnDq1.rst3
3 files changed, 37 insertions, 6 deletions
diff --git a/Lib/fractions.py b/Lib/fractions.py
index 389ab38..f8c6c9c 100644
--- a/Lib/fractions.py
+++ b/Lib/fractions.py
@@ -579,7 +579,8 @@ class Fraction(numbers.Rational):
f"for object of type {type(self).__name__!r}"
)
- def _operator_fallbacks(monomorphic_operator, fallback_operator):
+ def _operator_fallbacks(monomorphic_operator, fallback_operator,
+ handle_complex=True):
"""Generates forward and reverse operators given a purely-rational
operator and a function from the operator module.
@@ -666,7 +667,7 @@ class Fraction(numbers.Rational):
return monomorphic_operator(a, Fraction(b))
elif isinstance(b, float):
return fallback_operator(float(a), b)
- elif isinstance(b, complex):
+ elif handle_complex and isinstance(b, complex):
return fallback_operator(complex(a), b)
else:
return NotImplemented
@@ -679,7 +680,7 @@ class Fraction(numbers.Rational):
return monomorphic_operator(Fraction(a), b)
elif isinstance(a, numbers.Real):
return fallback_operator(float(a), float(b))
- elif isinstance(a, numbers.Complex):
+ elif handle_complex and isinstance(a, numbers.Complex):
return fallback_operator(complex(a), complex(b))
else:
return NotImplemented
@@ -830,7 +831,7 @@ class Fraction(numbers.Rational):
"""a // b"""
return (a.numerator * b.denominator) // (a.denominator * b.numerator)
- __floordiv__, __rfloordiv__ = _operator_fallbacks(_floordiv, operator.floordiv)
+ __floordiv__, __rfloordiv__ = _operator_fallbacks(_floordiv, operator.floordiv, False)
def _divmod(a, b):
"""(a // b, a % b)"""
@@ -838,14 +839,14 @@ class Fraction(numbers.Rational):
div, n_mod = divmod(a.numerator * db, da * b.numerator)
return div, Fraction(n_mod, da * db)
- __divmod__, __rdivmod__ = _operator_fallbacks(_divmod, divmod)
+ __divmod__, __rdivmod__ = _operator_fallbacks(_divmod, divmod, False)
def _mod(a, b):
"""a % b"""
da, db = a.denominator, b.denominator
return Fraction((a.numerator * db) % (b.numerator * da), da * db)
- __mod__, __rmod__ = _operator_fallbacks(_mod, operator.mod)
+ __mod__, __rmod__ = _operator_fallbacks(_mod, operator.mod, False)
def __pow__(a, b):
"""a ** b
diff --git a/Lib/test/test_fractions.py b/Lib/test/test_fractions.py
index af3cb21..b45bd09 100644
--- a/Lib/test/test_fractions.py
+++ b/Lib/test/test_fractions.py
@@ -1314,6 +1314,33 @@ class FractionTest(unittest.TestCase):
self.assertEqual(float(format(f, fmt2)), float(rhs))
self.assertEqual(float(format(-f, fmt2)), float('-' + rhs))
+ def test_complex_handling(self):
+ # See issue gh-102840 for more details.
+
+ a = F(1, 2)
+ b = 1j
+ message = "unsupported operand type(s) for %s: '%s' and '%s'"
+ # test forward
+ self.assertRaisesMessage(TypeError,
+ message % ("%", "Fraction", "complex"),
+ operator.mod, a, b)
+ self.assertRaisesMessage(TypeError,
+ message % ("//", "Fraction", "complex"),
+ operator.floordiv, a, b)
+ self.assertRaisesMessage(TypeError,
+ message % ("divmod()", "Fraction", "complex"),
+ divmod, a, b)
+ # test reverse
+ self.assertRaisesMessage(TypeError,
+ message % ("%", "complex", "Fraction"),
+ operator.mod, b, a)
+ self.assertRaisesMessage(TypeError,
+ message % ("//", "complex", "Fraction"),
+ operator.floordiv, b, a)
+ self.assertRaisesMessage(TypeError,
+ message % ("divmod()", "complex", "Fraction"),
+ divmod, b, a)
+
if __name__ == '__main__':
unittest.main()
diff --git a/Misc/NEWS.d/next/Library/2024-02-10-15-24-20.gh-issue-102840.4mnDq1.rst b/Misc/NEWS.d/next/Library/2024-02-10-15-24-20.gh-issue-102840.4mnDq1.rst
new file mode 100644
index 0000000..52668a9
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-02-10-15-24-20.gh-issue-102840.4mnDq1.rst
@@ -0,0 +1,3 @@
+Fix confused traceback when floordiv, mod, or divmod operations happens
+between instances of :class:`fractions.Fraction` and :class:`complex`.
+