diff options
author | Warren Weckesser <warren.weckesser@gmail.com> | 2017-06-27 00:25:57 -0400 |
---|---|---|
committer | Warren Weckesser <warren.weckesser@gmail.com> | 2017-08-26 03:52:52 -0400 |
commit | 1f1e8265af27e7f602a0428acf06c8201ebef915 (patch) | |
tree | 2c2f3bee1a52e41b1da3d7a68f813837e63dbdad /numpy/f2py/src/fortranobject.c | |
parent | 0725fff599e78fd2438b603a341f122e81a908fa (diff) | |
download | numpy-1f1e8265af27e7f602a0428acf06c8201ebef915.tar.gz |
BUG: f2py: Convert some error messages printed to stderr to exceptions.
In f2py/src/fortranobject.c, the function `check_and_fix_dimensions` does
pretty much what it says on the tin:
/*
This function fills in blanks (that are -1\'s) in dims list using
the dimensions from arr. It also checks that non-blank dims will
match with the corresponding values in arr dimensions.
*/
There are several error conditions detected by the function. In the code
before this change, when the function detected such an error, it would
print a message to stderr and return 1.
In this change, when an error is detected in `check_and_fix_dimensions`,
an exception is set.
This new feature of `check_and_fix_dimensions` is used in three places
in the function `array_from_pyobj()`.
In each case, there was an old comment of the form:
/* XXX: set exception */
In this change, the exception is now set in `check_and_fix_dimensions()`,
so those comments have been removed.
For some error conditions, the new code changes the exception that is
raised. For example, here's a scipy test before this change:
```
In [5]: from scipy.linalg import _fblas as fblas
In [6]: a = np.array([[1., 0.], [0., -2.], [2., 3.]])
In [7]: b = np.array([[0., 1.], [1., 0.], [0, 1.]])
In [8]: fblas.dsyr2k(a=a, b=b, alpha=1.0, c=np.zeros((15, 8)))
0-th dimension must be fixed to 3 but got 15
---------------------------------------------------------------------------
error Traceback (most recent call last)
<ipython-input-8-bc4d51f8d016> in <module>()
----> 1 f(a=a, b=b, alpha=1.0, c=np.zeros((15, 8)))
error: failed in converting 2nd keyword `c' of _fblas.dsyr2k to C/Fortran array
```
After this change, we get:
```
In [2]: from scipy.linalg import _fblas as fblas
In [3]: a = np.array([[1., 0.], [0., -2.], [2., 3.]])
In [4]: b = np.array([[0., 1.], [1., 0.], [0, 1.]])
In [5]: fblas.dsyr2k(a=a, b=b, alpha=1.0, c=np.zeros((15, 8)))
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-6-bc4d51f8d016> in <module>()
----> 1 f(a=a, b=b, alpha=1.0, c=np.zeros((15, 8)))
ValueError: 0-th dimension must be fixed to 3 but got 15
```
The spurious print has been changed to the exception message, but some
potentially useful information in the old exception message has been
lost.
Diffstat (limited to 'numpy/f2py/src/fortranobject.c')
-rw-r--r-- | numpy/f2py/src/fortranobject.c | 108 |
1 files changed, 70 insertions, 38 deletions
diff --git a/numpy/f2py/src/fortranobject.c b/numpy/f2py/src/fortranobject.c index 72854db47..f2036c427 100644 --- a/numpy/f2py/src/fortranobject.c +++ b/numpy/f2py/src/fortranobject.c @@ -590,6 +590,10 @@ static void f2py_report_on_array_copy_fromany(void) { * $Id: fortranobject.c,v 1.52 2005/07/11 07:44:20 pearu Exp $ */ +static int check_and_fix_dimensions(const PyArrayObject* arr, + const int rank, + npy_intp *dims); + static int count_nonpos(const int rank, const npy_intp *dims) { @@ -601,10 +605,6 @@ count_nonpos(const int rank, return r; } -static int check_and_fix_dimensions(const PyArrayObject* arr, - const int rank, - npy_intp *dims); - #ifdef DEBUG_COPY_ND_ARRAY void dump_dims(int rank, npy_intp* dims) { int i; @@ -719,8 +719,8 @@ PyArrayObject* array_from_pyobj(const int type_num, /* intent(cache) */ if (PyArray_ISONESEGMENT(arr) && PyArray_ITEMSIZE(arr)>=elsize) { - if (check_and_fix_dimensions(arr,rank,dims)) { - return NULL; /*XXX: set exception */ + if (check_and_fix_dimensions(arr, rank, dims)) { + return NULL; } if (intent & F2PY_INTENT_OUT) Py_INCREF(arr); @@ -741,8 +741,8 @@ PyArrayObject* array_from_pyobj(const int type_num, /* here we have always intent(in) or intent(inout) or intent(inplace) */ - if (check_and_fix_dimensions(arr,rank,dims)) { - return NULL; /*XXX: set exception */ + if (check_and_fix_dimensions(arr, rank, dims)) { + return NULL; } /* printf("intent alignement=%d\n", F2PY_GET_ALIGNMENT(intent)); @@ -842,8 +842,9 @@ PyArrayObject* array_from_pyobj(const int type_num, | NPY_ARRAY_FORCECAST, NULL); if (arr==NULL) return NULL; - if (check_and_fix_dimensions(arr,rank,dims)) - return NULL; /*XXX: set exception */ + if (check_and_fix_dimensions(arr, rank, dims)) { + return NULL; + } return arr; } @@ -854,11 +855,16 @@ PyArrayObject* array_from_pyobj(const int type_num, /*****************************************/ static -int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *dims) { +int check_and_fix_dimensions(const PyArrayObject* arr, const int rank, npy_intp *dims) +{ /* - This function fills in blanks (that are -1\'s) in dims list using + This function fills in blanks (that are -1's) in dims list using the dimensions from arr. It also checks that non-blank dims will match with the corresponding values in arr dimensions. + + Returns 0 if the function is successful. + + If an error condition is detected, an exception is set and 1 is returned. */ const npy_intp arr_size = (PyArray_NDIM(arr))?PyArray_Size((PyObject *)arr):1; #ifdef DEBUG_COPY_ND_ARRAY @@ -876,9 +882,10 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d d = PyArray_DIM(arr,i); if (dims[i] >= 0) { if (d>1 && dims[i]!=d) { - fprintf(stderr,"%d-th dimension must be fixed to %" NPY_INTP_FMT - " but got %" NPY_INTP_FMT "\n", - i,dims[i], d); + PyErr_Format(PyExc_ValueError, + "%d-th dimension must be fixed to %" + NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n", + i, dims[i], d); return 1; } if (!dims[i]) dims[i] = 1; @@ -889,9 +896,10 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d } for(i=PyArray_NDIM(arr);i<rank;++i) if (dims[i]>1) { - fprintf(stderr,"%d-th dimension must be %" NPY_INTP_FMT - " but got 0 (not defined).\n", - i,dims[i]); + PyErr_Format(PyExc_ValueError, + "%d-th dimension must be %" NPY_INTP_FMT + " but got 0 (not defined).\n", + i, dims[i]); return 1; } else if (free_axe<0) free_axe = i; @@ -902,9 +910,11 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d new_size *= dims[free_axe]; } if (new_size != arr_size) { - fprintf(stderr,"unexpected array size: new_size=%" NPY_INTP_FMT - ", got array with arr_size=%" NPY_INTP_FMT " (maybe too many free" - " indices)\n", new_size,arr_size); + PyErr_Format(PyExc_ValueError, + "unexpected array size: new_size=%" NPY_INTP_FMT + ", got array with arr_size=%" NPY_INTP_FMT + " (maybe too many free indices)\n", + new_size, arr_size); return 1; } } else if (rank==PyArray_NDIM(arr)) { @@ -915,9 +925,10 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d d = PyArray_DIM(arr,i); if (dims[i]>=0) { if (d > 1 && d!=dims[i]) { - fprintf(stderr,"%d-th dimension must be fixed to %" NPY_INTP_FMT - " but got %" NPY_INTP_FMT "\n", - i,dims[i],d); + PyErr_Format(PyExc_ValueError, + "%d-th dimension must be fixed to %" + NPY_INTP_FMT " but got %" NPY_INTP_FMT "\n", + i, dims[i], d); return 1; } if (!dims[i]) dims[i] = 1; @@ -925,8 +936,10 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d new_size *= dims[i]; } if (new_size != arr_size) { - fprintf(stderr,"unexpected array size: new_size=%" NPY_INTP_FMT - ", got array with arr_size=%" NPY_INTP_FMT "\n", new_size,arr_size); + PyErr_Format(PyExc_ValueError, + "unexpected array size: new_size=%" NPY_INTP_FMT + ", got array with arr_size=%" NPY_INTP_FMT "\n", + new_size, arr_size); return 1; } } else { /* [[1,2]] -> [[1],[2]] */ @@ -938,8 +951,10 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d if (PyArray_DIM(arr,i)>1) ++effrank; if (dims[rank-1]>=0) if (effrank>rank) { - fprintf(stderr,"too many axes: %d (effrank=%d), expected rank=%d\n", - PyArray_NDIM(arr),effrank,rank); + PyErr_Format(PyExc_ValueError, + "too many axes: %d (effrank=%d), " + "expected rank=%d\n", + PyArray_NDIM(arr), effrank, rank); return 1; } @@ -949,9 +964,11 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d else d = PyArray_DIM(arr,j++); if (dims[i]>=0) { if (d>1 && d!=dims[i]) { - fprintf(stderr,"%d-th dimension must be fixed to %" NPY_INTP_FMT - " but got %" NPY_INTP_FMT " (real index=%d)\n", - i,dims[i],d,j-1); + PyErr_Format(PyExc_ValueError, + "%d-th dimension must be fixed to %" + NPY_INTP_FMT " but got %" NPY_INTP_FMT + " (real index=%d)\n", + i, dims[i], d, j-1); return 1; } if (!dims[i]) dims[i] = 1; @@ -967,13 +984,28 @@ int check_and_fix_dimensions(const PyArrayObject* arr,const int rank,npy_intp *d } for (i=0,size=1;i<rank;++i) size *= dims[i]; if (size != arr_size) { - fprintf(stderr,"unexpected array size: size=%" NPY_INTP_FMT ", arr_size=%" NPY_INTP_FMT - ", rank=%d, effrank=%d, arr.nd=%d, dims=[", - size,arr_size,rank,effrank,PyArray_NDIM(arr)); - for (i=0;i<rank;++i) fprintf(stderr," %" NPY_INTP_FMT,dims[i]); - fprintf(stderr," ], arr.dims=["); - for (i=0;i<PyArray_NDIM(arr);++i) fprintf(stderr," %" NPY_INTP_FMT,PyArray_DIM(arr,i)); - fprintf(stderr," ]\n"); + char msg[200]; + int len; + snprintf(msg, sizeof(msg), + "unexpected array size: size=%" NPY_INTP_FMT + ", arr_size=%" NPY_INTP_FMT + ", rank=%d, effrank=%d, arr.nd=%d, dims=[", + size, arr_size, rank, effrank, PyArray_NDIM(arr)); + for (i = 0; i < rank; ++i) { + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, + " %" NPY_INTP_FMT, dims[i]); + } + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " ], arr.dims=["); + for (i = 0; i < PyArray_NDIM(arr); ++i) { + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, + " %" NPY_INTP_FMT, PyArray_DIM(arr, i)); + } + len = strlen(msg); + snprintf(msg + len, sizeof(msg) - len, " ]\n"); + PyErr_SetString(PyExc_ValueError, msg); return 1; } } |