1
1
from __future__ import unicode_literals
2
2
3
3
import inspect
4
+ import math
5
+ import numbers
4
6
5
7
from future .utils import PY2 , PY3 , exec_
6
8
@@ -29,8 +31,67 @@ def cmp(x, y):
29
31
cmp(x, y) -> integer
30
32
31
33
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
32
36
"""
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 )
34
95
35
96
from sys import intern
36
97
@@ -42,7 +103,13 @@ def oct(number):
42
103
return '0' + builtins .oct (number )[2 :]
43
104
44
105
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
+
46
113
unicode = str
47
114
unichr = chr
48
115
xrange = range
@@ -82,7 +149,7 @@ def execfile(filename, myglobals=None, mylocals=None):
82
149
if not isinstance (mylocals , Mapping ):
83
150
raise TypeError ('locals must be a mapping' )
84
151
with open (filename , "rb" ) as fin :
85
- source = fin .read ()
152
+ source = fin .read ()
86
153
code = compile (source , filename , "exec" )
87
154
exec_ (code , myglobals , mylocals )
88
155
0 commit comments