Commit a0e188d4 authored by Mark Florisson's avatar Mark Florisson

Memoryview slice item assignment, better errors, pass all tests

parent df5626e4
...@@ -594,8 +594,14 @@ class ExprNode(Node): ...@@ -594,8 +594,14 @@ class ExprNode(Node):
"Cannot convert '%s' to memoryviewslice" % "Cannot convert '%s' to memoryviewslice" %
(src_type,)) (src_type,))
elif not MemoryView.src_conforms_to_dst(src.type, dst_type): elif not MemoryView.src_conforms_to_dst(src.type, dst_type):
error(self.pos, "Memoryview '%s' not conformable to memoryview '%s'." % if src.type.dtype.same_as(dst_type.dtype):
(src.type, dst_type)) msg = "Memoryview '%s' not conformable to memoryview '%s'."
tup = src.type, dst_type
else:
msg = "Different base types for memoryviews (%s, %s)"
tup = src.type.dtype, dst_type.dtype
error(self.pos, msg % tup)
elif dst_type.is_pyobject: elif dst_type.is_pyobject:
if not src.type.is_pyobject: if not src.type.is_pyobject:
...@@ -2412,13 +2418,13 @@ class IndexNode(ExprNode): ...@@ -2412,13 +2418,13 @@ class IndexNode(ExprNode):
self.is_temp = True self.is_temp = True
if setting and self.base.type.is_memoryviewslice: if setting and self.base.type.is_memoryviewslice:
self.type.writable_needed = True self.base.type.writable_needed = True
elif setting: elif setting:
if not self.base.entry.type.writable: if not self.base.entry.type.writable:
error(self.pos, "Writing to readonly buffer") error(self.pos, "Writing to readonly buffer")
else: else:
self.writable_needed = True self.writable_needed = True
if self.type.is_buffer: if self.base.type.is_buffer:
self.base.entry.buffer_aux.writable_needed = True self.base.entry.buffer_aux.writable_needed = True
elif memoryviewslice_access: elif memoryviewslice_access:
...@@ -2570,7 +2576,7 @@ class IndexNode(ExprNode): ...@@ -2570,7 +2576,7 @@ class IndexNode(ExprNode):
if self.is_buffer_access: if self.is_buffer_access:
if code.globalstate.directives['nonecheck']: if code.globalstate.directives['nonecheck']:
self.put_nonecheck(code) self.put_nonecheck(code)
self.buffer_ptr_code = self.buffer_lookup_code(code) buffer_entry, self.buffer_ptr_code = self.buffer_lookup_code(code)
if self.type.is_pyobject: if self.type.is_pyobject:
# is_temp is True, so must pull out value and incref it. # is_temp is True, so must pull out value and incref it.
code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code)) code.putln("%s = *%s;" % (self.result(), self.buffer_ptr_code))
...@@ -2657,11 +2663,14 @@ class IndexNode(ExprNode): ...@@ -2657,11 +2663,14 @@ class IndexNode(ExprNode):
# Used from generate_assignment_code and InPlaceAssignmentNode # Used from generate_assignment_code and InPlaceAssignmentNode
if code.globalstate.directives['nonecheck']: if code.globalstate.directives['nonecheck']:
self.put_nonecheck(code) self.put_nonecheck(code)
ptrexpr = self.buffer_lookup_code(code)
buffer_entry, ptrexpr = self.buffer_lookup_code(code)
if self.buffer_type.dtype.is_pyobject: if self.buffer_type.dtype.is_pyobject:
# Must manage refcounts. Decref what is already there # Must manage refcounts. Decref what is already there
# and incref what we put in. # and incref what we put in.
ptr = code.funcstate.allocate_temp(self.buffer_type.buffer_ptr_type, manage_ref=False) ptr = code.funcstate.allocate_temp(buffer_entry.buf_ptr_type,
manage_ref=False)
rhs_code = rhs.result() rhs_code = rhs.result()
code.putln("%s = %s;" % (ptr, ptrexpr)) code.putln("%s = %s;" % (ptr, ptrexpr))
code.put_gotref("*%s" % ptr) code.put_gotref("*%s" % ptr)
...@@ -2735,12 +2744,14 @@ class IndexNode(ExprNode): ...@@ -2735,12 +2744,14 @@ class IndexNode(ExprNode):
buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry) buffer_entry = MemoryView.MemoryViewSliceBufferEntry(entry)
negative_indices = Buffer.buffer_defaults['negative_indices'] negative_indices = Buffer.buffer_defaults['negative_indices']
return Buffer.put_buffer_lookup_code(entry=buffer_entry,
index_signeds=[i.type.signed for i in self.indices], return buffer_entry, Buffer.put_buffer_lookup_code(
index_cnames=index_temps, entry=buffer_entry,
directives=code.globalstate.directives, index_signeds=[i.type.signed for i in self.indices],
pos=self.pos, code=code, index_cnames=index_temps,
negative_indices=negative_indices) directives=code.globalstate.directives,
pos=self.pos, code=code,
negative_indices=negative_indices)
def put_nonecheck(self, code): def put_nonecheck(self, code):
code.globalstate.use_utility_code(raise_noneindex_error_utility_code) code.globalstate.use_utility_code(raise_noneindex_error_utility_code)
...@@ -7681,6 +7692,13 @@ class CoerceToMemViewSliceNode(CoercionNode): ...@@ -7681,6 +7692,13 @@ class CoerceToMemViewSliceNode(CoercionNode):
self.type.from_py_function, self.type.from_py_function,
self.arg.py_result())) self.arg.py_result()))
error_cond = self.type.error_condition(self.result())
code.putln(code.error_goto_if(error_cond, self.pos))
def generate_disposal_code(self, code):
code.put_xdecref_memoryviewslice(self.result(),
have_gil=not self.env.nogil)
class CastNode(CoercionNode): class CastNode(CoercionNode):
# Wrap a node in a C type cast. # Wrap a node in a C type cast.
......
...@@ -14,9 +14,8 @@ STOP_ERR = "Axis specification only allowed in the 'stop' slot." ...@@ -14,9 +14,8 @@ STOP_ERR = "Axis specification only allowed in the 'stop' slot."
STEP_ERR = "Only the value 1 (one) or valid axis specification allowed in the step slot." STEP_ERR = "Only the value 1 (one) or valid axis specification allowed in the step slot."
ONE_ERR = "The value 1 (one) may appear in the first or last axis specification only." ONE_ERR = "The value 1 (one) may appear in the first or last axis specification only."
BOTH_CF_ERR = "Cannot specify an array that is both C and Fortran contiguous." BOTH_CF_ERR = "Cannot specify an array that is both C and Fortran contiguous."
NOT_AMP_ERR = "Invalid operator, only an ampersand '&' is allowed."
INVALID_ERR = "Invalid axis specification." INVALID_ERR = "Invalid axis specification."
EXPR_ERR = "no expressions allowed in axis spec, only names (e.g. cython.view.contig)." EXPR_ERR = "no expressions allowed in axis spec, only names and literals."
CF_ERR = "Invalid axis specification for a C/Fortran contiguous array." CF_ERR = "Invalid axis specification for a C/Fortran contiguous array."
def concat_flags(*flags): def concat_flags(*flags):
...@@ -24,9 +23,9 @@ def concat_flags(*flags): ...@@ -24,9 +23,9 @@ def concat_flags(*flags):
format_flag = "PyBUF_FORMAT" format_flag = "PyBUF_FORMAT"
memview_c_contiguous = concat_flags(format_flag, "PyBUF_C_CONTIGUOUS") memview_c_contiguous = "(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_f_contiguous = concat_flags(format_flag, "PyBUF_F_CONTIGUOUS") memview_f_contiguous = "(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_any_contiguous = concat_flags(format_flag, "PyBUF_ANY_CONTIGUOUS") memview_any_contiguous = "(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_full_access = "PyBUF_FULL" memview_full_access = "PyBUF_FULL"
#memview_strided_access = "PyBUF_STRIDED" #memview_strided_access = "PyBUF_STRIDED"
memview_strided_access = "PyBUF_RECORDS" memview_strided_access = "PyBUF_RECORDS"
...@@ -72,8 +71,8 @@ def mangle_dtype_name(dtype): ...@@ -72,8 +71,8 @@ def mangle_dtype_name(dtype):
import Buffer import Buffer
return Buffer.mangle_dtype_name(dtype) return Buffer.mangle_dtype_name(dtype)
def axes_to_str(axes): #def axes_to_str(axes):
return "".join([access[0].upper()+packing[0] for (access, packing) in axes]) # return "".join([access[0].upper()+packing[0] for (access, packing) in axes])
def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code, def put_acquire_memoryviewslice(lhs_cname, lhs_type, lhs_pos, rhs, code,
incref_rhs=True, have_gil=False): incref_rhs=True, have_gil=False):
...@@ -106,7 +105,7 @@ def put_assign_to_memviewslice(lhs_cname, rhs_cname, memviewslicetype, code, ...@@ -106,7 +105,7 @@ def put_assign_to_memviewslice(lhs_cname, rhs_cname, memviewslicetype, code,
code.putln("%s.strides[%d] = %s.strides[%d];" % (lhs_cname, i, rhs_cname, i)) code.putln("%s.strides[%d] = %s.strides[%d];" % (lhs_cname, i, rhs_cname, i))
code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % (lhs_cname, i, rhs_cname, i)) code.putln("%s.suboffsets[%d] = %s.suboffsets[%d];" % (lhs_cname, i, rhs_cname, i))
def get_buf_flag(specs): def get_buf_flags(specs):
is_c_contig, is_f_contig = is_cf_contig(specs) is_c_contig, is_f_contig = is_cf_contig(specs)
if is_c_contig: if is_c_contig:
...@@ -196,50 +195,65 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry): ...@@ -196,50 +195,65 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
suboffset = "%s.suboffsets[%d]" % (self.cname, dim) suboffset = "%s.suboffsets[%d]" % (self.cname, dim)
index = index_cnames[dim] index = index_cnames[dim]
if access == 'full' and packing in ('strided', 'follow'): flag = get_memoryview_flag(access, packing)
if flag == "generic":
code.globalstate.use_utility_code(memviewslice_index_helpers) code.globalstate.use_utility_code(memviewslice_index_helpers)
bufp = ('__pyx_memviewslice_index_full(%s, %s, %s, %s)' % bufp = ('__pyx_memviewslice_index_full(%s, %s, %s, %s)' %
(bufp, index, stride, suboffset)) (bufp, index, stride, suboffset))
elif access == 'full' and packing == 'contig': elif flag == "generic_contiguous":
# We can skip stride multiplication with the cast # We can skip stride multiplication with the cast
code.globalstate.use_utility_code(memviewslice_index_helpers) code.globalstate.use_utility_code(memviewslice_index_helpers)
bufp = '((char *) ((%s *) %s) + %s)' % (type_decl, bufp, index) bufp = '((char *) ((%s *) %s) + %s)' % (type_decl, bufp, index)
bufp = ('__pyx_memviewslice_index_full_contig(%s, %s)' % bufp = ('__pyx_memviewslice_index_full_contig(%s, %s)' %
(bufp, suboffset)) (bufp, suboffset))
elif access == 'ptr' and packing in ('strided', 'follow'): elif flag == "indirect":
bufp = ("(*((char **) %s + %s * %s) + %s)" % bufp = ("(*((char **) %s + %s * %s) + %s)" %
(bufp, index, stride, suboffset)) (bufp, index, stride, suboffset))
elif access == 'ptr' and packing == 'contig': elif flag == "indirect_contiguous":
bufp = "(*((char **) %s) + %s)" % (bufp, suboffset) bufp = "(*((char **) %s) + %s)" % (bufp, suboffset)
elif access == 'direct' and packing in ('strided', 'follow'): elif flag == "strided":
bufp = "(%s + %s * %s)" % (bufp, index, stride) bufp = "(%s + %s * %s)" % (bufp, index, stride)
else: else:
assert (access, packing) == ('direct', 'contig'), (access, packing) assert flag == 'contiguous', flag
bufp = '((char *) (((%s *) %s) + %s))' % (type_decl, bufp, index) bufp = '((char *) (((%s *) %s) + %s))' % (type_decl, bufp, index)
bufp = '( /* dim=%d */ %s )' % (dim, bufp) bufp = '( /* dim=%d */ %s )' % (dim, bufp)
return "((%s *) %s)" % (type_decl, bufp) return "((%s *) %s)" % (type_decl, bufp)
def get_memoryview_flag(access, packing):
if access == 'full' and packing in ('strided', 'follow'):
return 'generic'
elif access == 'full' and packing == 'contig':
return 'generic_contiguous'
elif access == 'ptr' and packing in ('strided', 'follow'):
return 'indirect'
elif access == 'ptr' and packing == 'contig':
return 'indirect_contiguous'
elif access == 'direct' and packing in ('strided', 'follow'):
return 'strided'
else:
assert (access, packing) == ('direct', 'contig'), (access, packing)
return 'contiguous'
def get_copy_func_name(to_memview): def get_copy_func_name(to_memview):
base = "__Pyx_BufferNew_%s_From_%s_%s" base = "__Pyx_BufferNew_%s_From_%s"
if to_memview.is_c_contig: if to_memview.is_c_contig:
return base % ('C', axes_to_str(to_memview.axes), mangle_dtype_name(to_memview.dtype)) return base % ('C', to_memview.specialization_suffix())
else: else:
return base % ('F', axes_to_str(to_memview.axes), mangle_dtype_name(to_memview.dtype)) return base % ('F', to_memview.specialization_suffix())
def get_copy_contents_name(from_mvs, to_mvs): def get_copy_contents_name(from_mvs, to_mvs):
dtype = from_mvs.dtype assert from_mvs.dtype == to_mvs.dtype
assert dtype == to_mvs.dtype return '__Pyx_BufferCopyContents_%s_to_%s' % (from_mvs.specialization_suffix(),
return ('__Pyx_BufferCopyContents_%s_%s_%s' % to_mvs.specialization_suffix())
(axes_to_str(from_mvs.axes),
axes_to_str(to_mvs.axes),
mangle_dtype_name(dtype)))
class IsContigFuncUtilCode(object): class IsContigFuncUtilCode(object):
......
...@@ -1428,16 +1428,20 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1428,16 +1428,20 @@ class FuncDefNode(StatNode, BlockNode):
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
# incref it to properly keep track of refcounts. # incref it to properly keep track of refcounts.
is_cdef = isinstance(self, CFuncDefNode)
for entry in lenv.arg_entries: for entry in lenv.arg_entries:
if entry.type.is_pyobject: if entry.type.is_pyobject:
if (acquire_gil or entry.assignments) and not entry.in_closure: if (acquire_gil or entry.assignments) and not entry.in_closure:
code.put_var_incref(entry) code.put_var_incref(entry)
# Note: all memoryviewslices are already newly acquired references
# or increffed defaults! # Note: defaults are always increffed. For def functions, we
#if entry.type.is_memoryviewslice: # we aquire arguments from object converstion, so we have
# code.put_incref_memoryviewslice(entry.cname, # new references. If we are a cdef function, we need to
# have_gil=not lenv.nogil) # incref our arguments
#code.put_incref("%s.memview" % entry.cname, cython_memoryview_ptr_type) if is_cdef and entry.type.is_memoryviewslice:
code.put_incref_memoryviewslice(entry.cname,
have_gil=not lenv.nogil)
# ----- Initialise local buffer auxiliary variables # ----- Initialise local buffer auxiliary variables
for entry in lenv.var_entries + lenv.arg_entries: for entry in lenv.var_entries + lenv.arg_entries:
if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used: if entry.type.is_buffer and entry.buffer_aux.buflocal_nd_var.used:
...@@ -1567,7 +1571,7 @@ class FuncDefNode(StatNode, BlockNode): ...@@ -1567,7 +1571,7 @@ class FuncDefNode(StatNode, BlockNode):
if entry.type.is_pyobject: if entry.type.is_pyobject:
if (acquire_gil or entry.assignments) and not entry.in_closure: if (acquire_gil or entry.assignments) and not entry.in_closure:
code.put_var_decref(entry) code.put_var_decref(entry)
if entry.type.is_memoryviewslice and isinstance(self, DefNode): if entry.type.is_memoryviewslice:
code.put_xdecref_memoryviewslice(entry.cname) code.put_xdecref_memoryviewslice(entry.cname)
#code.put_decref("%s.memview" % entry.cname, cython_memoryview_ptr_type) #code.put_decref("%s.memview" % entry.cname, cython_memoryview_ptr_type)
if self.needs_closure: if self.needs_closure:
......
...@@ -338,9 +338,7 @@ class MemoryViewSliceType(PyrexType): ...@@ -338,9 +338,7 @@ class MemoryViewSliceType(PyrexType):
to_py_function = None to_py_function = None
exception_value = None exception_value = None
exception_check = None exception_check = True
utility_counter = 0
def __init__(self, base_dtype, axes): def __init__(self, base_dtype, axes):
''' '''
...@@ -381,7 +379,7 @@ class MemoryViewSliceType(PyrexType): ...@@ -381,7 +379,7 @@ class MemoryViewSliceType(PyrexType):
self.dtype = base_dtype self.dtype = base_dtype
self.axes = axes self.axes = axes
self.ndim = len(axes) self.ndim = len(axes)
self.flags = MemoryView.get_buf_flag(self.axes) self.flags = MemoryView.get_buf_flags(self.axes)
self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes) self.is_c_contig, self.is_f_contig = MemoryView.is_cf_contig(self.axes)
assert not (self.is_c_contig and self.is_f_contig) assert not (self.is_c_contig and self.is_f_contig)
...@@ -416,7 +414,6 @@ class MemoryViewSliceType(PyrexType): ...@@ -416,7 +414,6 @@ class MemoryViewSliceType(PyrexType):
if self.scope is None: if self.scope is None:
import Symtab, MemoryView, Options import Symtab, MemoryView, Options
from MemoryView import axes_to_str
self.scope = scope = Symtab.CClassScope( self.scope = scope = Symtab.CClassScope(
'mvs_class_'+self.specialization_suffix(), 'mvs_class_'+self.specialization_suffix(),
...@@ -504,12 +501,12 @@ class MemoryViewSliceType(PyrexType): ...@@ -504,12 +501,12 @@ class MemoryViewSliceType(PyrexType):
def specialization_suffix(self): def specialization_suffix(self):
import MemoryView import MemoryView
return MemoryView.axes_to_str(self.axes) + '_' + MemoryView.mangle_dtype_name(self.dtype) dtype_name = MemoryView.mangle_dtype_name(self.dtype)
return "%s_%s" % (self.axes_to_name(), dtype_name)
def global_init_code(self, entry, code): #def global_init_code(self, entry, code):
code.putln("%s.data = NULL;" % entry.cname) # code.putln("%s.data = NULL;" % entry.cname)
code.putln("%s.memview = NULL;" % entry.cname) # code.putln("%s.memview = NULL;" % entry.cname)
#code.put_init_to_py_none("%s.memview" % entry.cname, cython_memoryview_ptr_type, nanny=False)
def check_for_null_code(self, cname): def check_for_null_code(self, cname):
return cname + '.memview' return cname + '.memview'
...@@ -535,15 +532,14 @@ class MemoryViewSliceType(PyrexType): ...@@ -535,15 +532,14 @@ class MemoryViewSliceType(PyrexType):
else: else:
c_or_f_flag = "0" c_or_f_flag = "0"
# specializing through UtilityCode.specialize is not so useful as suffix = self.specialization_suffix()
# specialize on too many things to include in the function name funcname = "__Pyx_PyObject_to_MemoryviewSlice_" + suffix
funcname = "__Pyx_PyObject_to_MemoryviewSlice_%d" % self.utility_counter
context = dict( context = dict(
MemoryView.context, MemoryView.context,
buf_flag = self.flags, buf_flag = self.flags,
ndim = self.ndim, ndim = self.ndim,
axes_specs = ', '.join(self.axes_specs_to_code()), axes_specs = ', '.join(self.axes_to_code()),
dtype_typedecl = self.dtype.declaration_code(""), dtype_typedecl = self.dtype.declaration_code(""),
struct_nesting_depth = self.dtype.struct_nesting_depth(), struct_nesting_depth = self.dtype.struct_nesting_depth(),
c_or_f_flag = c_or_f_flag, c_or_f_flag = c_or_f_flag,
...@@ -551,8 +547,6 @@ class MemoryViewSliceType(PyrexType): ...@@ -551,8 +547,6 @@ class MemoryViewSliceType(PyrexType):
) )
self.from_py_function = funcname self.from_py_function = funcname
MemoryViewSliceType.utility_counter += 1
return True return True
def create_to_py_utility_code(self, env): def create_to_py_utility_code(self, env):
...@@ -560,15 +554,15 @@ class MemoryViewSliceType(PyrexType): ...@@ -560,15 +554,15 @@ class MemoryViewSliceType(PyrexType):
def get_to_py_function(self, obj): def get_to_py_function(self, obj):
return "__pyx_memoryview_fromslice(&%s, %s.memview->obj, %s, %s);" % ( return "__pyx_memoryview_fromslice(&%s, %s.memview->obj, %s, %s);" % (
obj.result(), obj.result(), self.flags, self.ndim) obj.result(), obj.result(), self.flags, self.ndim)
def axes_specs_to_code(self): def axes_to_code(self):
"Return a list of code constants for each axis" "Return a list of code constants for each axis"
import MemoryView import MemoryView
d = MemoryView._spec_to_const d = MemoryView._spec_to_const
return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes] return ["(%s | %s)" % (d[a], d[p]) for a, p in self.axes]
def axes_specs_to_name(self): def axes_to_name(self):
"Return an abbreviated name for our axes" "Return an abbreviated name for our axes"
import MemoryView import MemoryView
d = MemoryView._spec_to_abbrev d = MemoryView._spec_to_abbrev
...@@ -577,6 +571,24 @@ class MemoryViewSliceType(PyrexType): ...@@ -577,6 +571,24 @@ class MemoryViewSliceType(PyrexType):
def error_condition(self, result_code): def error_condition(self, result_code):
return "!%s.memview" % result_code return "!%s.memview" % result_code
def __str__(self):
import MemoryView
axes_code_list = []
for access, packing in self.axes:
flag = MemoryView.get_memoryview_flag(access, packing)
if flag == "strided":
axes_code_list.append(":")
else:
axes_code_list.append("::" + flag)
if self.dtype.is_pyobject:
dtype_name = self.dtype.name
else:
dtype_name = self.dtype
return "%s[%s]" % (dtype_name, ", ".join(axes_code_list))
class BufferType(BaseType): class BufferType(BaseType):
# #
...@@ -632,6 +644,9 @@ class PyObjectType(PyrexType): ...@@ -632,6 +644,9 @@ class PyObjectType(PyrexType):
def __repr__(self): def __repr__(self):
return "<PyObjectType>" return "<PyObjectType>"
def __eq__(self, other):
return isinstance(other, PyObjectType) and self.name == other.name
def can_coerce_to_pyobject(self, env): def can_coerce_to_pyobject(self, env):
return True return True
......
...@@ -258,6 +258,9 @@ cdef class memoryview(object): ...@@ -258,6 +258,9 @@ cdef class memoryview(object):
bytesitem = itemp[:self.view.itemsize] bytesitem = itemp[:self.view.itemsize]
return struct.unpack(fmt, bytesitem) return struct.unpack(fmt, bytesitem)
def __repr__(self):
return "<MemoryView of %s at 0x%x>" % (self.obj.__class__.__name__, id(self))
def __str__(self): def __str__(self):
return "<MemoryView of %r at 0x%x>" % (self.obj, id(self)) return "<MemoryView of %r at 0x%x>" % (self.obj, id(self))
...@@ -283,8 +286,8 @@ cdef memoryview_cwrapper(object o, int flags): ...@@ -283,8 +286,8 @@ cdef memoryview_cwrapper(object o, int flags):
return memoryview(o, flags) return memoryview(o, flags)
@cname('__pyx_memoryview_fromslice') @cname('__pyx_memoryview_fromslice')
cdef memoryview memoryview_from_memview_cwrapper( cdef memoryview_from_memview_cwrapper({{memviewslice_name}} *memviewslice,
{{memviewslice_name}} *memviewslice, object orig_obj, int flags, int new_ndim): object orig_obj, int flags, int new_ndim):
cdef _memoryviewslice result = _memoryviewslice(orig_obj, flags) cdef _memoryviewslice result = _memoryviewslice(orig_obj, flags)
result.from_slice = memviewslice[0] result.from_slice = memviewslice[0]
......
# mode: error # mode: error
cimport cython cimport cython
from cython.view cimport contig as foo, full as bar, follow
from cython cimport view from cython cimport view
biz = cython.view.contig
foz = cython.view.full
adict = {'view': cython.view}
alist = [adict]
cdef signed short[::1, ::1] both cdef signed short[::1, ::1] both
cdef signed short[::1, :, :, ::1] both2 cdef signed short[::1, :, :, ::1] both2
...@@ -17,14 +17,15 @@ cdef long long[01::1, 0x01:, '0' :, False:] fort_contig0 ...@@ -17,14 +17,15 @@ cdef long long[01::1, 0x01:, '0' :, False:] fort_contig0
cdef signed char[1::] bad_start cdef signed char[1::] bad_start
cdef unsigned long[:,:1] bad_stop cdef unsigned long[:,:1] bad_stop
cdef unsigned long[:,::1,:] neither_c_or_f cdef unsigned long[:,::1,:] neither_c_or_f
cdef signed char[::1, ::view.follow & view.direct] bad_f_contig
cdef signed char[::1, ::view.follow] bad_f_contig2
cdef signed char[::view.contig | view.direct] not_ampersand
cdef signed char[::view.ptr & view.direct] no_access_spec
cdef signed char[::1-1+1] expr_spec cdef signed char[::1-1+1] expr_spec
cdef signed char[::blargh] bad_name cdef signed char[::blargh] bad_name
cdef double[::alist[0]['view'].full] expr_attribute cdef double[::alist[0]['view'].full] expr_attribute
cdef double[::view.ptr & view.follow] no_single_follow
cdef object[::1, :] unconformable1 = object()
cdef object[:, ::1] unconformable2 = unconformable1
cdef int[::1, :] dtype_unconformable = object()
unconformable1 = dtype_unconformable
_ERRORS = u''' _ERRORS = u'''
11:25: Cannot specify an array that is both C and Fortran contiguous. 11:25: Cannot specify an array that is both C and Fortran contiguous.
...@@ -36,12 +37,9 @@ _ERRORS = u''' ...@@ -36,12 +37,9 @@ _ERRORS = u'''
17:18: there must be nothing or the value 0 (zero) in the start slot. 17:18: there must be nothing or the value 0 (zero) in the start slot.
18:22: Axis specification only allowed in the 'stop' slot. 18:22: Axis specification only allowed in the 'stop' slot.
19:23: The value 1 (one) may appear in the first or last axis specification only. 19:23: The value 1 (one) may appear in the first or last axis specification only.
20:36: Invalid axis specification for a C/Fortran contiguous array. 20:22: Invalid axis specification.
21:28: Invalid axis specification for a C/Fortran contiguous array. 21:25: Invalid axis specification.
22:31: Invalid operator, only an ampersand '&' is allowed. 22:22: no expressions allowed in axis spec, only names and literals.
23:28: Invalid axis specification. 25:51: Memoryview 'object[::contiguous, :]' not conformable to memoryview 'object[:, ::contiguous]'.
24:22: Invalid axis specification. 28:36: Different base types for memoryviews (int, Python object)
25:25: Invalid axis specification.
26:22: no expressions allowed in axis spec, only names (e.g. cython.view.contig).
27:12: Invalid use of the follow specifier.
''' '''
...@@ -1062,22 +1062,6 @@ def nested_packed_struct(object[NestedPackedStruct] buf): ...@@ -1062,22 +1062,6 @@ def nested_packed_struct(object[NestedPackedStruct] buf):
""" """
print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c print buf[0].a, buf[0].b, buf[0].sub.a, buf[0].sub.b, buf[0].c
cdef struct LongComplex:
long double real
long double imag
cdef class LongComplexMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
cdef LongComplex* s
s = <LongComplex*>buf;
s.real, s.imag = value
return 0
cdef get_itemsize(self): return sizeof(LongComplex)
cdef get_default_format(self): return b"Zg"
#cdef extern from "complex.h":
# pass
@testcase @testcase
def complex_dtype(object[long double complex] buf): def complex_dtype(object[long double complex] buf):
......
This diff is collapsed.
...@@ -311,3 +311,16 @@ cdef class NestedPackedStructMockBuffer(MockBuffer): ...@@ -311,3 +311,16 @@ cdef class NestedPackedStructMockBuffer(MockBuffer):
cdef get_itemsize(self): return sizeof(NestedPackedStruct) cdef get_itemsize(self): return sizeof(NestedPackedStruct)
cdef get_default_format(self): return b"ci^ci@i" cdef get_default_format(self): return b"ci^ci@i"
cdef struct LongComplex:
long double real
long double imag
cdef class LongComplexMockBuffer(MockBuffer):
cdef int write(self, char* buf, object value) except -1:
cdef LongComplex* s
s = <LongComplex*>buf;
s.real, s.imag = value
return 0
cdef get_itemsize(self): return sizeof(LongComplex)
cdef get_default_format(self): return b"Zg"
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