mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00
Improve tests for str to Fraction conversion (GH-134010)
This commit is contained in:
parent
0afbd4e42a
commit
17d0fec702
1 changed files with 97 additions and 110 deletions
|
@ -1,7 +1,7 @@
|
||||||
"""Tests for Lib/fractions.py."""
|
"""Tests for Lib/fractions.py."""
|
||||||
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from test.support import requires_IEEE_754
|
from test.support import requires_IEEE_754, adjust_int_max_str_digits
|
||||||
import math
|
import math
|
||||||
import numbers
|
import numbers
|
||||||
import operator
|
import operator
|
||||||
|
@ -395,12 +395,14 @@ class FractionTest(unittest.TestCase):
|
||||||
|
|
||||||
def testFromString(self):
|
def testFromString(self):
|
||||||
self.assertEqual((5, 1), _components(F("5")))
|
self.assertEqual((5, 1), _components(F("5")))
|
||||||
|
self.assertEqual((5, 1), _components(F("005")))
|
||||||
self.assertEqual((3, 2), _components(F("3/2")))
|
self.assertEqual((3, 2), _components(F("3/2")))
|
||||||
self.assertEqual((3, 2), _components(F("3 / 2")))
|
self.assertEqual((3, 2), _components(F("3 / 2")))
|
||||||
self.assertEqual((3, 2), _components(F(" \n +3/2")))
|
self.assertEqual((3, 2), _components(F(" \n +3/2")))
|
||||||
self.assertEqual((-3, 2), _components(F("-3/2 ")))
|
self.assertEqual((-3, 2), _components(F("-3/2 ")))
|
||||||
self.assertEqual((13, 2), _components(F(" 013/02 \n ")))
|
self.assertEqual((13, 2), _components(F(" 0013/002 \n ")))
|
||||||
self.assertEqual((16, 5), _components(F(" 3.2 ")))
|
self.assertEqual((16, 5), _components(F(" 3.2 ")))
|
||||||
|
self.assertEqual((16, 5), _components(F("003.2")))
|
||||||
self.assertEqual((-16, 5), _components(F(" -3.2 ")))
|
self.assertEqual((-16, 5), _components(F(" -3.2 ")))
|
||||||
self.assertEqual((-3, 1), _components(F(" -3. ")))
|
self.assertEqual((-3, 1), _components(F(" -3. ")))
|
||||||
self.assertEqual((3, 5), _components(F(" .6 ")))
|
self.assertEqual((3, 5), _components(F(" .6 ")))
|
||||||
|
@ -419,116 +421,101 @@ class FractionTest(unittest.TestCase):
|
||||||
self.assertRaisesMessage(
|
self.assertRaisesMessage(
|
||||||
ZeroDivisionError, "Fraction(3, 0)",
|
ZeroDivisionError, "Fraction(3, 0)",
|
||||||
F, "3/0")
|
F, "3/0")
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '3/'",
|
def check_invalid(s):
|
||||||
F, "3/")
|
msg = "Invalid literal for Fraction: " + repr(s)
|
||||||
self.assertRaisesMessage(
|
self.assertRaisesMessage(ValueError, msg, F, s)
|
||||||
ValueError, "Invalid literal for Fraction: '/2'",
|
|
||||||
F, "/2")
|
check_invalid("3/")
|
||||||
self.assertRaisesMessage(
|
check_invalid("/2")
|
||||||
# Denominators don't need a sign.
|
# Denominators don't need a sign.
|
||||||
ValueError, "Invalid literal for Fraction: '3/+2'",
|
check_invalid("3/+2")
|
||||||
F, "3/+2")
|
check_invalid("3/-2")
|
||||||
self.assertRaisesMessage(
|
# Imitate float's parsing.
|
||||||
# Imitate float's parsing.
|
check_invalid("+ 3/2")
|
||||||
ValueError, "Invalid literal for Fraction: '+ 3/2'",
|
check_invalid("- 3/2")
|
||||||
F, "+ 3/2")
|
# Avoid treating '.' as a regex special character.
|
||||||
self.assertRaisesMessage(
|
check_invalid("3a2")
|
||||||
# Avoid treating '.' as a regex special character.
|
# Don't accept combinations of decimals and rationals.
|
||||||
ValueError, "Invalid literal for Fraction: '3a2'",
|
check_invalid("3/7.2")
|
||||||
F, "3a2")
|
check_invalid("3.2/7")
|
||||||
self.assertRaisesMessage(
|
# No space around dot.
|
||||||
# Don't accept combinations of decimals and rationals.
|
check_invalid("3 .2")
|
||||||
ValueError, "Invalid literal for Fraction: '3/7.2'",
|
check_invalid("3. 2")
|
||||||
F, "3/7.2")
|
# No space around e.
|
||||||
self.assertRaisesMessage(
|
check_invalid("3.2 e1")
|
||||||
# Don't accept combinations of decimals and rationals.
|
check_invalid("3.2e 1")
|
||||||
ValueError, "Invalid literal for Fraction: '3.2/7'",
|
# Fractional part don't need a sign.
|
||||||
F, "3.2/7")
|
check_invalid("3.+2")
|
||||||
self.assertRaisesMessage(
|
check_invalid("3.-2")
|
||||||
# Allow 3. and .3, but not .
|
# Only accept base 10.
|
||||||
ValueError, "Invalid literal for Fraction: '.'",
|
check_invalid("0x10")
|
||||||
F, ".")
|
check_invalid("0x10/1")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1/0x10")
|
||||||
ValueError, "Invalid literal for Fraction: '_'",
|
check_invalid("0x10.")
|
||||||
F, "_")
|
check_invalid("0x10.1")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1.0x10")
|
||||||
ValueError, "Invalid literal for Fraction: '_1'",
|
check_invalid("1.0e0x10")
|
||||||
F, "_1")
|
# Only accept decimal digits.
|
||||||
self.assertRaisesMessage(
|
check_invalid("³")
|
||||||
ValueError, "Invalid literal for Fraction: '1__2'",
|
check_invalid("³/2")
|
||||||
F, "1__2")
|
check_invalid("3/²")
|
||||||
self.assertRaisesMessage(
|
check_invalid("³.2")
|
||||||
ValueError, "Invalid literal for Fraction: '/_'",
|
check_invalid("3.²")
|
||||||
F, "/_")
|
check_invalid("3.2e²")
|
||||||
self.assertRaisesMessage(
|
check_invalid("¼")
|
||||||
ValueError, "Invalid literal for Fraction: '1_/'",
|
# Allow 3. and .3, but not .
|
||||||
F, "1_/")
|
check_invalid(".")
|
||||||
self.assertRaisesMessage(
|
check_invalid("_")
|
||||||
ValueError, "Invalid literal for Fraction: '_1/'",
|
check_invalid("_1")
|
||||||
F, "_1/")
|
check_invalid("1__2")
|
||||||
self.assertRaisesMessage(
|
check_invalid("/_")
|
||||||
ValueError, "Invalid literal for Fraction: '1__2/'",
|
check_invalid("1_/")
|
||||||
F, "1__2/")
|
check_invalid("_1/")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1__2/")
|
||||||
ValueError, "Invalid literal for Fraction: '1/_'",
|
check_invalid("1/_")
|
||||||
F, "1/_")
|
check_invalid("1/_1")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1/1__2")
|
||||||
ValueError, "Invalid literal for Fraction: '1/_1'",
|
check_invalid("1._111")
|
||||||
F, "1/_1")
|
check_invalid("1.1__1")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1.1e+_1")
|
||||||
ValueError, "Invalid literal for Fraction: '1/1__2'",
|
check_invalid("1.1e+1__1")
|
||||||
F, "1/1__2")
|
check_invalid("123.dd")
|
||||||
self.assertRaisesMessage(
|
check_invalid("123.5_dd")
|
||||||
ValueError, "Invalid literal for Fraction: '1._111'",
|
check_invalid("dd.5")
|
||||||
F, "1._111")
|
check_invalid("7_dd")
|
||||||
self.assertRaisesMessage(
|
check_invalid("1/dd")
|
||||||
ValueError, "Invalid literal for Fraction: '1.1__1'",
|
check_invalid("1/123_dd")
|
||||||
F, "1.1__1")
|
check_invalid("789edd")
|
||||||
self.assertRaisesMessage(
|
check_invalid("789e2_dd")
|
||||||
ValueError, "Invalid literal for Fraction: '1.1e+_1'",
|
|
||||||
F, "1.1e+_1")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '1.1e+1__1'",
|
|
||||||
F, "1.1e+1__1")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '123.dd'",
|
|
||||||
F, "123.dd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '123.5_dd'",
|
|
||||||
F, "123.5_dd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: 'dd.5'",
|
|
||||||
F, "dd.5")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '7_dd'",
|
|
||||||
F, "7_dd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '1/dd'",
|
|
||||||
F, "1/dd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '1/123_dd'",
|
|
||||||
F, "1/123_dd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '789edd'",
|
|
||||||
F, "789edd")
|
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '789e2_dd'",
|
|
||||||
F, "789e2_dd")
|
|
||||||
# Test catastrophic backtracking.
|
# Test catastrophic backtracking.
|
||||||
val = "9"*50 + "_"
|
val = "9"*50 + "_"
|
||||||
self.assertRaisesMessage(
|
check_invalid(val)
|
||||||
ValueError, "Invalid literal for Fraction: '" + val + "'",
|
check_invalid("1/" + val)
|
||||||
F, val)
|
check_invalid("1." + val)
|
||||||
self.assertRaisesMessage(
|
check_invalid("." + val)
|
||||||
ValueError, "Invalid literal for Fraction: '1/" + val + "'",
|
check_invalid("1.1+e" + val)
|
||||||
F, "1/" + val)
|
check_invalid("1.1e" + val)
|
||||||
self.assertRaisesMessage(
|
|
||||||
ValueError, "Invalid literal for Fraction: '1." + val + "'",
|
def test_limit_int(self):
|
||||||
F, "1." + val)
|
maxdigits = 5000
|
||||||
self.assertRaisesMessage(
|
with adjust_int_max_str_digits(maxdigits):
|
||||||
ValueError, "Invalid literal for Fraction: '1.1+e" + val + "'",
|
val = '1' * maxdigits
|
||||||
F, "1.1+e" + val)
|
num = (10**maxdigits - 1)//9
|
||||||
|
self.assertEqual((num, 1), _components(F(val)))
|
||||||
|
self.assertRaises(ValueError, F, val + '1')
|
||||||
|
self.assertEqual((num, 2), _components(F(val + '/2')))
|
||||||
|
self.assertRaises(ValueError, F, val + '1/2')
|
||||||
|
self.assertEqual((1, num), _components(F('1/' + val)))
|
||||||
|
self.assertRaises(ValueError, F, '1/1' + val)
|
||||||
|
self.assertEqual(((10**(maxdigits+1) - 1)//9, 10**maxdigits),
|
||||||
|
_components(F('1.' + val)))
|
||||||
|
self.assertRaises(ValueError, F, '1.1' + val)
|
||||||
|
self.assertEqual((num, 10**maxdigits), _components(F('.' + val)))
|
||||||
|
self.assertRaises(ValueError, F, '.1' + val)
|
||||||
|
self.assertRaises(ValueError, F, '1.1e1' + val)
|
||||||
|
self.assertEqual((11, 10), _components(F('1.1e' + '0' * maxdigits)))
|
||||||
|
self.assertRaises(ValueError, F, '1.1e' + '0' * (maxdigits+1))
|
||||||
|
|
||||||
def testImmutable(self):
|
def testImmutable(self):
|
||||||
r = F(7, 3)
|
r = F(7, 3)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue