Commit 05f7a479 authored by da-woods's avatar da-woods Committed by GitHub

Make memoryviews work with cache_builtins=False (GH-3415)

Now they make their own tiny cache of the relevant exceptions at module initialization so they can still access these without the GIL.

closes https://github.com/cython/cython/issues/3406
parent e6723d4d
...@@ -8,8 +8,12 @@ cimport cython ...@@ -8,8 +8,12 @@ cimport cython
# from cpython cimport ... # from cpython cimport ...
cdef extern from "Python.h": cdef extern from "Python.h":
ctypedef struct PyObject
int PyIndex_Check(object) int PyIndex_Check(object)
object PyLong_FromVoidPtr(void *) object PyLong_FromVoidPtr(void *)
PyObject *PyExc_IndexError
PyObject *PyExc_ValueError
PyObject *PyExc_MemoryError
cdef extern from "pythread.h": cdef extern from "pythread.h":
ctypedef void *PyThread_type_lock ctypedef void *PyThread_type_lock
...@@ -94,9 +98,6 @@ cdef extern from "<stdlib.h>": ...@@ -94,9 +98,6 @@ cdef extern from "<stdlib.h>":
void free(void *) nogil void free(void *) nogil
void *memcpy(void *dest, void *src, size_t n) nogil void *memcpy(void *dest, void *src, size_t n) nogil
# #
### cython.array class ### cython.array class
# #
...@@ -829,13 +830,13 @@ cdef int slice_memviewslice( ...@@ -829,13 +830,13 @@ cdef int slice_memviewslice(
if start < 0: if start < 0:
start += shape start += shape
if not 0 <= start < shape: if not 0 <= start < shape:
_err_dim(IndexError, "Index out of bounds (axis %d)", dim) _err_dim(PyExc_IndexError, "Index out of bounds (axis %d)", dim)
else: else:
# index is a slice # index is a slice
negative_step = have_step != 0 and step < 0 negative_step = have_step != 0 and step < 0
if have_step and step == 0: if have_step and step == 0:
_err_dim(ValueError, "Step may not be zero (axis %d)", dim) _err_dim(PyExc_ValueError, "Step may not be zero (axis %d)", dim)
# check our bounds and set defaults # check our bounds and set defaults
if have_start: if have_start:
...@@ -896,7 +897,7 @@ cdef int slice_memviewslice( ...@@ -896,7 +897,7 @@ cdef int slice_memviewslice(
if new_ndim == 0: if new_ndim == 0:
dst.data = (<char **> dst.data)[0] + suboffset dst.data = (<char **> dst.data)[0] + suboffset
else: else:
_err_dim(IndexError, "All dimensions preceding dimension %d " _err_dim(PyExc_IndexError, "All dimensions preceding dimension %d "
"must be indexed and not sliced", dim) "must be indexed and not sliced", dim)
else: else:
suboffset_dim[0] = new_ndim suboffset_dim[0] = new_ndim
...@@ -954,7 +955,7 @@ cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0: ...@@ -954,7 +955,7 @@ cdef int transpose_memslice({{memviewslice_name}} *memslice) nogil except 0:
shape[i], shape[j] = shape[j], shape[i] shape[i], shape[j] = shape[j], shape[i]
if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0: if memslice.suboffsets[i] >= 0 or memslice.suboffsets[j] >= 0:
_err(ValueError, "Cannot transpose memoryview with indirect dimensions") _err(PyExc_ValueError, "Cannot transpose memoryview with indirect dimensions")
return 1 return 1
...@@ -1221,7 +1222,7 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src, ...@@ -1221,7 +1222,7 @@ cdef void *copy_data_to_temp({{memviewslice_name}} *src,
result = malloc(size) result = malloc(size)
if not result: if not result:
_err(MemoryError, NULL) _err(PyExc_MemoryError, NULL)
# tmpslice[0] = src # tmpslice[0] = src
tmpslice.data = <char *> result tmpslice.data = <char *> result
...@@ -1254,15 +1255,15 @@ cdef int _err_extents(int i, Py_ssize_t extent1, ...@@ -1254,15 +1255,15 @@ cdef int _err_extents(int i, Py_ssize_t extent1,
(i, extent1, extent2)) (i, extent1, extent2))
@cname('__pyx_memoryview_err_dim') @cname('__pyx_memoryview_err_dim')
cdef int _err_dim(object error, char *msg, int dim) except -1 with gil: cdef int _err_dim(PyObject *error, char *msg, int dim) except -1 with gil:
raise error(msg.decode('ascii') % dim) raise (<object>error)(msg.decode('ascii') % dim)
@cname('__pyx_memoryview_err') @cname('__pyx_memoryview_err')
cdef int _err(object error, char *msg) except -1 with gil: cdef int _err(PyObject *error, char *msg) except -1 with gil:
if msg != NULL: if msg != NULL:
raise error(msg.decode('ascii')) raise (<object>error)(msg.decode('ascii'))
else: else:
raise error raise (<object>error)
@cname('__pyx_memoryview_copy_contents') @cname('__pyx_memoryview_copy_contents')
cdef int memoryview_copy_contents({{memviewslice_name}} src, cdef int memoryview_copy_contents({{memviewslice_name}} src,
...@@ -1297,7 +1298,7 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src, ...@@ -1297,7 +1298,7 @@ cdef int memoryview_copy_contents({{memviewslice_name}} src,
_err_extents(i, dst.shape[i], src.shape[i]) _err_extents(i, dst.shape[i], src.shape[i])
if src.suboffsets[i] >= 0: if src.suboffsets[i] >= 0:
_err_dim(ValueError, "Dimension %d is not direct", i) _err_dim(PyExc_ValueError, "Dimension %d is not direct", i)
if slices_overlap(&src, &dst, ndim, itemsize): if slices_overlap(&src, &dst, ndim, itemsize):
# slices overlap, copy to temp, copy temp to dst # slices overlap, copy to temp, copy temp to dst
......
...@@ -24,16 +24,16 @@ def foo(dtype_t[:] a, dtype_t_out[:, :] b): ...@@ -24,16 +24,16 @@ def foo(dtype_t[:] a, dtype_t_out[:, :] b):
_WARNINGS = """ _WARNINGS = """
22:10: 'cpdef_method' redeclared 22:10: 'cpdef_method' redeclared
33:10: 'cpdef_cname_method' redeclared 33:10: 'cpdef_cname_method' redeclared
446:72: Argument evaluation order in C function call is undefined and may not be as expected 447:72: Argument evaluation order in C function call is undefined and may not be as expected
446:72: Argument evaluation order in C function call is undefined and may not be as expected 447:72: Argument evaluation order in C function call is undefined and may not be as expected
749:34: Argument evaluation order in C function call is undefined and may not be as expected 750:34: Argument evaluation order in C function call is undefined and may not be as expected
749:34: Argument evaluation order in C function call is undefined and may not be as expected 750:34: Argument evaluation order in C function call is undefined and may not be as expected
943:27: Ambiguous exception value, same as default return value: 0 944:27: Ambiguous exception value, same as default return value: 0
943:27: Ambiguous exception value, same as default return value: 0 944:27: Ambiguous exception value, same as default return value: 0
974:29: Ambiguous exception value, same as default return value: 0 975:29: Ambiguous exception value, same as default return value: 0
974:29: Ambiguous exception value, same as default return value: 0 975:29: Ambiguous exception value, same as default return value: 0
1002:46: Ambiguous exception value, same as default return value: 0 1003:46: Ambiguous exception value, same as default return value: 0
1002:46: Ambiguous exception value, same as default return value: 0 1003:46: Ambiguous exception value, same as default return value: 0
1092:29: Ambiguous exception value, same as default return value: 0 1093:29: Ambiguous exception value, same as default return value: 0
1092:29: Ambiguous exception value, same as default return value: 0 1093:29: Ambiguous exception value, same as default return value: 0
""" """
PYTHON setup.py build_ext --inplace
################ setup.py #####################
from distutils.core import setup
from Cython.Build import cythonize
from Cython.Compiler import Options
Options.cache_builtins = False
setup(
ext_modules = cythonize("mview.pyx")
)
############### mview.pyx ################
# https://github.com/cython/cython/issues/3406
# Failure was at Cython compilation stage
def f(double [::1] x):
pass
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment