diff options
-rw-r--r-- | numpy/core/records.py | 12 | ||||
-rw-r--r-- | numpy/core/src/multiarray/descriptor.c | 48 | ||||
-rw-r--r-- | numpy/core/tests/test_records.py | 2 |
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) |