8000 [3.13] Improve tests for str to Fraction conversion (GH-134010) (GH-1… · python/cpython@f474264 · GitHub
[go: up one dir, main page]

Skip to content

Commit f474264

Browse files
[3.13] Improve tests for str to Fraction conversion (GH-134010) (GH-134017)
(cherry picked from commit 17d0fec) Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
1 parent ab8aafe commit f474264

File tree

1 file changed

+97
-110
lines changed

1 file changed

+97
-110
lines changed

Lib/test/test_fractions.py

Lines changed: 97 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import cmath
44
from decimal import Decimal
5-
from test.support import requires_IEEE_754
5+
from test.support import requires_IEEE_754, adjust_int_max_str_digits
66
import math
77
import numbers
88
import operator
@@ -357,12 +357,14 @@ def testInitFromDecimal(self):
357357

358358
def testFromString(self):
359359
self.assertEqual((5, 1), _components(F("5")))
360+
self.assertEqual((5, 1), _components(F("005")))
360361
self.assertEqual((3, 2), _components(F("3/2")))
361362
self.assertEqual((3, 2), _components(F("3 / 2")))
362363
self.assertEqual((3, 2), _components(F(" \n +3/2")))
363364
self.assertEqual((-3, 2), _components(F("-3/2 ")))
364-
self.assertEqual((13, 2), _components(F(" 013/02 \n ")))
365+
self.assertEqual((13, 2), _components(F(" 0013/002 \n ")))
365366
self.assertEqual((16, 5), _components(F(" 3.2 ")))
367+
self.assertEqual((16, 5), _components(F("003.2")))
366368
self.assertEqual((-16, 5), _components(F(" -3.2 ")))
367369
self.assertEqual((-3, 1), _components(F(" -3. ")))
368370
self.assertEqual((3, 5), _components(F(" .6 ")))
@@ -381,116 +383,101 @@ def testFromString(self):
381383
self.assertRaisesMessage(
382384
ZeroDivisionError, "Fraction(3, 0)",
383385
F, "3/0")
384-
self.assertRaisesMessage(
385-
ValueError, "Invalid literal for Fraction: '3/'",
386-
F, "3/")
387-
self.assertRaisesMessage(
388-
ValueError, "Invalid literal for Fraction: '/2'",
389-
F, "/2")
390-
self.assertRaisesMessage(
391-
# Denominators don't need a sign.
392-
ValueError, "Invalid literal for Fraction: '3/+2'",
393-
F, "3/+2")
394-
self.assertRaisesMessage(
395-
# Imitate float's parsing.
396-
ValueError, "Invalid literal for Fraction: '+ 3/2'",
397-
F, "+ 3/2")
398-
self.assertRaisesMessage(
399-
# Avoid treating '.' as a regex special character.
400-
ValueError, "Invalid literal for Fraction: '3a2'",
401-
F, "3a2")
402-
self.assertRaisesMessage(
403-
# Don't accept combinations of decimals and rationals.
404-
ValueError, "Invalid literal for Fraction: '3/7.2'",
405-
F, "3/7.2")
406-
self.assertRaisesMessage(
407-
# Don't accept combinations of decimals and rationals.
408-
ValueError, "Invalid literal for Fraction: '3.2/7'",
409-
F, "3.2/7")
410-
self.assertRaisesMessage(
411-
# Allow 3. and .3, but not .
412-
ValueError, "Invalid literal for Fraction: '.'",
413-
F, ".")
414-
self.assertRaisesMessage(
415-
ValueError, "Invalid literal for Fraction: '_'",
416-
F, "_")
417-
self.assertRaisesMessage(
418-
ValueError, "Invalid literal for Fraction: '_1'",
419-
F, "_1")
420-
self.assertRaisesMessage(
421-
ValueError, "Invalid literal for Fraction: '1__2'",
422-
F, "1__2")
423-
self.assertRaisesMessage(
424-
ValueError, "Invalid literal for Fraction: '/_'",
425-
F, "/_")
426-
self.assertRaisesMessage(
427-
ValueError, "Invalid literal for Fraction: '1_/'",
428-
F, "1_/")
429-
self.assertRaisesMessage(
430-
ValueError, "Invalid literal for Fraction: '_1/'",
431-
F, "_1/")
432-
self.assertRaisesMessage(
433-
ValueError, "Invalid literal for Fraction: '1__2/'",
434-
F, "1__2/")
435-
self.assertRaisesMessage(
436-
ValueError, "Invalid literal for Fraction: '1/_'",
437-
F, "1/_")
438-
self.assertRaisesMessage(
439-
ValueError, "Invalid literal for Fraction: '1/_1'",
440-
F, "1/_1")
441-
self.assertRaisesMessage(
442-
ValueError, "Invalid literal for Fraction: '1/1__2'",
443-
F, "1/1__2")
444-
self.assertRaisesMessage(
445-
ValueError, "Invalid literal for Fraction: '1._111'",
446-
F, "1._111")
447-
self.assertRaisesMessage(
448-
ValueError, "Invalid literal for Fraction: '1.1__1'",
449-
F, "1.1__1")
450-
self.assertRaisesMessage(
451-
ValueError, "Invalid literal for Fraction: '1.1e+_1'",
452- 9E81
F, "1.1e+_1")
453-
self.assertRaisesMessage(
454-
ValueError, "Invalid literal for Fraction: '1.1e+1__1'",
455-
F, "1.1e+1__1")
456-
self.assertRaisesMessage(
457-
ValueError, "Invalid literal for Fraction: '123.dd'",
458-
F, "123.dd")
459-
self.assertRaisesMessage(
460-
ValueError, "Invalid literal for Fraction: '123.5_dd'",
461-
F, "123.5_dd")
462-
self.assertRaisesMessage(
463-
ValueError, "Invalid literal for Fraction: 'dd.5'",
464-
F, "dd.5")
465-
self.assertRaisesMessage(
466-
ValueError, "Invalid literal for Fraction: '7_dd'",
467-
F, "7_dd")
468-
self.assertRaisesMessage(
469-
ValueError, "Invalid literal for Fraction: '1/dd'",
470-
F, "1/dd")
471-
self.assertRaisesMessage(
472-
ValueError, "Invalid literal for Fraction: '1/123_dd'",
473-
F, "1/123_dd")
474-
self.assertRaisesMessage(
475-
ValueError, "Invalid literal for Fraction: '789edd'",
476-
F, "789edd")
477-
self.assertRaisesMessage(
478-
ValueError, "Invalid literal for Fraction: '789e2_dd'",
479-
F, " F438 789e2_dd")
386+
387+
def check_invalid(s):
388+
msg = "Invalid literal for Fraction: " + repr(s)
389+
self.assertRaisesMessage(ValueError, msg, F, s)
390+
391+
check_invalid("3/")
392+
check_invalid("/2")
393+
# Denominators don't need a sign.
394+
check_invalid("3/+2")
395+
check_invalid("3/-2")
396+
# Imitate float's parsing.
397+
check_invalid("+ 3/2")
398+
check_invalid("- 3/2")
399+
# Avoid treating '.' as a regex special character.
400+
check_invalid("3a2")
401+
# Don't accept combinations of decimals and rationals.
402+
check_invalid("3/7.2")
403+
check_invalid("3.2/7")
404+
# No space around dot.
405+
check_invalid("3 .2")
406+
check_invalid("3. 2")
407+
# No space around e.
408+
check_invalid("3.2 e1")
409+
check_invalid("3.2e 1")
410+
# Fractional part don't need a sign.
411+
check_invalid("3.+2")
412+
check_invalid("3.-2")
413+
# Only accept base 10.
414+
check_invalid("0x10")
415+
check_invalid("0x10/1")
416+
check_invalid("1/0x10")
417+
check_invalid("0x10.")
418+
check_invalid("0x10.1")
419+
check_invalid("1.0x10")
420+
check_invalid("1.0e0x10")
421+
# Only accept decimal digits.
422+
check_invalid("³")
423+
check_invalid("³/2")
424+
check_invalid("3/²")
425+
check_invalid("³.2")
426+
check_invalid("3.²")
427+
check_invalid("3.2e²")
428+
check_invalid("¼")
429+
# Allow 3. and .3, but not .
430+
check_invalid(".")
431+
check_invalid("_")
432+
check_invalid("_1")
433+
check_invalid("1__2")
434+
check_invalid("/_")
435+
check_invalid("1_/")
436+
check_invalid("_1/")
437+
check_invalid("1__2/")
438+
check_invalid("1/_")
439+
check_invalid("1/_1")
440+
check_invalid("1/1__2")
441+
check_invalid("1._111")
442+
check_invalid("1.1__1")
443+
check_invalid("1.1e+_1")
444+
check_invalid("1.1e+1__1")
445+
check_invalid("123.dd")
446+
check_invalid("123.5_dd")
447+
check_invalid("dd.5")
448+
check_invalid("7_dd")
449+
check_invalid("1/dd")
450+
check_invalid("1/123_dd")
451+
check_invalid("789edd")
452+
check_invalid("789e2_dd")
480453
# Test catastrophic backtracking.
481454
val = "9"*50 + "_"
482-
self.assertRaisesMessage(
483-
ValueError, "Invalid literal for Fraction: '" + val + "'",
484-
F, val)
485-
self.assertRaisesMessage(
486-
ValueError, "Invalid literal for Fraction: '1/" + val + "'",
487-
F, "1/" + val)
488-
self.assertRaisesMessage(
489-
ValueError, "Invalid literal for Fraction: '1." + val + "'",
490-
F, "1." + val)
491-
self.assertRaisesMessage(
492-
ValueError, "Invalid literal for Fraction: '1.1+e" + val + "'",
493-
F, "1.1+e" + val)
455+
check_invalid(val)
456+
check_invalid("1/" + val)
457+
check_invalid("1." + val)
458+
check_invalid("." + val)
459+
check_invalid("1.1+e" + val)
460+
check_invalid("1.1e" + val)
461+
462+
def test_limit_int(self):
463+
maxdigits = 5000
464+
with adjust_int_max_str_digits(maxdigits):
465+
val = '1' * maxdigits
466+
num = (10**maxdigits - 1)//9
467+
self.assertEqual((num, 1), _components(F(val)))
468+
self.assertRaises(ValueError, F, val + '1')
469+
self.assertEqual((num, 2), _components(F(val + '/2')))
470+
self.assertRaises(ValueError, F, val + '1/2')
471+
self.assertEqual((1, num), _components(F('1/' + val)))
472+
self.assertRaises(ValueError, F, '1/1' + val)
473+
self.assertEqual(((10**(maxdigits+1) - 1)//9, 10**maxdigits),
474+
_components(F('1.' + val)))
475+
self.assertRaises(ValueError, F, '1.1' + val)
476+
self.assertEqual((num, 10**maxdigits), _components(F('.' + val)))
477+
self.assertRaises(ValueError, F, '.1' + val)
478+
self.assertRaises(ValueError, F, '1.1e1' + val)
479+
self.assertEqual((11, 10), _components(F('1.1e' + '0' * maxdigits)))
480+
self.assertRaises(ValueError, F, '1.1e' + '0' * (maxdigits+1))
494481

495482
def testImmutable(self):
496483
r = F(7, 3)

0 commit comments

Comments
 (0)
0