diff options
author | Charles Harris <charlesr.harris@gmail.com> | 2011-03-08 20:09:38 -0700 |
---|---|---|
committer | Charles Harris <charlesr.harris@gmail.com> | 2011-03-08 20:09:38 -0700 |
commit | 4aaa4b7e500514a3bc37b515445592d17dce65b1 (patch) | |
tree | feed198a228b6ba6ff90ac2bc9620fdabef4f194 | |
parent | 3e135e222e006cb039f41a0d1af2656d59c2dbb1 (diff) | |
download | numpy-4aaa4b7e500514a3bc37b515445592d17dce65b1.tar.gz |
ENH: Make discover_dimensions pass thru all errors in list/mapping
processing except KeyError. In the latter case an object is forced.
-rw-r--r-- | numpy/core/src/multiarray/ctors.c | 41 | ||||
-rw-r--r-- | numpy/core/tests/test_multiarray.py | 23 |
2 files changed, 39 insertions, 25 deletions
diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 1da1027ad..94602a5c9 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -830,16 +830,20 @@ discover_dimensions(PyObject *s, int *maxndim, npy_intp *d, int check_it, * presence of the __len__ attribute as well. In either case it * is possible to have an object that tests as a sequence but * doesn't behave as a sequence and consequently, the - * PySequence_GetItem call can fail. When that happens we - * truncate the dimensions and set the object creation flag. - * Raising an error is another option but it might break - * backward compatibility. We could probably be a bit stricter - * here for Python 3k because there are no old type objects. + * PySequence_GetItem call can fail. When that happens and the + * object looks like a dictionary, we truncate the dimensions + * and set the object creation flag, otherwise we pass the + * error back up the call chain. */ - *maxndim = 0; - *out_is_object = 1; - PyErr_Clear(); - return 0; + if (PyErr_ExceptionMatches(PyExc_KeyError)) { + PyErr_Clear(); + *maxndim = 0; + *out_is_object = 1; + return 0; + } + else { + return -1; + } } r = discover_dimensions(e, &maxndim_m1, d + 1, check_it, stop_at_string, stop_at_tuple, @@ -855,10 +859,15 @@ discover_dimensions(PyObject *s, int *maxndim, npy_intp *d, int check_it, /* Get the dimensions of the first item */ if ((e = PySequence_GetItem(s, i)) == NULL) { /* see comment above */ - *maxndim = 0; - *out_is_object = 1; - PyErr_Clear(); - return 0; + if (PyErr_ExceptionMatches(PyExc_KeyError)) { + PyErr_Clear(); + *maxndim = 0; + *out_is_object = 1; + return 0; + } + else { + return -1; + } } r = discover_dimensions(e, &maxndim_m1, dtmp, check_it, stop_at_string, stop_at_tuple, @@ -1540,13 +1549,9 @@ PyArray_GetArrayParamsFromObject(PyObject *op, stop_at_string, stop_at_tuple, &is_object) < 0) { Py_DECREF(*out_dtype); - if (PyErr_Occurred() && - PyErr_GivenExceptionMatches(PyErr_Occurred(), - PyExc_MemoryError)) { + if (PyErr_Occurred()) { return -1; } - /* Say it's an OBJECT scalar if there's an error */ - PyErr_Clear(); *out_dtype = PyArray_DescrFromType(NPY_OBJECT); if (*out_dtype == NULL) { return -1; diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 0c2d55ae6..2f3575649 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -305,21 +305,30 @@ class TestCreation(TestCase): def test_non_sequence_sequence(self): """Should not segfault. - Class Foo breaks the sequence protocol for new style classes, i.e., - those derived from object. At some point we may raise a warning in - this case. + Class Fail breaks the sequence protocol for new style classes, i.e., + those derived from object. Class Map is a mapping type indicated by + raising a ValueError. At some point we may raise a warning instead + of an error in the Fail case. """ - class Foo(object): + class Fail(object): def __len__(self): return 1 - def __getitem__(self): - raise ValueError('hi there') + def __getitem__(self, index): + raise ValueError() - a = np.array([Foo()]) + class Map(object): + def __len__(self): + return 1 + + def __getitem__(self, index): + raise KeyError() + + a = np.array([Map()]) assert_(a.shape == (1,)) assert_(a.dtype == np.dtype(object)) + assert_raises(ValueError, np.array, [Fail()]) class TestStructured(TestCase): |