From 7a3344a461fdb25c55cd5e4fa52abda895f01e20 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 11 Jan 2018 22:15:01 -0800 Subject: BUG: Fix crash on non-void structured array repr Fixes gh-9821 --- numpy/core/arrayprint.py | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'numpy/core/arrayprint.py') diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index 62f967131..3554fe3c4 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -365,9 +365,6 @@ def _get_format_function(data, **options): find the right formatting function for the dtype_ """ dtype_ = data.dtype - if dtype_.fields is not None: - return StructureFormat.from_data(data, **options) - dtypeobj = dtype_.type formatdict = _get_formatdict(data, **options) if issubclass(dtypeobj, _nt.bool_): @@ -394,7 +391,10 @@ def _get_format_function(data, **options): elif issubclass(dtypeobj, _nt.object_): return formatdict['object']() elif issubclass(dtypeobj, _nt.void): - return formatdict['void']() + if dtype_.names is not None: + return StructuredVoidFormat.from_data(data, **options) + else: + return formatdict['void']() else: return formatdict['numpystr']() @@ -1164,14 +1164,21 @@ class SubArrayFormat(object): return "[" + ", ".join(self.__call__(a) for a in arr) + "]" -class StructureFormat(object): +class StructuredVoidFormat(object): + """ + Formatter for structured np.void objects. + + This does not work on structured alias types like np.dtype(('i4', 'i2,i2')), + as alias scalars lose their field information, and the implementation + relies upon np.void.__getitem__. + """ def __init__(self, format_functions): self.format_functions = format_functions @classmethod def from_data(cls, data, **options): """ - This is a second way to initialize StructureFormat, using the raw data + This is a second way to initialize StructuredVoidFormat, using the raw data as input. Added to avoid changing the signature of __init__. """ format_functions = [] @@ -1192,13 +1199,24 @@ class StructureFormat(object): else: return "({})".format(", ".join(str_fields)) + +# for backwards compatibility +class StructureFormat(StructuredVoidFormat): + def __init__(self, *args, **kwargs): + # NumPy 1.14, 2018-02-14 + warnings.warn( + "StructureFormat has been replaced by StructuredVoidFormat", + DeprecationWarning, stacklevel=2) + super(StructureFormat, self).__init__(*args, **kwargs) + + def _void_scalar_repr(x): """ Implements the repr for structured-void scalars. It is called from the scalartypes.c.src code, and is placed here because it uses the elementwise formatters defined above. """ - return StructureFormat.from_data(array(x), **_format_options)(x) + return StructuredVoidFormat.from_data(array(x), **_format_options)(x) _typelessdata = [int_, float_, complex_, bool_] -- cgit v1.2.1 From fed44d7c309d0c2fd7c193efa39ba59652a43c44 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Thu, 11 Jan 2018 22:24:18 -0800 Subject: ENH: Always show dtype fields in the array repr, even for non-void --- numpy/core/arrayprint.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'numpy/core/arrayprint.py') diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index 3554fe3c4..929f55f5a 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -1254,6 +1254,11 @@ def dtype_is_implied(dtype): dtype = np.dtype(dtype) if _format_options['legacy'] == '1.13' and dtype.type == bool_: return False + + # not just void types can be structured, and names are not part of the repr + if dtype.names is not None: + return False + return dtype.type in _typelessdata @@ -1266,12 +1271,12 @@ def dtype_short_repr(dtype): >>> from numpy import * >>> assert eval(dtype_short_repr(dt)) == dt """ - # handle these separately so they don't give garbage like str256 - if issubclass(dtype.type, flexible): - if dtype.names is not None: - return "%s" % str(dtype) - else: - return "'%s'" % str(dtype) + if dtype.names is not None: + # structured dtypes give a list or tuple repr + return str(dtype) + elif issubclass(dtype.type, flexible): + # handle these separately so they don't give garbage like str256 + return "'%s'" % str(dtype) typename = dtype.name # quote typenames which can't be represented as python variable names -- cgit v1.2.1