Skip to content

Commit 207d2fd

Browse files
committed
introduce __mutable_buffer__ (rather hackily)
1 parent 116f72e commit 207d2fd

File tree

11 files changed

+67
-21
lines changed

11 files changed

+67
-21
lines changed

Include/internal/pycore_abstract.h

+4
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ _PyIndex_Check(PyObject *obj)
1919
PyObject *_PyNumber_PowerNoMod(PyObject *lhs, PyObject *rhs);
2020
PyObject *_PyNumber_InPlacePowerNoMod(PyObject *lhs, PyObject *rhs);
2121

22+
PyAPI_FUNC(PyObject *) _PyBuffer_MutableBufferGetter(PyObject *instance, void *ignored);
23+
24+
#define _PY_BUFFER_MUTABLE_BUFFER_GETSET { "__mutable_buffer__", _PyBuffer_MutableBufferGetter, NULL, NULL },
25+
2226
#ifdef __cplusplus
2327
}
2428
#endif

Lib/_collections_abc.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -457,15 +457,12 @@ def __subclasshook__(cls, C):
457457
class MutableBuffer(Buffer):
458458

459459
__slots__ = ()
460-
461-
@abstractmethod
462-
def __release_buffer__(self, buffer: memoryview, /) -> None:
463-
pass
460+
__mutable_buffer__ = True
464461

465462
@classmethod
466463
def __subclasshook__(cls, C):
467464
if cls is MutableBuffer:
468-
return _check_methods(C, "__buffer__", "__release_buffer__")
465+
return _check_methods(C, "__buffer__", "__mutable_buffer__")
469466
return NotImplemented
470467

471468

Modules/_ctypes/_ctypes.c

+13-4
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ bytes(cdata)
127127
#include "ctypes.h"
128128

129129
#include "pycore_long.h" // _PyLong_GetZero()
130+
#include "pycore_abstract.h" // _PY_BUFFER_MUTABLE_BUFFER_GETSET
130131

131132
PyObject *PyExc_ArgError = NULL;
132133

@@ -2809,6 +2810,11 @@ static PyBufferProcs PyCData_as_buffer = {
28092810
NULL,
28102811
};
28112812

2813+
static PyGetSetDef PyCData_getset[] = {
2814+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
2815+
{NULL}
2816+
};
2817+
28122818
/*
28132819
* CData objects are mutable, so they cannot be hashable!
28142820
*/
@@ -2918,7 +2924,7 @@ PyTypeObject PyCData_Type = {
29182924
0, /* tp_iternext */
29192925
PyCData_methods, /* tp_methods */
29202926
PyCData_members, /* tp_members */
2921-
0, /* tp_getset */
2927+
PyCData_getset, /* tp_getset */
29222928
0, /* tp_base */
29232929
0, /* tp_dict */
29242930
0, /* tp_descr_get */
@@ -3342,6 +3348,7 @@ static PyGetSetDef PyCFuncPtr_getsets[] = {
33423348
{ "argtypes", (getter)PyCFuncPtr_get_argtypes,
33433349
(setter)PyCFuncPtr_set_argtypes,
33443350
"specify the argument types", NULL },
3351+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
33453352
{ NULL, NULL }
33463353
};
33473354

@@ -4468,7 +4475,7 @@ static PyTypeObject Struct_Type = {
44684475
0, /* tp_iternext */
44694476
0, /* tp_methods */
44704477
0, /* tp_members */
4471-
0, /* tp_getset */
4478+
PyCData_getset, /* tp_getset */
44724479
0, /* tp_base */
44734480
0, /* tp_dict */
44744481
0, /* tp_descr_get */
@@ -4510,7 +4517,7 @@ static PyTypeObject Union_Type = {
45104517
0, /* tp_iternext */
45114518
0, /* tp_methods */
45124519
0, /* tp_members */
4513-
0, /* tp_getset */
4520+
PyCData_getset, /* tp_getset */
45144521
0, /* tp_base */
45154522
0, /* tp_dict */
45164523
0, /* tp_descr_get */
@@ -4830,7 +4837,7 @@ PyTypeObject PyCArray_Type = {
48304837
0, /* tp_iternext */
48314838
Array_methods, /* tp_methods */
48324839
0, /* tp_members */
4833-
0, /* tp_getset */
4840+
PyCData_getset, /* tp_getset */
48344841
0, /* tp_base */
48354842
0, /* tp_dict */
48364843
0, /* tp_descr_get */
@@ -4961,6 +4968,7 @@ Simple_get_value(CDataObject *self, void *Py_UNUSED(ignored))
49614968
static PyGetSetDef Simple_getsets[] = {
49624969
{ "value", (getter)Simple_get_value, (setter)Simple_set_value,
49634970
"current value", NULL },
4971+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
49644972
{ NULL, NULL }
49654973
};
49664974

@@ -5204,6 +5212,7 @@ static PyGetSetDef Pointer_getsets[] = {
52045212
{ "contents", (getter)Pointer_get_contents,
52055213
(setter)Pointer_set_contents,
52065214
"the object this pointer points to (read-write)", NULL },
5215+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
52075216
{ NULL, NULL }
52085217
};
52095218

Modules/_io/bytesio.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "Python.h"
2+
#include "pycore_abstract.h" // _PY_BUFFER_MUTABLE_BUFFER_GETSET
23
#include "pycore_object.h"
34
#include <stddef.h> // offsetof()
45
#include "_iomodule.h"
@@ -1124,6 +1125,11 @@ static PyBufferProcs bytesiobuf_as_buffer = {
11241125
(releasebufferproc) bytesiobuf_releasebuffer,
11251126
};
11261127

1128+
static PyGetSetDef bytesiobuf_getset[] = {
1129+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
1130+
{NULL}
1131+
};
1132+
11271133
Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type = {
11281134
PyVarObject_HEAD_INIT(NULL, 0)
11291135
"_io._BytesIOBuffer", /*tp_name*/
@@ -1154,7 +1160,7 @@ Py_EXPORTED_SYMBOL PyTypeObject _PyBytesIOBuffer_Type = {
11541160
0, /*tp_iternext*/
11551161
0, /*tp_methods*/
11561162
0, /*tp_members*/
1157-
0, /*tp_getset*/
1163+
bytesiobuf_getset, /*tp_getset*/
11581164
0, /*tp_base*/
11591165
0, /*tp_dict*/
11601166
0, /*tp_descr_get*/

Modules/arraymodule.c

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#define PY_SSIZE_T_CLEAN
1111
#include "Python.h"
12+
#include "pycore_abstract.h" // _PY_BUFFER_MUTABLE_BUFFER_GETSET
1213
#include "pycore_moduleobject.h" // _PyModule_GetState()
1314
#include "pycore_bytesobject.h" // _PyBytes_Repeat
1415
#include "structmember.h" // PyMemberDef
@@ -2277,6 +2278,7 @@ static PyGetSetDef array_getsets [] = {
22772278
"the typecode character used to create the array"},
22782279
{"itemsize", (getter) array_get_itemsize, NULL,
22792280
"the size, in bytes, of one array item"},
2281+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
22802282
{NULL}
22812283
};
22822284

Modules/mmapmodule.c

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424

2525
#define PY_SSIZE_T_CLEAN
2626
#include <Python.h>
27+
#include "pycore_abstract.h" // _PY_BUFFER_MUTABLE_BUFFER_GETSET
2728
#include "pycore_bytesobject.h" // _PyBytes_Find()
2829
#include "pycore_fileutils.h" // _Py_stat_struct
2930
#include "structmember.h" // PyMemberDef
@@ -887,6 +888,7 @@ static struct PyMethodDef mmap_object_methods[] = {
887888

888889
static PyGetSetDef mmap_object_getset[] = {
889890
{"closed", (getter) mmap_closed_get, NULL, NULL},
891+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
890892
{NULL}
891893
};
892894

Objects/abstract.c

+5
Original file line numberDiff line numberDiff line change
@@ -2967,3 +2967,8 @@ _Py_FreeCharPArray(char *const array[])
29672967
}
29682968
PyMem_Free((void*)array);
29692969
}
2970+
2971+
PyObject *
2972+
_PyBuffer_MutableBufferGetter(PyObject *instance, void *ignored) {
2973+
Py_RETURN_TRUE;
2974+
}

Objects/bytearrayobject.c

+7-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#define PY_SSIZE_T_CLEAN
44
#include "Python.h"
5-
#include "pycore_abstract.h" // _PyIndex_Check()
5+
#include "pycore_abstract.h" // _PyIndex_Check(), _PY_BUFFER_MUTABLE_BUFFER_GETSET
66
#include "pycore_bytes_methods.h"
77
#include "pycore_bytesobject.h"
88
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
@@ -2289,6 +2289,11 @@ Construct a mutable bytearray object from:\n\
22892289

22902290
static PyObject *bytearray_iter(PyObject *seq);
22912291

2292+
static PyGetSetDef bytearray_getset[] = {
2293+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
2294+
{NULL}
2295+
};
2296+
22922297
PyTypeObject PyByteArray_Type = {
22932298
PyVarObject_HEAD_INIT(&PyType_Type, 0)
22942299
"bytearray",
@@ -2320,7 +2325,7 @@ PyTypeObject PyByteArray_Type = {
23202325
0, /* tp_iternext */
23212326
bytearray_methods, /* tp_methods */
23222327
0, /* tp_members */
2323-
0, /* tp_getset */
2328+
bytearray_getset, /* tp_getset */
23242329
0, /* tp_base */
23252330
0, /* tp_dict */
23262331
0, /* tp_descr_get */

Objects/memoryobject.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
*/
1212

1313
#include "Python.h"
14-
#include "pycore_abstract.h" // _PyIndex_Check()
14+
#include "pycore_abstract.h" // _PyIndex_Check(), _PY_BUFFER_MUTABLE_BUFFER_GETSET
1515
#include "pycore_object.h" // _PyObject_GC_UNTRACK()
1616
#include "pycore_strhex.h" // _Py_strhex_with_sep()
1717
#include <stddef.h> // offsetof()
@@ -3186,6 +3186,7 @@ static PyGetSetDef memory_getsetlist[] = {
31863186
{"c_contiguous", (getter)memory_c_contiguous, NULL, memory_c_contiguous_doc},
31873187
{"f_contiguous", (getter)memory_f_contiguous, NULL, memory_f_contiguous_doc},
31883188
{"contiguous", (getter)memory_contiguous, NULL, memory_contiguous_doc},
3189+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
31893190
{NULL, NULL, NULL, NULL},
31903191
};
31913192

Objects/picklebufobject.c

+6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#define PY_SSIZE_T_CLEAN
44
#include "Python.h"
5+
#include "pycore_abstract.h" // _PY_BUFFER_MUTABLE_BUFFER_GETSET
56
#include <stddef.h>
67

78
typedef struct {
@@ -203,6 +204,10 @@ static PyMethodDef picklebuf_methods[] = {
203204
{NULL, NULL}
204205
};
205206

207+
static PyGetSetDef picklebuf_getset[] = {
208+
_PY_BUFFER_MUTABLE_BUFFER_GETSET
209+
{NULL}
210+
};
206211
PyTypeObject PyPickleBuffer_Type = {
207212
PyVarObject_HEAD_INIT(NULL, 0)
208213
.tp_name = "pickle.PickleBuffer",
@@ -216,4 +221,5 @@ PyTypeObject PyPickleBuffer_Type = {
216221
.tp_weaklistoffset = offsetof(PyPickleBufferObject, weakreflist),
217222
.tp_as_buffer = &picklebuf_as_buffer,
218223
.tp_methods = picklebuf_methods,
224+
.tp_getset = picklebuf_getset,
219225
};

Objects/typeobject.c

+17-8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "Python.h"
44
#include "pycore_call.h"
5+
#include "pycore_abstract.h" // _PyBuffer_MutableBufferGetter
56
#include "pycore_code.h" // CO_FAST_FREE
67
#include "pycore_compile.h" // _Py_Mangle()
78
#include "pycore_initconfig.h" // _PyStatus_OK()
@@ -6094,16 +6095,24 @@ type_add_getset(PyTypeObject *type)
60946095

60956096
PyObject *dict = type->tp_dict;
60966097
for (; gsp->name != NULL; gsp++) {
6097-
PyObject *descr = PyDescr_NewGetSet(type, gsp);
6098-
if (descr == NULL) {
6099-
return -1;
6100-
}
6101-
6102-
if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL) {
6098+
if (gsp->get == _PyBuffer_MutableBufferGetter) {
6099+
PyObject *name = PyUnicode_FromString(gsp->name);
6100+
if (PyDict_SetDefault(dict, name, Py_True) == NULL) {
6101+
Py_DECREF(name);
6102+
return -1;
6103+
}
6104+
Py_DECREF(name);
6105+
} else {
6106+
PyObject *descr = PyDescr_NewGetSet(type, gsp);
6107+
if (descr == NULL) {
6108+
return -1;
6109+
}
6110+
if (PyDict_SetDefault(dict, PyDescr_NAME(descr), descr) == NULL) {
6111+
Py_DECREF(descr);
6112+
return -1;
6113+
}
61036114
Py_DECREF(descr);
6104-
return -1;
61056115
}
6106-
Py_DECREF(descr);
61076116
}
61086117
return 0;
61096118
}

0 commit comments

Comments
 (0)