bpo-40724: Support setting buffer slots from type specs (GH-20648)

This is not part of the limited API but makes the buffer slots available for type specs.
This commit is contained in:
scoder 2020-06-06 21:35:10 +02:00 committed by GitHub
parent 68874a8502
commit f7c4e23642
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 2 deletions

View File

@ -1,7 +1,12 @@
/* Do not renumber the file; these numbers are part of the stable ABI. */ /* Do not renumber the file; these numbers are part of the stable ABI. */
#if defined(Py_LIMITED_API)
/* Disabled, see #10181 */ /* Disabled, see #10181 */
#undef Py_bf_getbuffer #undef Py_bf_getbuffer
#undef Py_bf_releasebuffer #undef Py_bf_releasebuffer
#else
#define Py_bf_getbuffer 1
#define Py_bf_releasebuffer 2
#endif
#define Py_mp_ass_subscript 3 #define Py_mp_ass_subscript 3
#define Py_mp_length 4 #define Py_mp_length 4
#define Py_mp_subscript 5 #define Py_mp_subscript 5

View File

@ -477,6 +477,11 @@ class CAPITest(unittest.TestCase):
self.assertEqual(ref(), inst) self.assertEqual(ref(), inst)
self.assertEqual(inst.weakreflist, ref) self.assertEqual(inst.weakreflist, ref)
def test_heaptype_with_buffer(self):
inst = _testcapi.HeapCTypeWithBuffer()
b = bytes(inst)
self.assertEqual(b, b"1234")
def test_c_subclass_of_heap_ctype_with_tpdealloc_decrefs_once(self): def test_c_subclass_of_heap_ctype_with_tpdealloc_decrefs_once(self):
subclass_instance = _testcapi.HeapCTypeSubclass() subclass_instance = _testcapi.HeapCTypeSubclass()
type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass) type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass)

View File

@ -0,0 +1 @@
Allow defining buffer slots in type specs.

View File

@ -6298,6 +6298,47 @@ static PyType_Spec HeapCTypeSubclass_spec = {
HeapCTypeSubclass_slots HeapCTypeSubclass_slots
}; };
PyDoc_STRVAR(heapctypewithbuffer__doc__,
"Heap type with buffer support.\n\n"
"The buffer is set to [b'1', b'2', b'3', b'4']");
typedef struct {
HeapCTypeObject base;
char buffer[4];
} HeapCTypeWithBufferObject;
static int
heapctypewithbuffer_getbuffer(HeapCTypeWithBufferObject *self, Py_buffer *view, int flags)
{
self->buffer[0] = '1';
self->buffer[1] = '2';
self->buffer[2] = '3';
self->buffer[3] = '4';
return PyBuffer_FillInfo(
view, (PyObject*)self, (void *)self->buffer, 4, 1, flags);
}
static int
heapctypewithbuffer_releasebuffer(HeapCTypeWithBufferObject *self, Py_buffer *view)
{
assert(view->obj == (void*) self);
}
static PyType_Slot HeapCTypeWithBuffer_slots[] = {
{Py_bf_getbuffer, heapctypewithbuffer_getbuffer},
{Py_bf_releasebuffer, heapctypewithbuffer_releasebuffer},
{Py_tp_doc, (char*)heapctypewithbuffer__doc__},
{0, 0},
};
static PyType_Spec HeapCTypeWithBuffer_spec = {
"_testcapi.HeapCTypeWithBuffer",
sizeof(HeapCTypeWithBufferObject),
0,
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
HeapCTypeWithBuffer_slots
};
PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__, PyDoc_STRVAR(heapctypesubclasswithfinalizer__doc__,
"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n" "Subclass of HeapCType with a finalizer that reassigns __class__.\n\n"
"__class__ is set to plain HeapCTypeSubclass during finalization.\n" "__class__ is set to plain HeapCTypeSubclass during finalization.\n"
@ -6775,6 +6816,12 @@ PyInit__testcapi(void)
} }
PyModule_AddObject(m, "HeapCTypeWithWeakref", HeapCTypeWithWeakref); PyModule_AddObject(m, "HeapCTypeWithWeakref", HeapCTypeWithWeakref);
PyObject *HeapCTypeWithBuffer = PyType_FromSpec(&HeapCTypeWithBuffer_spec);
if (HeapCTypeWithBuffer == NULL) {
return NULL;
}
PyModule_AddObject(m, "HeapCTypeWithBuffer", HeapCTypeWithBuffer);
PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass); PyObject *subclass_with_finalizer_bases = PyTuple_Pack(1, HeapCTypeSubclass);
if (subclass_with_finalizer_bases == NULL) { if (subclass_with_finalizer_bases == NULL) {
return NULL; return NULL;

4
Objects/typeslots.inc generated
View File

@ -1,6 +1,6 @@
/* Generated by typeslots.py */ /* Generated by typeslots.py */
0, offsetof(PyHeapTypeObject, as_buffer.bf_getbuffer),
0, offsetof(PyHeapTypeObject, as_buffer.bf_releasebuffer),
offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript), offsetof(PyHeapTypeObject, as_mapping.mp_ass_subscript),
offsetof(PyHeapTypeObject, as_mapping.mp_length), offsetof(PyHeapTypeObject, as_mapping.mp_length),
offsetof(PyHeapTypeObject, as_mapping.mp_subscript), offsetof(PyHeapTypeObject, as_mapping.mp_subscript),