11"""Tests for Lib/fractions.py."""
22
33from decimal import Decimal
4- from test .support import requires_IEEE_754
4+ from test .support import requires_IEEE_754 , adjust_int_max_str_digits
55import math
66import numbers
77import operator
@@ -395,12 +395,14 @@ class B(metaclass=M):
395395
396396 def testFromString (self ):
397397 self .assertEqual ((5 , 1 ), _components (F ("5" )))
398+ self .assertEqual ((5 , 1 ), _components (F ("005" )))
398399 self .assertEqual ((3 , 2 ), _components (F ("3/2" )))
399400 self .assertEqual ((3 , 2 ), _components (F ("3 / 2" )))
400401 self .assertEqual ((3 , 2 ), _components (F (" \n +3/2" )))
401402 self .assertEqual ((- 3 , 2 ), _components (F ("-3/2 " )))
402- self .assertEqual ((13 , 2 ), _components (F (" 013/02 \n " )))
403+ self .assertEqual ((13 , 2 ), _components (F (" 0013/002 \n " )))
403404 self .assertEqual ((16 , 5 ), _components (F (" 3.2 " )))
405+ self .assertEqual ((16 , 5 ), _components (F ("003.2" )))
404406 self .assertEqual ((- 16 , 5 ), _components (F (" -3.2 " )))
405407 self .assertEqual ((- 3 , 1 ), _components (F (" -3. " )))
406408 self .assertEqual ((3 , 5 ), _components (F (" .6 " )))
@@ -419,116 +421,101 @@ def testFromString(self):
419421 self .assertRaisesMessage (
420422 ZeroDivisionError , "Fraction(3, 0)" ,
421423 F , "3/0" )
422- self .assertRaisesMessage (
423- ValueError , "Invalid literal for Fraction: '3/'" ,
424- F , "3/" )
425- self .assertRaisesMessage (
426- ValueError , "Invalid literal for Fraction: '/2'" ,
427- F , "/2" )
428- self .assertRaisesMessage (
429- # Denominators don't need a sign.
430- ValueError , "Invalid literal for Fraction: '3/+2'" ,
431- F , "3/+2" )
432- self .assertRaisesMessage (
433- # Imitate float's parsing.
434- ValueError , "Invalid literal for Fraction: '+ 3/2'" ,
435- F , "+ 3/2" )
436- self .assertRaisesMessage (
437- # Avoid treating '.' as a regex special character.
438- ValueError , "Invalid literal for Fraction: '3a2'" ,
439- F , "3a2" )
440- self .assertRaisesMessage (
441- # Don't accept combinations of decimals and rationals.
442- ValueError , "Invalid literal for Fraction: '3/7.2'" ,
443- F , "3/7.2" )
444- self .assertRaisesMessage (
445- # Don't accept combinations of decimals and rationals.
446- ValueError , "Invalid literal for Fraction: '3.2/7'" ,
447- F , "3.2/7" )
448- self .assertRaisesMessage (
449- # Allow 3. and .3, but not .
450- ValueError , "Invalid literal for Fraction: '.'" ,
451- F , "." )
452- self .assertRaisesMessage (
453- ValueError , "Invalid literal for Fraction: '_'" ,
454- F , "_" )
455- self .assertRaisesMessage (
456- ValueError , "Invalid literal for Fraction: '_1'" ,
457- F , "_1" )
458- self .assertRaisesMessage (
459- ValueError , "Invalid literal for Fraction: '1__2'" ,
460- F , "1__2" )
461- self .assertRaisesMessage (
462- ValueError , "Invalid literal for Fraction: '/_'" ,
463- F , "/_" )
464- self .assertRaisesMessage (
465- ValueError , "Invalid literal for Fraction: '1_/'" ,
466- F , "1_/" )
467- self .assertRaisesMessage (
468- ValueError , "Invalid literal for Fraction: '_1/'" ,
469- F , "_1/" )
470- self .assertRaisesMessage (
471- ValueError , "Invalid literal for Fraction: '1__2/'" ,
472- F , "1__2/" )
473- self .assertRaisesMessage (
474- ValueError , "Invalid literal for Fraction: '1/_'" ,
475- F , "1/_" )
476- self .assertRaisesMessage (
477- ValueError , "Invalid literal for Fraction: '1/_1'" ,
478- F , "1/_1" )
479- self .assertRaisesMessage (
480- ValueError , "Invalid literal for Fraction: '1/1__2'" ,
481- F , "1/1__2" )
482- self .assertRaisesMessage (
483- ValueError , "Invalid literal for Fraction: '1._111'" ,
484- F , "1._111" )
485- self .assertRaisesMessage (
486- ValueError , "Invalid literal for Fraction: '1.1__1'" ,
487- F , "1.1__1" )
488- self .assertRaisesMessage (
489- ValueError , "Invalid literal for Fraction: '1.1e+_1'" ,
490- F , "1.1e+_1" )
491- self .assertRaisesMessage (
492- ValueError , "Invalid literal for Fraction: '1.1e+1__1'" ,
493- F , "1.1e+1__1" )
494- self .assertRaisesMessage (
495- ValueError , "Invalid literal for Fraction: '123.dd'" ,
496- F , "123.dd" )
497- self .assertRaisesMessage (
498- ValueError , "Invalid literal for Fraction: '123.5_dd'" ,
499- F , "123.5_dd" )
500- self .assertRaisesMessage (
501- ValueError , "Invalid literal for Fraction: 'dd.5'" ,
502- F , "dd.5" )
503- self .assertRaisesMessage (
504- ValueError , "Invalid literal for Fraction: '7_dd'" ,
505- F , "7_dd" )
506- self .assertRaisesMessage (
507- ValueError , "Invalid literal for Fraction: '1/dd'" ,
508- F , "1/dd" )
509- self .assertRaisesMessage (
510- ValueError , "Invalid literal for Fraction: '1/123_dd'" ,
511- F , "1/123_dd" )
512- self .assertRaisesMessage (
513- ValueError , "Invalid literal for Fraction: '789edd'" ,
514- F , "789edd" )
515- self .assertRaisesMessage (
516- ValueError , "Invalid literal for Fraction: '789e2_dd'" ,
517- F , "789e2_dd" )
424+
425+ def check_invalid (s ):
426+ msg = "Invalid literal for Fraction: " + repr (s )
427+ self .assertRaisesMessage (ValueError , msg , F , s )
428+
429+ check_invalid ("3/" )
430+ check_invalid ("/2" )
431+ # Denominators don't need a sign.
432+ check_invalid ("3/+2" )
433+ check_invalid ("3/-2" )
434+ # Imitate float's parsing.
435+ check_invalid ("+ 3/2" )
436+ check_invalid ("- 3/2" )
437+ # Avoid treating '.' as a regex special character.
438+ check_invalid ("3a2" )
439+ # Don't accept combinations of decimals and rationals.
440+ check_invalid ("3/7.2" )
441+ check_invalid ("3.2/7" )
442+ # No space around dot.
443+ check_invalid ("3 .2" )
444+ check_invalid ("3. 2" )
445+ # No space around e.
446+ check_invalid ("3.2 e1" )
447+ check_invalid ("3.2e 1" )
448+ # Fractional part don't need a sign.
449+ check_invalid ("3.+2" )
450+ check_invalid ("3.-2" )
451+ # Only accept base 10.
452+ check_invalid ("0x10" )
453+ check_invalid ("0x10/1" )
454+ check_invalid ("1/0x10" )
455+ check_invalid ("0x10." )
456+ check_invalid ("0x10.1" )
457+ check_invalid ("1.0x10" )
458+ check_invalid ("1.0e0x10" )
459+ # Only accept decimal digits.
460+ check_invalid ("³" )
461+ check_invalid ("³/2" )
462+ check_invalid ("3/²" )
463+ check_invalid ("³.2" )
464+ check_invalid ("3.²" )
465+ check_invalid ("3.2e²" )
466+ check_invalid ("¼" )
467+ # Allow 3. and .3, but not .
468+ check_invalid ("." )
469+ check_invalid ("_" )
470+ check_invalid ("_1" )
471+ check_invalid ("1__2" )
472+ check_invalid ("/_" )
473+ check_invalid ("1_/" )
474+ check_invalid ("_1/" )
475+ check_invalid ("1__2/" )
476+ check_invalid ("1/_" )
477+ check_invalid ("1/_1" )
478+ check_invalid ("1/1__2" )
479+ check_invalid ("1._111" )
480+ check_invalid ("1.1__1" )
481+ check_invalid ("1.1e+_1" )
482+ check_invalid ("1.1e+1__1" )
483+ check_invalid ("123.dd" )
484+ check_invalid ("123.5_dd" )
485+ check_invalid ("dd.5" )
486+ check_invalid ("7_dd" )
487+ check_invalid ("1/dd" )
488+ check_invalid ("1/123_dd" )
489+ check_invalid ("789edd" )
490+ check_invalid ("789e2_dd" )
518491 # Test catastrophic backtracking.
519492 val = "9" * 50 + "_"
520- self .assertRaisesMessage (
521- ValueError , "Invalid literal for Fraction: '" + val + "'" ,
522- F , val )
523- self .assertRaisesMessage (
524- ValueError , "Invalid literal for Fraction: '1/" + val + "'" ,
525- F , "1/" + val )
526- self .assertRaisesMessage (
527- ValueError , "Invalid literal for Fraction: '1." + val + "'" ,
528- F , "1." + val )
529- self .assertRaisesMessage (
530- ValueError , "Invalid literal for Fraction: '1.1+e" + val + "'" ,
531- F , "1.1+e" + val )
493+ check_invalid (val )
494+ check_invalid ("1/" + val )
495+ check_invalid ("1." + val )
496+ check_invalid ("." + val )
497+ check_invalid ("1.1+e" + val )
498+ check_invalid ("1.1e" + val )
499+
500+ def test_limit_int (self ):
501+ maxdigits = 5000
502+ with adjust_int_max_str_digits (maxdigits ):
503+ val = '1' * maxdigits
504+ num = (10 ** maxdigits - 1 )// 9
505+ self .assertEqual ((num , 1 ), _components (F (val )))
506+ self .assertRaises (ValueError , F , val + '1' )
507+ self .assertEqual ((num , 2 ), _components (F (val + '/2' )))
508+ self .assertRaises (ValueError , F , val + '1/2' )
509+ self .assertEqual ((1 , num ), _components (F ('1/' + val )))
510+ self .assertRaises (ValueError , F , '1/1' + val )
511+ self .assertEqual (((10 ** (maxdigits + 1 ) - 1 )// 9 , 10 ** maxdigits ),
512+ _components (F ('1.' + val )))
513+ self .assertRaises (ValueError , F , '1.1' + val )
514+ self .assertEqual ((num , 10 ** maxdigits ), _components (F ('.' + val )))
515+ self .assertRaises (ValueError , F , '.1' + val )
516+ self .assertRaises (ValueError , F , '1.1e1' + val )
517+ self .assertEqual ((11 , 10 ), _components (F ('1.1e' + '0' * maxdigits )))
518+ self .assertRaises (ValueError , F , '1.1e' + '0' * (maxdigits + 1 ))
532519
533520 def testImmutable (self ):
534521 r = F (7 , 3 )
0 commit comments