Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

gh-134160: Use multi-phase init in documentation examples#134296

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
AA-Turner merged 24 commits intopython:mainfromneonene:multi
May 26, 2025
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
24 commits
Select commitHold shift + click to select a range
8d8b366
Update docs
neoneneMay 19, 2025
88c5f3f
Don't change an unrelated example
neoneneMay 20, 2025
a4ade5c
Apply suggestions from code review
neoneneMay 21, 2025
d6c42e2
ditto
neoneneMay 21, 2025
97eae13
Suggested module names
neoneneMay 21, 2025
8ae6bae
Avoid modernization
neoneneMay 21, 2025
bc78288
typo
neoneneMay 21, 2025
c3ab022
Correction: "error"
neoneneMay 21, 2025
d65303c
Rephrase warning
neoneneMay 21, 2025
aec6781
keywdarg_module
neoneneMay 21, 2025
7dfd5ad
Update Doc/extending/extending.rst
neoneneMay 22, 2025
f7c72dd
Indicate xxlimited
neoneneMay 22, 2025
c84638c
Add seealso to index
neoneneMay 22, 2025
4e59e88
Update Doc/extending/embedding.rst
neoneneMay 22, 2025
d68e3e3
ditto (for copy-paste)
neoneneMay 22, 2025
f6465bd
Shrink slots
neoneneMay 22, 2025
1a65816
Remove module states
neoneneMay 22, 2025
a83e266
Correction: "SpamError"
neoneneMay 22, 2025
2d10958
Add a Py_mod_multiple_interpreters slot
neoneneMay 22, 2025
a28e67c
Cancel the prvious addition as needless
neoneneMay 22, 2025
9e6bff5
Merge remote-tracking branch 'upstream/main' into multi
AA-TurnerMay 26, 2025
d35a6b4
updates
AA-TurnerMay 26, 2025
9cb3092
PEP 7
AA-TurnerMay 26, 2025
6e5b1c5
revert module state for SpamError
AA-TurnerMay 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
PrevPrevious commit
NextNext commit
Remove module states
  • Loading branch information
@neonene
neonene committedMay 22, 2025
commit1a65816621cecdfc93a4b510326bc644108cf9df
117 changes: 40 additions & 77 deletionsDoc/extending/extending.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -204,59 +204,26 @@ value must be in a particular range or must satisfy other conditions,
:c:data:`PyExc_ValueError` is appropriate.

You can also define a new exception that is unique to your module. For this, you
usually declare an object variable in the module's state and initialize it
in the module's :c:data:`Py_mod_exec` function (:c:func:`!spam_module_exec`)
with an exception object::

typedef struct {
PyObject *SpamError;
} spam_state;
usually declare a static object variable at the beginning of your file::

static int
spam_module_exec(PyObject *module)
{
spam_state *state = PyModule_GetState(module);
if (state == NULL) {
return -1;
}
static PyObject *SpamError;

state->SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (state->SpamError == NULL) {
return -1;
}
if (PyModule_AddObjectRef(module, "SpamError", state->SpamError) < 0) {
return -1; // followed by spam_module_free() then Py_CLEAR()
}
and initialize it in the module's :c:data:`Py_mod_exec` function
(:c:func:`!spam_module_exec`)

return 0;
}
with an exception object::

static int
spam_module_traverse(PyObject *module, visitproc visit, void *arg) {
spam_state *state = PyModule_GetState(module);
if (state == NULL) {
spam_module_exec(PyObject *m)
{
SpamError = PyErr_NewException("spam.error", NULL, NULL);
if (PyModule_AddObjectRef(m, "error", SpamError) < 0) {
return -1;
}
Py_VISIT(st->SpamError);
return 0;
}

static int
spam_module_clear(PyObject *module) {
spam_state *state = PyModule_GetState(module);
if (state == NULL) {
return -1;
}
Py_CLEAR(st->SpamError);
return 0;
}

static void
spam_module_free(void *module)
{
(void)spam_module_clear((PyObject *)module);
}

static PyModuleDef_Slot spam_module_slots[] = {
{Py_mod_exec, spam_module_exec},
{0, NULL}
Expand All@@ -265,11 +232,8 @@ with an exception object::
static struct PyModuleDef spam_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
.m_size =sizeof(spam_state), //size of per-module state
.m_size =0, //non-negative
.m_slots = spam_module_slots,
.m_traverse = spam_module_traverse,
.m_clear = spam_module_clear,
.m_free = spam_module_free,
};

PyMODINIT_FUNC
Expand DownExpand Up@@ -306,10 +270,7 @@ call to :c:func:`PyErr_SetString` as shown below::
return NULL;
sts = system(command);
if (sts < 0) {
spam_state *state = PyModule_GetState(self);
if (state != NULL) {
PyErr_SetString(state->SpamError, "System command failed");
}
PyErr_SetString(SpamError, "System command failed");
return NULL;
}
return PyLong_FromLong(sts);
Expand DownExpand Up@@ -1297,25 +1258,19 @@ The ``#define`` is used to tell the header file that it is being included in the
exporting module, not a client module. Finally, the module's initialization
function must take care of initializing the C API pointer array::

typedef struct {
void *PySpam_API[PySpam_API_pointers];
} spam_state;

static int
spam_module_exec(PyObject *module)
spam_module_exec(PyObject *m)
{
spam_state *state = PyModule_GetState(module);
if (state == NULL) {
return -1;
}
static void *PySpam_API[PySpam_API_pointers];
PyObject *c_api_object;

/* Initialize the C API pointer array */
state->PySpam_API[PySpam_System_NUM] = PySpam_System;
PySpam_API[PySpam_System_NUM] =(void *)PySpam_System;

/* Create a Capsule containing the API pointer array's address */
PyObject *capi= PyCapsule_New(state->PySpam_API, "spam._C_API", NULL);
if (PyModule_Add(module, "_C_API", capi) < 0) {
Py_CLEAR(capi);
c_api_object= PyCapsule_New((void *)PySpam_API, "spam._C_API", NULL);

if (PyModule_Add(m, "_C_API", c_api_object) < 0) {
return -1;
}

Expand All@@ -1330,7 +1285,7 @@ function must take care of initializing the C API pointer array::
static struct PyModuleDef spam_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "spam",
.m_size =sizeof(spam_state),
.m_size =0,
.m_slots = spam_module_slots,
};

Expand All@@ -1340,6 +1295,9 @@ function must take care of initializing the C API pointer array::
return PyModuleDef_Init(&spam_module);
}

Note that ``PySpam_API`` is declared ``static``; otherwise the pointer
array would disappear when :c:func:`!PyInit_spam` terminates!

The bulk of the work is in the header file :file:`spammodule.h`, which looks
like this::

Expand DownExpand Up@@ -1368,9 +1326,21 @@ like this::
#else
/* This section is used in modules that use spammodule's API */

static void **PySpam_API;

#define PySpam_System \
(*(PySpam_System_RETURN (*)PySpam_System_PROTO) PySpam_API[PySpam_System_NUM])

/* Return -1 on error, 0 on success.
* PyCapsule_Import will set an exception if there's an error.
*/
static int
import_spam(void)
{
PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
return (PySpam_API != NULL) ? 0 : -1;
}

#endif

#ifdef __cplusplus
Expand All@@ -1379,22 +1349,15 @@ like this::

#endif /* !defined(Py_SPAMMODULE_H) */


typedef struct {
void **PySpam_API;
} client_state;
All that a client module must do in order to have access to the function
:c:func:`!PySpam_System` is to call the function (or rather macro)
:c:func:`!import_spam` in its initialization function::

static int
client_module_exec(PyObject *module)
client_module_exec(PyObject *m)
{
client_state *state = PyModule_GetState(module);
if (state == NULL) {
if (import_spam() < 0)
return -1;
}
state->PySpam_API = (void **)PyCapsule_Import("spam._C_API", 0);
if (state->PySpam_API == NULL) {
return -1;
}
/* additional initialization can happen here */
return 0;
}
Expand All@@ -1407,7 +1370,7 @@ like this::
static struct PyModuleDef client_module = {
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "client",
.m_size =sizeof(client_state),
.m_size =0,
.m_slots = client_module_slots,
};

Expand Down
6 changes: 3 additions & 3 deletionsDoc/extending/newtypes_tutorial.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -180,7 +180,7 @@ This initializes the :class:`!Custom` type, filling in a number of members
to the appropriate default values, including :c:member:`~PyObject.ob_type` that we initially
set to ``NULL``. ::

if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
if (PyModule_AddObjectRef(m, "Custom", (PyObject *)&CustomType) < 0) {
return -1;
}

Expand DownExpand Up@@ -878,13 +878,13 @@ issues, you can't fill that field directly with a reference to
function::

static int
sublist_module_exec(PyObject *mod)
sublist_module_exec(PyObject *m)
{
SubListType.tp_base = &PyList_Type;
if (PyType_Ready(&SubListType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "SubList", (PyObject *)&SubListType) < 0) {
if (PyModule_AddObjectRef(m, "SubList", (PyObject *)&SubListType) < 0) {
return -1;
}

Expand Down
4 changes: 2 additions & 2 deletionsDoc/includes/newtypes/custom.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -17,12 +17,12 @@ static PyTypeObject CustomType = {
};

static int
custom_module_exec(PyObject *mod)
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
if (PyModule_AddObjectRef(m, "Custom", (PyObject *)&CustomType) < 0) {
return -1;
}

Expand Down
5 changes: 2 additions & 3 deletionsDoc/includes/newtypes/custom2.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -107,12 +107,12 @@ static PyTypeObject CustomType = {
};

static int
custom_module_exec(PyObject *mod)
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
if (PyModule_AddObjectRef(m, "Custom", (PyObject *)&CustomType) < 0) {
return -1;
}

Expand All@@ -121,7 +121,6 @@ custom_module_exec(PyObject *mod)

static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
// Just use this while using static types
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
Expand Down
5 changes: 2 additions & 3 deletionsDoc/includes/newtypes/custom3.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -152,12 +152,12 @@ static PyTypeObject CustomType = {
};

static int
custom_module_exec(PyObject *mod)
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
if (PyModule_AddObjectRef(m, "Custom", (PyObject *)&CustomType) < 0) {
return -1;
}

Expand All@@ -166,7 +166,6 @@ custom_module_exec(PyObject *mod)

static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
// Just use this while using static types
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
Expand Down
5 changes: 2 additions & 3 deletionsDoc/includes/newtypes/custom4.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -171,12 +171,12 @@ static PyTypeObject CustomType = {
};

static int
custom_module_exec(PyObject *mod)
custom_module_exec(PyObject *m)
{
if (PyType_Ready(&CustomType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "Custom", (PyObject *)&CustomType) < 0) {
if (PyModule_AddObjectRef(m, "Custom", (PyObject *)&CustomType) < 0) {
return -1;
}

Expand All@@ -185,7 +185,6 @@ custom_module_exec(PyObject *mod)

static PyModuleDef_Slot custom_module_slots[] = {
{Py_mod_exec, custom_module_exec},
// Just use this while using static types
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
Expand Down
5 changes: 2 additions & 3 deletionsDoc/includes/newtypes/sublist.c
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -42,13 +42,13 @@ static PyTypeObject SubListType = {
};

static int
sublist_module_exec(PyObject *mod)
sublist_module_exec(PyObject *m)
{
SubListType.tp_base = &PyList_Type;
if (PyType_Ready(&SubListType) < 0)
return -1;

if (PyModule_AddObjectRef(mod, "SubList", (PyObject *)&SubListType) < 0) {
if (PyModule_AddObjectRef(m, "SubList", (PyObject *)&SubListType) < 0) {
return -1;
}

Expand All@@ -57,7 +57,6 @@ sublist_module_exec(PyObject *mod)

static PyModuleDef_Slot sublist_module_slots[] = {
{Py_mod_exec, sublist_module_exec},
// Just use this while using static types
{Py_mod_multiple_interpreters, Py_MOD_MULTIPLE_INTERPRETERS_NOT_SUPPORTED},
{0, NULL}
};
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp