| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -395,3 +395,42 @@ Object Protocol | |||
| 395 | 395 | returns ``NULL`` if the object cannot be iterated. | |
| 396 | 396 | ||
| 397 | 397 | .. versionadded:: 3.10 | |
| 398 | + | ||
| 399 | + .. c:function:: void *PyObject_GetTypeData(PyObject *o, PyTypeObject *cls) | ||
| 400 | + | ||
| 401 | + Get a pointer to subclass-specific data reserved for *cls*. | ||
| 402 | + | ||
| 403 | + The object *o* must be an instance of *cls*, and *cls* must have been | ||
| 404 | + created using negative :c:member:`PyType_Spec.basicsize`. | ||
| 405 | + Python does not check this. | ||
| 406 | + | ||
| 407 | + On error, set an exception and return ``NULL``. | ||
| 408 | + | ||
| 409 | + .. versionadded:: 3.12 | ||
| 410 | + | ||
| 411 | + .. c:function:: Py_ssize_t PyType_GetTypeDataSize(PyTypeObject *cls) | ||
| 412 | + | ||
| 413 | + Return the size of the instance memory space reserved for *cls*, i.e. the size of the | ||
| 414 | + memory :c:func:`PyObject_GetTypeData` returns. | ||
| 415 | + | ||
| 416 | + This may be larger than requested using :c:member:`-PyType_Spec.basicsize <PyType_Spec.basicsize>`; | ||
| 417 | + it is safe to use this larger size (e.g. with :c:func:`!memset`). | ||
| 418 | + | ||
| 419 | + The type *cls* **must** have been created using | ||
| 420 | + negative :c:member:`PyType_Spec.basicsize`. | ||
| 421 | + Python does not check this. | ||
| 422 | + | ||
| 423 | + On error, set an exception and return a negative value. | ||
| 424 | + | ||
| 425 | + .. versionadded:: 3.12 | ||
| 426 | + | ||
| 427 | + .. c:function:: void *PyObject_GetItemData(PyObject *o) | ||
| 428 | + | ||
| 429 | + Get a pointer to per-item data for a class with | ||
| 430 | + :const:`Py_TPFLAGS_ITEMS_AT_END`. | ||
| 431 | + | ||
| 432 | + On error, set an exception and return ``NULL``. | ||
| 433 | + :py:exc:`TypeError` is raised if *o* does not have | ||
| 434 | + :const:`Py_TPFLAGS_ITEMS_AT_END` set. | ||
| 435 | + | ||
| 436 | + .. versionadded:: 3.12 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -486,6 +486,22 @@ The following flags can be used with :c:member:`PyMemberDef.flags`: | |||
| 486 | 486 | Emit an ``object.__getattr__`` :ref:`audit event <audit-events>` | |
| 487 | 487 | before reading. | |
| 488 | 488 | ||
| 489 | + .. c:macro:: Py_RELATIVE_OFFSET | ||
| 490 | + | ||
| 491 | + Indicates that the :c:member:`~PyMemberDef.offset` of this ``PyMemberDef`` | ||
| 492 | + entry indicates an offset from the subclass-specific data, rather than | ||
| 493 | + from ``PyObject``. | ||
| 494 | + | ||
| 495 | + Can only be used as part of :c:member:`Py_tp_members <PyTypeObject.tp_members>` | ||
| 496 | + :c:type:`slot <PyTypeSlot>` when creating a class using negative | ||
| 497 | + :c:member:`~PyTypeDef.basicsize`. | ||
| 498 | + It is mandatory in that case. | ||
| 499 | + | ||
| 500 | + This flag is only used in :c:type:`PyTypeSlot`. | ||
| 501 | + When setting :c:member:`~PyTypeObject.tp_members` during | ||
| 502 | + class creation, Python clears it and sets | ||
| 503 | + :c:member:`PyMemberDef.offset` to the offset from the ``PyObject`` struct. | ||
| 504 | + | ||
| 489 | 505 | .. index:: | |
| 490 | 506 | single: READ_RESTRICTED | |
| 491 | 507 | single: WRITE_RESTRICTED | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -353,25 +353,57 @@ The following functions and structs are used to create | |||
| 353 | 353 | ||
| 354 | 354 | Structure defining a type's behavior. | |
| 355 | 355 | ||
| 356 | - .. c:member:: const char* PyType_Spec.name | ||
| 356 | + .. c:member:: const char* name | ||
| 357 | 357 | ||
| 358 | 358 | Name of the type, used to set :c:member:`PyTypeObject.tp_name`. | |
| 359 | 359 | ||
| 360 | - .. c:member:: int PyType_Spec.basicsize | ||
| 361 | - .. c:member:: int PyType_Spec.itemsize | ||
| 360 | + .. c:member:: int basicsize | ||
| 362 | 361 | ||
| 363 | - Size of the instance in bytes, used to set | ||
| 364 | - :c:member:`PyTypeObject.tp_basicsize` and | ||
| 365 | - :c:member:`PyTypeObject.tp_itemsize`. | ||
| 362 | + If positive, specifies the size of the instance in bytes. | ||
| 363 | + It is used to set :c:member:`PyTypeObject.tp_basicsize`. | ||
| 366 | 364 | ||
| 367 | - .. c:member:: int PyType_Spec.flags | ||
| 365 | + If zero, specifies that :c:member:`~PyTypeObject.tp_basicsize` | ||
| 366 | + should be inherited. | ||
| 367 | + | ||
| 368 | + If negative, the absolute value specifies how much space instances of the | ||
| 369 | + class need *in addition* to the superclass. | ||
| 370 | + Use :c:func:`PyObject_GetTypeData` to get a pointer to subclass-specific | ||
| 371 | + memory reserved this way. | ||
| 372 | + | ||
| 373 | + .. versionchanged:: 3.12 | ||
| 374 | + | ||
| 375 | + Previously, this field could not be negative. | ||
| 376 | + | ||
| 377 | + .. c:member:: int itemsize | ||
| 378 | + | ||
| 379 | + Size of one element of a variable-size type, in bytes. | ||
| 380 | + Used to set :c:member:`PyTypeObject.tp_itemsize`. | ||
| 381 | + See ``tp_itemsize`` documentation for caveats. | ||
| 382 | + | ||
| 383 | + If zero, :c:member:`~PyTypeObject.tp_itemsize` is inherited. | ||
| 384 | + Extending arbitrary variable-sized classes is dangerous, | ||
| 385 | + since some types use a fixed offset for variable-sized memory, | ||
| 386 | + which can then overlap fixed-sized memory used by a subclass. | ||
| 387 | + To help prevent mistakes, inheriting ``itemsize`` is only possible | ||
| 388 | + in the following situations: | ||
| 389 | + | ||
| 390 | + - The base is not variable-sized (its | ||
| 391 | + :c:member:`~PyTypeObject.tp_itemsize`). | ||
| 392 | + - The requested :c:member:`PyType_Spec.basicsize` is positive, | ||
| 393 | + suggesting that the memory layout of the base class is known. | ||
| 394 | + - The requested :c:member:`PyType_Spec.basicsize` is zero, | ||
| 395 | + suggesting that the subclass does not access the instance's memory | ||
| 396 | + directly. | ||
| 397 | + - With the :const:`Py_TPFLAGS_ITEMS_AT_END` flag. | ||
| 398 | + | ||
| 399 | + .. c:member:: unsigned int flags | ||
| 368 | 400 | ||
| 369 | 401 | Type flags, used to set :c:member:`PyTypeObject.tp_flags`. | |
| 370 | 402 | ||
| 371 | 403 | If the ``Py_TPFLAGS_HEAPTYPE`` flag is not set, | |
| 372 | 404 | :c:func:`PyType_FromSpecWithBases` sets it automatically. | |
| 373 | 405 | ||
| 374 | - .. c:member:: PyType_Slot *PyType_Spec.slots | ||
| 406 | + .. c:member:: PyType_Slot *slots | ||
| 375 | 407 | ||
| 376 | 408 | Array of :c:type:`PyType_Slot` structures. | |
| 377 | 409 | Terminated by the special slot value ``{0, NULL}``. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1171,6 +1171,26 @@ and :c:type:`PyType_Type` effectively act as defaults.) | |||
| 1171 | 1171 | :c:member:`~PyTypeObject.tp_weaklistoffset` field is set in a superclass. | |
| 1172 | 1172 | ||
| 1173 | 1173 | ||
| 1174 | + .. data:: Py_TPFLAGS_ITEMS_AT_END | ||
| 1175 | + | ||
| 1176 | + Only usable with variable-size types, i.e. ones with non-zero | ||
| 1177 | + :c:member:`~PyObject.tp_itemsize`. | ||
| 1178 | + | ||
| 1179 | + Indicates that the variable-sized portion of an instance of this type is | ||
| 1180 | + at the end of the instance's memory area, at an offset of | ||
| 1181 | + :c:expr:`Py_TYPE(obj)->tp_basicsize` (which may be different in each | ||
| 1182 | + subclass). | ||
| 1183 | + | ||
| 1184 | + When setting this flag, be sure that all superclasses either | ||
| 1185 | + use this memory layout, or are not variable-sized. | ||
| 1186 | + Python does not check this. | ||
| 1187 | + | ||
| 1188 | + .. versionadded:: 3.12 | ||
| 1189 | + | ||
| 1190 | + **Inheritance:** | ||
| 1191 | + | ||
| 1192 | + This flag is inherited. | ||
| 1193 | + | ||
| 1174 | 1194 | .. XXX Document more flags here? | |
| 1175 | 1195 | ||
| 1176 | 1196 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1159,6 +1159,21 @@ New Features | |||
| 1159 | 1159 | ||
| 1160 | 1160 | (Contributed by Petr Viktorin in :gh:`101101`.) | |
| 1161 | 1161 | ||
| 1162 | + * :pep:`697`: Added API for extending types whose instance memory layout is | ||
| 1163 | + opaque: | ||
| 1164 | + | ||
| 1165 | + - :c:member:`PyType_Spec.basicsize` can be zero or negative to specify | ||
| 1166 | + inheriting or extending the base class size. | ||
| 1167 | + - :c:func:`PyObject_GetTypeData` and :c:func:`PyType_GetTypeDataSize` | ||
| 1168 | + added to allow access to subclass-specific instance data. | ||
| 1169 | + - :const:`Py_TPFLAGS_ITEMS_AT_END` and :c:func:`PyObject_GetItemData` | ||
| 1170 | + added to allow safely extending certain variable-sized types, including | ||
| 1171 | + :c:var:`PyType_Type`. | ||
| 1172 | + - :c:macro:`Py_RELATIVE_OFFSET` added to allow defining | ||
| 1173 | + :c:type:`members <PyMemberDef>` in terms of a subclass-specific struct. | ||
| 1174 | + | ||
| 1175 | + (Contributed by Petr Viktorin in :gh:`103509`.) | ||
| 1176 | + | ||
| 1162 | 1177 | * Added the new limited C API function :c:func:`PyType_FromMetaclass`, | |
| 1163 | 1178 | which generalizes the existing :c:func:`PyType_FromModuleAndSpec` using | |
| 1164 | 1179 | an additional metaclass argument. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -553,6 +553,7 @@ Py_DEPRECATED(3.11) typedef int UsingDeprecatedTrashcanMacro; | |||
| 553 | 553 | Py_TRASHCAN_END; \ | |
| 554 | 554 | } while(0); | |
| 555 | 555 | ||
| 556 | + PyAPI_FUNC(void *) PyObject_GetItemData(PyObject *obj); | ||
| 556 | 557 | ||
| 557 | 558 | PyAPI_FUNC(int) _PyObject_VisitManagedDict(PyObject *obj, visitproc visit, void *arg); | |
| 558 | 559 | PyAPI_FUNC(void) _PyObject_ClearManagedDict(PyObject *obj); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -83,6 +83,7 @@ struct PyMemberDef { | |||
| 83 | 83 | #define Py_READONLY 1 | |
| 84 | 84 | #define Py_AUDIT_READ 2 // Added in 3.10, harmless no-op before that | |
| 85 | 85 | #define _Py_WRITE_RESTRICTED 4 // Deprecated, no-op. Do not reuse the value. | |
| 86 | + #define Py_RELATIVE_OFFSET 8 | ||
| 86 | 87 | ||
| 87 | 88 | PyAPI_FUNC(PyObject *) PyMember_GetOne(const char *, PyMemberDef *); | |
| 88 | 89 | PyAPI_FUNC(int) PyMember_SetOne(char *, PyMemberDef *, PyObject *); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -389,11 +389,6 @@ extern PyObject ** _PyObject_ComputedDictPointer(PyObject *); | |||
| 389 | 389 | extern void _PyObject_FreeInstanceAttributes(PyObject *obj); | |
| 390 | 390 | extern int _PyObject_IsInstanceDictEmpty(PyObject *); | |
| 391 | 391 | ||
| 392 | - // Access macro to the members which are floating "behind" the object | ||
| 393 | - static inline PyMemberDef* _PyHeapType_GET_MEMBERS(PyHeapTypeObject *etype) { | ||
| 394 | - return (PyMemberDef*)((char*)etype + Py_TYPE(etype)->tp_basicsize); | ||
| 395 | - } | ||
| 396 | - | ||
| 397 | 392 | PyAPI_FUNC(PyObject *) _PyObject_LookupSpecial(PyObject *, PyObject *); | |
| 398 | 393 | ||
| 399 | 394 | /* C function call trampolines to mitigate bad function pointer casts. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -355,6 +355,8 @@ PyAPI_FUNC(PyObject *) PyType_GetQualName(PyTypeObject *); | |||
| 355 | 355 | #endif | |
| 356 | 356 | #if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x030C0000 | |
| 357 | 357 | PyAPI_FUNC(PyObject *) PyType_FromMetaclass(PyTypeObject*, PyObject*, PyType_Spec*, PyObject*); | |
| 358 | + PyAPI_FUNC(void *) PyObject_GetTypeData(PyObject *obj, PyTypeObject *cls); | ||
| 359 | + PyAPI_FUNC(Py_ssize_t) PyType_GetTypeDataSize(PyTypeObject *cls); | ||
| 358 | 360 | #endif | |
| 359 | 361 | ||
| 360 | 362 | /* Generic type check */ | |
@@ -521,6 +523,9 @@ given type object has a specified feature. | |||
| 521 | 523 | // subject itself (rather than a mapped attribute on it): | |
| 522 | 524 | #define _Py_TPFLAGS_MATCH_SELF (1UL << 22) | |
| 523 | 525 | ||
| 526 | + /* Items (ob_size*tp_itemsize) are found at the end of an instance's memory */ | ||
| 527 | + #define Py_TPFLAGS_ITEMS_AT_END (1UL << 23) | ||
| 528 | + | ||
| 524 | 529 | /* These flags are used to determine if a type is a subclass. */ | |
| 525 | 530 | #define Py_TPFLAGS_LONG_SUBCLASS (1UL << 24) | |
| 526 | 531 | #define Py_TPFLAGS_LIST_SUBCLASS (1UL << 25) | |
| Back | FazBrowse Home | New Git URL |
0 commit comments