@@ -96,7 +96,7 @@ Quick Reference
9696 | | | __gt__, | | | | |
9797 | | | __ge__ | | | | |
9898 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
99- | :c:member: `~PyTypeObject.tp_weaklistoffset ` | :c:type: `Py_ssize_t ` | | | X | | ? |
99+ | ( :c:member: `~PyTypeObject.tp_weaklistoffset `) | :c:type: `Py_ssize_t ` | | | X | | ? |
100100 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
101101 | :c:member: `~PyTypeObject.tp_iter ` | :c:type: `getiterfunc ` | __iter__ | | | | X |
102102 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
@@ -117,7 +117,7 @@ Quick Reference
117117 | :c:member: `~PyTypeObject.tp_descr_set ` | :c:type: `descrsetfunc ` | __set__, | | | | X |
118118 | | | __delete__ | | | | |
119119 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
120- | :c:member: `~PyTypeObject.tp_dictoffset ` | :c:type: `Py_ssize_t ` | | | X | | ? |
120+ | ( :c:member: `~PyTypeObject.tp_dictoffset `) | :c:type: `Py_ssize_t ` | | | X | | ? |
121121 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
122122 | :c:member: `~PyTypeObject.tp_init ` | :c:type: `initproc ` | __init__ | X | X | | X |
123123 +------------------------------------------------+-----------------------------------+-------------------+---+---+---+---+
@@ -1018,7 +1018,6 @@ and :c:type:`PyType_Type` effectively act as defaults.)
10181018 :const: `Py_TPFLAGS_HAVE_GC ` flag bit is clear in the subtype and the
10191019 :c:member: `~PyTypeObject.tp_traverse ` and :c:member: `~PyTypeObject.tp_clear ` fields in the subtype exist and have
10201020 ``NULL `` values.
1021-
10221021 .. XXX are most flag bits *really* inherited individually?
10231022
10241023 **Default: **
@@ -1135,6 +1134,33 @@ and :c:type:`PyType_Type` effectively act as defaults.)
11351134 :const: `Py_TPFLAGS_IMMUTABLETYPE ` flag set. For extension types, it is
11361135 inherited whenever :c:member: `~PyTypeObject.tp_descr_get ` is inherited.
11371136
1137+ .. data :: Py_TPFLAGS_MANAGED_DICT
1138+
1139+ This bit indicates that instances of the class have a ``__dict___ ``
1140+ attribute, and that the space for the dictionary is managed by the VM.
1141+
1142+ If this flag is set, :const: `Py_TPFLAGS_HAVE_GC ` should also be set.
1143+
1144+ .. versionadded :: 3.12
1145+
1146+ **Inheritance: **
1147+
1148+ This flag is inherited unless the
1149+ :c:member: `~PyTypeObject.tp_dictoffset ` field is set in a superclass.
1150+
1151+
1152+ .. data :: Py_TPFLAGS_MANAGED_WEAKREF
1153+
1154+ This bit indicates that instances of the class should be weakly
1155+ referenceable.
1156+
1157+ .. versionadded :: 3.12
1158+
1159+ **Inheritance: **
1160+
1161+ This flag is inherited unless the
1162+ :c:member: `~PyTypeObject.tp_weaklistoffset ` field is set in a superclass.
1163+
11381164
11391165 .. XXX Document more flags here?
11401166
@@ -1487,6 +1513,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
14871513
14881514.. c :member :: Py_ssize_t PyTypeObject.tp_weaklistoffset
14891515
1516+ While this field is still supported, :const: `Py_TPFLAGS_MANAGED_WEAKREF `
1517+ should be used instead, if at all possible.
1518+
14901519 If the instances of this type are weakly referenceable, this field is greater
14911520 than zero and contains the offset in the instance structure of the weak
14921521 reference list head (ignoring the GC header, if present); this offset is used by
@@ -1497,26 +1526,22 @@ and :c:type:`PyType_Type` effectively act as defaults.)
14971526 Do not confuse this field with :c:member: `~PyTypeObject.tp_weaklist `; that is the list head for
14981527 weak references to the type object itself.
14991528
1529+ It is an error to set both the :const: `Py_TPFLAGS_MANAGED_WEAKREF ` bit and
1530+ :c:member: `~PyTypeObject.tp_weaklist `.
1531+
15001532 **Inheritance: **
15011533
15021534 This field is inherited by subtypes, but see the rules listed below. A subtype
15031535 may override this offset; this means that the subtype uses a different weak
15041536 reference list head than the base type. Since the list head is always found via
15051537 :c:member: `~PyTypeObject.tp_weaklistoffset `, this should not be a problem.
15061538
1507- When a type defined by a class statement has no :attr: `~object.__slots__ ` declaration,
1508- and none of its base types are weakly referenceable, the type is made weakly
1509- referenceable by adding a weak reference list head slot to the instance layout
1510- and setting the :c:member: `~PyTypeObject.tp_weaklistoffset ` of that slot's offset.
1511-
1512- When a type's :attr: `__slots__ ` declaration contains a slot named
1513- :attr: `__weakref__ `, that slot becomes the weak reference list head for
1514- instances of the type, and the slot's offset is stored in the type's
1515- :c:member: `~PyTypeObject.tp_weaklistoffset `.
1539+ **Default: **
15161540
1517- When a type's :attr: `__slots__ ` declaration does not contain a slot named
1518- :attr: `__weakref__ `, the type inherits its :c:member: `~PyTypeObject.tp_weaklistoffset ` from its
1519- base type.
1541+ If the :const: `Py_TPFLAGS_MANAGED_WEAKREF ` bit is set in the
1542+ :c:member: `~PyTypeObject.tp_dict ` field, then
1543+ :c:member: `~PyTypeObject.tp_weaklistoffset ` will be set to a negative value,
1544+ to indicate that it is unsafe to use this field.
15201545
15211546
15221547.. c :member :: getiterfunc PyTypeObject.tp_iter
@@ -1695,6 +1720,9 @@ and :c:type:`PyType_Type` effectively act as defaults.)
16951720
16961721.. c :member :: Py_ssize_t PyTypeObject.tp_dictoffset
16971722
1723+ While this field is still supported, :const: `Py_TPFLAGS_MANAGED_DICT ` should be
1724+ used instead, if at all possible.
1725+
16981726 If the instances of this type have a dictionary containing instance variables,
16991727 this field is non-zero and contains the offset in the instances of the type of
17001728 the instance variable dictionary; this offset is used by
@@ -1703,48 +1731,34 @@ and :c:type:`PyType_Type` effectively act as defaults.)
17031731 Do not confuse this field with :c:member: `~PyTypeObject.tp_dict `; that is the dictionary for
17041732 attributes of the type object itself.
17051733
1706- If the value of this field is greater than zero, it specifies the offset from
1707- the start of the instance structure. If the value is less than zero, it
1708- specifies the offset from the *end * of the instance structure. A negative
1709- offset is more expensive to use, and should only be used when the instance
1710- structure contains a variable-length part. This is used for example to add an
1711- instance variable dictionary to subtypes of :class: `str ` or :class: `tuple `. Note
1712- that the :c:member: `~PyTypeObject.tp_basicsize ` field should account for the dictionary added to
1713- the end in that case, even though the dictionary is not included in the basic
1714- object layout. On a system with a pointer size of 4 bytes,
1715- :c:member: `~PyTypeObject.tp_dictoffset ` should be set to ``-4 `` to indicate that the dictionary is
1716- at the very end of the structure.
1734+ The value specifies the offset of the dictionary from the start of the instance structure.
17171735
17181736 The :c:member: `~PyTypeObject.tp_dictoffset ` should be regarded as write-only.
17191737 To get the pointer to the dictionary call :c:func: `PyObject_GenericGetDict `.
17201738 Calling :c:func: `PyObject_GenericGetDict ` may need to allocate memory for the
17211739 dictionary, so it is may be more efficient to call :c:func: `PyObject_GetAttr `
17221740 when accessing an attribute on the object.
17231741
1724- **Inheritance: **
1725-
1726- This field is inherited by subtypes, but see the rules listed below. A subtype
1727- may override this offset; this means that the subtype instances store the
1728- dictionary at a difference offset than the base type. Since the dictionary is
1729- always found via :c:member: `~PyTypeObject.tp_dictoffset `, this should not be a problem.
1742+ It is an error to set both the :const: `Py_TPFLAGS_MANAGED_WEAKREF ` bit and
1743+ :c:member: `~PyTypeObject.tp_dictoffset `.
17301744
1731- When a type defined by a class statement has no :attr: `~object.__slots__ ` declaration,
1732- and none of its base types has an instance variable dictionary, a dictionary
1733- slot is added to the instance layout and the :c:member: `~PyTypeObject.tp_dictoffset ` is set to
1734- that slot's offset.
1735-
1736- When a type defined by a class statement has a :attr: `__slots__ ` declaration,
1737- the type inherits its :c:member: `~PyTypeObject.tp_dictoffset ` from its base type.
1745+ **Inheritance: **
17381746
1739- (Adding a slot named :attr: `~object.__dict__ ` to the :attr: `__slots__ ` declaration does
1740- not have the expected effect, it just causes confusion. Maybe this should be
1741- added as a feature just like :attr: `__weakref__ ` though.)
1747+ This field is inherited by subtypes. A subtype should not override this offset;
1748+ doing so could be unsafe, if C code tries to access the dictionary at the
1749+ previous offset.
1750+ To properly support inheritance, use :const: `Py_TPFLAGS_MANAGED_DICT `.
17421751
17431752 **Default: **
17441753
17451754 This slot has no default. For :ref: `static types <static-types >`, if the
17461755 field is ``NULL `` then no :attr: `__dict__ ` gets created for instances.
17471756
1757+ If the :const: `Py_TPFLAGS_MANAGED_DICT ` bit is set in the
1758+ :c:member: `~PyTypeObject.tp_dict ` field, then
1759+ :c:member: `~PyTypeObject.tp_dictoffset ` will be set to ``-1 ``, to indicate
1760+ that it is unsafe to use this field.
1761+
17481762
17491763.. c :member :: initproc PyTypeObject.tp_init
17501764
@@ -2663,18 +2677,16 @@ A type that supports weakrefs, instance dicts, and hashing::
26632677 typedef struct {
26642678 PyObject_HEAD
26652679 const char *data;
2666- PyObject *inst_dict;
2667- PyObject *weakreflist;
26682680 } MyObject;
26692681
26702682 static PyTypeObject MyObject_Type = {
26712683 PyVarObject_HEAD_INIT(NULL, 0)
26722684 .tp_name = "mymod.MyObject",
26732685 .tp_basicsize = sizeof(MyObject),
26742686 .tp_doc = PyDoc_STR("My objects"),
2675- .tp_weaklistoffset = offsetof(MyObject, weakreflist),
2676- .tp_dictoffset = offsetof(MyObject, inst_dict),
2677- .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_HAVE_GC ,
2687+ .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
2688+ Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_MANAGED_DICT |
2689+ Py_TPFLAGS_MANAGED_WEAKREF ,
26782690 .tp_new = myobj_new,
26792691 .tp_traverse = (traverseproc)myobj_traverse,
26802692 .tp_clear = (inquiry)myobj_clear,
0 commit comments