@@ -70,6 +70,32 @@ def isrecursive(object):
70
70
"""Determine if object requires a recursive representation."""
71
71
return _safe_repr (object , {}, None , 0 )[2 ]
72
72
73
+ class _safe_key :
74
+ """Helper function for key functions when sorting unorderable objects.
75
+
76
+ The wrapped-object will fallback to an Py2.x style comparison for
77
+ unorderable types (sorting first comparing the type name and then by
78
+ the obj ids). Does not work recursively, so dict.items() must have
79
+ _safe_key applied to both the key and the value.
80
+
81
+ """
82
+
83
+ __slots__ = ['obj' ]
84
+
85
+ def __init__ (self , obj ):
86
+ self .obj = obj
87
+
88
+ def __lt__ (self , other ):
89
+ rv = self .obj .__lt__ (other .obj )
90
+ if rv is NotImplemented :
91
+ rv = (str (type (self .obj )), id (self .obj )) < \
92
+ (str (type (other .obj )), id (other .obj ))
93
+ return rv
94
+
95
+ def _safe_tuple (t ):
96
+ "Helper function for comparing 2-tuples"
97
+ return _safe_key (t [0 ]), _safe_key (t [1 ])
98
+
73
99
class PrettyPrinter :
74
100
def __init__ (self , indent = 1 , width = 80 , depth = None , stream = None ):
75
101
"""Handle pretty printing operations onto a stream using a set of
@@ -145,7 +171,7 @@ def _format(self, object, stream, indent, allowance, context, level):
145
171
if length :
146
172
context [objid ] = 1
147
173
indent = indent + self ._indent_per_level
148
- items = sorted (object .items ())
174
+ items = sorted (object .items (), key = _safe_tuple )
149
175
key , ent = items [0 ]
150
176
rep = self ._repr (key , context , level )
151
177
write (rep )
@@ -178,14 +204,14 @@ def _format(self, object, stream, indent, allowance, context, level):
178
204
return
179
205
write ('{' )
180
206
endchar = '}'
181
- object = sorted (object )
207
+ object = sorted (object , key = _safe_key )
182
208
elif issubclass (typ , frozenset ):
183
209
if not length :
184
210
write ('frozenset()' )
185
211
return
186
212
write ('frozenset({' )
187
213
endchar = '})'
188
- object = sorted (object )
214
+ object = sorted (object , key = _safe_key )
189
215
indent += 10
190
216
else :
191
217
write ('(' )
@@ -267,14 +293,7 @@ def _safe_repr(object, context, maxlevels, level):
267
293
append = components .append
268
294
level += 1
269
295
saferepr = _safe_repr
270
- items = object .items ()
271
- try :
272
- items = sorted (items )
273
- except TypeError :
274
- def sortkey (item ):
275
- key , value = item
276
- return str (type (key )), key , value
277
- items = sorted (items , key = sortkey )
296
+ items = sorted (object .items (), key = _safe_tuple )
278
297
for k , v in items :
279
298
krepr , kreadable , krecur = saferepr (k , context , maxlevels , level )
280
299
vrepr , vreadable , vrecur = saferepr (v , context , maxlevels , level )
0 commit comments