11from __future__ import unicode_literals
22
33import inspect
4+ import math
5+ import numbers
46
57from future .utils import PY2 , PY3 , exec_
68
@@ -29,8 +31,67 @@ def cmp(x, y):
2931 cmp(x, y) -> integer
3032
3133 Return negative if x<y, zero if x==y, positive if x>y.
34+ Python2 had looser comparison allowing cmp None and non Numerical types and collections.
35+ Try to match the old behavior
3236 """
33- return (x > y ) - (x < y )
37+ if isinstance (x , set ) and isinstance (y , set ):
38+ raise TypeError ('cannot compare sets using cmp()' ,)
39+ try :
40+ if isinstance (x , numbers .Number ) and math .isnan (x ):
41+ if not isinstance (y , numbers .Number ):
42+ raise TypeError ('cannot compare float("nan"), {type_y} with cmp' .format (type_y = type (y )))
43+ if isinstance (y , int ):
44+ return 1
45+ else :
46+ return - 1
47+ if isinstance (y , numbers .Number ) and math .isnan (y ):
48+ if not isinstance (x , numbers .Number ):
49+ raise TypeError ('cannot compare {type_x}, float("nan") with cmp' .format (type_x = type (x )))
50+ if isinstance (x , int ):
51+ return - 1
52+ else :
53+ return 1
54+ return (x > y ) - (x < y )
55+ except TypeError :
56+ if x == y :
57+ return 0
58+ type_order = [
59+ type (None ),
60+ numbers .Number ,
61+ dict , list ,
62+ set ,
63+ (str , bytes ),
64+ ]
65+ x_type_index = y_type_index = None
66+ for i , type_match in enumerate (type_order ):
67+ if isinstance (x , type_match ):
68+ x_type_index = i
69+ if isinstance (y , type_match ):
70+ y_type_index = i
71+ if cmp (x_type_index , y_type_index ) == 0 :
72+ if isinstance (x , bytes ) and isinstance (y , str ):
73+ return cmp (x .decode ('ascii' ), y )
74+ if isinstance (y , bytes ) and isinstance (x , str ):
75+ return cmp (x , y .decode ('ascii' ))
76+ elif isinstance (x , list ):
77+ # if both arguments are lists take the comparison of the first non equal value
78+ for x_elem , y_elem in zip (x , y ):
79+ elem_cmp_val = cmp (x_elem , y_elem )
80+ if elem_cmp_val != 0 :
81+ return elem_cmp_val
82+ # if all elements are equal, return equal/0
83+ return 0
84+ elif isinstance (x , dict ):
85+ if len (x ) != len (y ):
86+ return cmp (len (x ), len (y ))
87+ else :
88+ x_key = min (a for a in x if a not in y or x [a ] != y [a ])
89+ y_key = min (b for b in y if b not in x or x [b ] != y [b ])
90+ if x_key != y_key :
91+ return cmp (x_key , y_key )
92+ else :
93+ return cmp (x [x_key ], y [y_key ])
94+ return cmp (x_type_index , y_type_index )
3495
3596 from sys import intern
3697
@@ -42,7 +103,13 @@ def oct(number):
42103 return '0' + builtins .oct (number )[2 :]
43104
44105 raw_input = input
45- from imp import reload
106+
107+ try :
108+ from importlib import reload
109+ except ImportError :
110+ # for python2, python3 <= 3.4
111+ from imp import reload
112+
46113 unicode = str
47114 unichr = chr
48115 xrange = range
@@ -82,7 +149,7 @@ def execfile(filename, myglobals=None, mylocals=None):
82149 if not isinstance (mylocals , Mapping ):
83150 raise TypeError ('locals must be a mapping' )
84151 with open (filename , "rb" ) as fin :
85- source = fin .read ()
152+ source = fin .read ()
86153 code = compile (source , filename , "exec" )
87154 exec_ (code , myglobals , mylocals )
88155
0 commit comments