gh-149044: Implement PEP 820 – PySlot: Unified slot system for the C API (GH-149055)

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
This commit is contained in:
Petr Viktorin 2026-05-05 09:18:04 +02:00 committed by GitHub
parent 5dd2161716
commit 508b49845d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 5433 additions and 935 deletions

View file

@ -2059,7 +2059,7 @@ import_run_modexport(PyThreadState *tstate, PyModExportFunction ex0,
/* This is like import_run_extension, but avoids interpreter switching
* and code for for single-phase modules.
*/
PyModuleDef_Slot *slots = ex0();
PySlot *slots = ex0();
if (!slots) {
if (!PyErr_Occurred()) {
PyErr_Format(

404
Python/slots.c Normal file
View file

@ -0,0 +1,404 @@
/* Common handling of type/module slots
*/
#include "Python.h"
#include "pycore_slots.h"
#include <stdio.h>
// Iterating through a recursive structure doesn't look great in a debugger.
// Flip the #if to 1 to get a trace on stderr.
// (The messages can also serve as code comments.)
#if 0
#define MSG(...) { \
fprintf(stderr, "slotiter: " __VA_ARGS__); fprintf(stderr, "\n");}
#else
#define MSG(...)
#endif
static char*
kind_name(_PySlot_KIND kind)
{
switch (kind) {
case _PySlot_KIND_TYPE: return "type";
case _PySlot_KIND_MOD: return "module";
case _PySlot_KIND_COMPAT: return "compat";
case _PySlot_KIND_SLOT: return "generic slot";
}
Py_UNREACHABLE();
}
static void
init_with_kind(_PySlotIterator *it, const void *slots,
_PySlot_KIND result_kind,
_PySlot_KIND slot_struct_kind)
{
MSG("");
MSG("init (%s slot iterator)", kind_name(result_kind));
it->state = it->states;
it->state->any_slot = slots;
it->state->slot_struct_kind = slot_struct_kind;
it->kind = result_kind;
it->name = NULL;
it->recursion_level = 0;
it->is_at_end = false;
it->is_first_run = true;
it->current.sl_id = 0;
memset(it->seen, 0, sizeof(it->seen));
}
void
_PySlotIterator_Init(_PySlotIterator *it, const PySlot *slots,
_PySlot_KIND result_kind)
{
init_with_kind(it, slots, result_kind, _PySlot_KIND_SLOT);
}
void
_PySlotIterator_InitLegacy(_PySlotIterator *it, const void *slots,
_PySlot_KIND kind)
{
init_with_kind(it, slots, kind, kind);
}
void
_PySlotIterator_Rewind(_PySlotIterator *it, const void *slots)
{
MSG("");
MSG("rewind (%s slot iterator)", kind_name(it->kind));
assert (it->is_at_end);
assert (it->recursion_level == 0);
assert (it->state == it->states);
it->is_at_end = false;
it->state->any_slot = slots;
it->is_first_run = false;
}
static Py_ssize_t
seen_index(uint16_t id)
{
return id / _PySlot_SEEN_ENTRY_BITS;
}
static unsigned int
seen_mask(uint16_t id)
{
return ((unsigned int)1) << (id % _PySlot_SEEN_ENTRY_BITS);
}
bool
_PySlotIterator_SawSlot(_PySlotIterator *it, int id)
{
assert (id > 0);
assert (id < _Py_slot_COUNT);
return it->seen[seen_index(id)] & seen_mask(id);
}
// Advance `it` to the next entry. Currently cannot fail.
static void
advance(_PySlotIterator *it)
{
MSG("advance (at level %d)", (int)it->recursion_level);
switch (it->state->slot_struct_kind) {
case _PySlot_KIND_SLOT: it->state->slot++; break;
case _PySlot_KIND_TYPE: it->state->tp_slot++; break;
case _PySlot_KIND_MOD: it->state->mod_slot++; break;
default:
Py_UNREACHABLE();
}
}
static int handle_first_run(_PySlotIterator *it);
bool
_PySlotIterator_Next(_PySlotIterator *it)
{
MSG("next");
assert(it);
assert(!it->is_at_end);
assert(!PyErr_Occurred());
it->current.sl_id = -1;
while (true) {
if (it->state->slot == NULL) {
if (it->recursion_level == 0) {
MSG("end (initial nesting level done)");
it->is_at_end = true;
return 0;
}
MSG("pop nesting level %d", (int)it->recursion_level);
it->recursion_level--;
it->state = &it->states[it->recursion_level];
advance(it);
continue;
}
switch (it->state->slot_struct_kind) {
case _PySlot_KIND_SLOT: {
MSG("copying PySlot structure");
it->current = *it->state->slot;
} break;
case _PySlot_KIND_TYPE: {
MSG("converting PyType_Slot structure");
memset(&it->current, 0, sizeof(it->current));
it->current.sl_id = (uint16_t)it->state->tp_slot->slot;
it->current.sl_flags = PySlot_INTPTR;
it->current.sl_ptr = (void*)it->state->tp_slot->pfunc;
} break;
case _PySlot_KIND_MOD: {
MSG("converting PyModuleDef_Slot structure");
memset(&it->current, 0, sizeof(it->current));
it->current.sl_id = (uint16_t)it->state->mod_slot->slot;
it->current.sl_flags = PySlot_INTPTR;
it->current.sl_ptr = (void*)it->state->mod_slot->value;
} break;
default: {
Py_UNREACHABLE();
} break;
}
/* shorter local names */
PySlot *const result = &it->current;
uint16_t flags = result->sl_flags;
MSG("slot %d, flags 0x%x, from %p",
(int)result->sl_id, (unsigned)flags, it->state->slot);
uint16_t orig_id = result->sl_id;
switch (it->kind) {
case _PySlot_KIND_TYPE:
result->sl_id = _PySlot_resolve_type_slot(result->sl_id);
break;
case _PySlot_KIND_MOD:
result->sl_id = _PySlot_resolve_mod_slot(result->sl_id);
break;
default:
Py_UNREACHABLE();
}
MSG("resolved to slot %d (%s)",
(int)result->sl_id, _PySlot_GetName(result->sl_id));
if (result->sl_id == Py_slot_invalid) {
MSG("error (unknown/invalid slot)");
if (flags & PySlot_OPTIONAL) {
advance(it);
continue;
}
_PySlot_err_bad_slot(kind_name(it->kind), orig_id);
goto error;
}
if (result->sl_id == Py_slot_end) {
MSG("sentinel slot, flags %x", (unsigned)flags);
if (flags & PySlot_OPTIONAL) {
MSG("error (bad flags on sentinel)");
PyErr_Format(PyExc_SystemError,
"invalid flags for Py_slot_end: 0x%x",
(unsigned int)flags);
goto error;
}
it->state->slot = NULL;
continue;
}
if (result->sl_id == Py_slot_subslots
|| result->sl_id == Py_tp_slots
|| result->sl_id == Py_mod_slots
) {
if (result->sl_ptr == NULL) {
MSG("NULL subslots; skipping");
advance(it);
continue;
}
if ((it->states[0].slot_struct_kind == _PySlot_KIND_MOD)
&& (it->state->slot_struct_kind == _PySlot_KIND_SLOT)
&& !(result->sl_flags & PySlot_STATIC))
{
PyErr_Format(PyExc_SystemError,
"slots included from PyModuleDef must be static");
goto error;
}
it->recursion_level++;
MSG("recursing into level %d", it->recursion_level);
if (it->recursion_level >= _PySlot_MAX_NESTING) {
MSG("error (too much nesting)");
PyErr_Format(PyExc_SystemError,
"%s (slot %d): too many levels of nested slots",
_PySlot_GetName(result->sl_id), orig_id);
goto error;
}
it->state = &it->states[it->recursion_level];
memset(it->state, 0, sizeof(_PySlotIterator_state));
it->state->slot = result->sl_ptr;
switch (result->sl_id) {
case Py_slot_subslots:
it->state->slot_struct_kind = _PySlot_KIND_SLOT; break;
case Py_tp_slots:
it->state->slot_struct_kind = _PySlot_KIND_TYPE; break;
case Py_mod_slots:
it->state->slot_struct_kind = _PySlot_KIND_MOD; break;
}
continue;
}
if (flags & PySlot_INTPTR) {
MSG("casting from intptr");
/* this should compile to nothing on common architectures */
switch (_PySlot_get_dtype(result->sl_id)) {
case _PySlot_DTYPE_SIZE: {
result->sl_size = (Py_ssize_t)(intptr_t)result->sl_ptr;
} break;
case _PySlot_DTYPE_INT64: {
result->sl_int64 = (int64_t)(intptr_t)result->sl_ptr;
} break;
case _PySlot_DTYPE_UINT64: {
result->sl_uint64 = (uint64_t)(intptr_t)result->sl_ptr;
} break;
case _PySlot_DTYPE_PTR:
case _PySlot_DTYPE_FUNC:
case _PySlot_DTYPE_VOID:
break;
}
}
advance(it);
switch (_PySlot_get_dtype(result->sl_id)) {
case _PySlot_DTYPE_VOID:
case _PySlot_DTYPE_PTR:
MSG("result: %d (%s): %p",
(int)result->sl_id, _PySlot_GetName(result->sl_id),
(void*)result->sl_ptr);
break;
case _PySlot_DTYPE_FUNC:
MSG("result: %d (%s): %p",
(int)result->sl_id, _PySlot_GetName(result->sl_id),
(void*)result->sl_func);
break;
case _PySlot_DTYPE_SIZE:
MSG("result: %d (%s): %zd",
(int)result->sl_id, _PySlot_GetName(result->sl_id),
(Py_ssize_t)result->sl_size);
break;
case _PySlot_DTYPE_INT64:
MSG("result: %d (%s): %ld",
(int)result->sl_id, _PySlot_GetName(result->sl_id),
(long)result->sl_int64);
break;
case _PySlot_DTYPE_UINT64:
MSG("result: %d (%s): %lu (0x%lx)",
(int)result->sl_id, _PySlot_GetName(result->sl_id),
(unsigned long)result->sl_int64,
(unsigned long)result->sl_int64);
break;
}
assert (result->sl_id > 0);
assert (result->sl_id <= _Py_slot_COUNT);
if (it->is_first_run && (handle_first_run(it) < 0)) {
goto error;
}
return result->sl_id != Py_slot_end;
}
Py_UNREACHABLE();
error:
it->current.sl_id = Py_slot_invalid;
return true;
}
/* Validate current slot, and do bookkeeping */
static int
handle_first_run(_PySlotIterator *it)
{
int id = it->current.sl_id;
if (_PySlot_get_must_be_static(id)) {
if (!(it->current.sl_flags & PySlot_STATIC)
&& (it->state->slot_struct_kind == _PySlot_KIND_SLOT))
{
PyErr_Format(
PyExc_SystemError,
"%s requires PySlot_STATIC",
_PySlot_GetName(id));
return -1;
}
}
_PySlot_PROBLEM_HANDLING null_handling = _PySlot_get_null_handling(id);
if (null_handling != _PySlot_PROBLEM_ALLOW) {
bool is_null = false;
switch (_PySlot_get_dtype(id)) {
case _PySlot_DTYPE_PTR: {
is_null = it->current.sl_ptr == NULL;
} break;
case _PySlot_DTYPE_FUNC: {
is_null = it->current.sl_func == NULL;
} break;
default: {
//Py_UNREACHABLE();
} break;
}
if (is_null) {
MSG("slot is NULL but shouldn't");
if (null_handling == _PySlot_PROBLEM_REJECT) {
MSG("error (NULL rejected)");
PyErr_Format(PyExc_SystemError,
"NULL not allowed for slot %s",
_PySlot_GetName(id));
return -1;
}
if (it->states[0].slot_struct_kind == _PySlot_KIND_SLOT) {
MSG("deprecated NULL");
if (PyErr_WarnFormat(
PyExc_DeprecationWarning,
1,
"NULL value in slot %s is deprecated",
_PySlot_GetName(id)) < 0)
{
return -1;
}
}
else {
MSG("unwanted NULL in legacy struct");
}
}
}
_PySlot_PROBLEM_HANDLING duplicate_handling = _PySlot_get_duplicate_handling(id);
if (duplicate_handling != _PySlot_PROBLEM_ALLOW) {
if (_PySlotIterator_SawSlot(it, id)) {
MSG("slot was seen before but shouldn't be duplicated");
if (duplicate_handling == _PySlot_PROBLEM_REJECT) {
MSG("error (duplicate rejected)");
PyErr_Format(
PyExc_SystemError,
"%s%s%s has multiple %s (%d) slots",
kind_name(it->kind),
it->name ? " " : "",
it->name ? it->name : "",
_PySlot_GetName(id),
(int)it->current.sl_id);
return -1;
}
if (it->states[0].slot_struct_kind == _PySlot_KIND_SLOT) {
MSG("deprecated duplicate");
if (PyErr_WarnFormat(
PyExc_DeprecationWarning,
0,
"%s%s%s has multiple %s (%d) slots. This is deprecated.",
kind_name(it->kind),
it->name ? " " : "",
it->name ? it->name : "",
_PySlot_GetName(id),
(int)it->current.sl_id) < 0) {
return -1;
}
}
else {
MSG("unwanted duplicate in legacy struct");
}
}
}
it->seen[seen_index(id)] |= seen_mask(id);
return 0;
}

836
Python/slots.toml Normal file
View file

@ -0,0 +1,836 @@
# This file lists all PySlot values
# This should only be used as input to Tools/build/generate_slots.py,
# its format can change at any time (e.g. we can switch to slots.csv)
# Entries:
# name: name of the slot
# kind:
# - 'type', 'mod': slots to create a particular kind of object
# - 'slot': special slots applicable to any kind of object
# - 'compat': old IDs that need to be resolved
# dtype: data type (tag for the union of sl_ptr, sl_size, etc.)
# equivalents: for 'compat' slots; the slots to resolve to
# is_type_field: slot that corresponds to a field in the type object (or in
# an array like PyNumberMethods).
# functype: C function type, where needed
# duplicates, nulls: How to handle common "problems" -- duplicate slots with
# the same ID, and NULL pointers, respectively
# - 'allow': not a problem for this slot
# - 'deprecated': issue a deprecation warning. Don't use for new slots.
# (typically, the problem was disallowed in docs, but allowed in practice)
# - 'reject': raise error
# The default for duplicate slots is 'reject'
# The default for NULLs is 'reject' for pointer slots; 'allow' for
# non-pointer ones
# must_be_static: true if slot needs the PySlot_STATIC flag (in PySlot struct)
[0]
name = 'Py_slot_end'
kind = 'slot'
dtype = 'void'
[1]
kind = 'compat'
equivalents = {type='Py_bf_getbuffer', mod='Py_mod_create'}
[2]
kind = 'compat'
equivalents = {type='Py_bf_releasebuffer', mod='Py_mod_exec'}
[3]
kind = 'compat'
equivalents = {type='Py_mp_ass_subscript', mod='Py_mod_multiple_interpreters'}
[4]
kind = 'compat'
equivalents = {type='Py_mp_length', mod='Py_mod_gil'}
[5]
name = 'Py_mp_subscript'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[6]
name = 'Py_nb_absolute'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[7]
name = 'Py_nb_add'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[8]
name = 'Py_nb_and'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[9]
name = 'Py_nb_bool'
kind = 'type'
is_type_field = true
functype = 'inquiry'
duplicates = 'deprecated'
nulls = 'deprecated'
[10]
name = 'Py_nb_divmod'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[11]
name = 'Py_nb_float'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[12]
name = 'Py_nb_floor_divide'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[13]
name = 'Py_nb_index'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[14]
name = 'Py_nb_inplace_add'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[15]
name = 'Py_nb_inplace_and'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[16]
name = 'Py_nb_inplace_floor_divide'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[17]
name = 'Py_nb_inplace_lshift'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[18]
name = 'Py_nb_inplace_multiply'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[19]
name = 'Py_nb_inplace_or'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[20]
name = 'Py_nb_inplace_power'
kind = 'type'
is_type_field = true
functype = 'ternaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[21]
name = 'Py_nb_inplace_remainder'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[22]
name = 'Py_nb_inplace_rshift'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[23]
name = 'Py_nb_inplace_subtract'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[24]
name = 'Py_nb_inplace_true_divide'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[25]
name = 'Py_nb_inplace_xor'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[26]
name = 'Py_nb_int'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[27]
name = 'Py_nb_invert'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[28]
name = 'Py_nb_lshift'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[29]
name = 'Py_nb_multiply'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[30]
name = 'Py_nb_negative'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[31]
name = 'Py_nb_or'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[32]
name = 'Py_nb_positive'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[33]
name = 'Py_nb_power'
kind = 'type'
is_type_field = true
functype = 'ternaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[34]
name = 'Py_nb_remainder'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[35]
name = 'Py_nb_rshift'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[36]
name = 'Py_nb_subtract'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[37]
name = 'Py_nb_true_divide'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[38]
name = 'Py_nb_xor'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[39]
name = 'Py_sq_ass_item'
kind = 'type'
is_type_field = true
functype = 'ssizeobjargproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[40]
name = 'Py_sq_concat'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[41]
name = 'Py_sq_contains'
kind = 'type'
is_type_field = true
functype = 'objobjproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[42]
name = 'Py_sq_inplace_concat'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[43]
name = 'Py_sq_inplace_repeat'
kind = 'type'
is_type_field = true
functype = 'ssizeargfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[44]
name = 'Py_sq_item'
kind = 'type'
is_type_field = true
functype = 'ssizeargfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[45]
name = 'Py_sq_length'
kind = 'type'
is_type_field = true
functype = 'lenfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[46]
name = 'Py_sq_repeat'
kind = 'type'
is_type_field = true
functype = 'ssizeargfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[47]
name = 'Py_tp_alloc'
kind = 'type'
is_type_field = true
functype = 'allocfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[48]
name = 'Py_tp_base'
kind = 'type'
is_type_field = true
dtype = 'ptr'
duplicates = 'deprecated'
nulls = 'deprecated'
[49]
name = 'Py_tp_bases'
kind = 'type'
is_type_field = true
dtype = 'ptr'
duplicates = 'deprecated'
nulls = 'deprecated'
[50]
name = 'Py_tp_call'
kind = 'type'
is_type_field = true
functype = 'ternaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[51]
name = 'Py_tp_clear'
kind = 'type'
is_type_field = true
functype = 'inquiry'
duplicates = 'deprecated'
nulls = 'deprecated'
[52]
name = 'Py_tp_dealloc'
kind = 'type'
is_type_field = true
functype = 'destructor'
duplicates = 'deprecated'
nulls = 'deprecated'
[53]
name = 'Py_tp_del'
kind = 'type'
is_type_field = true
functype = 'destructor'
duplicates = 'deprecated'
nulls = 'deprecated'
[54]
name = 'Py_tp_descr_get'
kind = 'type'
is_type_field = true
functype = 'descrgetfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[55]
name = 'Py_tp_descr_set'
kind = 'type'
is_type_field = true
functype = 'descrsetfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[56]
name = 'Py_tp_doc'
kind = 'type'
is_type_field = true
dtype = 'ptr'
nulls = 'allow'
[57]
name = 'Py_tp_getattr'
kind = 'type'
is_type_field = true
functype = 'getattrfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[58]
name = 'Py_tp_getattro'
kind = 'type'
is_type_field = true
functype = 'getattrofunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[59]
name = 'Py_tp_hash'
kind = 'type'
is_type_field = true
functype = 'hashfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[60]
name = 'Py_tp_init'
kind = 'type'
is_type_field = true
functype = 'initproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[61]
name = 'Py_tp_is_gc'
kind = 'type'
is_type_field = true
functype = 'inquiry'
duplicates = 'deprecated'
nulls = 'deprecated'
[62]
name = 'Py_tp_iter'
kind = 'type'
is_type_field = true
functype = 'getiterfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[63]
name = 'Py_tp_iternext'
kind = 'type'
is_type_field = true
functype = 'iternextfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[64]
name = 'Py_tp_methods'
kind = 'type'
is_type_field = true
dtype = 'ptr'
duplicates = 'deprecated'
nulls = 'deprecated'
must_be_static = true
[65]
name = 'Py_tp_new'
kind = 'type'
is_type_field = true
functype = 'newfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[66]
name = 'Py_tp_repr'
kind = 'type'
is_type_field = true
functype = 'reprfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[67]
name = 'Py_tp_richcompare'
kind = 'type'
is_type_field = true
functype = 'richcmpfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[68]
name = 'Py_tp_setattr'
kind = 'type'
is_type_field = true
functype = 'setattrfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[69]
name = 'Py_tp_setattro'
kind = 'type'
is_type_field = true
functype = 'setattrofunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[70]
name = 'Py_tp_str'
kind = 'type'
is_type_field = true
functype = 'reprfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[71]
name = 'Py_tp_traverse'
kind = 'type'
is_type_field = true
functype = 'traverseproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[72]
name = 'Py_tp_members'
kind = 'type'
is_type_field = true
dtype = 'ptr'
nulls = 'reject'
must_be_static = true
[73]
name = 'Py_tp_getset'
kind = 'type'
is_type_field = true
dtype = 'ptr'
duplicates = 'deprecated'
nulls = 'deprecated'
must_be_static = true
[74]
name = 'Py_tp_free'
kind = 'type'
is_type_field = true
functype = 'freefunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[75]
name = 'Py_nb_matrix_multiply'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[76]
name = 'Py_nb_inplace_matrix_multiply'
kind = 'type'
is_type_field = true
functype = 'binaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[77]
name = 'Py_am_await'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[78]
name = 'Py_am_aiter'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[79]
name = 'Py_am_anext'
kind = 'type'
is_type_field = true
functype = 'unaryfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[80]
name = 'Py_tp_finalize'
kind = 'type'
is_type_field = true
functype = 'destructor'
duplicates = 'deprecated'
nulls = 'deprecated'
[81]
name = 'Py_am_send'
kind = 'type'
is_type_field = true
functype = 'sendfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[82]
name = 'Py_tp_vectorcall'
kind = 'type'
is_type_field = true
functype = 'vectorcallfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[83]
name = 'Py_tp_token'
kind = 'type'
is_type_field = true
dtype = 'ptr'
field = 'ht_token'
duplicates = 'deprecated'
nulls = 'allow'
[84]
name = 'Py_mod_create'
kind = 'mod'
dtype = 'func'
nulls = 'deprecated'
[85]
name = 'Py_mod_exec'
kind = 'mod'
dtype = 'func'
duplicates = 'allow' # only alowed in PyModuleDef.m_slots
nulls = 'reject'
[86]
name = 'Py_mod_multiple_interpreters'
kind = 'mod'
dtype = 'uint64'
[87]
name = 'Py_mod_gil'
kind = 'mod'
dtype = 'uint64'
[88]
name = 'Py_bf_getbuffer'
kind = 'type'
is_type_field = true
functype = 'getbufferproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[89]
name = 'Py_bf_releasebuffer'
kind = 'type'
is_type_field = true
functype = 'releasebufferproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[90]
name = 'Py_mp_ass_subscript'
kind = 'type'
is_type_field = true
functype = 'objobjargproc'
duplicates = 'deprecated'
nulls = 'deprecated'
[91]
name = 'Py_mp_length'
kind = 'type'
is_type_field = true
functype = 'lenfunc'
duplicates = 'deprecated'
nulls = 'deprecated'
[92]
name = 'Py_slot_subslots'
kind = 'slot'
dtype = 'ptr'
nulls = 'allow'
[93]
name = 'Py_tp_slots'
kind = 'type'
dtype = 'ptr'
nulls = 'allow'
[94]
name = 'Py_mod_slots'
kind = 'mod'
dtype = 'ptr'
nulls = 'allow'
[95]
name = 'Py_tp_name'
kind = 'type'
dtype = 'ptr'
[96]
name = 'Py_tp_basicsize'
kind = 'type'
dtype = 'size'
[97]
name = 'Py_tp_extra_basicsize'
kind = 'type'
dtype = 'size'
[98]
name = 'Py_tp_itemsize'
kind = 'type'
dtype = 'size'
[99]
name = 'Py_tp_flags'
kind = 'type'
dtype = 'uint64'
[100]
name = 'Py_mod_name'
kind = 'mod'
dtype = 'ptr'
[101]
name = 'Py_mod_doc'
kind = 'mod'
dtype = 'ptr'
[102]
name = 'Py_mod_state_size'
kind = 'mod'
dtype = 'size'
[103]
name = 'Py_mod_methods'
kind = 'mod'
dtype = 'ptr'
must_be_static = true
[104]
name = 'Py_mod_state_traverse'
kind = 'mod'
dtype = 'func'
[105]
name = 'Py_mod_state_clear'
kind = 'mod'
dtype = 'func'
[106]
name = 'Py_mod_state_free'
kind = 'mod'
dtype = 'func'
[107]
name = 'Py_tp_metaclass'
kind = 'type'
dtype = 'ptr'
[108]
name = 'Py_tp_module'
kind = 'type'
dtype = 'ptr'
[109]
name = 'Py_mod_abi'
kind = 'mod'
dtype = 'ptr'
duplicates = 'allow'
[110]
name = 'Py_mod_token'
kind = 'mod'
dtype = 'ptr'

119
Python/slots_generated.c generated Normal file
View file

@ -0,0 +1,119 @@
/* Generated by Tools/build/generate_slots.py */
#include "Python.h"
#include "pycore_slots.h" // _PySlot_names
const char *const _PySlot_names[] = {
"Py_slot_end",
"Py_bf_getbuffer/Py_mod_create",
"Py_bf_releasebuffer/Py_mod_exec",
"Py_mp_ass_subscript/Py_mod_multiple_interpreters",
"Py_mp_length/Py_mod_gil",
"Py_mp_subscript",
"Py_nb_absolute",
"Py_nb_add",
"Py_nb_and",
"Py_nb_bool",
"Py_nb_divmod",
"Py_nb_float",
"Py_nb_floor_divide",
"Py_nb_index",
"Py_nb_inplace_add",
"Py_nb_inplace_and",
"Py_nb_inplace_floor_divide",
"Py_nb_inplace_lshift",
"Py_nb_inplace_multiply",
"Py_nb_inplace_or",
"Py_nb_inplace_power",
"Py_nb_inplace_remainder",
"Py_nb_inplace_rshift",
"Py_nb_inplace_subtract",
"Py_nb_inplace_true_divide",
"Py_nb_inplace_xor",
"Py_nb_int",
"Py_nb_invert",
"Py_nb_lshift",
"Py_nb_multiply",
"Py_nb_negative",
"Py_nb_or",
"Py_nb_positive",
"Py_nb_power",
"Py_nb_remainder",
"Py_nb_rshift",
"Py_nb_subtract",
"Py_nb_true_divide",
"Py_nb_xor",
"Py_sq_ass_item",
"Py_sq_concat",
"Py_sq_contains",
"Py_sq_inplace_concat",
"Py_sq_inplace_repeat",
"Py_sq_item",
"Py_sq_length",
"Py_sq_repeat",
"Py_tp_alloc",
"Py_tp_base",
"Py_tp_bases",
"Py_tp_call",
"Py_tp_clear",
"Py_tp_dealloc",
"Py_tp_del",
"Py_tp_descr_get",
"Py_tp_descr_set",
"Py_tp_doc",
"Py_tp_getattr",
"Py_tp_getattro",
"Py_tp_hash",
"Py_tp_init",
"Py_tp_is_gc",
"Py_tp_iter",
"Py_tp_iternext",
"Py_tp_methods",
"Py_tp_new",
"Py_tp_repr",
"Py_tp_richcompare",
"Py_tp_setattr",
"Py_tp_setattro",
"Py_tp_str",
"Py_tp_traverse",
"Py_tp_members",
"Py_tp_getset",
"Py_tp_free",
"Py_nb_matrix_multiply",
"Py_nb_inplace_matrix_multiply",
"Py_am_await",
"Py_am_aiter",
"Py_am_anext",
"Py_tp_finalize",
"Py_am_send",
"Py_tp_vectorcall",
"Py_tp_token",
"Py_mod_create",
"Py_mod_exec",
"Py_mod_multiple_interpreters",
"Py_mod_gil",
"Py_bf_getbuffer",
"Py_bf_releasebuffer",
"Py_mp_ass_subscript",
"Py_mp_length",
"Py_slot_subslots",
"Py_tp_slots",
"Py_mod_slots",
"Py_tp_name",
"Py_tp_basicsize",
"Py_tp_extra_basicsize",
"Py_tp_itemsize",
"Py_tp_flags",
"Py_mod_name",
"Py_mod_doc",
"Py_mod_state_size",
"Py_mod_methods",
"Py_mod_state_traverse",
"Py_mod_state_clear",
"Py_mod_state_free",
"Py_tp_metaclass",
"Py_tp_module",
"Py_mod_abi",
"Py_mod_token",
NULL
};