Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6463,8 +6463,7 @@ def test_warnings_module_has_signatures(self):

def test_weakref_module_has_signatures(self):
import weakref
no_signature = {'ReferenceType', 'ref'}
self._test_module_has_signatures(weakref, no_signature)
self._test_module_has_signatures(weakref)

def test_python_function_override_signature(self):
def func(*args, **kwargs):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Speed up creating :class:`weakref.ref` objects by adding a vectorcall implementation of the constructor generated by Argument Clinic. Patch by Pieter Eendebak.
109 changes: 109 additions & 0 deletions Objects/clinic/weakrefobject.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 43 additions & 24 deletions Objects/weakrefobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@
#include "pycore_pystate.h"
#include "pycore_weakref.h" // _PyWeakref_GET_REF()

#include "clinic/weakrefobject.c.h"

/*[clinic input]
module weakref
class weakref.ReferenceType "PyWeakReference *" "&_PyWeakref_RefType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=25211e4a7d687f3f]*/

#ifdef Py_GIL_DISABLED
/*
* Thread-safety for free-threaded builds
Expand Down Expand Up @@ -459,35 +467,44 @@ get_or_create_weakref(PyTypeObject *type, PyObject *obj, PyObject *callback)
}
}

static int
parse_weakref_init_args(const char *funcname, PyObject *args, PyObject *kwargs,
PyObject **obp, PyObject **callbackp)
{
return PyArg_UnpackTuple(args, funcname, 1, 2, obp, callbackp);
}
/*[clinic input]
@classmethod
@vectorcall
weakref.ReferenceType.__new__ as weakref_ref_new

ob: object

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: Should this be called "object" to match the docs https://docs.python.org/3/library/weakref.html#weakref.ref

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm. This is positional only, so not too important but I think that would indeed be better.

Note: the subclass KeyedRef is not positional only, and uses the name ob.

callback: object(c_default="NULL") = None
/

Create a weak reference to ob.

Calling the reference returns ob, or None once ob has been garbage
collected. If callback is given, it is called with the reference as
its only argument when ob is about to be finalized.
[clinic start generated code]*/

static PyObject *
weakref___new__(PyTypeObject *type, PyObject *args, PyObject *kwargs)
weakref_ref_new_impl(PyTypeObject *type, PyObject *ob, PyObject *callback)
/*[clinic end generated code: output=689332971ea485ce input=f9264872536c6be7]*/
{
PyObject *ob, *callback = NULL;
if (parse_weakref_init_args("__new__", args, kwargs, &ob, &callback)) {
return (PyObject *)get_or_create_weakref(type, ob, callback);
}
return NULL;
return (PyObject *)get_or_create_weakref(type, ob, callback);
}

static int
weakref___init__(PyObject *self, PyObject *args, PyObject *kwargs)
{
PyObject *tmp;
/*[clinic input]
weakref.ReferenceType.__init__ as weakref_ref_init

if (!_PyArg_NoKeywords("ref", kwargs))
return -1;
ob: object
callback: object = None
/
[clinic start generated code]*/

if (parse_weakref_init_args("__init__", args, kwargs, &tmp, &tmp))
return 0;
else
return -1;
static int
weakref_ref_init_impl(PyWeakReference *self, PyObject *ob,
PyObject *callback)
/*[clinic end generated code: output=57cec8c3671e296c input=7dd1cba6e88c7df8]*/
{
/* The arguments were already used by __new__; only validate them. */
return 0;
}


Expand All @@ -508,6 +525,7 @@ _PyWeakref_RefType = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
.tp_name = "weakref.ReferenceType",
.tp_basicsize = sizeof(PyWeakReference),
.tp_doc = weakref_ref_new__doc__,
.tp_dealloc = weakref_dealloc,
.tp_vectorcall_offset = offsetof(PyWeakReference, vectorcall),
.tp_call = PyVectorcall_Call,
Expand All @@ -520,10 +538,11 @@ _PyWeakref_RefType = {
.tp_richcompare = weakref_richcompare,
.tp_methods = weakref_methods,
.tp_members = weakref_members,
.tp_init = weakref___init__,
.tp_init = weakref_ref_init,
.tp_alloc = PyType_GenericAlloc,
.tp_new = weakref___new__,
.tp_new = weakref_ref_new,
.tp_free = PyObject_GC_Del,
.tp_vectorcall = weakref_ref_vectorcall,
};


Expand Down
Loading