22
33import cmath
44from decimal import Decimal
5- from test .support import requires_IEEE_754
5+ from test .support import requires_IEEE_754 , adjust_int_max_str_digits
66import math
77import numbers
88import 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- 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 , "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