Skip to content

Commit bdc0e44

Browse files
encukouErlend Egeberg AaslandJelleZijlstra
authored
PEP 630: add disclaimers re. heap types & conversion, add PyType_GetModuleByDef (GH-2319)
* PEP 630: add disclaimers re. heap types & conversion, and PyType_GetModuleByDef Co-authored-by: Erlend Egeberg Aasland <erlend.aasland@innova.no> Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
1 parent 88c6514 commit bdc0e44

File tree

1 file changed

+93
-24
lines changed

1 file changed

+93
-24
lines changed

pep-0630.rst

Lines changed: 93 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ describes problems of such per-process state and efforts to make
2121
per-module state, a better default, possible and easy to use.
2222

2323
The document also describes how to switch to per-module state where
24-
possible. The switch involves allocating space for that state, switching
25-
from static types to heap types, and—perhaps most importantly—accessing
26-
per-module state from code.
24+
possible. The switch involves allocating space for that state, potentially
25+
switching from static types to heap types, and—perhaps most
26+
importantly—accessing per-module state from code.
2727

2828
About this document
2929
-------------------
@@ -40,9 +40,15 @@ development, gaps identified in this text can show where to focus
4040
the effort, and the text can be updated as new features are implemented
4141

4242
Whenever this PEP mentions *extension modules*, the advice also
43-
applies to *built-in* modules, such as the C parts of the standard
44-
library. The standard library is expected to switch to per-module state
45-
early.
43+
applies to *built-in* modules.
44+
45+
.. note::
46+
This PEP contains generic advice. When following it, always take into
47+
account the specifics of your project.
48+
49+
For example, while much of this advice applies to the C parts of
50+
Python's standard library, the PEP does not factor in stdlib specifics
51+
(unusual backward compatibility issues, access to private API, etc.).
4652

4753
PEPs related to this effort are:
4854

@@ -101,7 +107,7 @@ testing the isolation, multiple module objects corresponding to a single
101107
extension can even be loaded in a single interpreter.
102108

103109
Per-module state provides an easy way to think about lifetime and
104-
resource ownership: the extension module author will set up when a
110+
resource ownership: the extension module will initialize when a
105111
module object is created, and clean up when it's freed. In this regard,
106112
a module is just like any other ``PyObject *``; there are no “on
107113
interpreter shutdown” hooks to think about—or forget about.
@@ -235,7 +241,8 @@ Set ``PyModuleDef.m_size`` to a positive number to request that many
235241
bytes of storage local to the module. Usually, this will be set to the
236242
size of some module-specific ``struct``, which can store all of the
237243
module's C-level state. In particular, it is where you should put
238-
pointers to classes (including exceptions) and settings (e.g. ``csv``'s
244+
pointers to classes (including exceptions, but excluding static types)
245+
and settings (e.g. ``csv``'s
239246
`field_size_limit <https://docs.python.org/3.8/library/csv.html#csv.field_size_limit>`__)
240247
which the C code needs to function.
241248

@@ -302,9 +309,9 @@ zero. In your own module, you're in control of ``m_size``, so this is
302309
easy to prevent.)
303310

304311
Heap types
305-
~~~~~~~~~~
312+
----------
306313

307-
Traditionally, types defined in C code were *static*, that is,
314+
Traditionally, types defined in C code are *static*, that is,
308315
``static PyTypeObject`` structures defined directly in code and
309316
initialized using ``PyType_Ready()``.
310317

@@ -321,10 +328,27 @@ the Python level: for example, you can't set ``str.myattribute = 123``.
321328
that shares any Python objects across interpreters implicitly depends
322329
on CPython's current, process-wide GIL.
323330

324-
An alternative to static types is *heap-allocated types*, or heap types
331+
Because they are immutable and process-global, static types cannot access
332+
“their” module state.
333+
If any method of such a type requires access to module state,
334+
the type must be converted to a *heap-allocated type*, or *heap type*
325335
for short. These correspond more closely to classes created by Python’s
326336
``class`` statement.
327337

338+
For new modules, using heap types by default is a good rule of thumb.
339+
340+
Static types can be converted to heap types, but note that
341+
the heap type API was not designed for “lossless” conversion
342+
from static types -- that is, creating a type that works exactly like a given
343+
static type. Unlike static types, heap type objects are mutable by default.
344+
Also, when rewriting the class definition in a new API,
345+
you are likely to unintentionally change a few details (e.g. pickle-ability
346+
or inherited slots). Always test the details that are important to you.
347+
348+
349+
Defining Heap Types
350+
~~~~~~~~~~~~~~~~~~~
351+
328352
Heap types can be created by filling a ``PyType_Spec`` structure, a
329353
description or “blueprint” of a class, and calling
330354
``PyType_FromModuleAndSpec()`` to construct a new class object.
@@ -370,7 +394,7 @@ is called on a *subclass* of your type, ``Py_TYPE(self)`` will refer to
370394
that subclass, which may be defined in different module than yours.
371395

372396
.. note::
373-
The following Python code. can illustrate the concept.
397+
The following Python code can illustrate the concept.
374398
``Base.get_defining_class`` returns ``Base`` even
375399
if ``type(self) == Sub``::
376400

@@ -424,6 +448,52 @@ For example::
424448
{NULL},
425449
}
426450

451+
Module State Access from Slot Methods, Getters and Setters
452+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
453+
454+
.. note::
455+
456+
This is new in Python 3.11.
457+
458+
.. After adding to limited API:
459+
460+
If you use the `limited API <https://docs.python.org/3/c-api/stable.html>__,
461+
you must update ``Py_LIMITED_API`` to ``0x030b0000``, losing ABI
462+
compatibility with earlier versions.
463+
464+
Slot methods -- the fast C equivalents for special methods, such as
465+
`nb_add <https://docs.python.org/3/c-api/typeobj.html#c.PyNumberMethods.nb_add>`__
466+
for ``__add__`` or `tp_new <https://docs.python.org/3/c-api/typeobj.html#c.PyTypeObject.tp_new>`__
467+
for initialization -- have a very simple API that doesn't allow
468+
passing in the defining class as in ``PyCMethod``.
469+
The same goes for getters and setters defined with
470+
`PyGetSetDef <https://docs.python.org/3/c-api/structures.html#c.PyGetSetDef>`__.
471+
472+
To access the module state in these cases, use the
473+
`PyType_GetModuleByDef <https://docs.python.org/typeobj.html#c.PyType_GetModuleByDef>`__
474+
function, and pass in the module definition.
475+
Once you have the module, call `PyModule_GetState <https://docs.python.org/3/c-api/module.html?highlight=pymodule_getstate#c.PyModule_GetState>`__
476+
to get the state::
477+
478+
PyObject *module = PyType_GetModuleByDef(Py_TYPE(self), &module_def);
479+
my_struct *state = (my_struct*)PyModule_GetState(module);
480+
if (state === NULL) {
481+
return NULL;
482+
}
483+
484+
``PyType_GetModuleByDef`` works by searching the `MRO <https://docs.python.org/3/glossary.html#term-method-resolution-order>`__
485+
(i.e. all superclasses) for the first superclass that has a corresponding
486+
module.
487+
488+
.. note::
489+
490+
In very exotic cases (inheritance chains spanning multiple modules
491+
created from the same definition), ``PyType_GetModuleByDef`` might not
492+
return the module of the true defining class. However, it will always
493+
return a module with the same definition, ensuring a compatible
494+
C memory layout.
495+
496+
427497
Open Issues
428498
-----------
429499

@@ -432,28 +502,18 @@ Several issues around per-module state and heap types are still open.
432502
Discussions about improving the situation are best held on the `capi-sig
433503
mailing list <https://mail.python.org/mailman3/lists/capi-sig.python.org/>`__.
434504

435-
Module State Access from Slot Methods, Getters and Setters
436-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
437-
438-
Currently (as of Python 3.9), there is no API to access the module state
439-
from:
440-
441-
- slot methods (meaning type slots, such as ``tp_new``, ``nb_add`` or
442-
``tp_iternext``)
443-
- getters and setters defined with ``tp_getset``
444-
445505
Type Checking
446506
~~~~~~~~~~~~~
447507

448-
Currently (as of Python 3.9), heap types have no good API to write
508+
Currently (as of Python 3.10), heap types have no good API to write
449509
``Py*_Check`` functions (like ``PyUnicode_Check`` exists for ``str``, a
450510
static type), and so it is not easy to ensure whether instances have a
451511
particular C layout.
452512

453513
Metaclasses
454514
~~~~~~~~~~~
455515

456-
Currently (as of Python 3.9), there is no good API to specify the
516+
Currently (as of Python 3.10), there is no good API to specify the
457517
*metaclass* of a heap type, that is, the ``ob_type`` field of the type
458518
object.
459519

@@ -466,6 +526,15 @@ its variable-size storage is currently consumed by slots. Fixing this
466526
is complicated by the fact that several classes in an inheritance
467527
hierarchy may need to reserve some state.
468528

529+
Lossless conversion to heap types
530+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
531+
532+
The heap type API was not designed for “lossless” conversion from static types,
533+
that is, creating a type that works exactly like a given static type.
534+
The best way to address it would probably be to write a guide that covers
535+
known “gotchas”.
536+
537+
469538
Copyright
470539
---------
471540

0 commit comments

Comments
 (0)