classification
Title: Expose weakref callback for introspection purposes.
Type: enhancement Stage: committed/rejected
Components: Interpreter Core Versions: Python 3.4
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: mark.dickinson Nosy List: benjamin.peterson, mark.dickinson, pitrou, python-dev, sbt, terry.reedy
Priority: normal Keywords: patch

Created on 2013-04-06 12:54 by mark.dickinson, last changed 2013-04-13 14:47 by mark.dickinson. This issue is now closed.

Files
File name Uploaded Description Edit
weakref___callback__.patch mark.dickinson, 2013-04-06 12:54 review
weakref___callback__2.patch mark.dickinson, 2013-04-06 15:04 review
Messages (12)
msg186122 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-04-06 12:54
It would be nice to be able to access the callback of a weakref as an attribute on the weakref itself.  For example:

Python 3.4.0a0 (default:2bf154ca43c6+, Apr  6 2013, 13:31:29) 
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import weakref
>>> x = {1, 2, 3}
>>> ref = weakref.ref(x, lambda ref: print("done"))
>>> ref.__callback__
<function <lambda> at 0x1004f56d0>
>>> del x
done
>>> ref.__callback__  # Returns None

I encountered this while writing a tool to show graphs of Python objects and their references to each other:  I wanted to be able to annotate each edge of the graph.  For something like a function, it's easy to use introspection to compare the reference target with f.__code__, f.__annotations__, etc.  For a weakref, I couldn't find an easy way to retrieve the callback (or even determine whether there *was* a callback associated to the weakref).  One can do a "gc.get_referents" call and hope that if there's exactly one object returned it's the callback, but that won't work so well with weakref.ref subclasses.

Patch attached:  it has tests but no doc updates as yet.
msg186124 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-04-06 13:43
Sounds fine to me.
msg186125 - (view) Author: Benjamin Peterson (benjamin.peterson) * (Python committer) Date: 2013-04-06 13:48
Instead of a getset, I think you just use a read-only T_OBJECT member.
msg186132 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-04-06 15:04
Ah yes; that's easier.  New patch including doc updates.
msg186151 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-04-06 19:27
"del x" will not be enough on non-refcounted implementations.
msg186154 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-04-06 19:31
True:  I'm not sure what to do about that---there are other tests in that test module that also rely on del resulting in immediate cleanup.  I'm not sure what other implementations are currently doing with this test module.

I could mark the new test as cpython only, or add a gc.collect (but I'm not sure if the latter is enough, either).
msg186155 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2013-04-06 19:31
Ah, then we can probably keep using the same style.
msg186655 - (view) Author: Terry J. Reedy (terry.reedy) * (Python committer) Date: 2013-04-12 17:41
> there are other tests in that test module that also rely on del resulting in immediate cleanup

I would mark them all as 'cpython-only', since they are. Other implementation must be omitting this test module, ignoring its failures, or patching out the specific tests.
msg186665 - (view) Author: Richard Oudkerk (sbt) * (Python committer) Date: 2013-04-12 18:52
> I could mark the new test as cpython only, or add a gc.collect (but I'm 
> not sure if the latter is enough, either).

test.support.gc_collect() should work on non-refcounted implementations.
msg186668 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-04-12 19:04
Ah, test.support.gc_collect looks useful.  Thanks!
msg186722 - (view) Author: Roundup Robot (python-dev) Date: 2013-04-13 14:45
New changeset 9e7d31b04d78 by Mark Dickinson in branch 'default':
Issue #17643: Add __callback__ attribute to weakref.ref.
http://hg.python.org/cpython/rev/9e7d31b04d78
msg186723 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2013-04-13 14:47
Committed, using support.gc_collect for the test that requires garbage collection.  Thanks for the reviews!
History
Date User Action Args
2013-04-13 14:47:28mark.dickinsonsetstatus: open -> closed
messages: + msg186723

assignee: mark.dickinson
resolution: fixed
stage: patch review -> committed/rejected
2013-04-13 14:45:57python-devsetnosy: + python-dev
messages: + msg186722
2013-04-12 19:04:59mark.dickinsonsetmessages: + msg186668
2013-04-12 18:52:24sbtsetnosy: + sbt
messages: + msg186665
2013-04-12 17:41:09terry.reedysetnosy: + terry.reedy
messages: + msg186655
2013-04-06 19:31:53pitrousetmessages: + msg186155
2013-04-06 19:31:19mark.dickinsonsetmessages: + msg186154
2013-04-06 19:27:12pitrousetmessages: + msg186151
2013-04-06 15:04:57mark.dickinsonsetfiles: + weakref___callback__2.patch

messages: + msg186132
2013-04-06 13:48:17benjamin.petersonsetnosy: + benjamin.peterson
messages: + msg186125
2013-04-06 13:43:10pitrousetnosy: + pitrou
messages: + msg186124
2013-04-06 12:54:57mark.dickinsoncreate