PEP 489: Update from Petr.
This commit is contained in:
parent
cb84322924
commit
d7780468e2
62
pep-0489.txt
62
pep-0489.txt
|
@ -128,13 +128,13 @@ PEP 384's PyType_Spec for types. The structure is defined as::
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int slot;
|
int slot;
|
||||||
void *value;
|
void *value;
|
||||||
} PyModuleDesc_Slot;
|
} PyModuleExport_Slot;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const char* doc;
|
const char* doc;
|
||||||
int flags;
|
int flags;
|
||||||
PyModuleDesc_Slot *slots;
|
PyModuleExport_Slot *slots;
|
||||||
} PyModuleDesc;
|
} PyModuleExport;
|
||||||
|
|
||||||
The *doc* member specifies the module's docstring.
|
The *doc* member specifies the module's docstring.
|
||||||
|
|
||||||
|
@ -142,7 +142,7 @@ The *flags* may currently be either 0 or ``PyModule_EXPORT_SINGLETON``, describe
|
||||||
in "Singleton Modules" below.
|
in "Singleton Modules" below.
|
||||||
Other flag values may be added in the future.
|
Other flag values may be added in the future.
|
||||||
|
|
||||||
The *slots* points to an array of PyModuleDesc_Slot structures, terminated
|
The *slots* points to an array of PyModuleExport_Slot structures, terminated
|
||||||
by a slot with id set to 0 (i.e. ``{0, NULL}``).
|
by a slot with id set to 0 (i.e. ``{0, NULL}``).
|
||||||
|
|
||||||
To specify a slot, a unique slot ID must be provided.
|
To specify a slot, a unique slot ID must be provided.
|
||||||
|
@ -164,7 +164,7 @@ Unknown slot IDs will cause the import to fail with ImportError.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
An alternate proposal is to use PyModuleDef instead of PyModuleDesc,
|
An alternate proposal is to use PyModuleDef instead of PyModuleExport,
|
||||||
re-purposing the m_reload pointer to hold the slots::
|
re-purposing the m_reload pointer to hold the slots::
|
||||||
|
|
||||||
typedef struct PyModuleDef {
|
typedef struct PyModuleDef {
|
||||||
|
@ -173,7 +173,7 @@ Unknown slot IDs will cause the import to fail with ImportError.
|
||||||
const char* m_doc;
|
const char* m_doc;
|
||||||
Py_ssize_t m_size;
|
Py_ssize_t m_size;
|
||||||
PyMethodDef *m_methods;
|
PyMethodDef *m_methods;
|
||||||
PyModuleDesc_Slot* m_slots; /* changed from `inquiry m_reload;` */
|
PyModuleExport_Slot* m_slots; /* changed from `inquiry m_reload;` */
|
||||||
traverseproc m_traverse;
|
traverseproc m_traverse;
|
||||||
inquiry m_clear;
|
inquiry m_clear;
|
||||||
freefunc m_free;
|
freefunc m_free;
|
||||||
|
@ -197,10 +197,10 @@ Py_mod_create
|
||||||
The Py_mod_create slot is used to support custom module subclasses.
|
The Py_mod_create slot is used to support custom module subclasses.
|
||||||
The value pointer must point to a function with the following signature::
|
The value pointer must point to a function with the following signature::
|
||||||
|
|
||||||
PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleDesc *desc)
|
PyObject* (*PyModuleCreateFunction)(PyObject *spec, PyModuleExport *exp)
|
||||||
|
|
||||||
The function receives a ModuleSpec instance, as defined in PEP 451,
|
The function receives a ModuleSpec instance, as defined in PEP 451,
|
||||||
and the PyModuleDesc structure.
|
and the PyModuleExport structure.
|
||||||
It should return a new module object, or set an error
|
It should return a new module object, or set an error
|
||||||
and return NULL.
|
and return NULL.
|
||||||
|
|
||||||
|
@ -213,12 +213,12 @@ types.ModuleType. Any type can be used, as long as it supports setting and
|
||||||
getting attributes, including at least the import-related attributes.
|
getting attributes, including at least the import-related attributes.
|
||||||
|
|
||||||
If a module instance is returned from Py_mod_create, the import machinery will
|
If a module instance is returned from Py_mod_create, the import machinery will
|
||||||
store a pointer to PyModuleDesc in the module object so that it may be
|
store a pointer to PyModuleExport in the module object so that it may be
|
||||||
retrieved by PyModule_GetDesc (described later).
|
retrieved by PyModule_GetExport (described later).
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
If PyModuleDef is used instead of PyModuleDesc, the def is stored
|
If PyModuleDef is used instead of PyModuleExport, the def is stored
|
||||||
instead, to be retrieved by PyModule_GetDef.
|
instead, to be retrieved by PyModule_GetDef.
|
||||||
|
|
||||||
Note that when this function is called, the module's entry in sys.modules
|
Note that when this function is called, the module's entry in sys.modules
|
||||||
|
@ -230,6 +230,9 @@ to not call user code from it.
|
||||||
Multiple Py_mod_create slots may not be specified. If they are, import
|
Multiple Py_mod_create slots may not be specified. If they are, import
|
||||||
will fail with ImportError.
|
will fail with ImportError.
|
||||||
|
|
||||||
|
If Py_mod_create is not specified, the import machinery will create a normal
|
||||||
|
module object, as if by calling PyModule_Create.
|
||||||
|
|
||||||
|
|
||||||
Py_mod_statedef
|
Py_mod_statedef
|
||||||
...............
|
...............
|
||||||
|
@ -290,7 +293,7 @@ The specified methods are added to the module, like with PyModuleDef.m_methods.
|
||||||
Py_mod_exec
|
Py_mod_exec
|
||||||
...........
|
...........
|
||||||
|
|
||||||
The function in this slot must have the signature::
|
The entry in this slot must point to a function with the following signature::
|
||||||
|
|
||||||
int (*PyModuleExecFunction)(PyObject* module)
|
int (*PyModuleExecFunction)(PyObject* module)
|
||||||
|
|
||||||
|
@ -298,7 +301,7 @@ It will be called to initialize a module. Usually, this amounts to
|
||||||
setting the module's initial attributes.
|
setting the module's initial attributes.
|
||||||
|
|
||||||
The "module" argument receives the module object to initialize. This will
|
The "module" argument receives the module object to initialize. This will
|
||||||
always be the module object created from the corresponding PyModuleDesc.
|
always be the module object created from the corresponding PyModuleExport.
|
||||||
When this function is called, import-related attributes (such as ``__spec__``)
|
When this function is called, import-related attributes (such as ``__spec__``)
|
||||||
will have been set, and the module has already been added to sys.modules.
|
will have been set, and the module has already been added to sys.modules.
|
||||||
|
|
||||||
|
@ -317,20 +320,21 @@ Legacy Init
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
If the PyModuleExport function is not defined, the import machinery will try to
|
If the PyModuleExport function is not defined, the import machinery will try to
|
||||||
initialize the module using the PyInit hook, as described in PEP 3121.
|
initialize the module using the "PyInit_<modulename>" hook,
|
||||||
|
as described in PEP 3121.
|
||||||
|
|
||||||
If PyModuleExport is defined, PyModuleInit will be ignored.
|
If the PyModuleExport function is defined, the PyInit function will be ignored.
|
||||||
Modules requiring compatibility with previous versions of CPython may implement
|
Modules requiring compatibility with previous versions of CPython may implement
|
||||||
PyModuleInit in addition to the new hook.
|
the PyInit function in addition to the new hook.
|
||||||
|
|
||||||
Modules using the legacy init API will be initialized entirely in the
|
Modules using the legacy init API will be initialized entirely in the
|
||||||
Loader.create_module step; Loader.exec_module will be a no-op.
|
Loader.create_module step; Loader.exec_module will be a no-op.
|
||||||
|
|
||||||
.. XXX: Give example code for a backwards-compatible Init based on slots
|
.. XXX: Give example code for a backwards-compatible PyInit based on slots
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
If PyModuleDef is reused, implementing the PyInit hook becomes easy:
|
If PyModuleDef is reused, implementing the PyInit function becomes easy:
|
||||||
|
|
||||||
* call PyModule_Create with the PyModuleDef (m_reload was ignored in
|
* call PyModule_Create with the PyModuleDef (m_reload was ignored in
|
||||||
previous Python versions, so the slots array will be ignored).
|
previous Python versions, so the slots array will be ignored).
|
||||||
|
@ -354,16 +358,16 @@ A simple rule of thumb is: Do not define any static data, except built-in types
|
||||||
with no mutable or user-settable class attributes.
|
with no mutable or user-settable class attributes.
|
||||||
|
|
||||||
|
|
||||||
PyModule_GetDesc
|
PyModule_GetExport
|
||||||
----------------
|
------------------
|
||||||
|
|
||||||
To retrieve the PyModuleDesc structure used to create a module,
|
To retrieve the PyModuleExport structure used to create a module,
|
||||||
a new function will be added::
|
a new function will be added::
|
||||||
|
|
||||||
PyModuleDesc* PyModule_GetDesc(PyObject *module)
|
PyModuleExport* PyModule_GetExport(PyObject *module)
|
||||||
|
|
||||||
The function returns NULL if the parameter is not a module object, or was not
|
The function returns NULL if the parameter is not a module object, or was not
|
||||||
created using PyModuleDesc.
|
created using PyModuleExport.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
|
@ -389,7 +393,7 @@ a reference to the module object, either directly or indirectly.
|
||||||
However, there are some modules that really need to be only loaded once:
|
However, there are some modules that really need to be only loaded once:
|
||||||
typically ones that wrap a C library with global state.
|
typically ones that wrap a C library with global state.
|
||||||
These modules should set the PyModule_EXPORT_SINGLETON flag
|
These modules should set the PyModule_EXPORT_SINGLETON flag
|
||||||
in PyModuleDesc.flags. When this flag is set, loading an additional
|
in PyModuleExport.flags. When this flag is set, loading an additional
|
||||||
copy of the module after it has been loaded once will return the previously
|
copy of the module after it has been loaded once will return the previously
|
||||||
loaded object.
|
loaded object.
|
||||||
This will be done on a low level, using _PyImport_FixupExtensionObject.
|
This will be done on a low level, using _PyImport_FixupExtensionObject.
|
||||||
|
@ -401,21 +405,21 @@ the interpreter state using three new functions, which parallel their
|
||||||
PyModuleDef counterparts, PyState_FindModule, PyState_AddModule,
|
PyModuleDef counterparts, PyState_FindModule, PyState_AddModule,
|
||||||
and PyState_RemoveModule::
|
and PyState_RemoveModule::
|
||||||
|
|
||||||
PyObject* PyState_FindSingletonModule(PyModuleDesc *desc)
|
PyObject* PyState_FindSingletonModule(PyModuleExport *exp)
|
||||||
int PyState_AddSingletonModule(PyObject *module, PyModuleDesc *desc)
|
int PyState_AddSingletonModule(PyObject *module, PyModuleExport *exp)
|
||||||
int PyState_RemoveSingletonModule(PyModuleDesc *desc)
|
int PyState_RemoveSingletonModule(PyModuleExport *exp)
|
||||||
|
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
If PyModuleDef is used instead of PyModuleDesc, the flag would be specified
|
If PyModuleDef is used instead of PyModuleExport, the flag would be specified
|
||||||
as a slot with NULL value, i.e. ``{Py_mod_flag_singleton, NULL}``.
|
as a slot with NULL value, i.e. ``{Py_mod_flag_singleton, NULL}``.
|
||||||
In this case, PyState_FindModule, PyState_AddModule and
|
In this case, PyState_FindModule, PyState_AddModule and
|
||||||
PyState_RemoveModule can be used instead of the new functions.
|
PyState_RemoveModule can be used instead of the new functions.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
|
|
||||||
Another possibility is to use PyModuleDef_Base in PyModuleDesc, and
|
Another possibility is to use PyModuleDef_Base in PyModuleExport, and
|
||||||
have PyState_FindModule and friends work with either of the two structures.
|
have PyState_FindModule and friends work with either of the two structures.
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue