Rodrigo Bernardo Pimentel <r...@isnomore.net> added the comment: If I'm understanding this correctly, this fails on 3.1 and not (although, actually, it does) on py3k/3.2 because:
* pprint._safe_key.__lt__ checks "rv = self.obj.__lt__(other.obj)" and falls back to id comparison if rv is NotImplemented * If the object passed to _safe_key is a class, self.obj.__lt__ will expect *self* as well as the other object. Therefore the verification above fails with "TypeError: expected 1 arguments, got 0". You can see that pprint works with an instance: >>> pprint.pprint({A(): 1, 1: 2}) {<__main__.A object at 0x8594d4c>: 1, 1: 2} * Finally, this works on py3k *for your example* because, for some reason, on py3k the comparison is being based on the 1 key. That is, the comparison on _safe_key.__lt__ happens to be 1.__lt__(A), instead of A.__lt__(1). Perhaps hashing changed after the 3.1 release? Anyway, py3k still fails when you force the comparison to happen on the class: >>> class B(object): pass ... >>> pprint.pprint({A: 1, B: 2}) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 55, in pprint printer.pprint(object) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 132, in pprint self._format(object, self._stream, 0, 0, {}, 0) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 155, in _format rep = self._repr(object, context, level - 1) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 245, in _repr self._depth, level) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 257, in format return _safe_repr(object, context, maxlevels, level) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 299, in _safe_repr items = sorted(object.items(), key=_safe_tuple) File "/home/rbp/python/dev/py3k/Lib/pprint.py", line 89, in __lt__ rv = self.obj.__lt__(other.obj) TypeError: expected 1 arguments, got 0 >>> So, basically, the fix on issue 3976 does't (always) work when there are classes as dict keys. I think switching from rv = self.obj.__lt__(other.obj) if rv is NotImplemented: to something like try: rv = self.obj < other.obj except TypeError: rv = (str(type(self.obj)), id(self.obj)) < \ (str(type(other.obj)), id(other.obj)) solves this. Or we can check first whether self.obj is a 'type', but I think it gets convoluted. If anyone can confirm that that's the way to go, I can produce one (though it's a trivial one). Raymond? ---------- _______________________________________ Python tracker <rep...@bugs.python.org> <http://bugs.python.org/issue10017> _______________________________________ _______________________________________________ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com