mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	Merge #27782 fix from 3.5
This commit is contained in:
		
						commit
						cbcd221de4
					
				
					 7 changed files with 83 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -324,7 +324,7 @@ The available slot types are:
 | 
			
		|||
   :c:type:`PyModule_Type`. Any type can be used, as long as it supports
 | 
			
		||||
   setting and getting import-related attributes.
 | 
			
		||||
   However, only ``PyModule_Type`` instances may be returned if the
 | 
			
		||||
   ``PyModuleDef`` has non-*NULL* ``m_methods``, ``m_traverse``, ``m_clear``,
 | 
			
		||||
   ``PyModuleDef`` has non-*NULL* ``m_traverse``, ``m_clear``,
 | 
			
		||||
   ``m_free``; non-zero ``m_size``; or slots other than ``Py_mod_create``.
 | 
			
		||||
 | 
			
		||||
.. c:var:: Py_mod_exec
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -77,7 +77,7 @@ typedef struct PyModuleDef{
 | 
			
		|||
  traverseproc m_traverse;
 | 
			
		||||
  inquiry m_clear;
 | 
			
		||||
  freefunc m_free;
 | 
			
		||||
}PyModuleDef;
 | 
			
		||||
} PyModuleDef;
 | 
			
		||||
 | 
			
		||||
#ifdef __cplusplus
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -212,6 +212,15 @@ def test_nonmodule(self):
 | 
			
		|||
        self.assertNotEqual(type(mod), type(unittest))
 | 
			
		||||
        self.assertEqual(mod.three, 3)
 | 
			
		||||
 | 
			
		||||
    # issue 27782
 | 
			
		||||
    def test_nonmodule_with_methods(self):
 | 
			
		||||
        '''Test creating a non-module object with methods defined'''
 | 
			
		||||
        name = self.name + '_nonmodule_with_methods'
 | 
			
		||||
        mod = self.load_module_by_name(name)
 | 
			
		||||
        self.assertNotEqual(type(mod), type(unittest))
 | 
			
		||||
        self.assertEqual(mod.three, 3)
 | 
			
		||||
        self.assertEqual(mod.bar(10, 1), 9)
 | 
			
		||||
 | 
			
		||||
    def test_null_slots(self):
 | 
			
		||||
        '''Test that NULL slots aren't a problem'''
 | 
			
		||||
        name = self.name + '_null_slots'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1679,6 +1679,7 @@ Nickolai Zeldovich
 | 
			
		|||
Yuxiao Zeng
 | 
			
		||||
Uwe Zessin
 | 
			
		||||
Cheng Zhang
 | 
			
		||||
Xiang Zhang
 | 
			
		||||
Kai Zhu
 | 
			
		||||
Tarek Ziadé
 | 
			
		||||
Jelle Zijlstra
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,10 @@ What's New in Python 3.6.0 beta 1
 | 
			
		|||
Core and Builtins
 | 
			
		||||
-----------------
 | 
			
		||||
 | 
			
		||||
- Issue #27782: 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.
 | 
			
		||||
 | 
			
		||||
- Issue #27487: Warn if a submodule argument to "python -m" or
 | 
			
		||||
  runpy.run_module() is found in sys.modules after parent packages are
 | 
			
		||||
  imported, but before the submodule is executed.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -248,6 +248,7 @@ PyInit__testmultiphase(PyObject *spec)
 | 
			
		|||
/**** Importing a non-module object ****/
 | 
			
		||||
 | 
			
		||||
static PyModuleDef def_nonmodule;
 | 
			
		||||
static PyModuleDef def_nonmodule_with_methods;
 | 
			
		||||
 | 
			
		||||
/* Create a SimpleNamespace(three=3) */
 | 
			
		||||
static PyObject*
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +256,7 @@ createfunc_nonmodule(PyObject *spec, PyModuleDef *def)
 | 
			
		|||
{
 | 
			
		||||
    PyObject *dct, *ns, *three;
 | 
			
		||||
 | 
			
		||||
    if (def != &def_nonmodule) {
 | 
			
		||||
    if (def != &def_nonmodule && def != &def_nonmodule_with_methods) {
 | 
			
		||||
        PyErr_SetString(PyExc_SystemError, "def does not match");
 | 
			
		||||
        return NULL;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -291,6 +292,36 @@ PyInit__testmultiphase_nonmodule(PyObject *spec)
 | 
			
		|||
    return PyModuleDef_Init(&def_nonmodule);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
PyDoc_STRVAR(nonmodule_bar_doc,
 | 
			
		||||
"bar(i,j)\n\
 | 
			
		||||
\n\
 | 
			
		||||
Return the difference of i - j.");
 | 
			
		||||
 | 
			
		||||
static PyObject *
 | 
			
		||||
nonmodule_bar(PyObject *self, PyObject *args)
 | 
			
		||||
{
 | 
			
		||||
    long i, j;
 | 
			
		||||
    long res;
 | 
			
		||||
    if (!PyArg_ParseTuple(args, "ll:bar", &i, &j))
 | 
			
		||||
        return NULL;
 | 
			
		||||
    res = i - j;
 | 
			
		||||
    return PyLong_FromLong(res);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static PyMethodDef nonmodule_methods[] = {
 | 
			
		||||
    {"bar", nonmodule_bar, METH_VARARGS, nonmodule_bar_doc},
 | 
			
		||||
    {NULL, NULL}           /* sentinel */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static PyModuleDef def_nonmodule_with_methods = TEST_MODULE_DEF(
 | 
			
		||||
    "_testmultiphase_nonmodule_with_methods", slots_create_nonmodule, nonmodule_methods);
 | 
			
		||||
 | 
			
		||||
PyMODINIT_FUNC
 | 
			
		||||
PyInit__testmultiphase_nonmodule_with_methods(PyObject *spec)
 | 
			
		||||
{
 | 
			
		||||
    return PyModuleDef_Init(&def_nonmodule_with_methods);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**** Non-ASCII-named modules ****/
 | 
			
		||||
 | 
			
		||||
static PyModuleDef def_nonascii_latin = { \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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");
 | 
			
		||||
    res = _add_methods_to_object(m, name, functions);
 | 
			
		||||
    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);
 | 
			
		||||
    }
 | 
			
		||||
    Py_DECREF(name);
 | 
			
		||||
    return 0;
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue