]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-134160: Add more comments for the xxlimited module (GH-140214) (GH-140664)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 28 Oct 2025 09:24:11 +0000 (10:24 +0100)
committerGitHub <noreply@github.com>
Tue, 28 Oct 2025 09:24:11 +0000 (10:24 +0100)
(cherry picked from commit 18e4a89e42c681fe035d4d39a71e79d3c6b70903)

Co-authored-by: Petr Viktorin <encukou@gmail.com>
Modules/xxlimited.c

index 0480fb0849876b023ff9e38682a4215532419c1e..09c8d9487f542664ca8a8e0114829d305a627191 100644 (file)
@@ -14,7 +14,9 @@
    This module roughly corresponds to::
 
       class Xxo:
-         """A class that explicitly stores attributes in an internal dict"""
+         """A class that explicitly stores attributes in an internal dict
+         (to simulate custom attribute handling).
+         """
 
           def __init__(self):
               # In the C class, "_x_attr" is not accessible from Python code
@@ -85,13 +87,16 @@ typedef struct {
 // Instance state
 typedef struct {
     PyObject_HEAD
-    PyObject            *x_attr;           /* Attributes dictionary */
+    PyObject            *x_attr;           /* Attributes dictionary.
+                                            * May be NULL, which acts as an
+                                            * empty dict.
+                                            */
     char                x_buffer[BUFSIZE]; /* buffer for Py_buffer */
     Py_ssize_t          x_exports;         /* how many buffer are exported */
 } XxoObject;
 
 #define XxoObject_CAST(op)  ((XxoObject *)(op))
-// XXX: no good way to do this yet
+// TODO: full support for type-checking was added in 3.14 (Py_tp_token)
 // #define XxoObject_Check(v)      Py_IS_TYPE(v, Xxo_Type)
 
 static XxoObject *
@@ -112,8 +117,13 @@ newXxoObject(PyObject *module)
     return self;
 }
 
-/* Xxo finalization */
+/* Xxo finalization.
+ *
+ * Types that store references to other PyObjects generally need to implement
+ * the GC slots: traverse, clear, dealloc, and (optionally) finalize.
+ */
 
+// traverse: Visit all references from an object, including its type
 static int
 Xxo_traverse(PyObject *op, visitproc visit, void *arg)
 {
@@ -126,6 +136,7 @@ Xxo_traverse(PyObject *op, visitproc visit, void *arg)
     return 0;
 }
 
+// clear: drop references in order to break all reference cycles
 static int
 Xxo_clear(PyObject *op)
 {
@@ -134,6 +145,8 @@ Xxo_clear(PyObject *op)
     return 0;
 }
 
+// finalize: like clear, but should leave the object in a consistent state.
+// Equivalent to `__del__` in Python.
 static void
 Xxo_finalize(PyObject *op)
 {
@@ -141,6 +154,7 @@ Xxo_finalize(PyObject *op)
     Py_CLEAR(self->x_attr);
 }
 
+// dealloc: drop all remaining references and free memory
 static void
 Xxo_dealloc(PyObject *self)
 {
@@ -155,6 +169,7 @@ Xxo_dealloc(PyObject *self)
 
 /* Xxo attribute handling */
 
+// Get an attribute.
 static PyObject *
 Xxo_getattro(PyObject *op, PyObject *name)
 {
@@ -168,9 +183,12 @@ Xxo_getattro(PyObject *op, PyObject *name)
             return NULL;
         }
     }
+    // Fall back to generic implementation (this handles special attributes,
+    // raising AttributeError, etc.)
     return PyObject_GenericGetAttr(op, name);
 }
 
+// Set or delete an attribute.
 static int
 Xxo_setattro(PyObject *op, PyObject *name, PyObject *v)
 {
@@ -198,7 +216,9 @@ Xxo_setattro(PyObject *op, PyObject *name, PyObject *v)
     }
 }
 
-/* Xxo methods */
+/* Xxo methods: C functions plus a PyMethodDef array that lists them and
+ * specifies metadata.
+ */
 
 static PyObject *
 Xxo_demo(PyObject *op, PyTypeObject *defining_class,
@@ -234,7 +254,10 @@ static PyMethodDef Xxo_methods[] = {
     {NULL,              NULL}           /* sentinel */
 };
 
-/* Xxo buffer interface */
+/* Xxo buffer interface: C functions later referenced from PyType_Slot array.
+ * Other interfaces (e.g. for sequence-like or number-like types) are defined
+ * similarly.
+ */
 
 static int
 Xxo_getbuffer(PyObject *op, Py_buffer *view, int flags)
@@ -300,6 +323,7 @@ static PyType_Spec Xxo_Type_spec = {
 /* Str type definition*/
 
 static PyType_Slot Str_Type_slots[] = {
+    // slots array intentionally kept empty
     {0, 0},  /* sentinel */
 };
 
@@ -400,12 +424,32 @@ xx_modexec(PyObject *m)
 }
 
 static PyModuleDef_Slot xx_slots[] = {
+
+    /* exec function to initialize the module (called as part of import
+     * after the object was added to sys.modules)
+     */
     {Py_mod_exec, xx_modexec},
+
+    /* Signal that this module supports being loaded in multiple interpreters
+     * with separate GILs (global interpreter locks).
+     * See "Isolating Extension Modules" on how to prepare a module for this:
+     *   https://docs.python.org/3/howto/isolating-extensions.html
+     */
     {Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
+
+    /* Signal that this module does not rely on the GIL for its own needs.
+     * Without this slot, free-threaded builds of CPython will enable
+     * the GIL when this module is loaded.
+     */
     {Py_mod_gil, Py_MOD_GIL_NOT_USED},
+
     {0, NULL}
 };
 
+// Module finalization: modules that hold references in their module state
+// need to implement the fullowing GC hooks. They're similar to the ones for
+// types (see "Xxo finalization").
+
 static int
 xx_traverse(PyObject *module, visitproc visit, void *arg)
 {
@@ -444,7 +488,9 @@ static struct PyModuleDef xxmodule = {
 };
 
 
-/* Export function for the module (*must* be called PyInit_xx) */
+/* Export function for the module. *Must* be called PyInit_xx; usually it is
+ * the only non-`static` object in a module definition.
+ */
 
 PyMODINIT_FUNC
 PyInit_xxlimited(void)