summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--numpy/core/records.py12
-rw-r--r--numpy/core/src/multiarray/descriptor.c48
-rw-r--r--numpy/core/tests/test_records.py2
3 files changed, 59 insertions, 3 deletions
diff --git a/numpy/core/records.py b/numpy/core/records.py
index 23680711f..4d912f9f4 100644
--- a/numpy/core/records.py
+++ b/numpy/core/records.py
@@ -215,6 +215,12 @@ class format_parser:
class record(nt.void):
"""A data-type scalar that allows field access as attribute lookup.
"""
+
+ # manually set name and module so that this class's type shows up
+ # as numpy.record when printed
+ __name__ = 'record'
+ __module__ = 'numpy'
+
def __repr__(self):
return self.__str__()
@@ -388,6 +394,12 @@ class recarray(ndarray):
dtype=[('x', '<i4'), ('y', '<f8'), ('z', '<i4')])
"""
+
+ # manually set name and module so that this class's type shows
+ # up as "numpy.recarray" when printed
+ __name__ = 'recarray'
+ __module__ = 'numpy'
+
def __new__(subtype, shape, dtype=None, buf=None, offset=0, strides=None,
formats=None, names=None, titles=None,
byteorder=None, aligned=False, order='C'):
diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c
index 9cf66020d..0993190b7 100644
--- a/numpy/core/src/multiarray/descriptor.c
+++ b/numpy/core/src/multiarray/descriptor.c
@@ -3159,6 +3159,8 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype, int includealignedflag)
static PyObject *
arraydescr_struct_str(PyArray_Descr *dtype, int includealignflag)
{
+ PyObject *sub;
+
/*
* The list str representation can't include the 'align=' flag,
* so if it is requested and the struct has the aligned flag set,
@@ -3166,10 +3168,52 @@ arraydescr_struct_str(PyArray_Descr *dtype, int includealignflag)
*/
if (!(includealignflag && (dtype->flags&NPY_ALIGNED_STRUCT)) &&
is_dtype_struct_simple_unaligned_layout(dtype)) {
- return arraydescr_struct_list_str(dtype);
+ sub = arraydescr_struct_list_str(dtype);
+ }
+ else {
+ sub = arraydescr_struct_dict_str(dtype, includealignflag);
+ }
+
+ /* If the data type has a non-void (subclassed) type, show it */
+ if (dtype->type_num == NPY_VOID && dtype->typeobj != &PyVoidArrType_Type) {
+ /*
+ * Note: We cannot get the type name from dtype->typeobj->tp_name
+ * because its value depends on whether the type is dynamically or
+ * statically allocated. Instead use __name__ and __module__.
+ * See https://docs.python.org/2/c-api/typeobj.html.
+ */
+
+ PyObject *str_name, *namestr, *str_module, *modulestr, *ret;
+
+ str_name = PyUString_FromString("__name__");
+ namestr = PyObject_GetAttr((PyObject*)(dtype->typeobj), str_name);
+ Py_DECREF(str_name);
+
+ if (namestr == NULL) {
+ /* this should never happen since types always have __name__ */
+ PyErr_Format(PyExc_RuntimeError,
+ "dtype does not have a __name__ attribute");
+ return NULL;
+ }
+
+ str_module = PyUString_FromString("__module__");
+ modulestr = PyObject_GetAttr((PyObject*)(dtype->typeobj), str_module);
+ Py_DECREF(str_module);
+
+ ret = PyUString_FromString("(");
+ if (modulestr != NULL) {
+ /* Note: if modulestr == NULL, the type is unpicklable */
+ PyUString_ConcatAndDel(&ret, modulestr);
+ PyUString_ConcatAndDel(&ret, PyUString_FromString("."));
+ }
+ PyUString_ConcatAndDel(&ret, namestr);
+ PyUString_ConcatAndDel(&ret, PyUString_FromString(", "));
+ PyUString_ConcatAndDel(&ret, sub);
+ PyUString_ConcatAndDel(&ret, PyUString_FromString(")"));
+ return ret;
}
else {
- return arraydescr_struct_dict_str(dtype, includealignflag);
+ return sub;
}
}
diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py
index 355e5480a..0c20f1693 100644
--- a/numpy/core/tests/test_records.py
+++ b/numpy/core/tests/test_records.py
@@ -74,7 +74,7 @@ class TestFromrecords(TestCase):
def test_recarray_from_repr(self):
x = np.rec.array([ (1, 2)], dtype=[('a', np.int8), ('b', np.int8)])
- y = eval("np." + repr(x))
+ y = eval("numpy." + repr(x), {'numpy': np})
assert_(isinstance(y, np.recarray))
assert_equal(y, x)