summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Harris <charlesr.harris@gmail.com>2011-03-08 20:09:38 -0700
committerCharles Harris <charlesr.harris@gmail.com>2011-03-08 20:09:38 -0700
commit4aaa4b7e500514a3bc37b515445592d17dce65b1 (patch)
treefeed198a228b6ba6ff90ac2bc9620fdabef4f194
parent3e135e222e006cb039f41a0d1af2656d59c2dbb1 (diff)
downloadnumpy-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.c41
-rw-r--r--numpy/core/tests/test_multiarray.py23
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):