diff options
author | da-woods <dw-git@d-woods.co.uk> | 2022-07-06 20:47:04 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-06 21:47:04 +0200 |
commit | 22f4444a1722fe0fd3f9157f1db35ab1c02522a9 (patch) | |
tree | cbe8fd01f75ffaa9bfb9a5356d31b2499d6c7554 | |
parent | c769c3295dec09fbbb607f249224ce385591dbcc (diff) | |
download | cython-22f4444a1722fe0fd3f9157f1db35ab1c02522a9.tar.gz |
Add tests for NULL objects in memoryviews (GH-4871)
Follow up on https://github.com/cython/cython/pull/4859 by adding tests for memoryviews too.
Additional refactoring to avoid invalid decref calls on test failures. Instead, the item is safely cleared directly before the access.
-rw-r--r-- | tests/buffers/bufaccess.pyx | 15 | ||||
-rw-r--r-- | tests/memoryview/memslice.pyx | 45 |
2 files changed, 49 insertions, 11 deletions
diff --git a/tests/buffers/bufaccess.pyx b/tests/buffers/bufaccess.pyx index 2a5e84185..053ea2890 100644 --- a/tests/buffers/bufaccess.pyx +++ b/tests/buffers/bufaccess.pyx @@ -10,7 +10,7 @@ from __future__ import unicode_literals from cpython.object cimport PyObject -from cpython.ref cimport Py_INCREF, Py_DECREF +from cpython.ref cimport Py_INCREF, Py_DECREF, Py_CLEAR cimport cython __test__ = {} @@ -1013,17 +1013,14 @@ def check_object_nulled_1d(MockBuffer[object, ndim=1] buf, int idx, obj): >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a]) >>> check_object_nulled_1d(A, 0, a) - >>> decref(a) # new reference "added" to A >>> check_object_nulled_1d(A, 1, a) - >>> decref(a) >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride - >>> decref(a) >>> get_refcount(a) == rc1 True """ - cdef void **data = <void **>buf.buffer - data[idx] = NULL + cdef PyObject **data = <PyObject **>buf.buffer + Py_CLEAR(data[idx]) res = buf[idx] # takes None buf[idx] = obj return res @@ -1037,14 +1034,12 @@ def check_object_nulled_2d(MockBuffer[object, ndim=2] buf, int idx1, int idx2, o >>> rc1 = get_refcount(a) >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) >>> check_object_nulled_2d(A, 0, 0, a) - >>> decref(a) # new reference "added" to A >>> check_object_nulled_2d(A, 1, 1, a) - >>> decref(a) >>> get_refcount(a) == rc1 True """ - cdef void **data = <void **>buf.buffer - data[idx1 + 2*idx2] = NULL + cdef PyObject **data = <PyObject **>buf.buffer + Py_CLEAR(data[idx1 + 2*idx2]) res = buf[idx1, idx2] # takes None buf[idx1, idx2] = obj return res diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx index 06bdf8673..24af61e17 100644 --- a/tests/memoryview/memslice.pyx +++ b/tests/memoryview/memslice.pyx @@ -5,7 +5,7 @@ from __future__ import unicode_literals from cpython.object cimport PyObject -from cpython.ref cimport Py_INCREF, Py_DECREF +from cpython.ref cimport Py_INCREF, Py_DECREF, Py_CLEAR cimport cython from cython cimport view @@ -1130,6 +1130,49 @@ def assign_temporary_to_object(object[:] buf): """ buf[1] = {3-2: 2+(2*4)-2} +@testcase +def check_object_nulled_1d(object[:] buf, int idx, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a]) + >>> check_object_nulled_1d(A, 0, a) + >>> check_object_nulled_1d(A, 1, a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], strides=(2,)) + >>> check_object_nulled_1d(A, 0, a) # only 0 due to stride + >>> get_refcount(a) == rc1 + True + """ + cdef ObjectMockBuffer omb = buf.base + cdef PyObject **data = <PyObject**>(omb.buffer) + Py_CLEAR(data[idx]) + res = buf[idx] # takes None + buf[idx] = obj + return res + +@testcase +def check_object_nulled_2d(object[:, ::1] buf, int idx1, int idx2, obj): + """ + See comments on printbuf_object above. + + >>> a = object() + >>> rc1 = get_refcount(a) + >>> A = ObjectMockBuffer(None, [a, a, a, a], shape=(2, 2)) + >>> check_object_nulled_2d(A, 0, 0, a) + >>> check_object_nulled_2d(A, 1, 1, a) + >>> get_refcount(a) == rc1 + True + """ + cdef ObjectMockBuffer omb = buf.base + cdef PyObject **data = <PyObject**>(omb.buffer) + Py_CLEAR(data[idx1 + 2*idx2]) + res = buf[idx1, idx2] # takes None + buf[idx1, idx2] = obj + return res + + # # Test __cythonbufferdefaults__ # |