Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
cbcd221d
Commit
cbcd221d
authored
Aug 21, 2016
by
Nick Coghlan
Browse files
Options
Browse Files
Download
Plain Diff
Merge #27782 fix from 3.5
parents
f9ed528f
8682f578
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
83 additions
and
32 deletions
+83
-32
Doc/c-api/module.rst
Doc/c-api/module.rst
+1
-1
Include/moduleobject.h
Include/moduleobject.h
+1
-1
Lib/test/test_importlib/extension/test_loader.py
Lib/test/test_importlib/extension/test_loader.py
+9
-0
Misc/ACKS
Misc/ACKS
+1
-0
Misc/NEWS
Misc/NEWS
+4
-0
Modules/_testmultiphase.c
Modules/_testmultiphase.c
+32
-1
Objects/moduleobject.c
Objects/moduleobject.c
+35
-29
No files found.
Doc/c-api/module.rst
View file @
cbcd221d
...
...
@@ -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
...
...
Include/moduleobject.h
View file @
cbcd221d
...
...
@@ -77,7 +77,7 @@ typedef struct PyModuleDef{
traverseproc
m_traverse
;
inquiry
m_clear
;
freefunc
m_free
;
}
PyModuleDef
;
}
PyModuleDef
;
#ifdef __cplusplus
}
...
...
Lib/test/test_importlib/extension/test_loader.py
View file @
cbcd221d
...
...
@@ -212,6 +212,15 @@ class MultiPhaseExtensionModuleTests(abc.LoaderTests):
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'
...
...
Misc/ACKS
View file @
cbcd221d
...
...
@@ -1679,6 +1679,7 @@ Nickolai Zeldovich
Yuxiao Zeng
Uwe Zessin
Cheng Zhang
Xiang Zhang
Kai Zhu
Tarek Ziadé
Jelle Zijlstra
...
...
Misc/NEWS
View file @
cbcd221d
...
...
@@ -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.
...
...
Modules/_testmultiphase.c
View file @
cbcd221d
...
...
@@ -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
=
{
\
...
...
Objects/moduleobject.c
View file @
cbcd221d
...
...
@@ -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_New
Object
(
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
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment