@@ -70,6 +70,32 @@ def isrecursive(object):
7070 """Determine if object requires a recursive representation."""
7171 return _safe_repr (object , {}, None , 0 )[2 ]
7272
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+
7399class PrettyPrinter :
74100 def __init__ (self , indent = 1 , width = 80 , depth = None , stream = None ):
75101 """Handle pretty printing operations onto a stream using a set of
@@ -145,7 +171,7 @@ def _format(self, object, stream, indent, allowance, context, level):
145171 if length :
146172 context [objid ] = 1
147173 indent = indent + self ._indent_per_level
148- items = sorted (object .items ())
174+ items = sorted (object .items (), key = _safe_tuple )
149175 key , ent = items [0 ]
150176 rep = self ._repr (key , context , level )
151177 write (rep )
@@ -178,14 +204,14 @@ def _format(self, object, stream, indent, allowance, context, level):
178204 return
179205 write ('{' )
180206 endchar = '}'
181- object = sorted (object )
207+ object = sorted (object , key = _safe_key )
182208 elif issubclass (typ , frozenset ):
183209 if not length :
184210 write ('frozenset()' )
185211 return
186212 write ('frozenset({' )
187213 endchar = '})'
188- object = sorted (object )
214+ object = sorted (object , key = _safe_key )
189215 indent += 10
190216 else :
191217 write ('(' )
@@ -267,14 +293,7 @@ def _safe_repr(object, context, maxlevels, level):
267293 append = components .append
268294 level += 1
269295 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 )
278297 for k , v in items :
279298 krepr , kreadable , krecur = saferepr (k , context , maxlevels , level )
280299 vrepr , vreadable , vrecur = saferepr (v , context , maxlevels , level )
0 commit comments