diff options
author | Nick Coghlan <ncoghlan@gmail.com> | 2016-08-21 07:41:56 (GMT) |
---|---|---|
committer | Nick Coghlan <ncoghlan@gmail.com> | 2016-08-21 07:41:56 (GMT) |
commit | 8682f578c1c8fd0486c886b001729907a5409a9f (patch) | |
tree | 2f54886ef578b7faf94e26fe32e24fbb258b896a /Objects | |
parent | 9c8aa9bffe755fe6126dc72dfd037c6b20e65906 (diff) | |
download | cpython-8682f578c1c8fd0486c886b001729907a5409a9f.zip cpython-8682f578c1c8fd0486c886b001729907a5409a9f.tar.gz cpython-8682f578c1c8fd0486c886b001729907a5409a9f.tar.bz2 |
Issue #27782: Fix m_methods handling in multiphase init
Multi-phase extension module import now correctly allows the
``m_methods`` field to be used to add module level functions
to instances of non-module types returned from ``Py_create_mod``.
Patch by Xiang Zhang.
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/moduleobject.c | 64 |
1 files changed, 35 insertions, 29 deletions
diff --git a/Objects/moduleobject.c b/Objects/moduleobject.c index a4cdc20..ac07642 100644 --- a/Objects/moduleobject.c +++ b/Objects/moduleobject.c @@ -130,6 +130,34 @@ check_api_version(const char *name, int module_api_version) return 1; } +static int +_add_methods_to_object(PyObject *module, PyObject *name, PyMethodDef *functions) +{ + PyObject *func; + PyMethodDef *fdef; + + for (fdef = functions; fdef->ml_name != NULL; fdef++) { + if ((fdef->ml_flags & METH_CLASS) || + (fdef->ml_flags & METH_STATIC)) { + PyErr_SetString(PyExc_ValueError, + "module functions cannot set" + " METH_CLASS or METH_STATIC"); + return -1; + } + func = PyCFunction_NewEx(fdef, (PyObject*)module, name); + if (func == NULL) { + return -1; + } + if (PyObject_SetAttrString(module, fdef->ml_name, func) != 0) { + Py_DECREF(func); + return -1; + } + Py_DECREF(func); + } + + return 0; +} + PyObject * PyModule_Create2(struct PyModuleDef* module, int module_api_version) { @@ -269,7 +297,7 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } } } else { - m = PyModule_New(name); + m = PyModule_NewObject(nameobj); if (m == NULL) { goto error; } @@ -297,7 +325,7 @@ PyModule_FromDefAndSpec2(struct PyModuleDef* def, PyObject *spec, int module_api } if (def->m_methods != NULL) { - ret = PyModule_AddFunctions(m, def->m_methods); + ret = _add_methods_to_object(m, nameobj, def->m_methods); if (ret != 0) { goto error; } @@ -331,7 +359,7 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) return -1; } - if (PyModule_Check(module) && def->m_size >= 0) { + if (def->m_size >= 0) { PyModuleObject *md = (PyModuleObject*)module; if (md->md_state == NULL) { /* Always set a state pointer; this serves as a marker to skip @@ -387,37 +415,15 @@ PyModule_ExecDef(PyObject *module, PyModuleDef *def) int PyModule_AddFunctions(PyObject *m, PyMethodDef *functions) { - PyObject *name, *func; - PyMethodDef *fdef; - - name = PyModule_GetNameObject(m); + int res; + PyObject *name = PyModule_GetNameObject(m); if (name == NULL) { return -1; } - for (fdef = functions; fdef->ml_name != NULL; fdef++) { - if ((fdef->ml_flags & METH_CLASS) || - (fdef->ml_flags & METH_STATIC)) { - PyErr_SetString(PyExc_ValueError, - "module functions cannot set" - " METH_CLASS or METH_STATIC"); - Py_DECREF(name); - return -1; - } - func = PyCFunction_NewEx(fdef, (PyObject*)m, name); - if (func == NULL) { - Py_DECREF(name); - return -1; - } - if (PyObject_SetAttrString(m, fdef->ml_name, func) != 0) { - Py_DECREF(func); - Py_DECREF(name); - return -1; - } - Py_DECREF(func); - } + res = _add_methods_to_object(m, name, functions); Py_DECREF(name); - return 0; + return res; } int |