Skip to content

gh-80384: Check that callback is callable at weak reference creation#151145

Open
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:weakref-check-callback-is-callable
Open

gh-80384: Check that callback is callable at weak reference creation#151145
serhiy-storchaka wants to merge 2 commits into
python:mainfrom
serhiy-storchaka:weakref-check-callback-is-callable

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Jun 9, 2026

Copy link
Copy Markdown
Member
  • Python functions weakref.ref() and weakref.proxy() now raise TypeError if the callback argument is not callable or None.
  • C functions PyWeakref_NewRef() and PyWeakref_NewProxy() now raise TypeError if the callback argument is not callable, None, or NULL.

@read-the-docs-community

read-the-docs-community Bot commented Jun 9, 2026

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #33058103 | 📁 Comparing 88afc02 against main (9fdbade)

  🔍 Preview build  

3 files changed
± c-api/weakref.html
± library/weakref.html
± whatsnew/changelog.html

…ation

* Python functions weakref.ref() and weakref.proxy() now raise TypeError
  if the callback argument is not callable or None.
* C functions PyWeakref_NewRef() and PyWeakref_NewProxy() now raise TypeError
  if the callback argument is not callable, None, or NULL.
@serhiy-storchaka serhiy-storchaka force-pushed the weakref-check-callback-is-callable branch from 0fe7893 to 06145a6 Compare June 9, 2026 12:03
@vstinner

vstinner commented Jun 9, 2026

Copy link
Copy Markdown
Member

test_traceback.test_recursion_error_during_traceback() does fail. The script calls ref(lambda: 0, []) whereas [] is not callable.

@serhiy-storchaka

Copy link
Copy Markdown
Member Author

@isidentical, do you remember the purpose of ref(lambda: 0, []) in that test (GH-27313)?

It's effect was raising a TypeError after destruction the weak-referred object (lambda: 0). Since this is not associated with any Python code, source_line should be NULL. I replaced the callback with ord, calling which should have the same effect.

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I just have a suggestion for test_traceback.

Comment on lines 208 to 210
def f():
ref(lambda: 0, [])
ref(lambda: 0, ord)
f()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test expects that calling the callback raises an exception. Currently, it raises a TypeError since [] (list) is not callable. I suggest making the exception more explicit:

                def callback(wr):
                    raise Exception("error")

                def f():
                    ref(lambda: 0, callback)
                    f()

Passing ord() is more surprising to me.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I correctly understand the purpose of this test, we cannot do this. This would insert a Python frame, this would give a non-NULL source_line. This is why the test used such indirect way of raising an exception.

I am not completely sure in my reconstruction, this is why I have not added an explaining comment, which would be helpful here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants