-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
[PEP 573] bpo-38787: Module State Access from C Extension Methods #17145
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Objects/typeobject.c
Outdated
@@ -2912,6 +2922,11 @@ PyType_FromSpecWithBases(PyType_Spec *spec, PyObject *bases) | |||
Py_INCREF(res->ht_qualname); | |||
type->tp_name = spec->name; | |||
|
|||
if (module) { | |||
Py_INCREF(module); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Py_XINCREF()
?
Objects/typeobject.c
Outdated
break; | ||
} | ||
|
||
type = (PyTypeObject *)PyTuple_GetItem(mro, pos); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the guarantee that prevents the two tuple item accesses (here and below) from running out of bounds?
Could that be worth a comment, at least?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A for
loop might be better: first use PyTuple_Size
to also check the type, then use the faster PyTuple_GET_ITEM
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lots of comments on first glance:
Include/object.h
Outdated
typedef struct { | ||
Py_ssize_t dict; | ||
Py_ssize_t weaklist; | ||
} PyType_offsets; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be unnecessary.
|
||
#define PyCFunction_Check(op) (Py_TYPE(op) == &PyCFunction_Type) | ||
#define PyCFunction_Check(op) ((Py_TYPE(op) == &PyCFunction_Type) || (PyType_IsSubtype(Py_TYPE(op), &PyCFunction_Type))) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use the existing PyCFunction_Type
for methods?
The METH_METHOD
flag should signal that the underlying struct is PyCMethodObject
; you'll also want to set tp_itemsize
and the use PyObject_GC_NewVar
.
Include/methodobject.h
Outdated
|
||
PyAPI_FUNC(PyCFunction) PyCFunction_GetFunction(PyObject *); | ||
PyAPI_FUNC(PyObject *) PyCFunction_GetSelf(PyObject *); | ||
PyAPI_FUNC(int) PyCFunction_GetFlags(PyObject *); | ||
PyAPI_FUNC(PyTypeObject *) PyCMethod_GetClass(PyObject *); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks unnecessary; the PEP only mentions PyCFunction_GET_CLASS
.
@@ -197,6 +202,18 @@ PyAPI_FUNC(PyObject*) PyType_FromSpecWithBases(PyType_Spec*, PyObject*); | |||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03040000 | |||
PyAPI_FUNC(void*) PyType_GetSlot(struct _typeobject*, int); | |||
#endif | |||
#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03080000 | |||
PyAPI_FUNC(PyObject*) PyType_FromModuleAndSpec(PyObject *, PyType_Spec *, PyObject *); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops, this is missing from the PEP's summary.
Include/object.h
Outdated
/* access macro to the members which are floating "behind" the object */ | ||
#define PyHeapType_GET_MEMBERS(etype) \ | ||
((PyMemberDef *)(((char *)etype) + Py_TYPE(etype)->tp_basicsize)) | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is duplicates the definition in Include/internal/object.h
.
Objects/descrobject.c
Outdated
if (descr->d_method->ml_flags & METH_METHOD) { | ||
return PyCMethod_New(descr->d_method, type, NULL, descr->d_common.d_type); | ||
} else { | ||
return PyCFunction_NewEx(descr->d_method, type, NULL); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be much simpler, since PyCFunction_NewEx(...)
is defined as PyCMethod_New(..., NULL)
.
Objects/methodobject.c
Outdated
if (ml->ml_flags & (METH_NOARGS | METH_O | METH_CLASS | METH_STATIC)) { | ||
PyErr_SetString(PyExc_SystemError, | ||
"METH_METHOD cannot be used with METH_NOARGS, " | ||
"METH_O, METH_CLASS, nor METH_STATIC"); | ||
return NULL; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it would allow (METH_VARARGS | METH_METHOD)
or METH_FASTCALL | METH_METHOD
Objects/typeobject.c
Outdated
break; | ||
} | ||
|
||
type = (PyTypeObject *)PyTuple_GetItem(mro, pos); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A for
loop might be better: first use PyTuple_Size
to also check the type, then use the faster PyTuple_GET_ITEM
.
Modules/_testmultiphase.c
Outdated
|
||
/*[clinic input] | ||
_testmultiphase.StateAccessType.__init__ | ||
cls: defining_class |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you also test with another slot, not only __init__
?
Tools/clinic/clinic.py
Outdated
fields.insert(0, normalize_snippet(""" | ||
PyTypeObject *cls; | ||
|
||
cls = PyType_DefiningTypeFromSlotFunc(Py_TYPE(self), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it always named cls
?
This is a WIP pull request for PEP 573.
The purpose of this PEP is to provide a way to access per-module state from methods belonging to classes defined in extension modules.
https://bugs.python.org/issue38787