Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Xavier Thompson
cython
Commits
a0e188d4
Commit
a0e188d4
authored
Jul 31, 2011
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Memoryview slice item assignment, better errors, pass all tests
parent
df5626e4
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
248 additions
and
267 deletions
+248
-267
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+31
-13
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+37
-23
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+11
-7
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+34
-19
Cython/Utility/MemoryView.pyx
Cython/Utility/MemoryView.pyx
+5
-2
tests/errors/memview_declarations.pyx
tests/errors/memview_declarations.pyx
+16
-18
tests/run/bufaccess.pyx
tests/run/bufaccess.pyx
+0
-16
tests/run/memslice.pyx
tests/run/memslice.pyx
+101
-169
tests/run/mockbuffers.pxi
tests/run/mockbuffers.pxi
+13
-0
No files found.
Cython/Compiler/ExprNodes.py
View file @
a0e188d4
...
...
@@ -594,8 +594,14 @@ class ExprNode(Node):
"Cannot convert '%s' to memoryviewslice"
%
(
src_type
,))
elif
not
MemoryView
.
src_conforms_to_dst
(
src
.
type
,
dst_type
):
error
(
self
.
pos
,
"Memoryview '%s' not conformable to memoryview '%s'."
%
(
src
.
type
,
dst_type
))
if
src
.
type
.
dtype
.
same_as
(
dst_type
.
dtype
):
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
:
if
not
src
.
type
.
is_pyobject
:
...
...
@@ -2412,13 +2418,13 @@ class IndexNode(ExprNode):
self
.
is_temp
=
True
if
setting
and
self
.
base
.
type
.
is_memoryviewslice
:
self
.
type
.
writable_needed
=
True
self
.
base
.
type
.
writable_needed
=
True
elif
setting
:
if
not
self
.
base
.
entry
.
type
.
writable
:
error
(
self
.
pos
,
"Writing to readonly buffer"
)
else
:
self
.
writable_needed
=
True
if
self
.
type
.
is_buffer
:
if
self
.
base
.
type
.
is_buffer
:
self
.
base
.
entry
.
buffer_aux
.
writable_needed
=
True
elif
memoryviewslice_access
:
...
...
@@ -2570,7 +2576,7 @@ class IndexNode(ExprNode):
if
self
.
is_buffer_access
:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
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
:
# is_temp is True, so must pull out value and incref it.
code
.
putln
(
"%s = *%s;"
%
(
self
.
result
(),
self
.
buffer_ptr_code
))
...
...
@@ -2657,11 +2663,14 @@ class IndexNode(ExprNode):
# Used from generate_assignment_code and InPlaceAssignmentNode
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
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
:
# Must manage refcounts. Decref what is already there
# 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
()
code
.
putln
(
"%s = %s;"
%
(
ptr
,
ptrexpr
))
code
.
put_gotref
(
"*%s"
%
ptr
)
...
...
@@ -2735,12 +2744,14 @@ class IndexNode(ExprNode):
buffer_entry
=
MemoryView
.
MemoryViewSliceBufferEntry
(
entry
)
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
],
index_cnames
=
index_temps
,
directives
=
code
.
globalstate
.
directives
,
pos
=
self
.
pos
,
code
=
code
,
negative_indices
=
negative_indices
)
return
buffer_entry
,
Buffer
.
put_buffer_lookup_code
(
entry
=
buffer_entry
,
index_signeds
=
[
i
.
type
.
signed
for
i
in
self
.
indices
],
index_cnames
=
index_temps
,
directives
=
code
.
globalstate
.
directives
,
pos
=
self
.
pos
,
code
=
code
,
negative_indices
=
negative_indices
)
def
put_nonecheck
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
raise_noneindex_error_utility_code
)
...
...
@@ -7681,6 +7692,13 @@ class CoerceToMemViewSliceNode(CoercionNode):
self
.
type
.
from_py_function
,
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
):
# Wrap a node in a C type cast.
...
...
Cython/Compiler/MemoryView.py
View file @
a0e188d4
...
...
@@ -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."
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."
NOT_AMP_ERR
=
"Invalid operator, only an ampersand '&' is allowed."
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."
def
concat_flags
(
*
flags
):
...
...
@@ -24,9 +23,9 @@ def concat_flags(*flags):
format_flag
=
"PyBUF_FORMAT"
memview_c_contiguous
=
concat_flags
(
format_flag
,
"PyBUF_C_CONTIGUOUS"
)
memview_f_contiguous
=
concat_flags
(
format_flag
,
"PyBUF_F_CONTIGUOUS"
)
memview_any_contiguous
=
concat_flags
(
format_flag
,
"PyBUF_ANY_CONTIGUOUS"
)
memview_c_contiguous
=
"(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_f_contiguous
=
"(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_any_contiguous
=
"(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT | PyBUF_WRITABLE)"
memview_full_access
=
"PyBUF_FULL"
#memview_strided_access = "PyBUF_STRIDED"
memview_strided_access
=
"PyBUF_RECORDS"
...
...
@@ -72,8 +71,8 @@ def mangle_dtype_name(dtype):
import
Buffer
return
Buffer
.
mangle_dtype_name
(
dtype
)
def
axes_to_str
(
axes
):
return
""
.
join
([
access
[
0
].
upper
()
+
packing
[
0
]
for
(
access
,
packing
)
in
axes
])
#
def axes_to_str(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
,
incref_rhs
=
True
,
have_gil
=
False
):
...
...
@@ -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.suboffsets[%d] = %s.suboffsets[%d];"
%
(
lhs_cname
,
i
,
rhs_cname
,
i
))
def
get_buf_flag
(
specs
):
def
get_buf_flag
s
(
specs
):
is_c_contig
,
is_f_contig
=
is_cf_contig
(
specs
)
if
is_c_contig
:
...
...
@@ -196,50 +195,65 @@ class MemoryViewSliceBufferEntry(Buffer.BufferEntry):
suboffset
=
"%s.suboffsets[%d]"
%
(
self
.
cname
,
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
)
bufp
=
(
'__pyx_memviewslice_index_full(%s, %s, %s, %s)'
%
(
bufp
,
index
,
stride
,
suboffset
))
elif
access
==
'full'
and
packing
==
'contig'
:
elif
flag
==
"generic_contiguous"
:
# We can skip stride multiplication with the cast
code
.
globalstate
.
use_utility_code
(
memviewslice_index_helpers
)
bufp
=
'((char *) ((%s *) %s) + %s)'
%
(
type_decl
,
bufp
,
index
)
bufp
=
(
'__pyx_memviewslice_index_full_contig(%s, %s)'
%
(
bufp
,
suboffset
))
elif
access
==
'ptr'
and
packing
in
(
'strided'
,
'follow'
)
:
elif
flag
==
"indirect"
:
bufp
=
(
"(*((char **) %s + %s * %s) + %s)"
%
(
bufp
,
index
,
stride
,
suboffset
))
elif
access
==
'ptr'
and
packing
==
'contig'
:
elif
flag
==
"indirect_contiguous"
:
bufp
=
"(*((char **) %s) + %s)"
%
(
bufp
,
suboffset
)
elif
access
==
'direct'
and
packing
in
(
'strided'
,
'follow'
)
:
elif
flag
==
"strided"
:
bufp
=
"(%s + %s * %s)"
%
(
bufp
,
index
,
stride
)
else
:
assert
(
access
,
packing
)
==
(
'direct'
,
'contig'
),
(
access
,
packing
)
assert
flag
==
'contiguous'
,
flag
bufp
=
'((char *) (((%s *) %s) + %s))'
%
(
type_decl
,
bufp
,
index
)
bufp
=
'( /* dim=%d */ %s )'
%
(
dim
,
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
):
base
=
"__Pyx_BufferNew_%s_From_%s
_%s
"
base
=
"__Pyx_BufferNew_%s_From_%s"
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
:
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
):
dtype
=
from_mvs
.
dtype
assert
dtype
==
to_mvs
.
dtype
return
(
'__Pyx_BufferCopyContents_%s_%s_%s'
%
(
axes_to_str
(
from_mvs
.
axes
),
axes_to_str
(
to_mvs
.
axes
),
mangle_dtype_name
(
dtype
)))
assert
from_mvs
.
dtype
==
to_mvs
.
dtype
return
'__Pyx_BufferCopyContents_%s_to_%s'
%
(
from_mvs
.
specialization_suffix
(),
to_mvs
.
specialization_suffix
())
class
IsContigFuncUtilCode
(
object
):
...
...
Cython/Compiler/Nodes.py
View file @
a0e188d4
...
...
@@ -1428,16 +1428,20 @@ class FuncDefNode(StatNode, BlockNode):
self
.
generate_argument_parsing_code
(
env
,
code
)
# If an argument is assigned to in the body, we must
# incref it to properly keep track of refcounts.
is_cdef
=
isinstance
(
self
,
CFuncDefNode
)
for
entry
in
lenv
.
arg_entries
:
if
entry
.
type
.
is_pyobject
:
if
(
acquire_gil
or
entry
.
assignments
)
and
not
entry
.
in_closure
:
code
.
put_var_incref
(
entry
)
# Note: all memoryviewslices are already newly acquired references
# or increffed defaults!
#if entry.type.is_memoryviewslice:
# code.put_incref_memoryviewslice(entry.cname,
# have_gil=not lenv.nogil)
#code.put_incref("%s.memview" % entry.cname, cython_memoryview_ptr_type)
# Note: defaults are always increffed. For def functions, we
# we aquire arguments from object converstion, so we have
# new references. If we are a cdef function, we need to
# incref our arguments
if
is_cdef
and
entry
.
type
.
is_memoryviewslice
:
code
.
put_incref_memoryviewslice
(
entry
.
cname
,
have_gil
=
not
lenv
.
nogil
)
# ----- Initialise local buffer auxiliary variables
for
entry
in
lenv
.
var_entries
+
lenv
.
arg_entries
:
if
entry
.
type
.
is_buffer
and
entry
.
buffer_aux
.
buflocal_nd_var
.
used
:
...
...
@@ -1567,7 +1571,7 @@ class FuncDefNode(StatNode, BlockNode):
if
entry
.
type
.
is_pyobject
:
if
(
acquire_gil
or
entry
.
assignments
)
and
not
entry
.
in_closure
:
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_decref("%s.memview" % entry.cname, cython_memoryview_ptr_type)
if
self
.
needs_closure
:
...
...
Cython/Compiler/PyrexTypes.py
View file @
a0e188d4
...
...
@@ -338,9 +338,7 @@ class MemoryViewSliceType(PyrexType):
to_py_function
=
None
exception_value
=
None
exception_check
=
None
utility_counter
=
0
exception_check
=
True
def
__init__
(
self
,
base_dtype
,
axes
):
'''
...
...
@@ -381,7 +379,7 @@ class MemoryViewSliceType(PyrexType):
self
.
dtype
=
base_dtype
self
.
axes
=
axes
self
.
ndim
=
len
(
axes
)
self
.
flags
=
MemoryView
.
get_buf_flag
(
self
.
axes
)
self
.
flags
=
MemoryView
.
get_buf_flag
s
(
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
)
...
...
@@ -416,7 +414,6 @@ class MemoryViewSliceType(PyrexType):
if
self
.
scope
is
None
:
import
Symtab
,
MemoryView
,
Options
from
MemoryView
import
axes_to_str
self
.
scope
=
scope
=
Symtab
.
CClassScope
(
'mvs_class_'
+
self
.
specialization_suffix
(),
...
...
@@ -504,12 +501,12 @@ class MemoryViewSliceType(PyrexType):
def
specialization_suffix
(
self
):
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
):
code
.
putln
(
"%s.data = 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 global_init_code(self, entry, code):
# code.putln("%s.data = NULL;" % entry.cname)
# code.putln("%s.memview = NULL;" % entry.cname)
def
check_for_null_code
(
self
,
cname
):
return
cname
+
'.memview'
...
...
@@ -535,15 +532,14 @@ class MemoryViewSliceType(PyrexType):
else
:
c_or_f_flag
=
"0"
# specializing through UtilityCode.specialize is not so useful as
# specialize on too many things to include in the function name
funcname
=
"__Pyx_PyObject_to_MemoryviewSlice_%d"
%
self
.
utility_counter
suffix
=
self
.
specialization_suffix
()
funcname
=
"__Pyx_PyObject_to_MemoryviewSlice_"
+
suffix
context
=
dict
(
MemoryView
.
context
,
buf_flag
=
self
.
flags
,
ndim
=
self
.
ndim
,
axes_specs
=
', '
.
join
(
self
.
axes_
specs_
to_code
()),
axes_specs
=
', '
.
join
(
self
.
axes_to_code
()),
dtype_typedecl
=
self
.
dtype
.
declaration_code
(
""
),
struct_nesting_depth
=
self
.
dtype
.
struct_nesting_depth
(),
c_or_f_flag
=
c_or_f_flag
,
...
...
@@ -551,8 +547,6 @@ class MemoryViewSliceType(PyrexType):
)
self
.
from_py_function
=
funcname
MemoryViewSliceType
.
utility_counter
+=
1
return
True
def
create_to_py_utility_code
(
self
,
env
):
...
...
@@ -560,15 +554,15 @@ class MemoryViewSliceType(PyrexType):
def
get_to_py_function
(
self
,
obj
):
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"
import
MemoryView
d
=
MemoryView
.
_spec_to_const
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"
import
MemoryView
d
=
MemoryView
.
_spec_to_abbrev
...
...
@@ -577,6 +571,24 @@ class MemoryViewSliceType(PyrexType):
def
error_condition
(
self
,
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
):
#
...
...
@@ -632,6 +644,9 @@ class PyObjectType(PyrexType):
def
__repr__
(
self
):
return
"<PyObjectType>"
def
__eq__
(
self
,
other
):
return
isinstance
(
other
,
PyObjectType
)
and
self
.
name
==
other
.
name
def
can_coerce_to_pyobject
(
self
,
env
):
return
True
...
...
Cython/Utility/MemoryView.pyx
View file @
a0e188d4
...
...
@@ -258,6 +258,9 @@ cdef class memoryview(object):
bytesitem
=
itemp
[:
self
.
view
.
itemsize
]
return
struct
.
unpack
(
fmt
,
bytesitem
)
def
__repr__
(
self
):
return
"<MemoryView of %s at 0x%x>"
%
(
self
.
obj
.
__class__
.
__name__
,
id
(
self
))
def
__str__
(
self
):
return
"<MemoryView of %r at 0x%x>"
%
(
self
.
obj
,
id
(
self
))
...
...
@@ -283,8 +286,8 @@ cdef memoryview_cwrapper(object o, int flags):
return
memoryview
(
o
,
flags
)
@
cname
(
'__pyx_memoryview_fromslice'
)
cdef
memoryview
memoryview_from_memview_cwrapper
(
{{
memviewslice_name
}}
*
memviewslice
,
object
orig_obj
,
int
flags
,
int
new_ndim
):
cdef
memoryview
_from_memview_cwrapper
({{
memviewslice_name
}}
*
memviewslice
,
object
orig_obj
,
int
flags
,
int
new_ndim
):
cdef
_memoryviewslice
result
=
_memoryviewslice
(
orig_obj
,
flags
)
result
.
from_slice
=
memviewslice
[
0
]
...
...
tests/errors/memview_declarations.pyx
View file @
a0e188d4
# mode: error
cimport
cython
from
cython.view
cimport
contig
as
foo
,
full
as
bar
,
follow
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
]
both2
...
...
@@ -17,14 +17,15 @@ cdef long long[01::1, 0x01:, '0' :, False:] fort_contig0
cdef
signed
char
[
1
::]
bad_start
cdef
unsigned
long
[:,:
1
]
bad_stop
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
[::
blargh
]
bad_name
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'''
11:25: Cannot specify an array that is both C and Fortran contiguous.
...
...
@@ -36,12 +37,9 @@ _ERRORS = u'''
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.
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.
21:28: Invalid axis specification for a C/Fortran contiguous array.
22:31: Invalid operator, only an ampersand '&' is allowed.
23:28: Invalid axis specification.
24:22: Invalid axis specification.
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.
20:22: Invalid axis specification.
21:25: Invalid axis specification.
22:22: no expressions allowed in axis spec, only names and literals.
25:51: Memoryview 'object[::contiguous, :]' not conformable to memoryview 'object[:, ::contiguous]'.
28:36: Different base types for memoryviews (int, Python object)
'''
tests/run/bufaccess.pyx
View file @
a0e188d4
...
...
@@ -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
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
def
complex_dtype
(
object
[
long
double
complex
]
buf
):
...
...
tests/run/memslice.pyx
View file @
a0e188d4
# Tests the buffer access syntax functionality by constructing
# mock buffer objects.
#
# Note that the buffers are mock objects created for testing
# the buffer access behaviour -- for instance there is no flag
# checking in the buffer objects (why test our test case?), rather
# what we want to test is what is passed into the flags argument.
#
# Note: see also bufaccess.pyx
from
__future__
import
unicode_literals
...
...
@@ -417,25 +410,6 @@ def list_comprehension(int[:] buf, len):
cdef
int
i
print
u"|"
.
join
([
unicode
(
buf
[
i
])
for
i
in
range
(
len
)])
#
# The negative_indices buffer option
#
@
testcase
def
no_negative_indices
(
object
[
int
,
negative_indices
=
False
]
buf
,
int
idx
):
"""
The most interesting thing here is to inspect the C source and
make sure optimal code is produced.
>>> A = IntMockBuffer(None, range(6))
>>> no_negative_indices(A, 3)
3
>>> no_negative_indices(A, -1)
Traceback (most recent call last):
...
IndexError: Out of bounds on buffer access (axis 0)
"""
return
buf
[
idx
]
@
testcase
@
cython
.
wraparound
(
False
)
def
wraparound_directive
(
int
[:]
buf
,
int
pos_idx
,
int
neg_idx
):
...
...
@@ -459,19 +433,6 @@ def wraparound_directive(int[:] buf, int pos_idx, int neg_idx):
#
# Test which flags are passed.
#
# @testcase
# def readonly(obj):
# """
# >>> R = UnsignedShortMockBuffer("R", range(27), shape=(3, 3, 3))
# >>> readonly(R)
# acquired R
# 25
# released R
# >>> [str(x) for x in R.recieved_flags] # Works in both py2 and py3
# ['FORMAT', 'INDIRECT', 'ND', 'STRIDES']
# """
# cdef unsigned short int[:, :, :] buf = obj
# print buf[2, 2, 1]
@
testcase
def
writable
(
obj
):
...
...
@@ -510,7 +471,7 @@ def c_contig(int[::1] buf):
>>> c_contig(A)
2
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'
, 'WRITABLE'
]
"""
return
buf
[
2
]
...
...
@@ -523,7 +484,7 @@ def c_contig_2d(int[:, ::1] buf):
>>> c_contig_2d(A)
7
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'
, 'WRITABLE'
]
"""
return
buf
[
1
,
3
]
...
...
@@ -534,12 +495,12 @@ def f_contig(int[::1, :] buf):
>>> f_contig(A)
2
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS'
, 'WRITABLE'
]
"""
return
buf
[
0
,
1
]
@
testcase
def
f_contig_2d
(
object
[
int
,
ndim
=
2
,
mode
=
'fortran'
]
buf
):
def
f_contig_2d
(
int
[::
1
,
:
]
buf
):
"""
Must set up strides manually to ensure Fortran ordering.
...
...
@@ -547,7 +508,7 @@ def f_contig_2d(object[int, ndim=2, mode='fortran'] buf):
>>> f_contig_2d(A)
7
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS'
, 'WRITABLE'
]
"""
return
buf
[
3
,
1
]
...
...
@@ -600,18 +561,6 @@ def unsafe_get(int[:] buf, int idx):
"""
return
buf
[
idx
]
# @testcase
# @cython.boundscheck(False)
# def unsafe_get_nonegative(object[int, negative_indices=False] buf, int idx):
# """
# Also inspect the C source to see that it is optimal...
#
# >>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
# >>> unsafe_get_nonegative(A, -2)
# 3
# """
# return buf[idx]
@
testcase
def
mixed_get
(
int
[:]
buf
,
int
unsafe_idx
,
int
safe_idx
):
"""
...
...
@@ -629,25 +578,6 @@ def mixed_get(int[:] buf, int unsafe_idx, int safe_idx):
two
=
buf
[
safe_idx
]
return
(
one
,
two
)
#
# Coercions
#
## @testcase
## def coercions(object[unsigned char] uc):
## """
## TODO
## """
## print type(uc[0])
## uc[0] = -1
## print uc[0]
## uc[0] = <int>3.14
## print uc[0]
## cdef char* ch = b"asfd"
## cdef object[object] objbuf
## objbuf[3] = ch
#
# Testing that accessing data using various types of buffer access
# all works.
...
...
@@ -759,7 +689,7 @@ def printbuf_td_cy_int(td_cy_int[:] buf, shape):
print
'END'
@
testcase
def
printbuf_td_h_short
(
object
[
td_h_short
]
buf
,
shape
):
def
printbuf_td_h_short
(
td_h_short
[:
]
buf
,
shape
):
"""
>>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,))
0 1 2 END
...
...
@@ -774,7 +704,7 @@ def printbuf_td_h_short(object[td_h_short] buf, shape):
print
'END'
@
testcase
def
printbuf_td_h_cy_short
(
object
[
td_h_cy_short
]
buf
,
shape
):
def
printbuf_td_h_cy_short
(
td_h_cy_short
[:
]
buf
,
shape
):
"""
>>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3)), (3,))
0 1 2 END
...
...
@@ -789,7 +719,7 @@ def printbuf_td_h_cy_short(object[td_h_cy_short] buf, shape):
print
'END'
@
testcase
def
printbuf_td_h_ushort
(
object
[
td_h_ushort
]
buf
,
shape
):
def
printbuf_td_h_ushort
(
td_h_ushort
[:
]
buf
,
shape
):
"""
>>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3)), (3,))
0 1 2 END
...
...
@@ -804,7 +734,7 @@ def printbuf_td_h_ushort(object[td_h_ushort] buf, shape):
print
'END'
@
testcase
def
printbuf_td_h_double
(
object
[
td_h_double
]
buf
,
shape
):
def
printbuf_td_h_double
(
td_h_double
[:
]
buf
,
shape
):
"""
>>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125]), (3,))
0.25 1.0 3.125 END
...
...
@@ -831,7 +761,7 @@ def get_refcount(x):
return
(
<
PyObject
*>
x
).
ob_refcnt
@
testcase
def
printbuf_object
(
object
[
object
]
buf
,
shape
):
def
printbuf_object
(
object
[
:
]
buf
,
shape
):
"""
Only play with unique objects, interned numbers etc. will have
unpredictable refcounts.
...
...
@@ -854,7 +784,7 @@ def printbuf_object(object[object] buf, shape):
print
repr
(
buf
[
i
]),
(
<
PyObject
*>
buf
[
i
]).
ob_refcnt
@
testcase
def
assign_to_object
(
object
[
object
]
buf
,
int
idx
,
obj
):
def
assign_to_object
(
object
[
:
]
buf
,
int
idx
,
obj
):
"""
See comments on printbuf_object above.
...
...
@@ -873,7 +803,7 @@ def assign_to_object(object[object] buf, int idx, obj):
buf
[
idx
]
=
obj
@
testcase
def
assign_temporary_to_object
(
object
[
object
]
buf
):
def
assign_temporary_to_object
(
object
[
:
]
buf
):
"""
See comments on printbuf_object above.
...
...
@@ -899,69 +829,11 @@ def assign_temporary_to_object(object[object] buf):
"""
buf
[
1
]
=
{
3
-
2
:
2
+
(
2
*
4
)
-
2
}
#
# cast option
#
@
testcase
def
buffer_cast
(
object
[
unsigned
int
,
cast
=
True
]
buf
,
int
idx
):
"""
Round-trip a signed int through unsigned int buffer access.
>>> A = IntMockBuffer(None, [-100])
>>> buffer_cast(A, 0)
-100
"""
cdef
unsigned
int
data
=
buf
[
idx
]
return
<
int
>
data
@
testcase
def
buffer_cast_fails
(
object
[
char
,
cast
=
True
]
buf
):
"""
Cannot cast between datatype of different sizes.
>>> buffer_cast_fails(IntMockBuffer(None, [0]))
Traceback (most recent call last):
...
ValueError: Item size of buffer (4 bytes) does not match size of 'char' (1 byte)
"""
return
buf
[
0
]
#
# Typed buffers
#
@
testcase
def
typedbuffer1
(
obj
):
"""
>>> typedbuffer1(IntMockBuffer("A", range(10)))
acquired A
released A
>>> typedbuffer1(None)
>>> typedbuffer1(4)
Traceback (most recent call last):
...
TypeError: Cannot convert int to memslice.IntMockBuffer
"""
cdef
IntMockBuffer
[
int
,
ndim
=
1
]
buf
=
obj
@
testcase
def
typedbuffer2
(
IntMockBuffer
[
int
,
ndim
=
1
]
obj
):
"""
>>> typedbuffer2(IntMockBuffer("A", range(10)))
acquired A
released A
>>> typedbuffer2(None)
>>> typedbuffer2(4)
Traceback (most recent call last):
...
TypeError: Argument 'obj' has incorrect type (expected memslice.IntMockBuffer, got int)
"""
pass
#
# Test __cythonbufferdefaults__
#
@
testcase
def
bufdefaults1
(
IntStridedMockBuffer
[
int
,
ndim
=
1
]
buf
):
def
bufdefaults1
(
int
[:
]
buf
):
"""
For IntStridedMockBuffer, mode should be
"strided" by defaults which should show
...
...
@@ -972,13 +844,13 @@ def bufdefaults1(IntStridedMockBuffer[int, ndim=1] buf):
acquired A
released A
>>> [str(x) for x in A.recieved_flags]
['FORMAT', 'ND', 'STRIDES']
['FORMAT', 'ND', 'STRIDES'
, 'WRITABLE'
]
"""
pass
@
testcase
def
basic_struct
(
object
[
MyStruct
]
buf
):
def
basic_struct
(
MyStruct
[:
]
buf
):
"""
See also buffmt.pyx
...
...
@@ -990,7 +862,7 @@ def basic_struct(object[MyStruct] buf):
print
buf
[
0
].
a
,
buf
[
0
].
b
,
buf
[
0
].
c
,
buf
[
0
].
d
,
buf
[
0
].
e
@
testcase
def
nested_struct
(
object
[
NestedStruct
]
buf
):
def
nested_struct
(
NestedStruct
[:
]
buf
):
"""
See also buffmt.pyx
...
...
@@ -1002,7 +874,7 @@ def nested_struct(object[NestedStruct] buf):
print
buf
[
0
].
x
.
a
,
buf
[
0
].
x
.
b
,
buf
[
0
].
y
.
a
,
buf
[
0
].
y
.
b
,
buf
[
0
].
z
@
testcase
def
packed_struct
(
object
[
PackedStruct
]
buf
):
def
packed_struct
(
PackedStruct
[:
]
buf
):
"""
See also buffmt.pyx
...
...
@@ -1017,7 +889,7 @@ def packed_struct(object[PackedStruct] buf):
print
buf
[
0
].
a
,
buf
[
0
].
b
@
testcase
def
nested_packed_struct
(
object
[
NestedPackedStruct
]
buf
):
def
nested_packed_struct
(
NestedPackedStruct
[:
]
buf
):
"""
See also buffmt.pyx
...
...
@@ -1030,25 +902,9 @@ 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
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
def
complex_dtype
(
object
[
long
double
complex
]
buf
):
def
complex_dtype
(
long
double
complex
[:
]
buf
):
"""
>>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)]))
-1j
...
...
@@ -1056,7 +912,7 @@ def complex_dtype(object[long double complex] buf):
print
buf
[
0
]
@
testcase
def
complex_inplace
(
object
[
long
double
complex
]
buf
):
def
complex_inplace
(
long
double
complex
[:
]
buf
):
"""
>>> complex_inplace(LongComplexMockBuffer(None, [(0, -1)]))
(1+1j)
...
...
@@ -1065,7 +921,7 @@ def complex_inplace(object[long double complex] buf):
print
buf
[
0
]
@
testcase
def
complex_struct_dtype
(
object
[
LongComplex
]
buf
):
def
complex_struct_dtype
(
LongComplex
[:
]
buf
):
"""
Note that the format string is "Zg" rather than "2g", yet a struct
is accessed.
...
...
@@ -1075,7 +931,7 @@ def complex_struct_dtype(object[LongComplex] buf):
print
buf
[
0
].
real
,
buf
[
0
].
imag
@
testcase
def
complex_struct_inplace
(
object
[
LongComplex
]
buf
):
def
complex_struct_inplace
(
LongComplex
[:
]
buf
):
"""
>>> complex_struct_inplace(LongComplexMockBuffer(None, [(0, -1)]))
1.0 1.0
...
...
@@ -1092,9 +948,85 @@ def complex_struct_inplace(object[LongComplex] buf):
def
buffer_nogil
():
"""
>>> buffer_nogil()
10
(10, 10)
"""
cdef
int
[:]
buf
=
IntMockBuffer
(
None
,
[
1
,
2
,
3
])
cdef
int
[:]
buf2
=
IntMockBuffer
(
None
,
[
4
,
5
,
6
])
with
nogil
:
buf
[
1
]
=
10
return
buf
[
1
]
buf2
=
buf
return
buf
[
1
],
buf2
[
1
]
#
### Test cdef functions
#
cdef
cdef
_function
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
ObjectMockBuffer
(
None
,
[[
"spam"
],[
"ham"
],[
"eggs"
]])):
print
'cdef called'
print
buf1
[
6
],
buf2
[
1
,
0
]
buf2
[
1
,
0
]
=
"eggs"
def
test_cdef_function
(
o1
,
o2
=
None
):
"""
>>> A = IntMockBuffer("A", range(10))
>>> test_cdef_function(A)
acquired A
cdef called
6 ham
released A
acquired A
cdef called
6 eggs
released A
>>> B = ObjectMockBuffer("B", range(25), shape=(5, 5))
>>> test_cdef_function(A, B)
acquired A
acquired B
cdef called
6 eggs
released A
released B
acquired A
acquired B
cdef called
6 eggs
released A
released B
"""
cdef
_function
(
o1
)
cdef
_function
(
o1
)
if
o2
:
cdef
_function
(
o1
,
o2
)
cdef
int
[:]
global_A
=
IntMockBuffer
(
"A"
,
range
(
10
))
cdef
object
[::
view
.
indirect
,
:]
global_B
=
ObjectMockBuffer
(
None
,
[[
"spam"
],[
"ham"
],[
"eggs"
]])
cdef
cdef
_function2
(
int
[:]
buf1
,
object
[::
view
.
indirect
,
:]
buf2
=
global_B
):
print
'cdef2 called'
print
buf1
[
6
],
buf2
[
1
,
0
]
buf2
[
1
,
0
]
=
"eggs"
def
test_cdef_function2
():
"""
>>> test_cdef_function2()
cdef2 called
6 ham
eggs
cdef2 called
6 eggs
"""
cdef
int
[:]
A
=
global_A
cdef
object
[::
view
.
indirect
,
:]
B
=
global_B
cdef
_function2
(
A
,
B
)
del
A
del
B
print
global_B
[
1
,
0
]
cdef
_function2
(
global_A
,
global_B
)
tests/run/mockbuffers.pxi
View file @
a0e188d4
...
...
@@ -311,3 +311,16 @@ cdef class NestedPackedStructMockBuffer(MockBuffer):
cdef
get_itemsize
(
self
):
return
sizeof
(
NestedPackedStruct
)
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"
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment