Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
ca76251
try 1
JelleZijlstra Oct 2, 2022
901b459
progress
JelleZijlstra Oct 3, 2022
c5407c7
this is better
JelleZijlstra Oct 4, 2022
86f2000
this seems to work
JelleZijlstra Oct 4, 2022
ac10887
one more test
JelleZijlstra Oct 5, 2022
2563016
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Oct 5, 2022
530a160
additions
JelleZijlstra Oct 5, 2022
de3a4bc
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Oct 12, 2022
116f72e
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Oct 21, 2022
207d2fd
introduce __mutable_buffer__ (rather hackily)
JelleZijlstra Oct 21, 2022
aee2c33
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Nov 6, 2022
007fdc1
Rip out __mutable_buffer__
JelleZijlstra Nov 6, 2022
46a9239
__release_buffer__ calls mv.release()
JelleZijlstra Nov 8, 2022
3020fee
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Nov 8, 2022
be9bf45
additional test
JelleZijlstra Nov 8, 2022
a6bf0e8
undo stray change
JelleZijlstra Nov 8, 2022
04d267e
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Dec 18, 2022
04d0a42
throw an error if already released
JelleZijlstra Dec 18, 2022
bb6d076
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Mar 8, 2023
5f755fe
Fix compiler warning
JelleZijlstra Mar 8, 2023
0b02e63
news
JelleZijlstra Mar 8, 2023
8e4db43
fix some tests
JelleZijlstra Mar 8, 2023
6c863bc
More tests. Add flags= argument to memoryview
JelleZijlstra Mar 10, 2023
3b4b7d6
Make memoryview flags arg private
JelleZijlstra Mar 11, 2023
f295012
regen global objects
JelleZijlstra Mar 11, 2023
1660ae4
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Apr 5, 2023
0af94ac
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Apr 5, 2023
b5ea908
Ignore new C globals for now
JelleZijlstra Apr 5, 2023
b22bfa9
not static (should not have committed this)
JelleZijlstra Apr 5, 2023
69e8f7c
Use tabs not spaces
JelleZijlstra Apr 5, 2023
4ca7a7c
Address Kumar's feedback
JelleZijlstra Apr 10, 2023
fd2d716
Merge branch 'main' into pep688v2
JelleZijlstra Apr 10, 2023
a70e12d
Address another piece of feedback
JelleZijlstra Apr 13, 2023
96c9253
Use a classmethod instead of a new arg to the memoryview constructor
JelleZijlstra Apr 13, 2023
1f7f7a0
fix typo
JelleZijlstra Apr 13, 2023
7665dde
Merge branch 'main' into pep688v2
JelleZijlstra Apr 25, 2023
e99c188
Merge branch 'main' into pep688v2
JelleZijlstra Apr 26, 2023
33691ea
Add Py_SAFE_DOWNCAST
JelleZijlstra Apr 26, 2023
8f5073f
Add some test cases (thanks Shantanu)
JelleZijlstra Apr 26, 2023
b69dc7c
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Apr 26, 2023
9d33003
Merge remote-tracking branch 'upstream/main' into pep688v2
JelleZijlstra Apr 29, 2023
cecb6a5
Remove spurious global strings
JelleZijlstra Apr 29, 2023
9b941a0
Merge branch 'main' into pep688v2
JelleZijlstra May 4, 2023
b22d66f
Merge branch 'main' of https://github.com/python/cpython into pep688v2
kumaraditya303 May 4, 2023
0f77bbb
fixup global objects
kumaraditya303 May 4, 2023
61f54ce
minor fixes
kumaraditya303 May 4, 2023
9f2d16b
newlines
JelleZijlstra May 4, 2023
5e0d2de
Rename variable
JelleZijlstra May 4, 2023
b380632
Check for INT_MAX
JelleZijlstra May 4, 2023
8502b98
Remove tp_new
JelleZijlstra May 4, 2023
b51465f
regen-all
JelleZijlstra May 4, 2023
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
Prev Previous commit
Next Next commit
More tests. Add flags= argument to memoryview
  • Loading branch information
JelleZijlstra committed Mar 10, 2023
commit 6c863bcf3560563a736ebcefba12c9155a6f7869
35 changes: 35 additions & 0 deletions Lib/test/test_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import unittest
from test import support
from test.support import os_helper
import inspect
from itertools import permutations, product
from random import randrange, sample, choice
import warnings
Expand Down Expand Up @@ -4502,6 +4503,40 @@ def __release_buffer__(self, buffer):
self.assertEqual(mv.tobytes(), b"hello")
self.assertFalse(wr.held)

def test_buffer_flags(self):
class PossiblyMutable:
def __init__(self, data, mutable) -> None:
self._data = bytearray(data)
self._mutable = mutable

def __buffer__(self, flags):
if flags & inspect.BufferFlags.WRITABLE:
if not self._mutable:
raise RuntimeError("not mutable")
return memoryview(self._data)
else:
return memoryview(bytes(self._data))

mutable = PossiblyMutable(b"hello", True)
immutable = PossiblyMutable(b"hello", False)
with memoryview(mutable, flags=inspect.BufferFlags.WRITABLE) as mv:
self.assertEqual(mv.tobytes(), b"hello")
mv[0] = ord(b'x')
self.assertEqual(mv.tobytes(), b"xello")
with memoryview(immutable, flags=inspect.BufferFlags.SIMPLE) as mv:
self.assertEqual(mv.tobytes(), b"hello")
with self.assertRaises(TypeError):
mv[0] = ord(b'x')
self.assertEqual(mv.tobytes(), b"hello")

with self.assertRaises(RuntimeError):
memoryview(immutable, flags=inspect.BufferFlags.WRITABLE)
with memoryview(immutable) as mv:
self.assertEqual(mv.tobytes(), b"hello")
with self.assertRaises(TypeError):
mv[0] = ord(b'x')
self.assertEqual(mv.tobytes(), b"hello")

def test_call_builtins(self):
ba = bytearray(b"hello")
mv = ba.__buffer__(0)
Expand Down
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@
@MODULE__XXTESTFUZZ_TRUE@_xxtestfuzz _xxtestfuzz/_xxtestfuzz.c _xxtestfuzz/fuzzer.c
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/vectorcall_limited.c _testcapi/heaptype.c _testcapi/unicode.c _testcapi/getargs.c _testcapi/pytime.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c

# Some testing modules MUST be built as shared libraries.
Expand Down
97 changes: 97 additions & 0 deletions Modules/_testcapi/buffer.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/* Test PEP 688 - Buffers */

#include "parts.h"

#include "structmember.h" // PyMemberDef
#include <stddef.h> // offsetof

typedef struct {
PyObject_HEAD
PyObject *obj;
long references;
Comment thread
JelleZijlstra marked this conversation as resolved.
Outdated
} testBufObject;

static PyObject *
testbuf_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
testBufObject *self = (testBufObject *)type->tp_alloc(type, 0);
if (self == NULL) {
return NULL;
}
self->obj = PyBytes_FromString("test");
Comment thread
JelleZijlstra marked this conversation as resolved.
Outdated
self->references = 0;
return (PyObject *)self;
}

static int
testbuf_traverse(testBufObject *self, visitproc visit, void *arg)
{
Py_VISIT(self->obj);
return 0;
}

static int
testbuf_clear(testBufObject *self)
{
Py_CLEAR(self->obj);
return 0;
}

static void
testbuf_dealloc(testBufObject *self)
{
PyObject_GC_UnTrack(self);
Py_XDECREF(self->obj);
Py_TYPE(self)->tp_free((PyObject *) self);
}

static int
testbuf_getbuf(testBufObject *self, Py_buffer *view, int flags)
{
int buf = PyObject_GetBuffer(self->obj, view, flags);
Py_SETREF(view->obj, Py_NewRef((PyObject *)self));
self->references++;
return buf;
}

static void
testbuf_releasebuf(testBufObject *self, Py_buffer *view)
{
self->references--;
assert(self->references >= 0);
}

static PyBufferProcs testbuf_as_buffer = {
.bf_getbuffer = (getbufferproc) testbuf_getbuf,
.bf_releasebuffer = (releasebufferproc) testbuf_releasebuf,
};

static struct PyMemberDef testbuf_members[] = {
{"references", T_LONG, offsetof(testBufObject, references), READONLY},
{NULL},
};

static PyTypeObject testBufType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "testBufType",
.tp_basicsize = sizeof(testBufObject),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_new = testbuf_new,
.tp_dealloc = (destructor) testbuf_dealloc,
.tp_traverse = (traverseproc) testbuf_traverse,
.tp_clear = (inquiry) testbuf_clear,
.tp_as_buffer = &testbuf_as_buffer,
.tp_members = testbuf_members
};

int
_PyTestCapi_Init_Buffer(PyObject *m) {
if (PyType_Ready(&testBufType) < 0) {
return -1;
}
if (PyModule_AddObjectRef(m, "testBuf", (PyObject *)&testBufType)) {
return -1;
}

return 0;
}
1 change: 1 addition & 0 deletions Modules/_testcapi/parts.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ int _PyTestCapi_Init_Float(PyObject *module);
int _PyTestCapi_Init_Structmember(PyObject *module);
int _PyTestCapi_Init_Exceptions(PyObject *module);
int _PyTestCapi_Init_Code(PyObject *module);
int _PyTestCapi_Init_Buffer(PyObject *module);

#ifdef LIMITED_API_AVAILABLE
int _PyTestCapi_Init_VectorcallLimited(PyObject *module);
Expand Down
90 changes: 3 additions & 87 deletions Modules/_testcapimodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -3746,86 +3746,6 @@ static PyTypeObject MyList_Type = {
MyList_new, /* tp_new */
};

typedef struct {
PyObject_HEAD
PyObject *obj;
long references;
} testBufObject;

static PyObject *
testbuf_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
testBufObject *self = (testBufObject *)type->tp_alloc(type, 0);
if (self == NULL) {
return NULL;
}
self->obj = PyBytes_FromString("test");
self->references = 0;
return (PyObject *)self;
}

static int
testbuf_traverse(testBufObject *self, visitproc visit, void *arg)
{
Py_VISIT(self->obj);
return 0;
}

static int
testbuf_clear(testBufObject *self)
{
Py_CLEAR(self->obj);
return 0;
}

static void
testbuf_dealloc(testBufObject *self)
{
PyObject_GC_UnTrack(self);
Py_XDECREF(self->obj);
Py_TYPE(self)->tp_free((PyObject *) self);
}

static int
testbuf_getbuf(testBufObject *self, Py_buffer *view, int flags)
{
int buf = PyObject_GetBuffer(self->obj, view, flags);
Py_SETREF(view->obj, Py_NewRef((PyObject *)self));
self->references++;
return buf;
}

static void
testbuf_releasebuf(testBufObject *self, Py_buffer *view)
{
self->references--;
assert(self->references >= 0);
}

static PyBufferProcs testbuf_as_buffer = {
.bf_getbuffer = (getbufferproc) testbuf_getbuf,
.bf_releasebuffer = (releasebufferproc) testbuf_releasebuf,
};

static struct PyMemberDef testbuf_members[] = {
{"references", T_LONG, offsetof(testBufObject, references), READONLY},
{NULL},
};

static PyTypeObject testBufType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "testBufType",
.tp_basicsize = sizeof(testBufObject),
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_new = testbuf_new,
.tp_dealloc = (destructor) testbuf_dealloc,
.tp_traverse = (traverseproc) testbuf_traverse,
.tp_clear = (inquiry) testbuf_clear,
.tp_as_buffer = &testbuf_as_buffer,
.tp_members = testbuf_members
};


/* Test PEP 560 */

typedef struct {
Expand Down Expand Up @@ -4057,13 +3977,6 @@ PyInit__testcapi(void)
Py_INCREF(&MyList_Type);
PyModule_AddObject(m, "MyList", (PyObject *)&MyList_Type);

if (PyType_Ready(&testBufType) < 0) {
return NULL;
}
if (PyModule_AddObjectRef(m, "testBuf", (PyObject *)&testBufType)) {
return NULL;
}

if (PyType_Ready(&GenericAlias_Type) < 0)
return NULL;
Py_INCREF(&GenericAlias_Type);
Expand Down Expand Up @@ -4172,6 +4085,9 @@ PyInit__testcapi(void)
if (_PyTestCapi_Init_Code(m) < 0) {
return NULL;
}
if (_PyTestCapi_Init_Buffer(m) < 0) {
return NULL;
}

#ifndef LIMITED_API_AVAILABLE
PyModule_AddObjectRef(m, "LIMITED_API_AVAILABLE", Py_False);
Expand Down
26 changes: 18 additions & 8 deletions Objects/clinic/memoryobject.c.h

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

8 changes: 5 additions & 3 deletions Objects/memoryobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -965,15 +965,17 @@ PyMemoryView_GetContiguous(PyObject *obj, int buffertype, char order)
memoryview.__new__

object: object
*
flags: int(c_default='PyBUF_FULL_RO') = PyBUF_FULL_RO

Create a new memoryview object which references the given object.
[clinic start generated code]*/

static PyObject *
memoryview_impl(PyTypeObject *type, PyObject *object)
/*[clinic end generated code: output=7de78e184ed66db8 input=f04429eb0bdf8c6e]*/
memoryview_impl(PyTypeObject *type, PyObject *object, int flags)
/*[clinic end generated code: output=f1c225d1ad24ec11 input=cab66ab4bb27f268]*/
{
return PyMemoryView_FromObject(object);
return PyMemoryView_FromObjectAndFlags(object, flags);
}


Expand Down
1 change: 1 addition & 0 deletions PCbuild/_testcapi.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@
<ClCompile Include="..\Modules\_testcapi\structmember.c" />
<ClCompile Include="..\Modules\_testcapi\exceptions.c" />
<ClCompile Include="..\Modules\_testcapi\code.c" />
<ClCompile Include="..\Modules\_testcapi\buffer.c" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc" />
Expand Down
3 changes: 3 additions & 0 deletions PCbuild/_testcapi.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@
<ClCompile Include="..\Modules\_testcapi\code.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\Modules\_testcapi\buffer.c">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\PC\python_nt.rc">
Expand Down