Browse Source
bpo-38787: C API for module state access from extension methods (PEP 573) (GH-19936)
bpo-38787: C API for module state access from extension methods (PEP 573) (GH-19936)
Module C state is now accessible from C-defined heap type methods (PEP 573). Patch by Marcel Plch and Petr Viktorin. Co-authored-by: Marcel Plch <mplch@redhat.com> Co-authored-by: Victor Stinner <vstinner@python.org>pull/19990/head
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 797 additions and 51 deletions
-
50Doc/c-api/structures.rst
-
36Doc/c-api/type.rst
-
32Include/cpython/methodobject.h
-
1Include/cpython/object.h
-
48Include/methodobject.h
-
5Include/object.h
-
73Lib/test/test_capi.py
-
2Lib/test/test_sys.py
-
1Makefile.pre.in
-
2Misc/NEWS.d/next/C API/2020-01-22-12-38-59.bpo-38787.HUH6hd.rst
-
235Modules/_testmultiphase.c
-
101Modules/clinic/_testmultiphase.c.h
-
47Objects/descrobject.c
-
83Objects/methodobject.c
-
1Objects/object.c
-
63Objects/typeobject.c
-
1PCbuild/pythoncore.vcxproj
-
3PCbuild/pythoncore.vcxproj.filters
-
64Tools/clinic/clinic.py
@ -0,0 +1,32 @@ |
|||
#ifndef Py_CPYTHON_METHODOBJECT_H |
|||
# error "this header file must not be included directly" |
|||
#endif |
|||
|
|||
PyAPI_DATA(PyTypeObject) PyCMethod_Type; |
|||
|
|||
/* Macros for direct access to these values. Type checks are *not* |
|||
done, so use with care. */ |
|||
#define PyCFunction_GET_FUNCTION(func) \ |
|||
(((PyCFunctionObject *)func) -> m_ml -> ml_meth) |
|||
#define PyCFunction_GET_SELF(func) \ |
|||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_STATIC ? \ |
|||
NULL : ((PyCFunctionObject *)func) -> m_self) |
|||
#define PyCFunction_GET_FLAGS(func) \ |
|||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags) |
|||
#define PyCFunction_GET_CLASS(func) \ |
|||
(((PyCFunctionObject *)func) -> m_ml -> ml_flags & METH_METHOD ? \ |
|||
((PyCMethodObject *)func) -> mm_class : NULL) |
|||
|
|||
typedef struct { |
|||
PyObject_HEAD |
|||
PyMethodDef *m_ml; /* Description of the C function to call */ |
|||
PyObject *m_self; /* Passed as 'self' arg to the C func, can be NULL */ |
|||
PyObject *m_module; /* The __module__ attribute, can be anything */ |
|||
PyObject *m_weakreflist; /* List of weak references */ |
|||
vectorcallfunc vectorcall; |
|||
} PyCFunctionObject; |
|||
|
|||
typedef struct { |
|||
PyCFunctionObject func; |
|||
PyTypeObject *mm_class; /* Class that defines this method */ |
|||
} PyCMethodObject; |
|||
@ -0,0 +1,2 @@ |
|||
Module C state is now accessible from C-defined heap type methods (:pep:`573`). |
|||
Patch by Marcel Plch and Petr Viktorin. |
|||
@ -0,0 +1,101 @@ |
|||
/*[clinic input] |
|||
preserve |
|||
[clinic start generated code]*/ |
|||
|
|||
PyDoc_STRVAR(_testmultiphase_StateAccessType_get_defining_module__doc__, |
|||
"get_defining_module($self, /)\n" |
|||
"--\n" |
|||
"\n" |
|||
"Return the module of the defining class."); |
|||
|
|||
#define _TESTMULTIPHASE_STATEACCESSTYPE_GET_DEFINING_MODULE_METHODDEF \ |
|||
{"get_defining_module", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_get_defining_module, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_get_defining_module__doc__}, |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_get_defining_module_impl(StateAccessTypeObject *self, |
|||
PyTypeObject *cls); |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_get_defining_module(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) |
|||
{ |
|||
PyObject *return_value = NULL; |
|||
static const char * const _keywords[] = { NULL}; |
|||
static _PyArg_Parser _parser = {":get_defining_module", _keywords, 0}; |
|||
|
|||
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser |
|||
)) { |
|||
goto exit; |
|||
} |
|||
return_value = _testmultiphase_StateAccessType_get_defining_module_impl(self, cls); |
|||
|
|||
exit: |
|||
return return_value; |
|||
} |
|||
|
|||
PyDoc_STRVAR(_testmultiphase_StateAccessType_increment_count_clinic__doc__, |
|||
"increment_count_clinic($self, /, n=1, *, twice=False)\n" |
|||
"--\n" |
|||
"\n" |
|||
"Add \'n\' from the module-state counter.\n" |
|||
"\n" |
|||
"Pass \'twice\' to double that amount.\n" |
|||
"\n" |
|||
"This tests Argument Clinic support for defining_class."); |
|||
|
|||
#define _TESTMULTIPHASE_STATEACCESSTYPE_INCREMENT_COUNT_CLINIC_METHODDEF \ |
|||
{"increment_count_clinic", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_increment_count_clinic, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_increment_count_clinic__doc__}, |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_increment_count_clinic_impl(StateAccessTypeObject *self, |
|||
PyTypeObject *cls, |
|||
int n, int twice); |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_increment_count_clinic(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) |
|||
{ |
|||
PyObject *return_value = NULL; |
|||
static const char * const _keywords[] = {"n", "twice", NULL}; |
|||
static _PyArg_Parser _parser = {"|i$p:increment_count_clinic", _keywords, 0}; |
|||
int n = 1; |
|||
int twice = 0; |
|||
|
|||
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, |
|||
&n, &twice)) { |
|||
goto exit; |
|||
} |
|||
return_value = _testmultiphase_StateAccessType_increment_count_clinic_impl(self, cls, n, twice); |
|||
|
|||
exit: |
|||
return return_value; |
|||
} |
|||
|
|||
PyDoc_STRVAR(_testmultiphase_StateAccessType_get_count__doc__, |
|||
"get_count($self, /)\n" |
|||
"--\n" |
|||
"\n" |
|||
"Return the value of the module-state counter."); |
|||
|
|||
#define _TESTMULTIPHASE_STATEACCESSTYPE_GET_COUNT_METHODDEF \ |
|||
{"get_count", (PyCFunction)(void(*)(void))_testmultiphase_StateAccessType_get_count, METH_METHOD|METH_FASTCALL|METH_KEYWORDS, _testmultiphase_StateAccessType_get_count__doc__}, |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_get_count_impl(StateAccessTypeObject *self, |
|||
PyTypeObject *cls); |
|||
|
|||
static PyObject * |
|||
_testmultiphase_StateAccessType_get_count(StateAccessTypeObject *self, PyTypeObject *cls, PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames) |
|||
{ |
|||
PyObject *return_value = NULL; |
|||
static const char * const _keywords[] = { NULL}; |
|||
static _PyArg_Parser _parser = {":get_count", _keywords, 0}; |
|||
|
|||
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser |
|||
)) { |
|||
goto exit; |
|||
} |
|||
return_value = _testmultiphase_StateAccessType_get_count_impl(self, cls); |
|||
|
|||
exit: |
|||
return return_value; |
|||
} |
|||
/*[clinic end generated code: output=39eea487e94e7f5d input=a9049054013a1b77]*/ |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue