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
5fbfb6f6
Commit
5fbfb6f6
authored
Feb 07, 2012
by
Mark Florisson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Support None memoryview slices
parent
3aa13fa7
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
153 additions
and
22 deletions
+153
-22
Cython/Compiler/ExprNodes.py
Cython/Compiler/ExprNodes.py
+36
-9
Cython/Utility/MemoryView.pyx
Cython/Utility/MemoryView.pyx
+3
-0
Cython/Utility/MemoryView_C.c
Cython/Utility/MemoryView_C.c
+10
-4
docs/src/userguide/memoryviews.rst
docs/src/userguide/memoryviews.rst
+9
-5
tests/run/memslice.pyx
tests/run/memslice.pyx
+95
-4
No files found.
Cython/Compiler/ExprNodes.py
View file @
5fbfb6f6
...
@@ -2886,8 +2886,7 @@ class IndexNode(ExprNode):
...
@@ -2886,8 +2886,7 @@ class IndexNode(ExprNode):
def
generate_result_code
(
self
,
code
):
def
generate_result_code
(
self
,
code
):
if
self
.
is_buffer_access
or
self
.
memslice_index
:
if
self
.
is_buffer_access
or
self
.
memslice_index
:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
self
.
nonecheck
(
code
)
self
.
put_nonecheck
(
code
)
buffer_entry
,
self
.
buffer_ptr_code
=
self
.
buffer_lookup_code
(
code
)
buffer_entry
,
self
.
buffer_ptr_code
=
self
.
buffer_lookup_code
(
code
)
if
self
.
type
.
is_pyobject
:
if
self
.
type
.
is_pyobject
:
# is_temp is True, so must pull out value and incref it.
# is_temp is True, so must pull out value and incref it.
...
@@ -2895,6 +2894,7 @@ class IndexNode(ExprNode):
...
@@ -2895,6 +2894,7 @@ class IndexNode(ExprNode):
code
.
putln
(
"__Pyx_INCREF((PyObject*)%s);"
%
self
.
result
())
code
.
putln
(
"__Pyx_INCREF((PyObject*)%s);"
%
self
.
result
())
elif
self
.
memslice_slice
:
elif
self
.
memslice_slice
:
self
.
nonecheck
(
code
)
self
.
put_memoryviewslice_slice_code
(
code
)
self
.
put_memoryviewslice_slice_code
(
code
)
elif
self
.
is_temp
:
elif
self
.
is_temp
:
...
@@ -2969,9 +2969,7 @@ class IndexNode(ExprNode):
...
@@ -2969,9 +2969,7 @@ class IndexNode(ExprNode):
def
generate_buffer_setitem_code
(
self
,
rhs
,
code
,
op
=
""
):
def
generate_buffer_setitem_code
(
self
,
rhs
,
code
,
op
=
""
):
# Used from generate_assignment_code and InPlaceAssignmentNode
# Used from generate_assignment_code and InPlaceAssignmentNode
if
code
.
globalstate
.
directives
[
'nonecheck'
]
and
not
self
.
memslice_index
:
self
.
nonecheck
(
code
)
self
.
put_nonecheck
(
code
)
buffer_entry
,
ptrexpr
=
self
.
buffer_lookup_code
(
code
)
buffer_entry
,
ptrexpr
=
self
.
buffer_lookup_code
(
code
)
if
self
.
buffer_type
.
dtype
.
is_pyobject
:
if
self
.
buffer_type
.
dtype
.
is_pyobject
:
...
@@ -3133,10 +3131,23 @@ class IndexNode(ExprNode):
...
@@ -3133,10 +3131,23 @@ class IndexNode(ExprNode):
import
MemoryView
import
MemoryView
MemoryView
.
assign_scalar
(
self
,
rhs
,
code
)
MemoryView
.
assign_scalar
(
self
,
rhs
,
code
)
def
nonecheck
(
self
,
code
):
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
self
.
put_nonecheck
(
code
)
def
put_nonecheck
(
self
,
code
):
def
put_nonecheck
(
self
,
code
):
code
.
globalstate
.
use_utility_code
(
raise_noneindex_error_utility_code
)
if
self
.
base
.
type
.
is_memoryviewslice
:
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
"%s == Py_None"
)
%
self
.
base
.
result_as
(
PyrexTypes
.
py_object_type
))
code
.
globalstate
.
use_utility_code
(
code
.
putln
(
"__Pyx_RaiseNoneIndexingError();"
)
raise_noneindex_memview_error_utility_code
)
code
.
putln
(
"if (unlikely((PyObject *) %s.memview == Py_None)) {"
%
self
.
base
.
result
())
code
.
putln
(
"__Pyx_RaiseNoneMemviewIndexingError();"
)
else
:
code
.
globalstate
.
use_utility_code
(
raise_noneindex_error_utility_code
)
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
"%s == Py_None"
)
%
self
.
base
.
result_as
(
PyrexTypes
.
py_object_type
))
code
.
putln
(
"__Pyx_RaiseNoneIndexingError();"
)
code
.
putln
(
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
code
.
error_goto
(
self
.
pos
))
code
.
putln
(
"}"
)
code
.
putln
(
"}"
)
...
@@ -4515,6 +4526,9 @@ class AttributeNode(ExprNode):
...
@@ -4515,6 +4526,9 @@ class AttributeNode(ExprNode):
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
error_goto_if_null
(
self
.
result
(),
self
.
pos
)))
code
.
put_gotref
(
self
.
py_result
())
code
.
put_gotref
(
self
.
py_result
())
elif
self
.
type
.
is_memoryviewslice
:
elif
self
.
type
.
is_memoryviewslice
:
if
code
.
globalstate
.
directives
[
'nonecheck'
]:
self
.
put_nonecheck
(
code
)
if
self
.
is_memslice_transpose
:
if
self
.
is_memslice_transpose
:
# transpose the slice
# transpose the slice
for
access
,
packing
in
self
.
type
.
axes
:
for
access
,
packing
in
self
.
type
.
axes
:
...
@@ -4537,6 +4551,9 @@ class AttributeNode(ExprNode):
...
@@ -4537,6 +4551,9 @@ class AttributeNode(ExprNode):
'"Memoryview is not initialized");'
'"Memoryview is not initialized");'
'%s'
'%s'
'}'
%
(
self
.
result
(),
code
.
error_goto
(
self
.
pos
)))
'}'
%
(
self
.
result
(),
code
.
error_goto
(
self
.
pos
)))
elif
(
self
.
obj
.
type
.
is_memoryviewslice
and
code
.
globalstate
.
directives
[
'nonecheck'
]):
self
.
put_nonecheck
(
code
)
else
:
else
:
# result_code contains what is needed, but we may need to insert
# result_code contains what is needed, but we may need to insert
# a check and raise an exception
# a check and raise an exception
...
@@ -4614,7 +4631,7 @@ class AttributeNode(ExprNode):
...
@@ -4614,7 +4631,7 @@ class AttributeNode(ExprNode):
if
self
.
obj
.
type
.
is_extension_type
:
if
self
.
obj
.
type
.
is_extension_type
:
test
=
"%s == Py_None"
%
self
.
obj
.
result_as
(
PyrexTypes
.
py_object_type
)
test
=
"%s == Py_None"
%
self
.
obj
.
result_as
(
PyrexTypes
.
py_object_type
)
elif
self
.
obj
.
type
.
is_memoryviewslice
:
elif
self
.
obj
.
type
.
is_memoryviewslice
:
test
=
"
!%s.memview
"
%
self
.
obj
.
result
()
test
=
"
(PyObject *) %s.memview == Py_None
"
%
self
.
obj
.
result
()
else
:
else
:
assert
False
assert
False
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
test
))
code
.
putln
(
"if (%s) {"
%
code
.
unlikely
(
test
))
...
@@ -9647,6 +9664,16 @@ static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void) {
...
@@ -9647,6 +9664,16 @@ static CYTHON_INLINE void __Pyx_RaiseNoneIndexingError(void) {
}
}
'''
)
'''
)
raise_noneindex_memview_error_utility_code
=
UtilityCode
(
proto
=
"""
static CYTHON_INLINE void __Pyx_RaiseNoneMemviewIndexingError(void);
"""
,
impl
=
'''
static CYTHON_INLINE void __Pyx_RaiseNoneMemviewIndexingError(void) {
PyErr_SetString(PyExc_TypeError, "Cannot index None memoryview slice");
}
'''
)
raise_none_iter_error_utility_code
=
UtilityCode
(
raise_none_iter_error_utility_code
=
UtilityCode
(
proto
=
"""
proto
=
"""
static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
static CYTHON_INLINE void __Pyx_RaiseNoneNotIterableError(void);
...
...
Cython/Utility/MemoryView.pyx
View file @
5fbfb6f6
...
@@ -921,6 +921,9 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
...
@@ -921,6 +921,9 @@ cdef memoryview_fromslice({{memviewslice_name}} *memviewslice,
cdef
_memoryviewslice
result
cdef
_memoryviewslice
result
cdef
int
i
cdef
int
i
if
<
PyObject
*>
memviewslice
.
memview
==
Py_None
:
return
None
# assert 0 < ndim <= memviewslice.memview.view.ndim, (
# assert 0 < ndim <= memviewslice.memview.view.ndim, (
# ndim, memviewslice.memview.view.ndim)
# ndim, memviewslice.memview.view.ndim)
...
...
Cython/Utility/MemoryView_C.c
View file @
5fbfb6f6
...
@@ -163,9 +163,15 @@ static CYTHON_INLINE char *__pyx_memviewslice_index_full(const char *bufp, Py_ss
...
@@ -163,9 +163,15 @@ static CYTHON_INLINE char *__pyx_memviewslice_index_full(const char *bufp, Py_ss
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
obj
)
{
static
CYTHON_INLINE
{{
memviewslice_name
}}
{{
funcname
}}(
PyObject
*
obj
)
{
{{
memviewslice_name
}}
result
=
{{
memslice_init
}};
{{
memviewslice_name
}}
result
=
{{
memslice_init
}};
struct
__pyx_memoryview_obj
*
memview
;
struct
__pyx_memoryview_obj
*
memview
=
\
if
(
obj
==
Py_None
)
{
(
struct
__pyx_memoryview_obj
*
)
__pyx_memoryview_new
(
obj
,
{{
buf_flag
}},
0
);
/* We don't bother to refcount None */
result
.
memview
=
(
struct
__pyx_memoryview_obj
*
)
Py_None
;
return
result
;
}
memview
=
(
struct
__pyx_memoryview_obj
*
)
__pyx_memoryview_new
(
obj
,
{{
buf_flag
}},
0
);
__Pyx_BufFmt_StackElem
stack
[{{
struct_nesting_depth
}}];
__Pyx_BufFmt_StackElem
stack
[{{
struct_nesting_depth
}}];
int
axes_specs
[]
=
{
{{
axes_specs
}}
};
int
axes_specs
[]
=
{
{{
axes_specs
}}
};
int
retcode
;
int
retcode
;
...
@@ -419,7 +425,7 @@ __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
...
@@ -419,7 +425,7 @@ __Pyx_INC_MEMVIEW({{memviewslice_name}} *memslice, int have_gil, int lineno)
{
{
int
first_time
;
int
first_time
;
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
if
(
!
memview
)
if
(
!
memview
||
(
PyObject
*
)
memview
==
Py_None
)
return
;
/* allow uninitialized memoryview assignment */
return
;
/* allow uninitialized memoryview assignment */
if
(
memview
->
acquisition_count
<
0
)
if
(
memview
->
acquisition_count
<
0
)
...
@@ -444,7 +450,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
...
@@ -444,7 +450,7 @@ static CYTHON_INLINE void __Pyx_XDEC_MEMVIEW({{memviewslice_name}} *memslice,
int
last_time
;
int
last_time
;
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
struct
{{
memview_struct_name
}}
*
memview
=
memslice
->
memview
;
if
(
!
memview
)
if
(
!
memview
||
(
PyObject
*
)
memview
==
Py_None
)
return
;
return
;
if
(
memview
->
acquisition_count
<=
0
)
if
(
memview
->
acquisition_count
<=
0
)
...
...
docs/src/userguide/memoryviews.rst
View file @
5fbfb6f6
...
@@ -218,11 +218,15 @@ e.g. do::
...
@@ -218,11 +218,15 @@ e.g. do::
Of course, you are not restricted to using NumPy's type (such as ``np.int32_t`` here), you can use any usable type.
Of course, you are not restricted to using NumPy's type (such as ``np.int32_t`` here), you can use any usable type.
The future
None Slices
==========
===========
In the future some functionality may be added for convenience, like
Although memoryview slices are not objects they can be set to None and they can be be
checked for being None as well::
1. A numpy-like `.flat` attribute (that allows efficient iteration)
def func(double[:] myarray = None):
2. Indexing with newaxis or None to introduce a new axis
print myarray is None
Unlike object attributes of extension classes, memoryview slices are not initialized
to None.
.. _NumPy: http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#memory-layout
.. _NumPy: http://docs.scipy.org/doc/numpy/reference/arrays.ndarray.html#memory-layout
tests/run/memslice.pyx
View file @
5fbfb6f6
...
@@ -52,9 +52,8 @@ def acquire_release(o1, o2):
...
@@ -52,9 +52,8 @@ def acquire_release(o1, o2):
released A
released A
released B
released B
>>> acquire_release(None, B)
>>> acquire_release(None, B)
Traceback (most recent call last):
acquired B
...
released B
TypeError: 'NoneType' does not have the buffer interface
"""
"""
cdef
int
[:]
buf
cdef
int
[:]
buf
buf
=
o1
buf
=
o1
...
@@ -148,7 +147,7 @@ def acquire_nonbuffer1(first, second=None):
...
@@ -148,7 +147,7 @@ def acquire_nonbuffer1(first, second=None):
>>> acquire_nonbuffer1(None, 2)
>>> acquire_nonbuffer1(None, 2)
Traceback (most recent call last):
Traceback (most recent call last):
...
...
TypeError: '
NoneType
' does not have the buffer interface
TypeError: '
int
' does not have the buffer interface
>>> acquire_nonbuffer1(4, object())
>>> acquire_nonbuffer1(4, object())
Traceback (most recent call last):
Traceback (most recent call last):
...
...
...
@@ -2086,3 +2085,95 @@ def test_dtype_object_scalar_assignment():
...
@@ -2086,3 +2085,95 @@ def test_dtype_object_scalar_assignment():
(
<
object
>
m
)[:]
=
SingleObject
(
3
)
(
<
object
>
m
)[:]
=
SingleObject
(
3
)
assert
m
[
0
]
==
m
[
4
]
==
m
[
-
1
]
==
3
assert
m
[
0
]
==
m
[
4
]
==
m
[
-
1
]
==
3
#
### Test slices that are set to None
#
@
testcase
def
test_coerce_to_from_None
(
double
[:]
m1
,
double
[:]
m2
=
None
):
"""
>>> test_coerce_to_from_None(None)
(None, None)
>>> test_coerce_to_from_None(None, None)
(None, None)
"""
return
m1
,
m2
@
testcase
def
test_noneslice_attrib
(
double
[:]
m
):
"""
>>> test_noneslice_attrib(None)
'NoneType' object has no attribute 'copy'
'NoneType' object has no attribute 'T'
"""
cdef
double
[:]
m2
with
cython
.
nonecheck
(
True
):
try
:
m2
=
m
.
copy
()
except
Exception
,
e
:
print
e
.
args
[
0
]
try
:
m2
=
m
.
T
except
Exception
,
e
:
print
e
.
args
[
0
]
@
testcase
def
test_noneslice_index
(
double
[:]
m
):
"""
>>> test_noneslice_index(None)
Cannot index None memoryview slice
Cannot index None memoryview slice
Cannot index None memoryview slice
Cannot index None memoryview slice
"""
with
cython
.
nonecheck
(
True
):
try
:
m
[
10
]
except
Exception
,
e
:
print
e
.
args
[
0
]
try
:
m
[:]
except
Exception
,
e
:
print
e
.
args
[
0
]
try
:
m
[
10
]
=
2
except
Exception
,
e
:
print
e
.
args
[
0
]
try
:
m
[:]
=
2
except
Exception
,
e
:
print
e
.
args
[
0
]
@
testcase
def
test_noneslice_compare
(
double
[:]
m
):
"""
>>> test_noneslice_compare(None)
(True, True)
"""
with
cython
.
nonecheck
(
True
):
result
=
m
is
None
return
result
,
m
is
None
cdef
class
NoneSliceAttr
(
object
):
cdef
double
[:]
m
@
testcase
def
test_noneslice_ext_attr
():
"""
>>> test_noneslice_ext_attr()
AttributeError Memoryview is not initialized
None
"""
cdef
NoneSliceAttr
obj
=
NoneSliceAttr
()
with
cython
.
nonecheck
(
True
):
try
:
print
obj
.
m
except
Exception
,
e
:
print
type
(
e
).
__name__
,
e
.
args
[
0
]
obj
.
m
=
None
print
obj
.
m
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