8000 bpo-46613: Add PyType_GetModuleByDef to the public API (GH-31081) · Python-Repository-Hub/cpython@2049469 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2049469

Browse files
encukouvstinner
andauthored
bpo-46613: Add PyType_GetModuleByDef to the public API (pythonGH-31081)
* Make PyType_GetModuleByDef public (remove underscore) Co-authored-by: Victor Stinner <vstinner@python.org>
1 parent e0bcfd0 commit 2049469

File tree

21 files changed

+56
-36
lines changed

21 files changed

+56
-36
lines changed

Doc/c-api/type.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ Type Objects
149149
``Py_TYPE(self)`` may be a *subclass* of the intended class, and subclasses
150150
are not necessarily defined in the same module as their superclass.
151151
See :c:type:`PyCMethod` to get the class that defines the method.
152+
See :c:func:`PyType_GetModuleByDef` for cases when ``PyCMethod`` cannot
153+
be used.
152154
153155
.. versionadded:: 3.9
154156
@@ -166,6 +168,21 @@ Type Objects
166168
167169
.. versionadded:: 3.9
168170
171+
.. c:function:: PyObject* PyType_GetModuleByDef(PyTypeObject *type, struct PyModuleDef *def)
172+
173+
Find the first superclass whose module was created from
174+
the given :c:type:`PyModuleDef` *def*, and return that module.
175+
176+
If no module is found, raises a :py:class:`TypeError` and returns ``NULL``.
177+
178+
This function is intended to be used together with
179+
:c:func:`PyModule_GetState()` to get module state from slot methods (such as
180+
:c:member:`~PyTypeObject.tp_init` or :c:member:`~PyNumberMethods.nb_add`)
181+
and other places where a method's defining class cannot be passed using the
182+
:c:type:`PyCMethod` calling convention.
183+
184+
.. versionadded:: 3.11
185+
169186
170187
Creating Heap-Allocated Types
171188
.............................

Doc/howto/clinic.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,15 +1249,15 @@ The ``defining_class`` converter is not compatible with ``__init__`` and ``__new
12491249
methods, which cannot use the ``METH_METHOD`` convention.
12501250

12511251
It is not possible to use ``defining_class`` with slot methods. In order to
1252-
fetch the module state from such methods, use ``_PyType_GetModuleByDef`` to
1253-
look up the module and then :c:func:`PyModule_GetState` to fetch the module
1252+
fetch the module state from such methods, use :c:func:`PyType_GetModuleByDef`
1253+
to look up the module and then :c:func:`PyModule_GetState` to fetch the module
12541254
state. Example from the ``setattro`` slot method in
12551255
``Modules/_threadmodule.c``::
12561256

12571257
static int
12581258
local_setattro(localobject *self, PyObject *name, PyObject *v)
12591259
{
1260-
PyObject *module = _PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
1260+
PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &thread_module);
12611261
thread_module_state *state = get_thread_state(module);
12621262
...
12631263
}

Doc/whatsnew/3.11.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,11 @@ New Features
708708

709709
(Contributed by Christian Heimes in :issue:`45459`.)
710710

711+
* Added the :c:data:`PyType_GetModuleByDef` function, used to get the module
712+
in which a method was defined, in cases where this information is not
713+
available directly (via :c:type:`PyCMethod`).
714+
(Contributed by Petr Viktorin in :issue:`46613`.)
715+
711716

712717
Porting to Python 3.11
713718
----------------------

Include/cpython/object.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ PyAPI_FUNC(PyTypeObject *) _PyType_CalculateMetaclass(PyTypeObject *, PyObject *
265265
PyAPI_FUNC(PyObject *) _PyType_GetDocFromInternalDoc(const char *, const char *);
266266
PyAPI_FUNC(PyObject *) _PyType_GetTextSignatureFromInternalDoc(const char *, const char *);
267267
struct PyModuleDef;
268-
PyAPI_FUNC(PyObject *) _PyType_GetModuleByDef(PyTypeObject *, struct PyModuleDef *);
268+
PyAPI_FUNC(PyObject *) PyType_GetModuleByDef(PyTypeObject *, struct PyModuleDef *);
269269

270270
struct _Py_Identifier;
271271
PyAPI_FUNC(int) PyObject_Print(PyObject *, FILE *, int);

Lib/test/test_capi.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1071,15 +1071,15 @@ def test_state_access(self):
10711071
increment_count(1, 2, 3)
10721072

10731073
def test_get_module_bad_def(self):
1074-
# _PyType_GetModuleByDef fails gracefully if it doesn't
1074+
# PyType_GetModuleByDef fails gracefully if it doesn't
10751075
# find what it's looking for.
10761076
# see bpo-46433
10771077
instance = self.module.StateAccessType()
10781078
with self.assertRaises(TypeError):
10791079
instance.getmodulebydef_bad_def()
10801080

10811081
def test_get_module_static_in_mro(self):
1082-
# Here, the class _PyType_GetModuleByDef is looking for
1082+
# Here, the class PyType_GetModuleByDef is looking for
10831083
# appears in the MRO after a static type (Exception).
10841084
# see bpo-46433
10851085
class Subclass(BaseException, self.module.StateAccessType):
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Added function :c:func:`PyType_GetModuleByDef`, which allows accesss to
2+
module state when a method's defining class is not available.

Modules/_csv.c

Lines changed: 1 addition & 1 deletion
379
Original file line numberDiff line numberDiff line change
@@ -374,7 +374,7 @@ static char *dialect_kws[] = {
374374
static _csvstate *
375375
_csv_state_from_type(PyTypeObject *type, const char *name)
376376
{
377-
PyObject *module = _PyType_GetModuleByDef(type, &_csvmodule);
377+
PyObject *module = PyType_GetModuleByDef(type, &_csvmodule);
378378
if (module == NULL) {
379
return NULL;
380380
}

Modules/_functoolsmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ partial_call(partialobject *pto, PyObject *args, PyObject *kwargs);
5151
static inline _functools_state *
5252
get_functools_state_by_type(PyTypeObject *type)
5353
{
54-
PyObject *module = _PyType_GetModuleByDef(type, &_functools_module);
54+
PyObject *module = PyType_GetModuleByDef(type, &_functools_module);
5555
if (module == NULL) {
5656
return NULL;
5757
}

Modules/_queuemodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ simplequeue_get_state(PyObject *module)
2121
}
2222
static struct PyModuleDef queuemodule;
2323
#define simplequeue_get_state_by_type(type) \
24-
(simplequeue_get_state(_PyType_GetModuleByDef(type, &queuemodule)))
24+
(simplequeue_get_state(PyType_GetModuleByDef(type, &queuemodule)))
2525

2626
typedef struct {
2727
PyObject_HEAD

Modules/_randommodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ get_random_state(PyObject *module)
9999
static struct PyModuleDef _randommodule;
100100

101101
#define _randomstate_type(type) \
102-
(get_random_state(_PyType_GetModuleByDef(type, &_randommodule)))
102+
(get_random_state(PyType_GetModuleByDef(type, &_randommodule)))
103103

104104
typedef struct {
105105
PyObject_HEAD

0 commit comments

Comments
 (0)
0