summaryrefslogtreecommitdiff
path: root/numpy/f2py/src/fortranobject.c
diff options
context:
space:
mode:
authorWarren Weckesser <warren.weckesser@gmail.com>2017-06-27 00:25:57 -0400
committerWarren Weckesser <warren.weckesser@gmail.com>2017-08-26 03:52:52 -0400
commit1f1e8265af27e7f602a0428acf06c8201ebef915 (patch)
tree2c2f3bee1a52e41b1da3d7a68f813837e63dbdad /numpy/f2py/src/fortranobject.c
parent0725fff599e78fd2438b603a341f122e81a908fa (diff)
downloadnumpy-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.c108
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;
}
}