Title: Make `weakref.WeakKeyDictionary.__repr__` meaningful
Type: enhancement Stage:
Components: Library (Lib) Versions: Python 3.7
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: cool-RR, fdrake, josh.r, pitrou
Priority: normal Keywords:

Created on 2016-09-26 16:28 by cool-RR, last changed 2016-09-29 17:13 by fdrake.

Messages (3)
msg277431 - (view) Author: Ram Rachum (cool-RR) * Date: 2016-09-26 16:28
Both `WeakKeyDictionary` and `WeakValueDictionary` have opaque `__repr__` methods:

>>> x = weakref.WeakKeyDictionary({object: 2, type: 4,})
>>> x
<WeakKeyDictionary at 0x32e6198>
>>> dict(x)
{<class 'type'>: 4, <class 'object'>: 2}

This makes it annoying to view them at a glance. Is there a reason for it? (I don't know, maybe because they're weakref? Though I'm not sure how that would affect this decision.)

If there isn't a reason, then maybe there should be a nice `__repr__` that lets you see the objects inside?
msg277442 - (view) Author: Josh Rosenberg (josh.r) * (Python triager) Date: 2016-09-26 17:58
Well, I could see a "friendly" repr being avoided to:

1. Save work (iterating safely involves iteration guards and explicitly acquiring strong references to every key)
2. Avoid pretending the state is stable (the repr at time X could be different at time X+epsilon)
3. Avoiding the possibility of __repr__ implementations for contained items doing terrible things (e.g. mutating the WeakKeyDictionary, or deleting the last external reference to a key). In the case where a __repr__ deletes the last external reference to a key that WeakKeyDictionary's __repr__ already iterated past, it means the repr is wrong before it even returns.
4. The repr wouldn't match the normal repr behavior; ideally, you can copy and paste a repr and get back an equivalent object. But of course, copy and pasting WeakKeyDictionary({Spam(1): 1, Spam(2): 2}) would actually get you back WeakKeyDictionary({}), because the objects you passed in don't share the identity of the ones in the original WeakKeyDictionary (which have existing references somewhere), and the instant the constructor returns, they'd lose their last reference and be deleted from the newly created WeakKeyDictionary
5. The above problems get even worse if the repr ends up being reentrant (which is more likely in this case; weakrefs are often used to break cycles); any stage of the recursive repr could end up mutating

None of these mean that the feature would be impossible/undesirable. #4 *might* be a reason to keep __repr__ as is though, and have __str__ display the more friendly version (e.g. `return '{}({!r})'.format(type(self).__name__, dict(self))` ); __str__ is supposed to be friendly without being a means of reproducing the object, so it wouldn't be quite as misleading.
msg277709 - (view) Author: Fred Drake (fdrake) (Python committer) Date: 2016-09-29 17:13
I don't recall that the issues discussed here were considered when these classes were added; functionality was the issue at the time.

I'm not particularly opposed to adding a more data-ful repr for the weakref-oriented mappings, but I'm not really convinced they'd be all that valuable, either.  Interesting mappings are often too well populated to deal with using repr.
Date User Action Args
2016-09-29 17:13:51fdrakesetmessages: + msg277709
2016-09-26 17:58:34josh.rsetnosy: + josh.r
messages: + msg277442
2016-09-26 16:43:00serhiy.storchakasetnosy: + fdrake, pitrou

versions: + Python 3.7, - Python 3.6
2016-09-26 16:28:49cool-RRcreate