@@ -264,6 +264,24 @@ Type Objects
264264
265265   .. versionadded:: 3.11 
266266
267+ .. c:function:: int PyType_GetBaseByToken(PyTypeObject *type, void *token, PyTypeObject **result)  
268+ 
269+    Find the first superclass in *type *'s :term: `method resolution order ` whose 
270+    :c:macro: `Py_tp_token ` token is equal to the given one. 
271+ 
272+    * If found, set *\* result:term: `strong reference ` 
273+      to it and return ``1 ``. 
274+    * If not found, set *\* resultNULL `` and return ``0 ``. 
275+    * On error, set *\* resultNULL `` and return ``-1 `` with an 
276+      exception set. 
277+ 
278+    The *result * argument may be ``NULL ``, in which case *\* result 
279+    Use this if you need only the return value. 
280+ 
281+    The *token * argument may not be ``NULL ``. 
282+ 
283+    .. versionadded :: 3.14  
284+ 
267285.. c :function :: int  PyUnstable_Type_AssignVersionTag (PyTypeObject *type)   
268286
269287   Attempt to assign a version tag to the given type. 
@@ -488,6 +506,11 @@ The following functions and structs are used to create
488506      * ``Py_nb_add `` to set :c:member: `PyNumberMethods.nb_add ` 
489507      * ``Py_sq_length `` to set :c:member: `PySequenceMethods.sq_length ` 
490508
509+       An additional slot is supported that does not correspond to a 
510+       :c:type: `!PyTypeObject ` struct field: 
511+ 
512+       * :c:data: `Py_tp_token ` 
513+ 
491514      The following “offset” fields cannot be set using :c:type: `PyType_Slot `: 
492515
493516         * :c:member: `~PyTypeObject.tp_weaklistoffset ` 
@@ -538,4 +561,47 @@ The following functions and structs are used to create
538561      The desired value of the slot. In most cases, this is a pointer 
539562      to a function. 
540563
541-       Slots other than ``Py_tp_doc`` may not be ``NULL``. 
564+       *pfunc* values may not be ``NULL``, except for the following slots: 
565+ 
566+       * ``Py_tp_doc`` 
567+       * :c:data:`Py_tp_token` (for clarity, prefer :c:data: `Py_TP_USE_SPEC ` 
568+         rather than ``NULL ``) 
569+ 
570+ .. c:macro:: Py_tp_token 
571+ 
572+    A :c:member:`~PyType_Slot.slot` that records a static memory layout ID 
573+    for a class. 
574+ 
575+    If the :c:type:`PyType_Spec` of the class is statically 
576+    allocated, the token can be set to the spec using the special value 
577+    :c:data:`Py_TP_USE_SPEC`: 
578+ 
579+    .. code-block:: c 
580+ 
581+       static PyType_Slot foo_slots[] = { 
582+          {Py_tp_token, Py_TP_USE_SPEC}, 
583+ 
584+    It can also be set to an arbitrary pointer, but you must ensure that: 
585+ 
586+    * The pointer outlives the class, so it's not reused for something else 
587+      while the class exists. 
588+    * It "belongs" to the extension module where the class lives, so it will not 
589+      clash with other extensions. 
590+ 
591+    Use :c:func: `PyType_GetBaseByToken ` to check if a class's superclass has 
592+    a given token -- that is, check whether the memory layout is compatible. 
593+ 
594+    To get the token for a given class  (without considering superclasses), 
595+    use :c:func: `PyType_GetSlot ` with ``Py_tp_token ``. 
596+ 
597+    .. versionadded :: 3.14  
598+ 
599+    .. c :namespace :: NULL   
600+ 
601+ c :macro :: Py_TP_USE_SPEC 
602+ 
603+ :c:data: `Py_tp_token ` to set the token to the
604+       class's :c:type: `PyType_Spec `. 
605+       Expands to ``NULL ``. 
606+ 
607+       .. versionadded :: 3.14  
0 commit comments