Skip to content

[3.9] bpo-40724: Support setting buffer slots from type specs (GH-20648) #20683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Include/typeslots.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
/* Do not renumber the file; these numbers are part of the stable ABI. */
#if defined(Py_LIMITED_API)
/* Disabled, see #10181 */
#undef Py_bf_getbuffer
#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_length 4
#define Py_mp_subscript 5
Expand Down
5 changes: 5 additions & 0 deletions Lib/test/test_capi.py
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,11 @@ def test_heaptype_with_weakref(self):
self.assertEqual(ref(), inst)
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):
subclass_instance = _testcapi.HeapCTypeSubclass()
type_refcnt = sys.getrefcount(_testcapi.HeapCTypeSubclass)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Allow defining buffer slots in type specs.
47 changes: 47 additions & 0 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -6298,6 +6298,47 @@ static PyType_Spec HeapCTypeSubclass_spec = {
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__,
"Subclass of HeapCType with a finalizer that reassigns __class__.\n\n"
"__class__ is set to plain HeapCTypeSubclass during finalization.\n"
Expand Down Expand Up @@ -6775,6 +6816,12 @@ PyInit__testcapi(void)
}
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);
if (subclass_with_finalizer_bases == NULL) {
return NULL;
Expand Down
4 changes: 2 additions & 2 deletions Objects/typeslots.inc

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.