8000 Merge pull request #5483 from ahaldane/dtype_showtype · numpy/numpy@7ce93ba · GitHub
[go: up one dir, main page]

Skip to content

Commit 7ce93ba

committed
Merge pull request #5483 from ahaldane/dtype_showtype
ENH: Show subclass type in dtype repr and str of structured arrays
2 parents e1ff626 + 86efa7d commit 7ce93ba

File tree

3 files changed

+59
-3
lines changed

3 files changed

+59
-3
lines changed

numpy/core/records.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ def _createdescr(self, byteorder):
215215
class record(nt.void):
216216
"""A data-type scalar that allows field access as attribute lookup.
217217
"""
218+
219+
# manually set name and module so that this class's type shows up
220+
# as numpy.record when printed
221+
__name__ = 'record'
222+
__module__ = 'numpy'
223+
218224
def __repr__(self):
219225
return self.__str__()
220226

@@ -388,6 +394,12 @@ class recarray(ndarray):
388394
dtype=[('x', '<i4'), ('y', '<f8'), ('z', '<i4')])
389395
390396
"""
397+
398+
# manually set name and module so that this class's type shows
399+
# up as "numpy.recarray" when printed
400+
__name__ = 'recarray'
401+
__module__ = 'numpy'
402+
391403
def __new__(subtype, shape, dtype=None, buf=None, offset=0, strides=None,
392404
formats=None, names=None, titles=None,
393405
byteorder=None, aligned=False, order='C'):

numpy/core/src/multiarray/descriptor.c

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3159,17 +3159,61 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype, int includealignedflag)
31593159
static PyObject *
31603160
arraydescr_struct_str(PyArray_Descr *dtype, int includealignflag)
31613161
{
3162+
PyObject *sub;
3163+
31623164
/*
31633165
* The list str representation can't include the 'align=' flag,
31643166
* so if it is requested and the struct has the aligned flag set,
31653167
* we must use the dict str instead.
31663168
*/
31673169
if (!(includealignflag && (dtype->flags&NPY_ALIGNED_STRUCT)) &&
31683170
is_dtype_struct_simple_unaligned_layout(dtype)) {
3169-
return arraydescr_struct_list_str(dtype);
3171+
sub = arraydescr_struct_list_str(dtype);
3172+
}
3173+
else {
3174+
sub = arraydescr_struct_dict_str(dtype, includealignflag);
3175+
}
3176+
3177+
/* If the data type has a non-void (subclassed) type, show it */
3178+
if (dtype->type_num == NPY_VOID && dtype->typeobj != &PyVoidArrType_Type) {
3179+
/*
3180+
* Note: We cannot get the type name from dtype->typeobj->tp_name
3181+
* because its value depends on whether the type is dynamically or
3182+
* statically allocated. Instead use __name__ and __module__.
3183+
* See https://docs.python.org/2/c-api/typeobj.html.
3184+
*/
3185+
3186+
PyObject *str_name, *namestr, *str_module, *modulestr, *ret;
3187+
3188+
str_name = PyUString_FromString("__name__");
3189+
namestr = PyObject_GetAttr((PyObject*)(dtype->typeobj), str_name);
3190+
Py_DECREF(str_name);
3191+
3192+
if (namestr == NULL) {
3193+
/* this should never happen since types always have __name__ */
3194+
PyErr_Format(PyExc_RuntimeError,
3195+
"dtype does not have a __name__ attribute");
3196+
return NULL;
3197+
}
3198+
3199+
str_module = PyUString_FromString("__module__");
3200+
modulestr = PyObject_GetAttr((PyObject*)(dtype->typeobj), str_module);
3201+
Py_DECREF(str_module);
3202+
3203+
ret = PyUString_FromString("(");
3204+
if (modulestr != NULL) {
3205+
/* Note: if modulestr == NULL, the type is unpicklable */
3206+
PyUString_ConcatAndDel(&ret, modulestr);
3207+
PyUString_ConcatAndDel(&ret, PyUString_FromString("."));
3208+
}
3209+
PyUString_ConcatAndDel(&ret, namestr);
3210+
PyUString_ConcatAndDel(&ret, PyUString_FromString(", "));
3211+
PyUString_ConcatAndDel(&ret, sub);
3212+
PyUString_ConcatAndDel(&ret, PyUString_FromString(")"));
3213+
return ret;
31703214
}
31713215
else {
3172-
return arraydescr_struct_dict_str(dtype, includealignflag);
3216+
return sub;
31733217
}
31743218
}
31753219

numpy/core/tests/test_records.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def test_recarray_from_obj(self):
7474

7575
def test_recarray_from_repr(self):
7676
x = np.rec.array([ (1, 2)], dtype=[('a', np.int8), ('b', np.int8)])
77-
y = eval("np." + repr(x))
77+
y = eval("numpy." + repr(x), {'numpy': np})
7878
assert_(isinstance(y, np.recarray))
7979
assert_equal(y, x)
8080

0 commit comments

Comments
 (0)
0