@@ -53,20 +53,6 @@ def _hash_algorithm(numerator, denominator):
5353    result  =  hash_  if  numerator  >=  0  else  - hash_ 
5454    return  - 2  if  result  ==  - 1  else  result 
5555
56- _RATIONAL_FORMAT  =  re .compile (r""" 
57-     \A\s*                                  # optional whitespace at the start, 
58-     (?P<sign>[-+]?)                        # an optional sign, then 
59-     (?=\d|\.\d)                            # lookahead for digit or .digit 
60-     (?P<num>\d*|\d+(_\d+)*)                # numerator (possibly empty) 
61-     (?:                                    # followed by 
62-        (?:\s*/\s*(?P<denom>\d+(_\d+)*))?   # an optional denominator 
63-     |                                      # or 
64-        (?:\.(?P<decimal>\d*|\d+(_\d+)*))?  # an optional fractional part 
65-        (?:E(?P<exp>[-+]?\d+(_\d+)*))?      # and optional exponent 
66-     ) 
67-     \s*\z                                  # and optional whitespace to finish 
68- """ , re .VERBOSE  |  re .IGNORECASE )
69- 
7056
7157# Helpers for formatting 
7258
@@ -238,11 +224,6 @@ def __new__(cls, numerator=0, denominator=None):
238224                self ._denominator  =  1 
239225                return  self 
240226
241-             elif  isinstance (numerator , numbers .Rational ):
242-                 self ._numerator  =  numerator .numerator 
243-                 self ._denominator  =  numerator .denominator 
244-                 return  self 
245- 
246227            elif  (isinstance (numerator , float ) or 
247228                  (not  isinstance (numerator , type ) and 
248229                   hasattr (numerator , 'as_integer_ratio' ))):
@@ -252,31 +233,52 @@ def __new__(cls, numerator=0, denominator=None):
252233
253234            elif  isinstance (numerator , str ):
254235                # Handle construction from strings. 
255-                 m  =  _RATIONAL_FORMAT .match (numerator )
256-                 if  m  is  None :
257-                     raise  ValueError ('Invalid literal for Fraction: %r'  % 
258-                                      numerator )
259-                 numerator  =  int (m .group ('num' ) or  '0' )
260-                 denom  =  m .group ('denom' )
261-                 if  denom :
262-                     denominator  =  int (denom )
263-                 else :
264-                     denominator  =  1 
265-                     decimal  =  m .group ('decimal' )
266-                     if  decimal :
267-                         decimal  =  decimal .replace ('_' , '' )
268-                         scale  =  10 ** len (decimal )
269-                         numerator  =  numerator  *  scale  +  int (decimal )
270-                         denominator  *=  scale 
271-                     exp  =  m .group ('exp' )
272-                     if  exp :
273-                         exp  =  int (exp )
274-                         if  exp  >=  0 :
275-                             numerator  *=  10 ** exp 
236+                 fraction_literal  =  numerator 
237+                 num , _ , denom  =  fraction_literal .partition ('/' )
238+                 try :
239+                     num  =  num .strip ()
240+                     denom  =  denom .strip ()
241+                     if  num  and  denom  and  denom [0 ].isdigit ():
242+                         denominator  =  int (denom )
243+                         numerator  =  int (num )
244+                     elif  num  and  not  _ :
245+                         denominator  =  1 
246+                         num , _ , exp  =  num .replace ('E' , 'e' ).partition ('e' )
247+                         if  _  and  not  exp :
248+                             raise  ValueError 
249+                         num , _ , decimal  =  num .partition ('.' )
250+                         if  decimal :
251+                             if  num  and  num [0 ] in  ('+' , '-' ):
252+                                 sign  =  num [0 ] ==  '-' 
253+                                 num  =  num [1 :]
254+                             else :
255+                                 sign  =  0 
256+                             numerator  =  int (num  or  '0' )
257+                             decimal_len  =  len (decimal .replace ('_' , '' ))
258+                             decimal  =  int (decimal )
259+                             scale  =  10 ** decimal_len 
260+                             numerator  =  numerator * scale  +  decimal 
261+                             denominator  *=  scale 
262+                             if  sign :
263+                                 numerator  =  - numerator 
276264                        else :
277-                             denominator  *=  10 ** - exp 
278-                 if  m .group ('sign' ) ==  '-' :
279-                     numerator  =  - numerator 
265+                             numerator  =  int (num )
266+                         if  exp :
267+                             exp  =  int (exp )
268+                             if  exp  >=  0 :
269+                                 numerator  *=  10 ** exp 
270+                             else :
271+                                 denominator  *=  10 ** - exp 
272+                     else :
273+                         raise  ValueError 
274+                 except  ValueError :
275+                     raise  ValueError ('Invalid literal for Fraction: %r'  % 
276+                                      fraction_literal )
277+ 
278+             elif  isinstance (numerator , numbers .Rational ):
279+                 self ._numerator  =  numerator .numerator 
280+                 self ._denominator  =  numerator .denominator 
281+                 return  self 
280282
281283            else :
282284                raise  TypeError ("argument should be a string or a Rational " 
0 commit comments