-
-
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