Commit ded64d16 authored by Dag Sverre Seljebotn's avatar Dag Sverre Seljebotn

Updated buffers to beta 3 of Py3

parent 871351b5
...@@ -242,9 +242,7 @@ def put_acquire_arg_buffer(entry, code, pos): ...@@ -242,9 +242,7 @@ def put_acquire_arg_buffer(entry, code, pos):
# entry.buffer_aux.buffer_info_var.cname)) # entry.buffer_aux.buffer_info_var.cname))
def get_release_buffer_code(entry): def get_release_buffer_code(entry):
return "__Pyx_SafeReleaseBuffer((PyObject*)%s, &%s)" % ( return "__Pyx_SafeReleaseBuffer(&%s)" % entry.buffer_aux.buffer_info_var.cname
entry.cname,
entry.buffer_aux.buffer_info_var.cname)
def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
is_initialized, pos, code): is_initialized, pos, code):
...@@ -274,8 +272,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type, ...@@ -274,8 +272,7 @@ def put_assign_to_buffer(lhs_cname, rhs_cname, buffer_aux, buffer_type,
if is_initialized: if is_initialized:
# Release any existing buffer # Release any existing buffer
code.putln('__Pyx_SafeReleaseBuffer((PyObject*)%s, &%s);' % ( code.putln('__Pyx_SafeReleaseBuffer(&%s);' % bufstruct)
lhs_cname, bufstruct))
# Acquire # Acquire
retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type) retcode_cname = code.funcstate.allocate_temp(PyrexTypes.c_int_type)
code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname)) code.putln("%s = %s;" % (retcode_cname, getbuffer % rhs_cname))
...@@ -606,7 +603,9 @@ def use_py2_buffer_functions(env): ...@@ -606,7 +603,9 @@ def use_py2_buffer_functions(env):
code += dedent(""" code += dedent("""
} }
static void __Pyx_ReleaseBuffer(PyObject *obj, Py_buffer *view) { static void __Pyx_ReleaseBuffer(Py_buffer *view) {
PyObject* obj = view->obj;
if (obj) {
""") """)
if len(types) > 0: if len(types) > 0:
clause = "if" clause = "if"
...@@ -615,6 +614,9 @@ def use_py2_buffer_functions(env): ...@@ -615,6 +614,9 @@ def use_py2_buffer_functions(env):
code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release) code += "%s (PyObject_TypeCheck(obj, %s)) %s(obj, view);" % (clause, t, release)
clause = "else if" clause = "else if"
code += dedent(""" code += dedent("""
Py_DECREF(obj);
view->obj = NULL;
}
} }
#endif #endif
...@@ -623,10 +625,10 @@ def use_py2_buffer_functions(env): ...@@ -623,10 +625,10 @@ def use_py2_buffer_functions(env):
env.use_utility_code([dedent("""\ env.use_utility_code([dedent("""\
#if (PY_MAJOR_VERSION < 3) && !(Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER) #if (PY_MAJOR_VERSION < 3) && !(Py_TPFLAGS_DEFAULT & Py_TPFLAGS_HAVE_NEWBUFFER)
static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags); static int __Pyx_GetBuffer(PyObject *obj, Py_buffer *view, int flags);
static void __Pyx_ReleaseBuffer(PyObject *obj, Py_buffer *view); static void __Pyx_ReleaseBuffer(Py_buffer *view);
#else #else
#define __Pyx_GetBuffer PyObject_GetBuffer #define __Pyx_GetBuffer PyObject_GetBuffer
#define __Pyx_ReleaseBuffer PyObject_ReleaseBuffer #define __Pyx_ReleaseBuffer PyBuffer_Release
#endif #endif
"""), code], codename) """), code], codename)
...@@ -655,20 +657,21 @@ static void __Pyx_RaiseBufferIndexError(int axis) { ...@@ -655,20 +657,21 @@ static void __Pyx_RaiseBufferIndexError(int axis) {
# exporter. # exporter.
# #
acquire_utility_code = ["""\ acquire_utility_code = ["""\
static INLINE void __Pyx_SafeReleaseBuffer(PyObject* obj, Py_buffer* info); static INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info);
static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf); /*proto*/ static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf); /*proto*/
static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts); /*proto*/ static INLINE const char* __Pyx_ConsumeWhitespace(const char* ts); /*proto*/
static INLINE const char* __Pyx_BufferTypestringCheckEndian(const char* ts); /*proto*/ static INLINE const char* __Pyx_BufferTypestringCheckEndian(const char* ts); /*proto*/
static void __Pyx_BufferNdimError(Py_buffer* buffer, int expected_ndim); /*proto*/ static void __Pyx_BufferNdimError(Py_buffer* buffer, int expected_ndim); /*proto*/
""", """ """, """
static INLINE void __Pyx_SafeReleaseBuffer(PyObject* obj, Py_buffer* info) { static INLINE void __Pyx_SafeReleaseBuffer(Py_buffer* info) {
if (info->buf == NULL) return; if (info->buf == NULL) return;
if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL; if (info->suboffsets == __Pyx_minusones) info->suboffsets = NULL;
__Pyx_ReleaseBuffer(obj, info); __Pyx_ReleaseBuffer(info);
} }
static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) { static INLINE void __Pyx_ZeroBuffer(Py_buffer* buf) {
buf->buf = NULL; buf->buf = NULL;
buf->obj = NULL;
buf->strides = __Pyx_zeros; buf->strides = __Pyx_zeros;
buf->shape = __Pyx_zeros; buf->shape = __Pyx_zeros;
buf->suboffsets = __Pyx_minusones; buf->suboffsets = __Pyx_minusones;
......
...@@ -104,14 +104,15 @@ builtin_types_table = [ ...@@ -104,14 +104,15 @@ builtin_types_table = [
builtin_structs_table = [ builtin_structs_table = [
('Py_buffer', 'Py_buffer', ('Py_buffer', 'Py_buffer',
[("buf", PyrexTypes.c_void_ptr_type), [("buf", PyrexTypes.c_void_ptr_type),
("obj", PyrexTypes.py_object_type),
("len", PyrexTypes.c_py_ssize_t_type), ("len", PyrexTypes.c_py_ssize_t_type),
("itemsize", PyrexTypes.c_py_ssize_t_type),
("readonly", PyrexTypes.c_bint_type), ("readonly", PyrexTypes.c_bint_type),
("format", PyrexTypes.c_char_ptr_type),
("ndim", PyrexTypes.c_int_type), ("ndim", PyrexTypes.c_int_type),
("format", PyrexTypes.c_char_ptr_type),
("shape", PyrexTypes.c_py_ssize_t_ptr_type), ("shape", PyrexTypes.c_py_ssize_t_ptr_type),
("strides", PyrexTypes.c_py_ssize_t_ptr_type), ("strides", PyrexTypes.c_py_ssize_t_ptr_type),
("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type), ("suboffsets", PyrexTypes.c_py_ssize_t_ptr_type),
("itemsize", PyrexTypes.c_py_ssize_t_type),
("internal", PyrexTypes.c_void_ptr_type), ("internal", PyrexTypes.c_void_ptr_type),
]) ])
] ]
......
...@@ -429,14 +429,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): ...@@ -429,14 +429,15 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode):
code.putln("") code.putln("")
code.putln(" typedef struct {") code.putln(" typedef struct {")
code.putln(" void *buf;") code.putln(" void *buf;")
code.putln(" PyObject *obj;")
code.putln(" Py_ssize_t len;") code.putln(" Py_ssize_t len;")
code.putln(" Py_ssize_t itemsize;")
code.putln(" int readonly;") code.putln(" int readonly;")
code.putln(" const char *format;")
code.putln(" int ndim;") code.putln(" int ndim;")
code.putln(" char *format;")
code.putln(" Py_ssize_t *shape;") code.putln(" Py_ssize_t *shape;")
code.putln(" Py_ssize_t *strides;") code.putln(" Py_ssize_t *strides;")
code.putln(" Py_ssize_t *suboffsets;") code.putln(" Py_ssize_t *suboffsets;")
code.putln(" Py_ssize_t itemsize;")
code.putln(" void *internal;") code.putln(" void *internal;")
code.putln(" } Py_buffer;") code.putln(" } Py_buffer;")
code.putln("") code.putln("")
......
...@@ -860,6 +860,9 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -860,6 +860,9 @@ class FuncDefNode(StatNode, BlockNode):
lenv = self.local_scope lenv = self.local_scope
is_getbuffer_slot = (self.entry.name == "__getbuffer__" and
self.entry.scope.is_c_class_scope)
# Generate C code for header and body of function # Generate C code for header and body of function
code.enter_cfunc_scope() code.enter_cfunc_scope()
code.return_from_error_cleanup_label = code.new_label() code.return_from_error_cleanup_label = code.new_label()
...@@ -902,6 +905,9 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -902,6 +905,9 @@ class FuncDefNode(StatNode, BlockNode):
acquire_gil = self.need_gil_acquisition(lenv) acquire_gil = self.need_gil_acquisition(lenv)
if acquire_gil: if acquire_gil:
code.putln("PyGILState_STATE _save = PyGILState_Ensure();") code.putln("PyGILState_STATE _save = PyGILState_Ensure();")
# ----- Automatic lead-ins for certain special functions
if is_getbuffer_slot:
self.getbuffer_init(code)
# ----- Fetch arguments # ----- Fetch arguments
self.generate_argument_parsing_code(env, code) self.generate_argument_parsing_code(env, code)
# If an argument is assigned to in the body, we must # If an argument is assigned to in the body, we must
...@@ -971,17 +977,27 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -971,17 +977,27 @@ class FuncDefNode(StatNode, BlockNode):
"%s = %s;" % ( "%s = %s;" % (
Naming.retval_cname, Naming.retval_cname,
err_val)) err_val))
if buffers_present:
# Else, non-error return will be an empty clause if is_getbuffer_slot:
self.getbuffer_error_cleanup(code)
# If we are using the non-error cleanup section we should
# jump past it if we have an error. The if-test below determine
# whether this section is used.
if buffers_present or is_getbuffer_slot:
code.put_goto(code.return_from_error_cleanup_label) code.put_goto(code.return_from_error_cleanup_label)
# ----- Non-error return cleanup # ----- Non-error return cleanup
# PS! If adding something here, modify the conditions for the # If you add anything here, remember to add a condition to the
# goto statement in error cleanup above # if-test above in the error block (so that it can jump past this
# block).
code.put_label(code.return_label) code.put_label(code.return_label)
for entry in lenv.buffer_entries: for entry in lenv.buffer_entries:
if entry.used: if entry.used:
code.putln("%s;" % Buffer.get_release_buffer_code(entry)) code.putln("%s;" % Buffer.get_release_buffer_code(entry))
if is_getbuffer_slot:
self.getbuffer_normal_cleanup(code)
# ----- Return cleanup for both error and no-error return # ----- Return cleanup for both error and no-error return
code.put_label(code.return_from_error_cleanup_label) code.put_label(code.return_from_error_cleanup_label)
if not Options.init_local_none: if not Options.init_local_none:
...@@ -1042,8 +1058,27 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1042,8 +1058,27 @@ class FuncDefNode(StatNode, BlockNode):
# For Python class methods, create and store function object # For Python class methods, create and store function object
if self.assmt: if self.assmt:
self.assmt.generate_execution_code(code) self.assmt.generate_execution_code(code)
#
# Special code for the __getbuffer__ call
#
def getbuffer_init(self, code):
info = self.local_scope.arg_entries[1].cname
# Python 3.0 betas have a bug in memoryview which makes it call
# getbuffer with a NULL parameter. For now we work around this;
# the following line should be removed when this bug is fixed.
code.putln("if (%s == NULL) return 0;" % info)
code.putln("%s->obj = Py_None; Py_INCREF(Py_None);" % info)
def getbuffer_error_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname
code.putln("Py_DECREF(%s->obj); %s->obj = NULL;" %
(info, info))
def getbuffer_normal_cleanup(self, code):
info = self.local_scope.arg_entries[1].cname
code.putln("if (%s->obj == Py_None) { Py_DECREF(Py_None); %s->obj = NULL; }" %
(info, info))
class CFuncDefNode(FuncDefNode): class CFuncDefNode(FuncDefNode):
# C function definition. # C function definition.
......
...@@ -43,6 +43,7 @@ cdef extern from "numpy/arrayobject.h": ...@@ -43,6 +43,7 @@ cdef extern from "numpy/arrayobject.h":
raise RuntimeError("Py_intptr_t and Py_ssize_t differs in size, numpy.pxd does not support this") raise RuntimeError("Py_intptr_t and Py_ssize_t differs in size, numpy.pxd does not support this")
info.buf = PyArray_DATA(self) info.buf = PyArray_DATA(self)
# info.obj = None # this is automatic
info.ndim = PyArray_NDIM(self) info.ndim = PyArray_NDIM(self)
info.strides = <Py_ssize_t*>PyArray_STRIDES(self) info.strides = <Py_ssize_t*>PyArray_STRIDES(self)
info.shape = <Py_ssize_t*>PyArray_DIMS(self) info.shape = <Py_ssize_t*>PyArray_DIMS(self)
......
...@@ -25,11 +25,11 @@ setup_string = u""" ...@@ -25,11 +25,11 @@ setup_string = u"""
""" """
def testcase(func): def testcase2(func):
__test__[func.__name__] = setup_string + func.__doc__ __test__[func.__name__] = setup_string + func.__doc__
return func return func
def testcas(a): def testcase(a):
pass pass
...@@ -50,7 +50,7 @@ def printbuf(): ...@@ -50,7 +50,7 @@ def printbuf():
cdef object[int, ndim=2] buf cdef object[int, ndim=2] buf
print buf print buf
@testcase @testcase2
def acquire_release(o1, o2): def acquire_release(o1, o2):
""" """
>>> acquire_release(A, B) >>> acquire_release(A, B)
...@@ -949,11 +949,10 @@ cdef class MockBuffer: ...@@ -949,11 +949,10 @@ cdef class MockBuffer:
def __getbuffer__(MockBuffer self, Py_buffer* buffer, int flags): def __getbuffer__(MockBuffer self, Py_buffer* buffer, int flags):
if self.fail: if self.fail:
raise ValueError("Failing on purpose") raise ValueError("Failing on purpose")
if buffer is NULL:
print u"locking!"
return
if buffer == NULL:
return
self.recieved_flags = [] self.recieved_flags = []
cdef int value cdef int value
for name, value in available_flags: for name, value in available_flags:
...@@ -961,6 +960,7 @@ cdef class MockBuffer: ...@@ -961,6 +960,7 @@ cdef class MockBuffer:
self.recieved_flags.append(name) self.recieved_flags.append(name)
buffer.buf = <void*>(<char*>self.buffer + (<int>self.offset * self.itemsize)) buffer.buf = <void*>(<char*>self.buffer + (<int>self.offset * self.itemsize))
buffer.obj = self
buffer.len = self.len buffer.len = self.len
buffer.readonly = 0 buffer.readonly = 0
buffer.format = <char*>self.format buffer.format = <char*>self.format
......
...@@ -8,18 +8,16 @@ if sys.version_info[0] >= 3: ...@@ -8,18 +8,16 @@ if sys.version_info[0] >= 3:
__doc__ += u""" __doc__ += u"""
>>> ms = memoryview(s) >>> ms = memoryview(s)
>>> ms.tobytes() >>> ms.tobytes()
bytearray(b'abcdefg') b'abcdefg'
>>> m1 = memoryview(b1) >>> m1 = memoryview(b1)
>>> m1.tobytes() >>> m1.tobytes()
locking! b'abcdefg'
bytearray(b'abcdefg')
>>> m2 = memoryview(b2) >>> m2 = memoryview(b2)
>>> m2.tobytes() >>> m2.tobytes()
locking! releasing!
unlocking! b'abcdefg'
bytearray(b'abcdefg')
>>> del m1 >>> del m1
>>> del m2 >>> del m2
...@@ -30,10 +28,8 @@ s = "abcdefg" ...@@ -30,10 +28,8 @@ s = "abcdefg"
cdef class TestBuffer: cdef class TestBuffer:
def __getbuffer__(self, Py_buffer* buffer, int flags): def __getbuffer__(self, Py_buffer* buffer, int flags):
if buffer is NULL:
print u"locking!"
return
buffer.buf = <char*>s buffer.buf = <char*>s
buffer.obj = self
buffer.len = len(s) buffer.len = len(s)
buffer.readonly = 0 buffer.readonly = 0
buffer.format = "B" buffer.format = "B"
...@@ -46,7 +42,4 @@ cdef class TestBuffer: ...@@ -46,7 +42,4 @@ cdef class TestBuffer:
cdef class TestBufferRelease(TestBuffer): cdef class TestBufferRelease(TestBuffer):
def __releasebuffer__(self, Py_buffer* buffer): def __releasebuffer__(self, Py_buffer* buffer):
if buffer is NULL: print u"releasing!"
print u"unlocking!"
else:
print u"releasing!"
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment