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
Gwenaël Samain
cython
Commits
9ca6532b
Commit
9ca6532b
authored
Feb 16, 2018
by
scoder
Committed by
GitHub
Feb 16, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1869 from scoder/readonly_buffers
implement read-only memoryviews
parents
83ffbe08
e4838d84
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
371 additions
and
196 deletions
+371
-196
CHANGES.rst
CHANGES.rst
+7
-4
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+23
-15
Cython/Compiler/FusedNode.py
Cython/Compiler/FusedNode.py
+2
-2
Cython/Compiler/MemoryView.py
Cython/Compiler/MemoryView.py
+6
-6
Cython/Compiler/Nodes.py
Cython/Compiler/Nodes.py
+10
-19
Cython/Compiler/Parsing.py
Cython/Compiler/Parsing.py
+6
-3
Cython/Compiler/PyrexTypes.py
Cython/Compiler/PyrexTypes.py
+57
-37
Cython/Utility/MemoryView.pyx
Cython/Utility/MemoryView.pyx
+12
-2
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+3
-3
docs/src/userguide/memoryviews.rst
docs/src/userguide/memoryviews.rst
+27
-0
tests/buffers/bufaccess.pyx
tests/buffers/bufaccess.pyx
+8
-8
tests/buffers/mockbuffers.pxi
tests/buffers/mockbuffers.pxi
+11
-6
tests/errors/e_arrayassign.pyx
tests/errors/e_arrayassign.pyx
+3
-2
tests/memoryview/memoryview.pyx
tests/memoryview/memoryview.pyx
+1
-1
tests/memoryview/memslice.pyx
tests/memoryview/memslice.pyx
+105
-88
tests/memoryview/numpy_memoryview_readonly.pyx
tests/memoryview/numpy_memoryview_readonly.pyx
+90
-0
No files found.
CHANGES.rst
View file @
9ca6532b
...
@@ -8,10 +8,6 @@ Cython Changelog
...
@@ -8,10 +8,6 @@ Cython Changelog
Features added
Features added
--------------
--------------
* When compiling with gcc, the module init function is now tuned for small
code size instead of whatever compile flags were provided externally.
(Github issue #2102)
* Cdef classes can now multiply inherit from ordinary Python classes.
* Cdef classes can now multiply inherit from ordinary Python classes.
(The primary base must still be a c class, possibly ``object``, and
(The primary base must still be a c class, possibly ``object``, and
the other bases must *not* be cdef classes.)
the other bases must *not* be cdef classes.)
...
@@ -19,6 +15,13 @@ Features added
...
@@ -19,6 +15,13 @@ Features added
* Type inference is now supported for Pythran compiled NumPy expressions.
* Type inference is now supported for Pythran compiled NumPy expressions.
Patch by Nils Braun. (Github issue #1954)
Patch by Nils Braun. (Github issue #1954)
* The ``const`` modifier can be applied to memoryview declarations to allow
read-only buffers as input. (Github issues #1605, #1869)
* When compiling with gcc, the module init function is now tuned for small
code size instead of whatever compile flags were provided externally.
(Github issue #2102)
* C file includes are moved behind the module declarations if possible, to allow
* C file includes are moved behind the module declarations if possible, to allow
them to depend on module declarations themselves.
them to depend on module declarations themselves.
Patch by Jeroen Demeyer. (Github issue #1896)
Patch by Jeroen Demeyer. (Github issue #1896)
...
...
Cython/Compiler/ExprNodes.py
View file @
9ca6532b
...
@@ -870,7 +870,10 @@ class ExprNode(Node):
...
@@ -870,7 +870,10 @@ class ExprNode(Node):
elif
not
src_type
.
is_error
:
elif
not
src_type
.
is_error
:
error
(
self
.
pos
,
error
(
self
.
pos
,
"Cannot convert '%s' to memoryviewslice"
%
(
src_type
,))
"Cannot convert '%s' to memoryviewslice"
%
(
src_type
,))
elif
not
src
.
type
.
conforms_to
(
dst_type
,
broadcast
=
self
.
is_memview_broadcast
,
else
:
if
src
.
type
.
writable_needed
:
dst_type
.
writable_needed
=
True
if
not
src
.
type
.
conforms_to
(
dst_type
,
broadcast
=
self
.
is_memview_broadcast
,
copying
=
self
.
is_memview_copy_assignment
):
copying
=
self
.
is_memview_copy_assignment
):
if
src
.
type
.
dtype
.
same_as
(
dst_type
.
dtype
):
if
src
.
type
.
dtype
.
same_as
(
dst_type
.
dtype
):
msg
=
"Memoryview '%s' not conformable to memoryview '%s'."
msg
=
"Memoryview '%s' not conformable to memoryview '%s'."
...
@@ -4298,6 +4301,11 @@ class MemoryViewIndexNode(BufferIndexNode):
...
@@ -4298,6 +4301,11 @@ class MemoryViewIndexNode(BufferIndexNode):
indices
=
self
.
indices
indices
=
self
.
indices
have_slices
,
indices
,
newaxes
=
MemoryView
.
unellipsify
(
indices
,
self
.
base
.
type
.
ndim
)
have_slices
,
indices
,
newaxes
=
MemoryView
.
unellipsify
(
indices
,
self
.
base
.
type
.
ndim
)
if
not
getting
:
self
.
writable_needed
=
True
if
self
.
base
.
is_name
or
self
.
base
.
is_attribute
:
self
.
base
.
entry
.
type
.
writable_needed
=
True
self
.
memslice_index
=
(
not
newaxes
and
len
(
indices
)
==
self
.
base
.
type
.
ndim
)
self
.
memslice_index
=
(
not
newaxes
and
len
(
indices
)
==
self
.
base
.
type
.
ndim
)
axes
=
[]
axes
=
[]
...
@@ -12772,12 +12780,12 @@ class CoerceToMemViewSliceNode(CoercionNode):
...
@@ -12772,12 +12780,12 @@ class CoerceToMemViewSliceNode(CoercionNode):
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
self
.
type
.
create_from_py_utility_code
(
self
.
env
)
self
.
type
.
create_from_py_utility_code
(
self
.
env
)
code
.
putln
(
"%s = %s(%s);"
%
(
self
.
result
(),
code
.
putln
(
self
.
type
.
from_py_call_code
(
self
.
type
.
from_py_function
,
self
.
arg
.
py_result
()
,
self
.
arg
.
py_result
()))
self
.
result
(),
self
.
pos
,
error_cond
=
self
.
type
.
error_condition
(
self
.
result
())
code
code
.
putln
(
code
.
error_goto_if
(
error_cond
,
self
.
pos
))
))
class
CastNode
(
CoercionNode
):
class
CastNode
(
CoercionNode
):
...
...
Cython/Compiler/FusedNode.py
View file @
9ca6532b
...
@@ -390,7 +390,7 @@ class FusedCFuncDefNode(StatListNode):
...
@@ -390,7 +390,7 @@ class FusedCFuncDefNode(StatListNode):
coerce_from_py_func
=
memslice_type
.
from_py_function
,
coerce_from_py_func
=
memslice_type
.
from_py_function
,
dtype
=
dtype
)
dtype
=
dtype
)
decl_code
.
putln
(
decl_code
.
putln
(
"{{memviewslice_cname}} {{coerce_from_py_func}}(object)"
)
"{{memviewslice_cname}} {{coerce_from_py_func}}(object
, int
)"
)
pyx_code
.
context
.
update
(
pyx_code
.
context
.
update
(
specialized_type_name
=
specialized_type
.
specialization_string
,
specialized_type_name
=
specialized_type
.
specialization_string
,
...
@@ -400,7 +400,7 @@ class FusedCFuncDefNode(StatListNode):
...
@@ -400,7 +400,7 @@ class FusedCFuncDefNode(StatListNode):
u"""
u"""
# try {{dtype}}
# try {{dtype}}
if itemsize == -1 or itemsize == {{sizeof_dtype}}:
if itemsize == -1 or itemsize == {{sizeof_dtype}}:
memslice = {{coerce_from_py_func}}(arg)
memslice = {{coerce_from_py_func}}(arg
, 0
)
if memslice.memview:
if memslice.memview:
__PYX_XDEC_MEMVIEW(&memslice, 1)
__PYX_XDEC_MEMVIEW(&memslice, 1)
# print 'found a match for the buffer through format parsing'
# print 'found a match for the buffer through format parsing'
...
...
Cython/Compiler/MemoryView.py
View file @
9ca6532b
...
@@ -28,12 +28,12 @@ def concat_flags(*flags):
...
@@ -28,12 +28,12 @@ def concat_flags(*flags):
format_flag
=
"PyBUF_FORMAT"
format_flag
=
"PyBUF_FORMAT"
memview_c_contiguous
=
"(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT
| PyBUF_WRITABLE
)"
memview_c_contiguous
=
"(PyBUF_C_CONTIGUOUS | PyBUF_FORMAT)"
memview_f_contiguous
=
"(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT
| PyBUF_WRITABLE
)"
memview_f_contiguous
=
"(PyBUF_F_CONTIGUOUS | PyBUF_FORMAT)"
memview_any_contiguous
=
"(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT
| PyBUF_WRITABLE
)"
memview_any_contiguous
=
"(PyBUF_ANY_CONTIGUOUS | PyBUF_FORMAT)"
memview_full_access
=
"PyBUF_FULL"
memview_full_access
=
"PyBUF_FULL
_RO
"
#memview_strided_access = "PyBUF_STRIDED"
#memview_strided_access = "PyBUF_STRIDED
_RO
"
memview_strided_access
=
"PyBUF_RECORDS"
memview_strided_access
=
"PyBUF_RECORDS
_RO
"
MEMVIEW_DIRECT
=
'__Pyx_MEMVIEW_DIRECT'
MEMVIEW_DIRECT
=
'__Pyx_MEMVIEW_DIRECT'
MEMVIEW_PTR
=
'__Pyx_MEMVIEW_PTR'
MEMVIEW_PTR
=
'__Pyx_MEMVIEW_PTR'
...
...
Cython/Compiler/Nodes.py
View file @
9ca6532b
...
@@ -3753,18 +3753,12 @@ class DefNodeWrapper(FuncDefNode):
...
@@ -3753,18 +3753,12 @@ class DefNodeWrapper(FuncDefNode):
entry
=
arg
.
entry
entry
=
arg
.
entry
code
.
putln
(
"%s = %s;"
%
(
entry
.
cname
,
item
))
code
.
putln
(
"%s = %s;"
%
(
entry
.
cname
,
item
))
else
:
else
:
func
=
arg
.
type
.
from_py_function
if
arg
.
type
.
from_py_function
:
if
func
:
if
arg
.
default
:
if
arg
.
default
:
# C-typed default arguments must be handled here
# C-typed default arguments must be handled here
code
.
putln
(
'if (%s) {'
%
item
)
code
.
putln
(
'if (%s) {'
%
item
)
rhs
=
"%s(%s)"
%
(
func
,
item
)
code
.
putln
(
arg
.
type
.
from_py_call_code
(
if
arg
.
type
.
is_enum
:
item
,
arg
.
entry
.
cname
,
arg
.
pos
,
code
))
rhs
=
arg
.
type
.
cast_code
(
rhs
)
code
.
putln
(
"%s = %s; %s"
%
(
arg
.
entry
.
cname
,
rhs
,
code
.
error_goto_if
(
arg
.
type
.
error_condition
(
arg
.
entry
.
cname
),
arg
.
pos
)))
if
arg
.
default
:
if
arg
.
default
:
code
.
putln
(
'} else {'
)
code
.
putln
(
'} else {'
)
code
.
putln
(
"%s = %s;"
%
(
code
.
putln
(
"%s = %s;"
%
(
...
@@ -4005,17 +3999,14 @@ class DefNodeWrapper(FuncDefNode):
...
@@ -4005,17 +3999,14 @@ class DefNodeWrapper(FuncDefNode):
def
generate_arg_conversion_from_pyobject
(
self
,
arg
,
code
):
def
generate_arg_conversion_from_pyobject
(
self
,
arg
,
code
):
new_type
=
arg
.
type
new_type
=
arg
.
type
func
=
new_type
.
from_py_function
# copied from CoerceFromPyTypeNode
# copied from CoerceFromPyTypeNode
if
func
:
if
new_type
.
from_py_function
:
lhs
=
arg
.
entry
.
cname
code
.
putln
(
new_type
.
from_py_call_code
(
rhs
=
"%s(%s)"
%
(
func
,
arg
.
hdr_cname
)
arg
.
hdr_cname
,
if
new_type
.
is_enum
:
arg
.
entry
.
cname
,
rhs
=
PyrexTypes
.
typecast
(
new_type
,
PyrexTypes
.
c_long_type
,
rhs
)
arg
.
pos
,
code
.
putln
(
"%s = %s; %s"
%
(
code
,
lhs
,
))
rhs
,
code
.
error_goto_if
(
new_type
.
error_condition
(
arg
.
entry
.
cname
),
arg
.
pos
)))
else
:
else
:
error
(
arg
.
pos
,
"Cannot convert Python object argument to type '%s'"
%
new_type
)
error
(
arg
.
pos
,
"Cannot convert Python object argument to type '%s'"
%
new_type
)
...
...
Cython/Compiler/Parsing.py
View file @
9ca6532b
...
@@ -2481,9 +2481,12 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
...
@@ -2481,9 +2481,12 @@ def p_c_simple_base_type(s, self_flag, nonempty, templates = None):
error
(
pos
,
"Expected an identifier, found '%s'"
%
s
.
sy
)
error
(
pos
,
"Expected an identifier, found '%s'"
%
s
.
sy
)
if
s
.
systring
==
'const'
:
if
s
.
systring
==
'const'
:
s
.
next
()
s
.
next
()
base_type
=
p_c_base_type
(
s
,
base_type
=
p_c_base_type
(
s
,
self_flag
=
self_flag
,
nonempty
=
nonempty
,
templates
=
templates
)
self_flag
=
self_flag
,
nonempty
=
nonempty
,
templates
=
templates
)
if
isinstance
(
base_type
,
Nodes
.
MemoryViewSliceTypeNode
):
return
Nodes
.
CConstTypeNode
(
pos
,
base_type
=
base_type
)
# reverse order to avoid having to write "(const int)[:]"
base_type
.
base_type_node
=
Nodes
.
CConstTypeNode
(
pos
,
base_type
=
base_type
.
base_type_node
)
return
base_type
return
Nodes
.
CConstTypeNode
(
pos
,
base_type
=
base_type
)
if
looking_at_base_type
(
s
):
if
looking_at_base_type
(
s
):
#print "p_c_simple_base_type: looking_at_base_type at", s.position()
#print "p_c_simple_base_type: looking_at_base_type at", s.position()
is_basic
=
1
is_basic
=
1
...
...
Cython/Compiler/PyrexTypes.py
View file @
9ca6532b
...
@@ -316,6 +316,21 @@ class PyrexType(BaseType):
...
@@ -316,6 +316,21 @@ class PyrexType(BaseType):
def
needs_nonecheck
(
self
):
def
needs_nonecheck
(
self
):
return
0
return
0
def
_assign_from_py_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
,
extra_args
=
None
):
args
=
', '
+
', '
.
join
(
'%s'
%
arg
for
arg
in
extra_args
)
if
extra_args
else
''
convert_call
=
"%s(%s%s)"
%
(
from_py_function
or
self
.
from_py_function
,
source_code
,
args
,
)
if
self
.
is_enum
:
convert_call
=
typecast
(
self
,
c_long_type
,
convert_call
)
return
'%s = %s; %s'
%
(
result_code
,
convert_call
,
code
.
error_goto_if
(
error_condition
or
self
.
error_condition
(
result_code
),
error_pos
))
def
public_decl
(
base_code
,
dll_linkage
):
def
public_decl
(
base_code
,
dll_linkage
):
if
dll_linkage
:
if
dll_linkage
:
...
@@ -493,12 +508,11 @@ class CTypedefType(BaseType):
...
@@ -493,12 +508,11 @@ class CTypedefType(BaseType):
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
from_py_function
=
None
,
error_condition
=
None
):
if
from_py_function
is
None
:
from_py_function
=
self
.
from_py_function
if
error_condition
is
None
:
error_condition
=
self
.
error_condition
(
result_code
)
return
self
.
typedef_base_type
.
from_py_call_code
(
return
self
.
typedef_base_type
.
from_py_call_code
(
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
,
error_condition
)
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
or
self
.
from_py_function
,
error_condition
or
self
.
error_condition
(
result_code
)
)
def
overflow_check_binop
(
self
,
binop
,
env
,
const_rhs
=
False
):
def
overflow_check_binop
(
self
,
binop
,
env
,
const_rhs
=
False
):
env
.
use_utility_code
(
UtilityCode
.
load
(
"Common"
,
"Overflow.c"
))
env
.
use_utility_code
(
UtilityCode
.
load
(
"Common"
,
"Overflow.c"
))
...
@@ -621,6 +635,7 @@ class MemoryViewSliceType(PyrexType):
...
@@ -621,6 +635,7 @@ class MemoryViewSliceType(PyrexType):
def
same_as_resolved_type
(
self
,
other_type
):
def
same_as_resolved_type
(
self
,
other_type
):
return
((
other_type
.
is_memoryviewslice
and
return
((
other_type
.
is_memoryviewslice
and
self
.
writable_needed
==
other_type
.
writable_needed
and
self
.
dtype
.
same_as
(
other_type
.
dtype
)
and
self
.
dtype
.
same_as
(
other_type
.
dtype
)
and
self
.
axes
==
other_type
.
axes
)
or
self
.
axes
==
other_type
.
axes
)
or
other_type
is
error_type
)
other_type
is
error_type
)
...
@@ -767,7 +782,18 @@ class MemoryViewSliceType(PyrexType):
...
@@ -767,7 +782,18 @@ class MemoryViewSliceType(PyrexType):
src
=
self
src
=
self
if
src
.
dtype
!=
dst
.
dtype
:
if
self
.
writable_needed
and
not
dst
.
writable_needed
:
return
False
src_dtype
,
dst_dtype
=
src
.
dtype
,
dst
.
dtype
if
dst_dtype
.
is_const
:
# Requesting read-only views is always ok => consider only the non-const base type.
dst_dtype
=
dst_dtype
.
const_base_type
if
src_dtype
.
is_const
:
# When assigning between read-only views, compare only the non-const base types.
src_dtype
=
src_dtype
.
const_base_type
if
src_dtype
!=
dst_dtype
:
return
False
return
False
if
src
.
ndim
!=
dst
.
ndim
:
if
src
.
ndim
!=
dst
.
ndim
:
...
@@ -885,11 +911,12 @@ class MemoryViewSliceType(PyrexType):
...
@@ -885,11 +911,12 @@ class MemoryViewSliceType(PyrexType):
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
from_py_function
=
None
,
error_condition
=
None
):
return
'%s = %s(%s); %s'
%
(
# NOTE: auto-detection of readonly buffers is disabled:
result_code
,
# writable = self.writable_needed or not self.dtype.is_const
from_py_function
or
self
.
from_py_function
,
writable
=
not
self
.
dtype
.
is_const
source_code
,
return
self
.
_assign_from_py_code
(
code
.
error_goto_if
(
error_condition
or
self
.
error_condition
(
result_code
),
error_pos
))
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
,
error_condition
,
extra_args
=
[
'PyBUF_WRITABLE'
if
writable
else
'0'
])
def
create_to_py_utility_code
(
self
,
env
):
def
create_to_py_utility_code
(
self
,
env
):
self
.
_dtype_to_py_func
,
self
.
_dtype_from_py_func
=
self
.
dtype_object_conversion_funcs
(
env
)
self
.
_dtype_to_py_func
,
self
.
_dtype_from_py_func
=
self
.
dtype_object_conversion_funcs
(
env
)
...
@@ -917,25 +944,29 @@ class MemoryViewSliceType(PyrexType):
...
@@ -917,25 +944,29 @@ class MemoryViewSliceType(PyrexType):
if
self
.
dtype
.
is_pyobject
:
if
self
.
dtype
.
is_pyobject
:
utility_name
=
"MemviewObjectToObject"
utility_name
=
"MemviewObjectToObject"
else
:
else
:
to_py
=
self
.
dtype
.
create_to_py_utility_code
(
env
)
self
.
dtype
.
create_to_py_utility_code
(
env
)
from_py
=
self
.
dtype
.
create_from_py_utility_code
(
env
)
to_py_function
=
self
.
dtype
.
to_py_function
if
not
(
to_py
or
from_py
):
return
"NULL"
,
"NULL"
if
not
self
.
dtype
.
to_py_function
:
from_py_function
=
None
get_function
=
"NULL"
if
not
self
.
dtype
.
is_const
:
self
.
dtype
.
create_from_py_utility_code
(
env
)
from_py_function
=
self
.
dtype
.
from_py_function
if
not
self
.
dtype
.
from_py_function
:
if
not
(
to_py_function
or
from_py_function
):
return
"NULL"
,
"NULL"
if
not
to_py_function
:
get_function
=
"NULL"
if
not
from_py_function
:
set_function
=
"NULL"
set_function
=
"NULL"
utility_name
=
"MemviewDtypeToObject"
utility_name
=
"MemviewDtypeToObject"
error_condition
=
(
self
.
dtype
.
error_condition
(
'value'
)
or
error_condition
=
(
self
.
dtype
.
error_condition
(
'value'
)
or
'PyErr_Occurred()'
)
'PyErr_Occurred()'
)
context
.
update
(
context
.
update
(
to_py_function
=
self
.
dtype
.
to_py_function
,
to_py_function
=
to_py_function
,
from_py_function
=
self
.
dtype
.
from_py_function
,
from_py_function
=
from_py_function
,
dtype
=
self
.
dtype
.
empty_declaration_code
(),
dtype
=
self
.
dtype
.
empty_declaration_code
(),
error_condition
=
error_condition
,
error_condition
=
error_condition
,
)
)
utility
=
TempitaUtilityCode
.
load_cached
(
utility
=
TempitaUtilityCode
.
load_cached
(
...
@@ -1470,11 +1501,9 @@ class CType(PyrexType):
...
@@ -1470,11 +1501,9 @@ class CType(PyrexType):
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
from_py_function
=
None
,
error_condition
=
None
):
return
'%s = %s(%s); %s'
%
(
return
self
.
_assign_from_py_code
(
result_code
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
,
error_condition
)
from_py_function
or
self
.
from_py_function
,
source_code
,
code
.
error_goto_if
(
error_condition
or
self
.
error_condition
(
result_code
),
error_pos
))
class
PythranExpr
(
CType
):
class
PythranExpr
(
CType
):
...
@@ -2438,6 +2467,7 @@ class CArrayType(CPointerBaseType):
...
@@ -2438,6 +2467,7 @@ class CArrayType(CPointerBaseType):
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
from_py_function
=
None
,
error_condition
=
None
):
assert
not
error_condition
,
'%s: %s'
%
(
error_pos
,
error_condition
)
call_code
=
"%s(%s, %s, %s)"
%
(
call_code
=
"%s(%s, %s, %s)"
%
(
from_py_function
or
self
.
from_py_function
,
from_py_function
or
self
.
from_py_function
,
source_code
,
result_code
,
self
.
size
)
source_code
,
result_code
,
self
.
size
)
...
@@ -3879,16 +3909,6 @@ class CEnumType(CIntLike, CType):
...
@@ -3879,16 +3909,6 @@ class CEnumType(CIntLike, CType):
self
.
name
,
self
.
cname
,
self
.
typedef_flag
,
namespace
)
self
.
name
,
self
.
cname
,
self
.
typedef_flag
,
namespace
)
return
self
return
self
def
from_py_call_code
(
self
,
source_code
,
result_code
,
error_pos
,
code
,
from_py_function
=
None
,
error_condition
=
None
):
rhs
=
"%s(%s)"
%
(
from_py_function
or
self
.
from_py_function
,
source_code
)
return
'%s = %s;%s'
%
(
result_code
,
typecast
(
self
,
c_long_type
,
rhs
),
' %s'
%
code
.
error_goto_if
(
error_condition
or
self
.
error_condition
(
result_code
),
error_pos
))
def
create_type_wrapper
(
self
,
env
):
def
create_type_wrapper
(
self
,
env
):
from
.UtilityCode
import
CythonUtilityCode
from
.UtilityCode
import
CythonUtilityCode
env
.
use_utility_code
(
CythonUtilityCode
.
load
(
env
.
use_utility_code
(
CythonUtilityCode
.
load
(
...
...
Cython/Utility/MemoryView.pyx
View file @
9ca6532b
...
@@ -65,6 +65,7 @@ cdef extern from *:
...
@@ -65,6 +65,7 @@ cdef extern from *:
PyBUF_STRIDES
PyBUF_STRIDES
PyBUF_INDIRECT
PyBUF_INDIRECT
PyBUF_RECORDS
PyBUF_RECORDS
PyBUF_RECORDS_RO
ctypedef
struct
__Pyx_TypeInfo
:
ctypedef
struct
__Pyx_TypeInfo
:
pass
pass
...
@@ -408,6 +409,9 @@ cdef class memoryview(object):
...
@@ -408,6 +409,9 @@ cdef class memoryview(object):
return
self
.
convert_item_to_object
(
itemp
)
return
self
.
convert_item_to_object
(
itemp
)
def
__setitem__
(
memoryview
self
,
object
index
,
object
value
):
def
__setitem__
(
memoryview
self
,
object
index
,
object
value
):
if
self
.
view
.
readonly
:
raise
TypeError
(
"Cannot assign to read-only memoryview"
)
have_slices
,
index
=
_unellipsify
(
index
,
self
.
view
.
ndim
)
have_slices
,
index
=
_unellipsify
(
index
,
self
.
view
.
ndim
)
if
have_slices
:
if
have_slices
:
...
@@ -507,6 +511,9 @@ cdef class memoryview(object):
...
@@ -507,6 +511,9 @@ cdef class memoryview(object):
@
cname
(
'getbuffer'
)
@
cname
(
'getbuffer'
)
def
__getbuffer__
(
self
,
Py_buffer
*
info
,
int
flags
):
def
__getbuffer__
(
self
,
Py_buffer
*
info
,
int
flags
):
if
flags
&
PyBUF_WRITABLE
and
self
.
view
.
readonly
:
raise
ValueError
(
"Cannot create writable memory view from read-only memoryview"
)
if
flags
&
PyBUF_STRIDES
:
if
flags
&
PyBUF_STRIDES
:
info
.
shape
=
self
.
view
.
shape
info
.
shape
=
self
.
view
.
shape
else
:
else
:
...
@@ -531,7 +538,7 @@ cdef class memoryview(object):
...
@@ -531,7 +538,7 @@ cdef class memoryview(object):
info
.
ndim
=
self
.
view
.
ndim
info
.
ndim
=
self
.
view
.
ndim
info
.
itemsize
=
self
.
view
.
itemsize
info
.
itemsize
=
self
.
view
.
itemsize
info
.
len
=
self
.
view
.
len
info
.
len
=
self
.
view
.
len
info
.
readonly
=
0
info
.
readonly
=
self
.
view
.
readonly
info
.
obj
=
self
info
.
obj
=
self
__pyx_getbuffer
=
capsule
(
<
void
*>
&
__pyx_memoryview_getbuffer
,
"getbuffer(obj, view, flags)"
)
__pyx_getbuffer
=
capsule
(
<
void
*>
&
__pyx_memoryview_getbuffer
,
"getbuffer(obj, view, flags)"
)
...
@@ -1012,7 +1019,10 @@ cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
...
@@ -1012,7 +1019,10 @@ cdef memoryview_fromslice({{memviewslice_name}} memviewslice,
(
<
__pyx_buffer
*>
&
result
.
view
).
obj
=
Py_None
(
<
__pyx_buffer
*>
&
result
.
view
).
obj
=
Py_None
Py_INCREF
(
Py_None
)
Py_INCREF
(
Py_None
)
if
(
<
memoryview
>
memviewslice
.
memview
).
flags
&
PyBUF_WRITABLE
:
result
.
flags
=
PyBUF_RECORDS
result
.
flags
=
PyBUF_RECORDS
else
:
result
.
flags
=
PyBUF_RECORDS_RO
result
.
view
.
shape
=
<
Py_ssize_t
*>
result
.
from_slice
.
shape
result
.
view
.
shape
=
<
Py_ssize_t
*>
result
.
from_slice
.
shape
result
.
view
.
strides
=
<
Py_ssize_t
*>
result
.
from_slice
.
strides
result
.
view
.
strides
=
<
Py_ssize_t
*>
result
.
from_slice
.
strides
...
...
Cython/Utility/MemoryView_C.c
View file @
9ca6532b
...
@@ -82,7 +82,7 @@ typedef volatile __pyx_atomic_int_type __pyx_atomic_int;
...
@@ -82,7 +82,7 @@ typedef volatile __pyx_atomic_int_type __pyx_atomic_int;
/////////////// ObjectToMemviewSlice.proto ///////////////
/////////////// ObjectToMemviewSlice.proto ///////////////
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
);
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
,
int
writable_flag
);
////////// MemviewSliceInit.proto //////////
////////// MemviewSliceInit.proto //////////
...
@@ -127,7 +127,7 @@ static CYTHON_INLINE char *__pyx_memviewslice_index_full(
...
@@ -127,7 +127,7 @@ static CYTHON_INLINE char *__pyx_memviewslice_index_full(
/////////////// ObjectToMemviewSlice ///////////////
/////////////// ObjectToMemviewSlice ///////////////
//@requires: MemviewSliceValidateAndInit
//@requires: MemviewSliceValidateAndInit
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
obj
)
{
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
obj
,
int
writable_flag
)
{
{{
memviewslice_name
}}
result
=
{{
memslice_init
}};
{{
memviewslice_name
}}
result
=
{{
memslice_init
}};
__Pyx_BufFmt_StackElem
stack
[{{
struct_nesting_depth
}}];
__Pyx_BufFmt_StackElem
stack
[{{
struct_nesting_depth
}}];
int
axes_specs
[]
=
{
{{
axes_specs
}}
};
int
axes_specs
[]
=
{
{{
axes_specs
}}
};
...
@@ -140,7 +140,7 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj) {
...
@@ -140,7 +140,7 @@ static CYTHON_INLINE {{memviewslice_name}} {{funcname}}(PyObject *obj) {
}
}
retcode
=
__Pyx_ValidateAndInit_memviewslice
(
axes_specs
,
{{
c_or_f_flag
}},
retcode
=
__Pyx_ValidateAndInit_memviewslice
(
axes_specs
,
{{
c_or_f_flag
}},
{{
buf_flag
}},
{{
ndim
}},
{{
buf_flag
}}
|
writable_flag
,
{{
ndim
}},
&
{{
dtype_typeinfo
}},
stack
,
&
{{
dtype_typeinfo
}},
stack
,
&
result
,
obj
);
&
result
,
obj
);
...
...
docs/src/userguide/memoryviews.rst
View file @
9ca6532b
...
@@ -227,6 +227,33 @@ As for NumPy, new axes can be introduced by indexing an array with ``None`` ::
...
@@ -227,6 +227,33 @@ As for NumPy, new axes can be introduced by indexing an array with ``None`` ::
One may mix new axis indexing with all other forms of indexing and slicing.
One may mix new axis indexing with all other forms of indexing and slicing.
See also an example_.
See also an example_.
Read-only views
---------------
Since Cython 0.28, the memoryview item type can be declared as ``const`` to
support read-only buffers as input::
cdef const double[:] myslice # const item type => read-only view
a = np.linspace(0, 10, num=50)
a.setflags(write=False)
myslice = a
Note that this does not *require* the input buffer to be read-only::
a = np.linspace(0, 10, num=50)
myslice = a # read-only view of a writable buffer
Writable buffers are still accepted by ``const`` views, but read-only
buffers are not accepted for non-const, writable views::
cdef double[:] myslice # a normal read/write memory view
a = np.linspace(0, 10, num=50)
a.setflags(write=False)
myslice = a # ERROR: requesting writable memory view from read-only buffer!
Comparison to the old buffer support
Comparison to the old buffer support
====================================
====================================
...
...
tests/buffers/bufaccess.pyx
View file @
9ca6532b
...
@@ -599,7 +599,7 @@ def readonly(obj):
...
@@ -599,7 +599,7 @@ def readonly(obj):
acquired R
acquired R
25
25
released R
released R
>>> [str(x) for x in R.rec
ie
ved_flags] # Works in both py2 and py3
>>> [str(x) for x in R.rec
ei
ved_flags] # Works in both py2 and py3
['FORMAT', 'INDIRECT', 'ND', 'STRIDES']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES']
"""
"""
cdef
object
[
unsigned
short
int
,
ndim
=
3
]
buf
=
obj
cdef
object
[
unsigned
short
int
,
ndim
=
3
]
buf
=
obj
...
@@ -612,7 +612,7 @@ def writable(obj):
...
@@ -612,7 +612,7 @@ def writable(obj):
>>> writable(R)
>>> writable(R)
acquired R
acquired R
released R
released R
>>> [str(x) for x in R.rec
ie
ved_flags] # Py2/3
>>> [str(x) for x in R.rec
ei
ved_flags] # Py2/3
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
cdef
object
[
unsigned
short
int
,
ndim
=
3
]
buf
=
obj
cdef
object
[
unsigned
short
int
,
ndim
=
3
]
buf
=
obj
...
@@ -626,7 +626,7 @@ def strided(object[int, ndim=1, mode='strided'] buf):
...
@@ -626,7 +626,7 @@ def strided(object[int, ndim=1, mode='strided'] buf):
acquired A
acquired A
released A
released A
2
2
>>> [str(x) for x in A.rec
ie
ved_flags] # Py2/3
>>> [str(x) for x in A.rec
ei
ved_flags] # Py2/3
['FORMAT', 'ND', 'STRIDES']
['FORMAT', 'ND', 'STRIDES']
Check that the suboffsets were patched back prior to release.
Check that the suboffsets were patched back prior to release.
...
@@ -641,7 +641,7 @@ def c_contig(object[int, ndim=1, mode='c'] buf):
...
@@ -641,7 +641,7 @@ def c_contig(object[int, ndim=1, mode='c'] buf):
>>> A = IntMockBuffer(None, range(4))
>>> A = IntMockBuffer(None, range(4))
>>> c_contig(A)
>>> c_contig(A)
2
2
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
"""
"""
return
buf
[
2
]
return
buf
[
2
]
...
@@ -654,7 +654,7 @@ def c_contig_2d(object[int, ndim=2, mode='c'] buf):
...
@@ -654,7 +654,7 @@ def c_contig_2d(object[int, ndim=2, mode='c'] buf):
>>> A = IntMockBuffer(None, range(12), shape=(3,4))
>>> A = IntMockBuffer(None, range(12), shape=(3,4))
>>> c_contig_2d(A)
>>> c_contig_2d(A)
7
7
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
"""
"""
return
buf
[
1
,
3
]
return
buf
[
1
,
3
]
...
@@ -665,7 +665,7 @@ def f_contig(object[int, ndim=1, mode='fortran'] buf):
...
@@ -665,7 +665,7 @@ def f_contig(object[int, ndim=1, mode='fortran'] buf):
>>> A = IntMockBuffer(None, range(4))
>>> A = IntMockBuffer(None, range(4))
>>> f_contig(A)
>>> f_contig(A)
2
2
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
"""
"""
return
buf
[
2
]
return
buf
[
2
]
...
@@ -678,7 +678,7 @@ def f_contig_2d(object[int, ndim=2, mode='fortran'] buf):
...
@@ -678,7 +678,7 @@ def f_contig_2d(object[int, ndim=2, mode='fortran'] buf):
>>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4))
>>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4))
>>> f_contig_2d(A)
>>> f_contig_2d(A)
7
7
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS']
"""
"""
return
buf
[
3
,
1
]
return
buf
[
3
,
1
]
...
@@ -1103,7 +1103,7 @@ def bufdefaults1(IntStridedMockBuffer[int, ndim=1] buf):
...
@@ -1103,7 +1103,7 @@ def bufdefaults1(IntStridedMockBuffer[int, ndim=1] buf):
>>> bufdefaults1(A)
>>> bufdefaults1(A)
acquired A
acquired A
released A
released A
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES']
['FORMAT', 'ND', 'STRIDES']
"""
"""
pass
pass
...
...
tests/buffers/mockbuffers.pxi
View file @
9ca6532b
...
@@ -18,16 +18,17 @@ cdef class MockBuffer:
...
@@ -18,16 +18,17 @@ cdef class MockBuffer:
cdef
object
format
,
offset
cdef
object
format
,
offset
cdef
void
*
buffer
cdef
void
*
buffer
cdef
Py_ssize_t
len
,
itemsize
cdef
Py_ssize_t
len
,
itemsize
cdef
int
ndim
cdef
Py_ssize_t
*
strides
cdef
Py_ssize_t
*
strides
cdef
Py_ssize_t
*
shape
cdef
Py_ssize_t
*
shape
cdef
Py_ssize_t
*
suboffsets
cdef
Py_ssize_t
*
suboffsets
cdef
object
label
,
log
cdef
object
label
,
log
cdef
int
ndim
cdef
bint
writable
cdef
readonly
object
rec
ie
ved_flags
,
release_ok
cdef
readonly
object
rec
ei
ved_flags
,
release_ok
cdef
public
object
fail
cdef
public
object
fail
def
__init__
(
self
,
label
,
data
,
shape
=
None
,
strides
=
None
,
format
=
None
,
offset
=
0
):
def
__init__
(
self
,
label
,
data
,
shape
=
None
,
strides
=
None
,
format
=
None
,
writable
=
True
,
offset
=
0
):
# It is important not to store references to data after the constructor
# It is important not to store references to data after the constructor
# as refcounting is checked on object buffers.
# as refcounting is checked on object buffers.
self
.
label
=
label
self
.
label
=
label
...
@@ -35,6 +36,7 @@ cdef class MockBuffer:
...
@@ -35,6 +36,7 @@ cdef class MockBuffer:
self
.
log
=
""
self
.
log
=
""
self
.
offset
=
offset
self
.
offset
=
offset
self
.
itemsize
=
self
.
get_itemsize
()
self
.
itemsize
=
self
.
get_itemsize
()
self
.
writable
=
writable
if
format
is
None
:
format
=
self
.
get_default_format
()
if
format
is
None
:
format
=
self
.
get_default_format
()
if
shape
is
None
:
shape
=
(
len
(
data
),)
if
shape
is
None
:
shape
=
(
len
(
data
),)
if
strides
is
None
:
if
strides
is
None
:
...
@@ -127,16 +129,19 @@ cdef class MockBuffer:
...
@@ -127,16 +129,19 @@ cdef class MockBuffer:
if
self
.
fail
:
if
self
.
fail
:
raise
ValueError
(
"Failing on purpose"
)
raise
ValueError
(
"Failing on purpose"
)
self
.
rec
ie
ved_flags
=
[]
self
.
rec
ei
ved_flags
=
[]
cdef
int
value
cdef
int
value
for
name
,
value
in
available_flags
:
for
name
,
value
in
available_flags
:
if
(
value
&
flags
)
==
value
:
if
(
value
&
flags
)
==
value
:
self
.
recieved_flags
.
append
(
name
)
self
.
received_flags
.
append
(
name
)
if
flags
&
cpython
.
buffer
.
PyBUF_WRITABLE
and
not
self
.
writable
:
raise
BufferError
(
"Writable buffer requested from read-only mock: %s"
%
' | '
.
join
(
self
.
received_flags
))
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
.
obj
=
self
buffer
.
len
=
self
.
len
buffer
.
len
=
self
.
len
buffer
.
readonly
=
0
buffer
.
readonly
=
not
self
.
writable
buffer
.
format
=
<
char
*>
self
.
format
buffer
.
format
=
<
char
*>
self
.
format
buffer
.
ndim
=
self
.
ndim
buffer
.
ndim
=
self
.
ndim
buffer
.
shape
=
self
.
shape
buffer
.
shape
=
self
.
shape
...
...
tests/errors/e_arrayassign.pyx
View file @
9ca6532b
# mode: error
# mode: error
# cython: auto_pickle=False
ctypedef
int
[
1
]
int_array
ctypedef
int
[
1
]
int_array
ctypedef
int
[
2
]
int_array2
ctypedef
int
[
2
]
int_array2
...
@@ -30,6 +31,6 @@ d = z # not an error
...
@@ -30,6 +31,6 @@ d = z # not an error
_ERRORS
=
u"""
_ERRORS
=
u"""
2
0
:0: Assignment to slice of wrong length, expected 2, got 1
2
1
:0: Assignment to slice of wrong length, expected 2, got 1
2
1
:0: Assignment to slice of wrong length, expected 1, got 2
2
2
:0: Assignment to slice of wrong length, expected 1, got 2
"""
"""
tests/memoryview/memoryview.pyx
View file @
9ca6532b
...
@@ -420,7 +420,7 @@ def writable(unsigned short int[:, :, :] mslice):
...
@@ -420,7 +420,7 @@ def writable(unsigned short int[:, :, :] mslice):
>>> writable(R)
>>> writable(R)
acquired R
acquired R
released R
released R
>>> [str(x) for x in R.rec
ie
ved_flags] # Py2/3
>>> [str(x) for x in R.rec
ei
ved_flags] # Py2/3
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
buf
=
mslice
buf
=
mslice
...
...
tests/memoryview/memslice.pyx
View file @
9ca6532b
...
@@ -279,8 +279,8 @@ def cascaded_buffer_assignment(obj):
...
@@ -279,8 +279,8 @@ def cascaded_buffer_assignment(obj):
@
testcase
@
testcase
def
tuple_buffer_assignment1
(
a
,
b
):
def
tuple_buffer_assignment1
(
a
,
b
):
"""
"""
>>> A = IntMockBuffer("A", range(6))
>>> A = IntMockBuffer("A", range(6))
# , writable=False)
>>> B = IntMockBuffer("B", range(6))
>>> B = IntMockBuffer("B", range(6))
# , writable=False)
>>> tuple_buffer_assignment1(A, B)
>>> tuple_buffer_assignment1(A, B)
acquired A
acquired A
acquired B
acquired B
...
@@ -293,8 +293,8 @@ def tuple_buffer_assignment1(a, b):
...
@@ -293,8 +293,8 @@ def tuple_buffer_assignment1(a, b):
@
testcase
@
testcase
def
tuple_buffer_assignment2
(
tup
):
def
tuple_buffer_assignment2
(
tup
):
"""
"""
>>> A = IntMockBuffer("A", range(6))
>>> A = IntMockBuffer("A", range(6))
# , writable=False)
>>> B = IntMockBuffer("B", range(6))
>>> B = IntMockBuffer("B", range(6))
# , writable=False)
>>> tuple_buffer_assignment2((A, B))
>>> tuple_buffer_assignment2((A, B))
acquired A
acquired A
acquired B
acquired B
...
@@ -312,7 +312,7 @@ def explicitly_release_buffer():
...
@@ -312,7 +312,7 @@ def explicitly_release_buffer():
released A
released A
After release
After release
"""
"""
cdef
int
[:]
x
=
IntMockBuffer
(
"A"
,
range
(
10
))
cdef
int
[:]
x
=
IntMockBuffer
(
"A"
,
range
(
10
))
# , writable=False)
del
x
del
x
print
"After release"
print
"After release"
...
@@ -358,7 +358,7 @@ def get_int_2d(int[:, :] buf, int i, int j):
...
@@ -358,7 +358,7 @@ def get_int_2d(int[:, :] buf, int i, int j):
def
get_int_2d_uintindex
(
int
[:,
:]
buf
,
unsigned
int
i
,
unsigned
int
j
):
def
get_int_2d_uintindex
(
int
[:,
:]
buf
,
unsigned
int
i
,
unsigned
int
j
):
"""
"""
Unsigned indexing:
Unsigned indexing:
>>> C = IntMockBuffer("C", range(6), (2,3))
>>> C = IntMockBuffer("C", range(6), (2,3))
# , writable=False)
>>> get_int_2d_uintindex(C, 0, 0)
>>> get_int_2d_uintindex(C, 0, 0)
acquired C
acquired C
released C
released C
...
@@ -422,6 +422,10 @@ def set_int_2d(int[:, :] buf, int i, int j, int value):
...
@@ -422,6 +422,10 @@ def set_int_2d(int[:, :] buf, int i, int j, int value):
...
...
IndexError: Out of bounds on buffer access (axis 1)
IndexError: Out of bounds on buffer access (axis 1)
>>> C = IntMockBuffer("C", range(6), (2,3), writable=False)
>>> set_int_2d(C, -2, -3, 9)
Traceback (most recent call last):
BufferError: Writable buffer requested from read-only mock: FORMAT | ND | STRIDES | WRITABLE
"""
"""
buf
[
i
,
j
]
=
value
buf
[
i
,
j
]
=
value
...
@@ -588,11 +592,11 @@ def char_index_vars(int[:, :] buf, char i, char j, int value):
...
@@ -588,11 +592,11 @@ def char_index_vars(int[:, :] buf, char i, char j, int value):
@
testcase
@
testcase
def
list_comprehension
(
int
[:]
buf
,
len
):
def
list_comprehension
(
int
[:]
buf
,
len
):
"""
"""
>>> list_comprehension(IntMockBuffer(None, [1,2,3]), 3)
>>> list_comprehension(IntMockBuffer(None, [1,2,3]), 3)
# , writable=False), 3)
1|2|3
1|2|3
"""
"""
cdef
int
i
cdef
int
i
print
u"|"
.
join
([
unicode
(
buf
[
i
])
for
i
in
range
(
len
)])
print
"|"
.
join
([
str
(
buf
[
i
])
for
i
in
range
(
len
)])
@
testcase
@
testcase
@
cython
.
wraparound
(
False
)
@
cython
.
wraparound
(
False
)
...
@@ -600,7 +604,7 @@ def wraparound_directive(int[:] buf, int pos_idx, int neg_idx):
...
@@ -600,7 +604,7 @@ def wraparound_directive(int[:] buf, int pos_idx, int neg_idx):
"""
"""
Again, the most interesting thing here is to inspect the C source.
Again, the most interesting thing here is to inspect the C source.
>>> A = IntMockBuffer(None, range(4))
>>> A = IntMockBuffer(None, range(4))
# , writable=False)
>>> wraparound_directive(A, 2, -1)
>>> wraparound_directive(A, 2, -1)
5
5
>>> wraparound_directive(A, -1, 2)
>>> wraparound_directive(A, -1, 2)
...
@@ -625,22 +629,22 @@ def writable(obj):
...
@@ -625,22 +629,22 @@ def writable(obj):
>>> writable(R)
>>> writable(R)
acquired R
acquired R
released R
released R
>>> [str(x) for x in R.rec
ie
ved_flags] # Py2/3
>>> [str(x) for x in R.rec
ei
ved_flags] # Py2/3
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
cdef
unsigned
short
int
[:,
:,
:]
buf
=
obj
cdef
unsigned
short
int
[:,
:,
:]
buf
=
obj
buf
[
2
,
2
,
1
]
=
23
buf
[
2
,
2
,
1
]
=
23
@
testcase
@
testcase
def
strided
(
int
[:]
buf
):
def
strided
(
const
int
[:]
buf
):
"""
"""
>>> A = IntMockBuffer("A", range(4))
>>> A = IntMockBuffer("A", range(4)
, writable=False
)
>>> strided(A)
>>> strided(A)
acquired A
acquired A
released A
released A
2
2
>>> [str(x) for x in A.rec
ie
ved_flags] # Py2/3
>>> [str(x) for x in A.rec
ei
ved_flags] # Py2/3
['FORMAT', 'ND', 'STRIDES'
, 'WRITABLE'
]
['FORMAT', 'ND', 'STRIDES']
Check that the suboffsets were patched back prior to release.
Check that the suboffsets were patched back prior to release.
>>> A.release_ok
>>> A.release_ok
...
@@ -649,13 +653,13 @@ def strided(int[:] buf):
...
@@ -649,13 +653,13 @@ def strided(int[:] buf):
return
buf
[
2
]
return
buf
[
2
]
@
testcase
@
testcase
def
c_contig
(
int
[::
1
]
buf
):
def
c_contig
(
const
int
[::
1
]
buf
):
"""
"""
>>> A = IntMockBuffer(None, range(4))
>>> A = IntMockBuffer(None, range(4)
, writable=False
)
>>> c_contig(A)
>>> c_contig(A)
2
2
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS'
, 'WRITABLE'
]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS']
"""
"""
return
buf
[
2
]
return
buf
[
2
]
...
@@ -664,10 +668,10 @@ def c_contig_2d(int[:, ::1] buf):
...
@@ -664,10 +668,10 @@ def c_contig_2d(int[:, ::1] buf):
"""
"""
Multi-dim has separate implementation
Multi-dim has separate implementation
>>> A = IntMockBuffer(None, range(12), shape=(3,4))
>>> A = IntMockBuffer(None, range(12), shape=(3,4))
# , writable=False)
>>> c_contig_2d(A)
>>> c_contig_2d(A)
7
7
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'C_CONTIGUOUS', 'WRITABLE']
"""
"""
return
buf
[
1
,
3
]
return
buf
[
1
,
3
]
...
@@ -675,10 +679,10 @@ def c_contig_2d(int[:, ::1] buf):
...
@@ -675,10 +679,10 @@ def c_contig_2d(int[:, ::1] buf):
@
testcase
@
testcase
def
f_contig
(
int
[::
1
,
:]
buf
):
def
f_contig
(
int
[::
1
,
:]
buf
):
"""
"""
>>> A = IntMockBuffer(None, range(4), shape=(2, 2), strides=(1, 2))
>>> A = IntMockBuffer(None, range(4), shape=(2, 2), strides=(1, 2))
# , writable=False)
>>> f_contig(A)
>>> f_contig(A)
2
2
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE']
"""
"""
return
buf
[
0
,
1
]
return
buf
[
0
,
1
]
...
@@ -688,10 +692,10 @@ def f_contig_2d(int[::1, :] buf):
...
@@ -688,10 +692,10 @@ def f_contig_2d(int[::1, :] buf):
"""
"""
Must set up strides manually to ensure Fortran ordering.
Must set up strides manually to ensure Fortran ordering.
>>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4))
>>> A = IntMockBuffer(None, range(12), shape=(4,3), strides=(1, 4))
# , writable=False)
>>> f_contig_2d(A)
>>> f_contig_2d(A)
7
7
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'F_CONTIGUOUS', 'WRITABLE']
"""
"""
return
buf
[
3
,
1
]
return
buf
[
3
,
1
]
...
@@ -711,9 +715,9 @@ def generic(int[::view.generic, ::view.generic] buf1,
...
@@ -711,9 +715,9 @@ def generic(int[::view.generic, ::view.generic] buf1,
11
11
released A
released A
released B
released B
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
>>> [str(x) for x in B.rec
ie
ved_flags]
>>> [str(x) for x in B.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
print
buf1
[
1
,
1
]
print
buf1
[
1
,
1
]
...
@@ -741,9 +745,9 @@ def generic(int[::view.generic, ::view.generic] buf1,
...
@@ -741,9 +745,9 @@ def generic(int[::view.generic, ::view.generic] buf1,
# 11
# 11
# released A
# released A
# released B
# released B
# >>> [str(x) for x in A.rec
ie
ved_flags]
# >>> [str(x) for x in A.rec
ei
ved_flags]
# ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
# ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
# >>> [str(x) for x in B.rec
ie
ved_flags]
# >>> [str(x) for x in B.rec
ei
ved_flags]
# ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
# ['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
# """
# """
# print buf1[1, 1]
# print buf1[1, 1]
...
@@ -771,9 +775,9 @@ def indirect_strided_and_contig(
...
@@ -771,9 +775,9 @@ def indirect_strided_and_contig(
11
11
released A
released A
released B
released B
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
>>> [str(x) for x in B.rec
ie
ved_flags]
>>> [str(x) for x in B.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
print
buf1
[
1
,
1
]
print
buf1
[
1
,
1
]
...
@@ -802,9 +806,9 @@ def indirect_contig(
...
@@ -802,9 +806,9 @@ def indirect_contig(
11
11
released A
released A
released B
released B
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
>>> [str(x) for x in B.rec
ie
ved_flags]
>>> [str(x) for x in B.rec
ei
ved_flags]
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'INDIRECT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
print
buf1
[
1
,
1
]
print
buf1
[
1
,
1
]
...
@@ -827,7 +831,7 @@ def indirect_contig(
...
@@ -827,7 +831,7 @@ def indirect_contig(
@
testcase
@
testcase
def
safe_get
(
int
[:]
buf
,
int
idx
):
def
safe_get
(
int
[:]
buf
,
int
idx
):
"""
"""
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
# , writable=False)
Validate our testing buffer...
Validate our testing buffer...
>>> safe_get(A, 0)
>>> safe_get(A, 0)
...
@@ -857,7 +861,7 @@ def safe_get(int[:] buf, int idx):
...
@@ -857,7 +861,7 @@ def safe_get(int[:] buf, int idx):
def
unsafe_get
(
int
[:]
buf
,
int
idx
):
def
unsafe_get
(
int
[:]
buf
,
int
idx
):
"""
"""
Access outside of the area the buffer publishes.
Access outside of the area the buffer publishes.
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
# , writable=False)
>>> unsafe_get(A, -4)
>>> unsafe_get(A, -4)
4
4
>>> unsafe_get(A, -5)
>>> unsafe_get(A, -5)
...
@@ -870,7 +874,7 @@ def unsafe_get(int[:] buf, int idx):
...
@@ -870,7 +874,7 @@ def unsafe_get(int[:] buf, int idx):
@
testcase
@
testcase
def
mixed_get
(
int
[:]
buf
,
int
unsafe_idx
,
int
safe_idx
):
def
mixed_get
(
int
[:]
buf
,
int
unsafe_idx
,
int
safe_idx
):
"""
"""
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
>>> A = IntMockBuffer(None, range(10), shape=(3,), offset=5)
# , writable=False)
>>> mixed_get(A, -4, 0)
>>> mixed_get(A, -4, 0)
(4, 5)
(4, 5)
>>> mixed_get(A, 0, -4)
>>> mixed_get(A, 0, -4)
...
@@ -902,12 +906,12 @@ def printbuf_int_2d(o, shape):
...
@@ -902,12 +906,12 @@ def printbuf_int_2d(o, shape):
"""
"""
Strided:
Strided:
>>> printbuf_int_2d(IntMockBuffer("A", range(6), (2,3)), (2,3))
>>> printbuf_int_2d(IntMockBuffer("A", range(6), (2,3)
, writable=False
), (2,3))
acquired A
acquired A
0 1 2 END
0 1 2 END
3 4 5 END
3 4 5 END
released A
released A
>>> printbuf_int_2d(IntMockBuffer("A", range(100), (3,3), strides=(20,5)), (3,3))
>>> printbuf_int_2d(IntMockBuffer("A", range(100), (3,3), strides=(20,5)
, writable=False
), (3,3))
acquired A
acquired A
0 5 10 END
0 5 10 END
20 25 30 END
20 25 30 END
...
@@ -915,14 +919,14 @@ def printbuf_int_2d(o, shape):
...
@@ -915,14 +919,14 @@ def printbuf_int_2d(o, shape):
released A
released A
Indirect:
Indirect:
>>> printbuf_int_2d(IntMockBuffer("A", [[1,2],[3,4]]), (2,2))
>>> printbuf_int_2d(IntMockBuffer("A", [[1,2],[3,4]]
, writable=False
), (2,2))
acquired A
acquired A
1 2 END
1 2 END
3 4 END
3 4 END
released A
released A
"""
"""
# should make shape builtin
# should make shape builtin
cdef
int
[::
view
.
generic
,
::
view
.
generic
]
buf
cdef
const
int
[::
view
.
generic
,
::
view
.
generic
]
buf
buf
=
o
buf
=
o
cdef
int
i
,
j
cdef
int
i
,
j
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -933,14 +937,14 @@ def printbuf_int_2d(o, shape):
...
@@ -933,14 +937,14 @@ def printbuf_int_2d(o, shape):
@
testcase
@
testcase
def
printbuf_float
(
o
,
shape
):
def
printbuf_float
(
o
,
shape
):
"""
"""
>>> printbuf_float(FloatMockBuffer("F", [1.0, 1.25, 0.75, 1.0]), (4,))
>>> printbuf_float(FloatMockBuffer("F", [1.0, 1.25, 0.75, 1.0]
, writable=False
), (4,))
acquired F
acquired F
1.0 1.25 0.75 1.0 END
1.0 1.25 0.75 1.0 END
released F
released F
"""
"""
# should make shape builtin
# should make shape builtin
cdef
float
[:]
buf
cdef
const
float
[:]
buf
buf
=
o
buf
=
o
cdef
int
i
,
j
cdef
int
i
,
j
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -982,9 +986,9 @@ ctypedef td_h_short td_h_cy_short
...
@@ -982,9 +986,9 @@ ctypedef td_h_short td_h_cy_short
@
testcase
@
testcase
def
printbuf_td_cy_int
(
td_cy_int
[:]
buf
,
shape
):
def
printbuf_td_cy_int
(
td_cy_int
[:]
buf
,
shape
):
"""
"""
>>> printbuf_td_cy_int(IntMockBuffer(None, range(3)), (3,))
>>> printbuf_td_cy_int(IntMockBuffer(None, range(3)), (3,))
# , writable=False), (3,))
0 1 2 END
0 1 2 END
>>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,))
>>> printbuf_td_cy_int(ShortMockBuffer(None, range(3)), (3,))
# , writable=False), (3,))
Traceback (most recent call last):
Traceback (most recent call last):
...
...
ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short'
ValueError: Buffer dtype mismatch, expected 'td_cy_int' but got 'short'
...
@@ -997,9 +1001,9 @@ def printbuf_td_cy_int(td_cy_int[:] buf, shape):
...
@@ -997,9 +1001,9 @@ def printbuf_td_cy_int(td_cy_int[:] buf, shape):
@
testcase
@
testcase
def
printbuf_td_h_short
(
td_h_short
[:]
buf
,
shape
):
def
printbuf_td_h_short
(
td_h_short
[:]
buf
,
shape
):
"""
"""
>>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_short(ShortMockBuffer(None, range(3)), (3,))
# , writable=False), (3,))
0 1 2 END
0 1 2 END
>>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_short(IntMockBuffer(None, range(3)), (3,))
# , writable=False), (3,))
Traceback (most recent call last):
Traceback (most recent call last):
...
...
ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int'
ValueError: Buffer dtype mismatch, expected 'td_h_short' but got 'int'
...
@@ -1010,14 +1014,14 @@ def printbuf_td_h_short(td_h_short[:] buf, shape):
...
@@ -1010,14 +1014,14 @@ def printbuf_td_h_short(td_h_short[:] buf, shape):
print
'END'
print
'END'
@
testcase
@
testcase
def
printbuf_td_h_cy_short
(
td_h_cy_short
[:]
buf
,
shape
):
def
printbuf_td_h_cy_short
(
const
td_h_cy_short
[:]
buf
,
shape
):
"""
"""
>>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_cy_short(ShortMockBuffer(None, range(3)
, writable=False
), (3,))
0 1 2 END
0 1 2 END
>>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_cy_short(IntMockBuffer(None, range(3)
, writable=False
), (3,))
Traceback (most recent call last):
Traceback (most recent call last):
...
...
ValueError: Buffer dtype mismatch, expected 'td_h_cy_short' but got 'int'
ValueError: Buffer dtype mismatch, expected '
const
td_h_cy_short' but got 'int'
"""
"""
cdef
int
i
cdef
int
i
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -1025,14 +1029,14 @@ def printbuf_td_h_cy_short(td_h_cy_short[:] buf, shape):
...
@@ -1025,14 +1029,14 @@ def printbuf_td_h_cy_short(td_h_cy_short[:] buf, shape):
print
'END'
print
'END'
@
testcase
@
testcase
def
printbuf_td_h_ushort
(
td_h_ushort
[:]
buf
,
shape
):
def
printbuf_td_h_ushort
(
const
td_h_ushort
[:]
buf
,
shape
):
"""
"""
>>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_ushort(UnsignedShortMockBuffer(None, range(3)
, writable=False
), (3,))
0 1 2 END
0 1 2 END
>>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)), (3,))
>>> printbuf_td_h_ushort(ShortMockBuffer(None, range(3)
, writable=False
), (3,))
Traceback (most recent call last):
Traceback (most recent call last):
...
...
ValueError: Buffer dtype mismatch, expected 'td_h_ushort' but got 'short'
ValueError: Buffer dtype mismatch, expected '
const
td_h_ushort' but got 'short'
"""
"""
cdef
int
i
cdef
int
i
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -1040,14 +1044,14 @@ def printbuf_td_h_ushort(td_h_ushort[:] buf, shape):
...
@@ -1040,14 +1044,14 @@ def printbuf_td_h_ushort(td_h_ushort[:] buf, shape):
print
'END'
print
'END'
@
testcase
@
testcase
def
printbuf_td_h_double
(
td_h_double
[:]
buf
,
shape
):
def
printbuf_td_h_double
(
const
td_h_double
[:]
buf
,
shape
):
"""
"""
>>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125]), (3,))
>>> printbuf_td_h_double(DoubleMockBuffer(None, [0.25, 1, 3.125]
, writable=False
), (3,))
0.25 1.0 3.125 END
0.25 1.0 3.125 END
>>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]), (3,))
>>> printbuf_td_h_double(FloatMockBuffer(None, [0.25, 1, 3.125]
, writable=False
), (3,))
Traceback (most recent call last):
Traceback (most recent call last):
...
...
ValueError: Buffer dtype mismatch, expected 'td_h_double' but got 'float'
ValueError: Buffer dtype mismatch, expected '
const
td_h_double' but got 'float'
"""
"""
cdef
int
i
cdef
int
i
for
i
in
range
(
shape
[
0
]):
for
i
in
range
(
shape
[
0
]):
...
@@ -1079,7 +1083,7 @@ def printbuf_object(object[:] buf, shape):
...
@@ -1079,7 +1083,7 @@ def printbuf_object(object[:] buf, shape):
>>> a, b, c = "globally_unique_string_23234123", {4:23}, [34,3]
>>> a, b, c = "globally_unique_string_23234123", {4:23}, [34,3]
>>> get_refcount(a), get_refcount(b), get_refcount(c)
>>> get_refcount(a), get_refcount(b), get_refcount(c)
(2, 2, 2)
(2, 2, 2)
>>> A = ObjectMockBuffer(None, [a, b, c])
>>> A = ObjectMockBuffer(None, [a, b, c])
# , writable=False)
>>> printbuf_object(A, (3,))
>>> printbuf_object(A, (3,))
'globally_unique_string_23234123' 2
'globally_unique_string_23234123' 2
{4: 23} 2
{4: 23} 2
...
@@ -1145,11 +1149,11 @@ def bufdefaults1(int[:] buf):
...
@@ -1145,11 +1149,11 @@ def bufdefaults1(int[:] buf):
"strided" by defaults which should show
"strided" by defaults which should show
up in the flags.
up in the flags.
>>> A = IntStridedMockBuffer("A", range(10))
>>> A = IntStridedMockBuffer("A", range(10))
# , writable=False)
>>> bufdefaults1(A)
>>> bufdefaults1(A)
acquired A
acquired A
released A
released A
>>> [str(x) for x in A.rec
ie
ved_flags]
>>> [str(x) for x in A.rec
ei
ved_flags]
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
['FORMAT', 'ND', 'STRIDES', 'WRITABLE']
"""
"""
pass
pass
...
@@ -1160,9 +1164,9 @@ def basic_struct(MyStruct[:] buf):
...
@@ -1160,9 +1164,9 @@ def basic_struct(MyStruct[:] buf):
"""
"""
See also buffmt.pyx
See also buffmt.pyx
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii"))
>>> basic_struct(MyStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ccqii"))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
"""
"""
print
buf
[
0
].
a
,
buf
[
0
].
b
,
buf
[
0
].
c
,
buf
[
0
].
d
,
buf
[
0
].
e
print
buf
[
0
].
a
,
buf
[
0
].
b
,
buf
[
0
].
c
,
buf
[
0
].
d
,
buf
[
0
].
e
...
@@ -1172,9 +1176,9 @@ def nested_struct(NestedStruct[:] buf):
...
@@ -1172,9 +1176,9 @@ def nested_struct(NestedStruct[:] buf):
"""
"""
See also buffmt.pyx
See also buffmt.pyx
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i"))
>>> nested_struct(NestedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="T{ii}T{2i}i"))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
"""
"""
print
buf
[
0
].
x
.
a
,
buf
[
0
].
x
.
b
,
buf
[
0
].
y
.
a
,
buf
[
0
].
y
.
b
,
buf
[
0
].
z
print
buf
[
0
].
x
.
a
,
buf
[
0
].
x
.
b
,
buf
[
0
].
y
.
a
,
buf
[
0
].
y
.
b
,
buf
[
0
].
z
...
@@ -1184,11 +1188,11 @@ def packed_struct(PackedStruct[:] buf):
...
@@ -1184,11 +1188,11 @@ def packed_struct(PackedStruct[:] buf):
"""
"""
See also buffmt.pyx
See also buffmt.pyx
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)]))
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)]))
# , writable=False))
1 2
1 2
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}"))
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c^i}"))
# , writable=False))
1 2
1 2
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}"))
>>> packed_struct(PackedStructMockBuffer(None, [(1, 2)], format="T{c=i}"))
# , writable=False))
1 2
1 2
"""
"""
...
@@ -1199,11 +1203,11 @@ def nested_packed_struct(NestedPackedStruct[:] buf):
...
@@ -1199,11 +1203,11 @@ def nested_packed_struct(NestedPackedStruct[:] buf):
"""
"""
See also buffmt.pyx
See also buffmt.pyx
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)]))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i"))
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="ci^ci@i"))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i"))
>>> nested_packed_struct(NestedPackedStructMockBuffer(None, [(1, 2, 3, 4, 5)], format="^c@i^ci@i"))
# , writable=False))
1 2 3 4 5
1 2 3 4 5
"""
"""
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
...
@@ -1212,7 +1216,7 @@ def nested_packed_struct(NestedPackedStruct[:] buf):
...
@@ -1212,7 +1216,7 @@ def nested_packed_struct(NestedPackedStruct[:] buf):
@
testcase
@
testcase
def
complex_dtype
(
long
double
complex
[:]
buf
):
def
complex_dtype
(
long
double
complex
[:]
buf
):
"""
"""
>>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)]))
>>> complex_dtype(LongComplexMockBuffer(None, [(0, -1)]))
# , writable=False))
-1j
-1j
"""
"""
print
buf
[
0
]
print
buf
[
0
]
...
@@ -1231,7 +1235,7 @@ def complex_struct_dtype(LongComplex[:] buf):
...
@@ -1231,7 +1235,7 @@ def complex_struct_dtype(LongComplex[:] buf):
"""
"""
Note that the format string is "Zg" rather than "2g", yet a struct
Note that the format string is "Zg" rather than "2g", yet a struct
is accessed.
is accessed.
>>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)]))
>>> complex_struct_dtype(LongComplexMockBuffer(None, [(0, -1)]))
# , writable=False))
0.0 -1.0
0.0 -1.0
"""
"""
print
buf
[
0
].
real
,
buf
[
0
].
imag
print
buf
[
0
].
real
,
buf
[
0
].
imag
...
@@ -1359,7 +1363,7 @@ def test_cdef_function2():
...
@@ -1359,7 +1363,7 @@ def test_cdef_function2():
def
test_generic_slicing
(
arg
,
indirect
=
False
):
def
test_generic_slicing
(
arg
,
indirect
=
False
):
"""
"""
Test simple slicing
Test simple slicing
>>> test_generic_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
>>> test_generic_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
# , writable=False))
acquired A
acquired A
3 9 2
3 9 2
308 -11 1
308 -11 1
...
@@ -1367,7 +1371,7 @@ def test_generic_slicing(arg, indirect=False):
...
@@ -1367,7 +1371,7 @@ def test_generic_slicing(arg, indirect=False):
released A
released A
Test direct slicing, negative slice oob in dim 2
Test direct slicing, negative slice oob in dim 2
>>> test_generic_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
>>> test_generic_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
# , writable=False))
acquired A
acquired A
0 0 2
0 0 2
12 -3 1
12 -3 1
...
@@ -1375,13 +1379,13 @@ def test_generic_slicing(arg, indirect=False):
...
@@ -1375,13 +1379,13 @@ def test_generic_slicing(arg, indirect=False):
released A
released A
Test indirect slicing
Test indirect slicing
>>> test_generic_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)), indirect=True)
>>> test_generic_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)), indirect=True)
# , writable=False), indirect=True)
acquired A
acquired A
2 0 2
2 0 2
0 1 -1
0 1 -1
released A
released A
>>> test_generic_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)), indirect=True)
>>> test_generic_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)), indirect=True)
# , writable=False), indirect=True)
acquired A
acquired A
3 9 2
3 9 2
10 1 -1
10 1 -1
...
@@ -1413,7 +1417,7 @@ def test_generic_slicing(arg, indirect=False):
...
@@ -1413,7 +1417,7 @@ def test_generic_slicing(arg, indirect=False):
def
test_indirect_slicing
(
arg
):
def
test_indirect_slicing
(
arg
):
"""
"""
Test indirect slicing
Test indirect slicing
>>> test_indirect_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)))
>>> test_indirect_slicing(IntMockBuffer("A", shape_5_3_4_list, shape=(5, 3, 4)))
# , writable=False))
acquired A
acquired A
5 3 2
5 3 2
0 0 -1
0 0 -1
...
@@ -1428,7 +1432,7 @@ def test_indirect_slicing(arg):
...
@@ -1428,7 +1432,7 @@ def test_indirect_slicing(arg):
58
58
released A
released A
>>> test_indirect_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)))
>>> test_indirect_slicing(IntMockBuffer("A", shape_9_14_21_list, shape=(9, 14, 21)))
# , writable=False))
acquired A
acquired A
5 14 3
5 14 3
0 16 -1
0 16 -1
...
@@ -1553,7 +1557,7 @@ def test_direct_slicing(arg):
...
@@ -1553,7 +1557,7 @@ def test_direct_slicing(arg):
Fused types would be convenient to test this stuff!
Fused types would be convenient to test this stuff!
Test simple slicing
Test simple slicing
>>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
>>> test_direct_slicing(IntMockBuffer("A", range(8 * 14 * 11), shape=(8, 14, 11)))
# , writable=False))
acquired A
acquired A
3 9 2
3 9 2
308 -11 1
308 -11 1
...
@@ -1561,7 +1565,7 @@ def test_direct_slicing(arg):
...
@@ -1561,7 +1565,7 @@ def test_direct_slicing(arg):
released A
released A
Test direct slicing, negative slice oob in dim 2
Test direct slicing, negative slice oob in dim 2
>>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
>>> test_direct_slicing(IntMockBuffer("A", range(1 * 2 * 3), shape=(1, 2, 3)))
# , writable=False))
acquired A
acquired A
0 0 2
0 0 2
12 -3 1
12 -3 1
...
@@ -1586,7 +1590,7 @@ def test_direct_slicing(arg):
...
@@ -1586,7 +1590,7 @@ def test_direct_slicing(arg):
@
testcase
@
testcase
def
test_slicing_and_indexing
(
arg
):
def
test_slicing_and_indexing
(
arg
):
"""
"""
>>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5))
>>> a = IntStridedMockBuffer("A", range(10 * 3 * 5), shape=(10, 3, 5))
# , writable=False)
>>> test_slicing_and_indexing(a)
>>> test_slicing_and_indexing(a)
acquired A
acquired A
5 2
5 2
...
@@ -1622,7 +1626,7 @@ def test_oob():
...
@@ -1622,7 +1626,7 @@ def test_oob():
...
...
IndexError: Index out of bounds (axis 1)
IndexError: Index out of bounds (axis 1)
"""
"""
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
# , writable=False)
print
a
[:,
20
]
print
a
[:,
20
]
...
@@ -1665,7 +1669,7 @@ def test_nogil_oob2():
...
@@ -1665,7 +1669,7 @@ def test_nogil_oob2():
...
...
IndexError: Index out of bounds (axis 0)
IndexError: Index out of bounds (axis 0)
"""
"""
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
cdef
int
[:,
:]
a
=
IntMockBuffer
(
"A"
,
range
(
4
*
9
),
shape
=
(
4
,
9
))
# , writable=False)
with
nogil
:
with
nogil
:
a
[
100
,
9
:]
a
[
100
,
9
:]
...
@@ -1711,7 +1715,7 @@ def test_convert_slicenode_to_indexnode():
...
@@ -1711,7 +1715,7 @@ def test_convert_slicenode_to_indexnode():
2
2
released A
released A
"""
"""
cdef
int
[:]
a
=
IntMockBuffer
(
"A"
,
range
(
10
),
shape
=
(
10
,))
cdef
int
[:]
a
=
IntMockBuffer
(
"A"
,
range
(
10
),
shape
=
(
10
,))
# , writable=False)
with
nogil
:
with
nogil
:
a
=
a
[
2
:
4
]
a
=
a
[
2
:
4
]
print
a
[
0
]
print
a
[
0
]
...
@@ -1721,10 +1725,10 @@ def test_convert_slicenode_to_indexnode():
...
@@ -1721,10 +1725,10 @@ def test_convert_slicenode_to_indexnode():
@
cython
.
wraparound
(
False
)
@
cython
.
wraparound
(
False
)
def
test_memslice_prange
(
arg
):
def
test_memslice_prange
(
arg
):
"""
"""
>>> test_memslice_prange(IntMockBuffer("A", range(400), shape=(20, 4, 5)))
>>> test_memslice_prange(IntMockBuffer("A", range(400), shape=(20, 4, 5)))
# FIXME: , writable=False))
acquired A
acquired A
released A
released A
>>> test_memslice_prange(IntMockBuffer("A", range(200), shape=(100, 2, 1)))
>>> test_memslice_prange(IntMockBuffer("A", range(200), shape=(100, 2, 1)))
# FIXME: , writable=False))
acquired A
acquired A
released A
released A
"""
"""
...
@@ -2388,7 +2392,7 @@ def test_inplace_assignment():
...
@@ -2388,7 +2392,7 @@ def test_inplace_assignment():
@
testcase
@
testcase
def
test_newaxis
(
int
[:]
one_D
):
def
test_newaxis
(
int
[:]
one_D
):
"""
"""
>>> A = IntMockBuffer("A", range(6))
>>> A = IntMockBuffer("A", range(6))
# , writable=False)
>>> test_newaxis(A)
>>> test_newaxis(A)
acquired A
acquired A
3
3
...
@@ -2410,7 +2414,7 @@ def test_newaxis(int[:] one_D):
...
@@ -2410,7 +2414,7 @@ def test_newaxis(int[:] one_D):
@
testcase
@
testcase
def
test_newaxis2
(
int
[:,
:]
two_D
):
def
test_newaxis2
(
int
[:,
:]
two_D
):
"""
"""
>>> A = IntMockBuffer("A", range(6), shape=(3, 2))
>>> A = IntMockBuffer("A", range(6), shape=(3, 2))
# , writable=False)
>>> test_newaxis2(A)
>>> test_newaxis2(A)
acquired A
acquired A
shape: 3 1 1
shape: 3 1 1
...
@@ -2444,3 +2448,16 @@ def test_newaxis2(int[:, :] two_D):
...
@@ -2444,3 +2448,16 @@ def test_newaxis2(int[:, :] two_D):
_print_attributes
(
d
)
_print_attributes
(
d
)
@
testcase
def
test_const_buffer
(
const
int
[:]
a
):
"""
>>> A = IntMockBuffer("A", range(6), shape=(6,), writable=False)
>>> test_const_buffer(A)
acquired A
0
5
released A
"""
cdef
const
int
[:]
c
=
a
print
(
a
[
0
])
print
(
c
[
-
1
])
tests/memoryview/numpy_memoryview_readonly.pyx
0 → 100644
View file @
9ca6532b
# mode: run
# tag: readonly, const, numpy
import
numpy
as
np
def
new_array
():
return
np
.
arange
(
10
).
astype
(
'float'
)
ARRAY
=
new_array
()
cdef
getmax
(
const
double
[:]
x
):
"""Example code, should work with both ro and rw memoryviews"""
cdef
double
max_val
=
-
float
(
'inf'
)
for
val
in
x
:
if
val
>
max_val
:
max_val
=
val
return
max_val
cdef
update_array
(
double
[:]
x
):
"""Modifying a ro memoryview should raise an error"""
x
[
0
]
=
23.
cdef
getconst
(
const
double
[:]
x
):
"""Should accept ro memoryviews"""
return
x
[
0
]
def
test_mmview_rw
(
x
):
"""
>>> test_mmview_rw(ARRAY)
9.0
"""
return
getmax
(
x
)
def
test_mmview_ro
(
x
):
"""
>>> test_mmview_ro(new_array())
9.0
"""
x
.
setflags
(
write
=
False
)
assert
x
.
flags
.
writeable
is
False
return
getmax
(
x
)
def
test_update_mmview_rw
(
x
):
"""
>>> test_update_mmview_rw(new_array())
23.0
"""
update_array
(
x
)
return
x
[
0
]
def
test_update_mmview_ro
(
x
):
"""
>>> test_update_mmview_ro(new_array())
0.0
"""
x
.
setflags
(
write
=
False
)
assert
x
.
flags
.
writeable
is
False
try
:
update_array
(
x
)
except
ValueError
:
pass
else
:
assert
False
,
"RO error not raised!"
return
getconst
(
x
)
def
test_rw_call_getmax
(
double
[:]
x
):
"""
>>> test_rw_call_getmax(new_array())
23.0
"""
update_array
(
x
)
assert
getconst
(
x
)
==
23
return
getmax
(
x
)
def
test_const_mmview_ro
(
x
):
"""
>>> test_const_mmview_ro(new_array())
0.0
"""
x
.
setflags
(
write
=
False
)
assert
x
.
flags
.
writeable
is
False
return
getconst
(
x
)
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