@@ -392,6 +392,13 @@ def __repr__(self):
392392class RectComplex (Rect , complex ):
393393 pass
394394
395+ class Ratio :
396+ def __init__ (self , ratio ):
397+ self ._ratio = ratio
398+ def as_integer_ratio (self ):
399+ return self ._ratio
400+
401+
395402class FractionTest (unittest .TestCase ):
396403
397404 def assertTypedEquals (self , expected , actual ):
@@ -474,14 +481,9 @@ def testInitFromDecimal(self):
474481 self .assertRaises (OverflowError , F , Decimal ('-inf' ))
475482
476483 def testInitFromIntegerRatio (self ):
477- class Ratio :
478- def __init__ (self , ratio ):
479- self ._ratio = ratio
480- def as_integer_ratio (self ):
481- return self ._ratio
482-
483484 self .assertEqual ((7 , 3 ), _components (F (Ratio ((7 , 3 )))))
484- errmsg = "argument should be a string or a number"
485+ errmsg = (r"argument should be a string or a Rational instance or "
486+ r"have the as_integer_ratio\(\) method" )
485487 # the type also has an "as_integer_ratio" attribute.
486488 self .assertRaisesRegex (TypeError , errmsg , F , Ratio )
487489 # bad ratio
@@ -507,6 +509,8 @@ class B(metaclass=M):
507509 pass
508510 self .assertRaisesRegex (TypeError , errmsg , F , B )
509511 self .assertRaisesRegex (TypeError , errmsg , F , B ())
512+ self .assertRaises (TypeError , F .from_number , B )
513+ self .assertRaises (TypeError , F .from_number , B ())
510514
511515 def testFromString (self ):
512516 self .assertEqual ((5 , 1 ), _components (F ("5" )))
@@ -746,6 +750,36 @@ def testFromDecimal(self):
746750 ValueError , "Cannot convert sNaN to Fraction." ,
747751 F .from_decimal , Decimal ("snan" ))
748752
753+ def testFromNumber (self , cls = F ):
754+ def check (arg , numerator , denominator ):
755+ f = cls .from_number (arg )
756+ self .assertIs (type (f ), cls )
757+ self .assertEqual (f .numerator , numerator )
758+ self .assertEqual (f .denominator , denominator )
759+
760+ check (10 , 10 , 1 )
761+ check (2.5 , 5 , 2 )
762+ check (Decimal ('2.5' ), 5 , 2 )
763+ check (F (22 , 7 ), 22 , 7 )
764+ check (DummyFraction (22 , 7 ), 22 , 7 )
765+ check (Rat (22 , 7 ), 22 , 7 )
766+ check (Ratio ((22 , 7 )), 22 , 7 )
767+ self .assertRaises (TypeError , cls .from_number , 3 + 4j )
768+ self .assertRaises (TypeError , cls .from_number , '5/2' )
769+ self .assertRaises (TypeError , cls .from_number , [])
770+ self .assertRaises (OverflowError , cls .from_number , float ('inf' ))
771+ self .assertRaises (OverflowError , cls .from_number , Decimal ('inf' ))
772+
773+ # as_integer_ratio not defined in a class
774+ class A :
775+ pass
776+ a = A ()
777+ a .as_integer_ratio = lambda : (9 , 5 )
778+ check (a , 9 , 5 )
779+
780+ def testFromNumber_subclass (self ):
781+ self .testFromNumber (DummyFraction )
782+
749783 def test_is_integer (self ):
750784 self .assertTrue (F (1 , 1 ).is_integer ())
751785 self .assertTrue (F (- 1 , 1 ).is_integer ())
0 commit comments