8000 ENH: missingdata: Change NA repr to use strings like the dtype repr does · numpy/numpy@9d9f549 · GitHub
[go: up one dir, main page]

Skip to content

Commit 9d9f549

Browse files
committed
ENH: missingdata: Change NA repr to use strings like the dtype repr does
1 parent a702e7e commit 9d9f549

File tree

5 files changed

+77
-53
lines changed

5 files changed

+77
-53
lines changed

numpy/core/src/multiarray/descriptor.c

Lines changed: 50 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2764,15 +2764,15 @@ arraydescr_struct_list_str(PyArray_Descr *dtype)
27642764
}
27652765
/* Special case subarray handling here */
27662766
if (PyDataType_HASSUBARRAY(fld_dtype)) {
2767-
tmp = arraydescr_short_construction_repr(
2768-
fld_dtype->subarray->base, 0);
2767+
tmp = arraydescr_construction_repr(
2768+
fld_dtype->subarray->base, 0, 1);
27692769
PyUString_ConcatAndDel(&ret, tmp);
27702770
PyUString_ConcatAndDel(&ret, PyUString_FromString(", "));
27712771
PyUString_ConcatAndDel(&ret,
27722772
PyObject_Str(fld_dtype->subarray->shape));
27732773
}
27742774
else {
2775-
tmp = arraydescr_short_construction_repr(fld_dtype, 0);
2775+
tmp = arraydescr_construction_repr(fld_dtype, 0, 1);
27762776
PyUString_ConcatAndDel(&ret, tmp);
27772777
}
27782778
PyUString_ConcatAndDel(&ret, PyUString_FromString(")"));
@@ -2830,7 +2830,7 @@ arraydescr_struct_dict_str(PyArray_Descr *dtype, int includealignedflag)
28302830
if (title != NULL && title != Py_None) {
28312831
has_titles = 1;
28322832
}
2833-
tmp = arraydescr_short_construction_repr(fld_dtype, 0);
2833+
tmp = arraydescr_construction_repr(fld_dtype, 0, 1);
28342834
PyUString_ConcatAndDel(&ret, tmp);
28352835
if (i != names_size - 1) {
28362836
PyUString_ConcatAndDel(&ret, PyUString_FromString(","));
@@ -2914,7 +2914,7 @@ arraydescr_subarray_str(PyArray_Descr *dtype)
29142914
PyObject *p, *ret;
29152915

29162916
ret = PyUString_FromString("(");
2917-
p = arraydescr_short_construction_repr(dtype->subarray->base, 0);
2917+
p = arraydescr_construction_repr(dtype->subarray->base, 0, 1);
29182918
PyUString_ConcatAndDel(&ret, p);
29192919
PyUString_ConcatAndDel(&ret, PyUString_FromString(", "));
29202920
PyUString_ConcatAndDel(&ret, PyObject_Str(dtype->subarray->shape));
@@ -2968,26 +2968,10 @@ arraydescr_struct_repr(PyArray_Descr *dtype)
29682968
return s;
29692969
}
29702970

2971-
/*
2972-
* This creates a shorter repr using 'kind' and 'itemsize',
2973-
* instead of the longer type name. This is the object passed
2974-
* as the first parameter to the dtype constructor, and if no
2975-
* additional constructor parameters are given, will reproduce
2976-
* the exact memory layout.
2977-
*
2978-
* If 'includealignflag' is true, this includes the 'align=True' 10000 parameter
2979-
* inside the struct dtype construction dict when needed. Use this flag
2980-
* if you want a proper repr string without the 'dtype()' part around it.
2981-
*
2982-
* If 'includealignflag' is false, this does not preserve the
2983-
* 'align=True' parameter or sticky NPY_ALIGNED_STRUCT flag for
2984-
* struct arrays like the regular repr does, because the 'align'
2985-
* flag is not part of first dtype constructor parameter. This
2986-
* mode is intended for a full 'repr', where the 'align=True' is
2987-
* provided as the second parameter.
2988-
*/
2971+
/* See descriptor.h for documentation */
29892972
NPY_NO_EXPORT PyObject *
2990-
arraydescr_short_construction_repr(PyArray_Descr *dtype, int includealignflag)
2973+
arraydescr_construction_repr(PyArray_Descr *dtype, int includealignflag,
2974+
int shortrepr)
29912975
{
29922976
PyObject *ret;
29932977
PyArray_DatetimeMetaData *meta;
@@ -3019,11 +3003,44 @@ arraydescr_short_construction_repr(PyArray_Descr *dtype, int includealignflag)
30193003

30203004
/* Handle booleans, numbers, and custom dtypes */
30213005
if (dtype->type_num == NPY_BOOL) {
3022-
return PyUString_FromString("'?'");
3006+
if (shortrepr) {
3007+
return PyUString_FromString("'?'");
3008+
}
3009+
else {
3010+
return PyUString_FromString("'bool'");
3011+
}
30233012
}
30243013
else if (PyTypeNum_ISNUMBER(dtype->type_num)) {
3025-
return PyUString_FromFormat("'%s%c%d'", byteorder, (int)dtype->kind,
3026-
dtype->elsize);
3014+
/* Short repr with endianness, like '<f8' */
3015+
if (shortrepr || (dtype->byteorder != NPY_NATIVE &&
3016+
dtype->byteorder != NPY_IGNORE)) {
3017+
return PyUString_FromFormat("'%s%c%d'", byteorder,
3018+
(int)dtype->kind, dtype->elsize);
3019+
}
3020+
/* Longer repr, like 'float64' */
3021+
else {
3022+
char *kindstr;
3023+
switch (dtype->kind) {
3024+
case 'u':
3025+
kindstr = "uint";
3026+
break;
3027+
case 'i':
3028+
kindstr = "int";
3029+
break;
3030+
case 'f':
3031+
kindstr = "float";
3032+
break;
3033+
case 'c':
3034+
kindstr = "complex";
3035+
break;
3036+
default:
3037+
PyErr_Format(PyExc_RuntimeError,
3038+
"internal dtype repr error, unknown kind '%c'",
3039+
(int)dtype->kind);
3040+
return NULL;
3041+
}
3042+
return PyUString_FromFormat("'%s%d'", kindstr, 8*dtype->elsize);
3043+
}
30273044
}
30283045
else if (PyTypeNum_ISUSERDEF(dtype->type_num)) {
30293046
char *s = strrchr(dtype->typeobj->tp_name, '.');
@@ -3102,27 +3119,17 @@ arraydescr_short_construction_repr(PyArray_Descr *dtype, int includealignflag)
31023119
static PyObject *
31033120
arraydescr_repr(PyArray_Descr *dtype)
31043121
{
3105-
PyObject *sub, *s;
3122+
PyObject *ret;
31063123

31073124
if (PyDataType_HASFIELDS(dtype)) {
31083125
return arraydescr_struct_repr(dtype);
31093126
}
31103127
else {
3111-
s = PyUString_FromString("dtype(");
3112-
sub = arraydescr_str(dtype);
3113-
if (sub == NULL) {
3114-
return NULL;
3115-
}
3116-
if (!PyDataType_HASSUBARRAY(dtype)) {
3117-
PyObject *t=PyUString_FromString("'");
3118-
PyUString_Concat(&sub, t);
3119-
PyUString_ConcatAndDel(&t, sub);
3120-
sub = t;
3121-
}
3122-
PyUString_ConcatAndDel(&s, sub);
3123-
sub = PyUString_FromString(")");
3124-
PyUString_ConcatAndDel(&s, sub);
3125-
return s;
3128+
ret = PyUString_FromString("dtype(");
3129+
PyUString_ConcatAndDel(&ret,
3130+
arraydescr_construction_repr(dtype, 1, 0));
3131+
PyUString_ConcatAndDel(&ret, PyUString_FromString(")"));
3132+
return ret;
31263133
}
31273134
}
31283135

numpy/core/src/multiarray/descriptor.h

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,15 @@ NPY_NO_EXPORT PyArray_Descr *
1111
_arraydescr_fromobj(PyObject *obj);
1212

1313
/*
14-
* This creates a shorter repr using 'kind' and 'itemsize',
15-
* instead of the longer type name. This is the object passed
16-
* as the first parameter to the dtype constructor, and if no
17-
* additional constructor parameters are given, will reproduce
18-
* the exact memory layout.
14+
* Creates a string repr of the dtype, excluding the 'dtype()' part
15+
* surrounding the object. This object may be a string, a list, or
16+
* a dict depending on the nature of the dtype. This
17+
* is the object passed as the first parameter to the dtype
18+
* constructor, and if no additional constructor parameters are
19+
* given, will reproduce the exact memory layout.
20+
*
21+
* If 'shortrepr' is non-zero, this creates a shorter repr using
22+
* 'kind' and 'itemsize', instead of the longer type name.
1923
*
2024
* If 'includealignflag' is true, this includes the 'align=True' parameter
2125
* inside the struct dtype construction dict when needed. Use this flag
@@ -29,7 +33,8 @@ _arraydescr_fromobj(PyObject *obj);
2933
* provided as the second parameter.
3034
*/
3135
NPY_NO_EXPORT PyObject *
32-
arraydescr_short_construction_repr(PyArray_Descr *dtype, int includealignflag);
36+
arraydescr_construction_repr(PyArray_Descr *dtype, int includealignflag,
37+
int shortrepr);
3338

3439
#ifdef NPY_ENABLE_SEPARATE_COMPILATION
3540
extern NPY_NO_EXPORT char *_datetime_strings[];

numpy/core/src/multiarray/na_singleton.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ na_repr(NpyNA_fields *self)
120120
s = PyUString_FromFormat("NA(%d, dtype=", (int)self->payload);
121121
}
122122
PyUString_ConcatAndDel(&s,
123-
arraydescr_short_construction_repr(self->dtype, 1));
123+
arraydescr_construction_repr(self->dtype, 1, 0));
124124
PyUString_ConcatAndDel(&s,
125125
PyUString_FromString(")"));
126126
return s;

numpy/core/src/multiarray/nditer_api.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -745,7 +745,8 @@ NpyIter_IsFirstVisit(NpyIter *iter, int iop)
745745
/*
746746
* In reduction buffering mode, there's a double loop being
747747
* tracked in the buffer part of the iterator data structure.
748-
* We need to check the two levels of that loop as well.
748+
* We only need to check the outer level of this two-level loop,
749+
* because of the requirement that EXTERNAL_LOOP be enabled.
749750
*/
750751
if (itflags&NPY_ITFLAG_BUFFER) {
751752
NpyIter_BufferData *bufferdata = NIT_BUFFERDATA(iter);

numpy/core/tests/test_na.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,21 @@ def test_na_repr():
5858
assert_equal(repr(np.NA(10)), 'NA(10)')
5959

6060
# With just a dtype
61-
assert_equal(repr(np.NA(dtype='>c16')), "NA(dtype='>c16')")
61+
assert_equal(repr(np.NA(dtype='?')), "NA(dtype='bool')")
62+
if sys.byteorder == 'little':
63+
assert_equal(repr(np.NA(dtype='<c16')), "NA(dtype='complex128')")
64+
assert_equal(repr(np.NA(dtype='>c16')), "NA(dtype='>c16')")
65+
else:
66+
assert_equal(repr(np.NA(dtype='>c16')), "NA(dtype='complex128')")
67+
assert_equal(repr(np.NA(dtype='<c16')), "NA(dtype='<c16')")
6268

6369
# With a payload and a dtype
64-
assert_equal(repr(np.NA(10, dtype='>f4')), "NA(10, dtype='>f4')")
70+
if sys.byteorder == 'little':
71+
assert_equal(repr(np.NA(10, dtype='<f4')), "NA(10, dtype='float32')")
72+
assert_equal(repr(np.NA(10, dtype='>f4')), "NA(10, dtype='>f4')")
73+
else:
74+
assert_equal(repr(np.NA(10, dtype='>f4')), "NA(10, dtype='float32')")
75+
assert_equal(repr(np.NA(10, dtype='<f4')), "NA(10, dtype='<f4')")
6576

6677
def test_na_comparison():
6778
# NA cannot be converted to a boolean

0 commit comments

Comments
 (0)
0