summaryrefslogtreecommitdiff
path: root/numpy/core/arrayprint.py
diff options
context:
space:
mode:
authorAntony Lee <anntzer.lee@gmail.com>2021-09-29 20:09:32 +0200
committerGitHub <noreply@github.com>2021-09-29 13:09:32 -0500
commita6f7d14e60e3d56fe1c0073730a06e23cf696c5a (patch)
tree4f836f1bb7532f7b9265f9d07a868a61c4e79bbe /numpy/core/arrayprint.py
parente7f5d62f793379a62d1c351eedaa3a59f6f542d5 (diff)
downloadnumpy-a6f7d14e60e3d56fe1c0073730a06e23cf696c5a.tar.gz
ENH: Add spaces after punctuation in dtype repr/str. (#19686)
Before: ``` In [1]: np.dtype({"names": ["a"], "formats": [int], "offsets": [2]}) Out[1]: dtype({'names':['a'], 'formats':['<i8'], 'offsets':[2], 'itemsize':10}) ``` After: ``` In [1]: np.dtype({"names": ["a"], "formats": [int], "offsets": [2]}) Out[1]: dtype({'names': ['a'], 'formats': ['<i8'], 'offsets': [2], 'itemsize': 10}) ``` * Allow switching back to old dtype printing format. * Add changelog.
Diffstat (limited to 'numpy/core/arrayprint.py')
-rw-r--r--numpy/core/arrayprint.py98
1 files changed, 67 insertions, 31 deletions
diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py
index 2a4bef669..d7e9bf795 100644
--- a/numpy/core/arrayprint.py
+++ b/numpy/core/arrayprint.py
@@ -24,6 +24,7 @@ __docformat__ = 'restructuredtext'
import functools
import numbers
+import sys
try:
from _thread import get_ident
except ImportError:
@@ -56,12 +57,17 @@ _format_options = {
'infstr': 'inf',
'sign': '-',
'formatter': None,
- 'legacy': False}
+ # Internally stored as an int to simplify comparisons; converted from/to
+ # str/False on the way in/out.
+ 'legacy': sys.maxsize}
def _make_options_dict(precision=None, threshold=None, edgeitems=None,
linewidth=None, suppress=None, nanstr=None, infstr=None,
sign=None, formatter=None, floatmode=None, legacy=None):
- """ make a dictionary out of the non-None arguments, plus sanity checks """
+ """
+ Make a dictionary out of the non-None arguments, plus conversion of
+ *legacy* and sanity checks.
+ """
options = {k: v for k, v in locals().items() if v is not None}
@@ -76,9 +82,18 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None,
if sign not in [None, '-', '+', ' ']:
raise ValueError("sign option must be one of ' ', '+', or '-'")
- if legacy not in [None, False, '1.13']:
- warnings.warn("legacy printing option can currently only be '1.13' or "
- "`False`", stacklevel=3)
+ if legacy == False:
+ options['legacy'] = sys.maxsize
+ elif legacy == '1.13':
+ options['legacy'] = 113
+ elif legacy == '1.21':
+ options['legacy'] = 121
+ elif legacy is None:
+ pass # OK, do nothing.
+ else:
+ warnings.warn(
+ "legacy printing option can currently only be '1.13', '1.21', or "
+ "`False`", stacklevel=3)
if threshold is not None:
# forbid the bad threshold arg suggested by stack overflow, gh-12351
@@ -186,11 +201,21 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
legacy : string or `False`, optional
If set to the string `'1.13'` enables 1.13 legacy printing mode. This
approximates numpy 1.13 print output by including a space in the sign
- position of floats and different behavior for 0d arrays. If set to
- `False`, disables legacy mode. Unrecognized strings will be ignored
- with a warning for forward compatibility.
+ position of floats and different behavior for 0d arrays. This also
+ enables 1.21 legacy printing mode (described below).
+
+ If set to the string `'1.21'` enables 1.21 legacy printing mode. This
+ approximates numpy 1.21 print output of complex structured dtypes
+ by not inserting spaces after commas that separate fields and after
+ colons.
+
+ If set to `False`, disables legacy mode.
+
+ Unrecognized strings will be ignored with a warning for forward
+ compatibility.
.. versionadded:: 1.14.0
+ .. versionchanged:: 1.22.0
See Also
--------
@@ -257,11 +282,13 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
_format_options.update(opt)
# set the C variable for legacy mode
- if _format_options['legacy'] == '1.13':
+ if _format_options['legacy'] == 113:
set_legacy_print_mode(113)
# reset the sign option in legacy mode to avoid confusion
_format_options['sign'] = '-'
- elif _format_options['legacy'] is False:
+ elif _format_options['legacy'] == 121:
+ set_legacy_print_mode(121)
+ elif _format_options['legacy'] == sys.maxsize:
set_legacy_print_mode(0)
@@ -292,7 +319,16 @@ def get_printoptions():
set_printoptions, printoptions, set_string_function
"""
- return _format_options.copy()
+ opts = _format_options.copy()
+ opts['legacy'] = {
+ 113: '1.13', 121: '1.21', sys.maxsize: False,
+ }[opts['legacy']]
+ return opts
+
+
+def _get_legacy_print_mode():
+ """Return the legacy print mode as an int."""
+ return _format_options['legacy']
@set_module('numpy')
@@ -678,7 +714,7 @@ def array2string(a, max_line_width=None, precision=None,
options = _format_options.copy()
options.update(overrides)
- if options['legacy'] == '1.13':
+ if options['legacy'] <= 113:
if style is np._NoValue:
style = repr
@@ -690,7 +726,7 @@ def array2string(a, max_line_width=None, precision=None,
" except in 1.13 'legacy' mode",
DeprecationWarning, stacklevel=3)
- if options['legacy'] != '1.13':
+ if options['legacy'] > 113:
options['linewidth'] -= len(suffix)
# treat as a null array if any of shape elements == 0
@@ -702,7 +738,7 @@ def array2string(a, max_line_width=None, precision=None,
def _extendLine(s, line, word, line_width, next_line_prefix, legacy):
needs_wrap = len(line) + len(word) > line_width
- if legacy != '1.13':
+ if legacy > 113:
# don't wrap lines if it won't help
if len(line) <= len(next_line_prefix):
needs_wrap = False
@@ -719,7 +755,7 @@ def _extendLine_pretty(s, line, word, line_width, next_line_prefix, legacy):
Extends line with nicely formatted (possibly multi-line) string ``word``.
"""
words = word.splitlines()
- if len(words) == 1 or legacy == '1.13':
+ if len(words) == 1 or legacy <= 113:
return _extendLine(s, line, word, line_width, next_line_prefix, legacy)
max_word_length = max(len(word) for word in words)
@@ -765,7 +801,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
# when recursing, add a space to align with the [ added, and reduce the
# length of the line by 1
next_hanging_indent = hanging_indent + ' '
- if legacy == '1.13':
+ if legacy <= 113:
next_width = curr_width
else:
next_width = curr_width - len(']')
@@ -785,7 +821,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
# last axis (rows) - wrap elements if they would not fit on one line
if axes_left == 1:
# the length up until the beginning of the separator / bracket
- if legacy == '1.13':
+ if legacy <= 113:
elem_width = curr_width - len(separator.rstrip())
else:
elem_width = curr_width - max(len(separator.rstrip()), len(']'))
@@ -800,7 +836,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
if show_summary:
s, line = _extendLine(
s, line, summary_insert, elem_width, hanging_indent, legacy)
- if legacy == '1.13':
+ if legacy <= 113:
line += ", "
else:
line += separator
@@ -811,7 +847,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
s, line, word, elem_width, hanging_indent, legacy)
line += separator
- if legacy == '1.13':
+ if legacy <= 113:
# width of the separator is not considered on 1.13
elem_width = curr_width
word = recurser(index + (-1,), next_hanging_indent, next_width)
@@ -830,7 +866,7 @@ def _formatArray(a, format_function, line_width, next_line_prefix,
s += hanging_indent + nested + line_sep
if show_summary:
- if legacy == '1.13':
+ if legacy <= 113:
# trailing space, fixed nbr of newlines, and fixed separator
s += hanging_indent + summary_insert + ", \n"
else:
@@ -875,7 +911,7 @@ class FloatingFormat:
sign = '+' if sign else '-'
self._legacy = legacy
- if self._legacy == '1.13':
+ if self._legacy <= 113:
# when not 0d, legacy does not support '-'
if data.shape != () and sign == '-':
sign = ' '
@@ -919,7 +955,7 @@ class FloatingFormat:
self.min_digits = None
elif self.exp_format:
trim, unique = '.', True
- if self.floatmode == 'fixed' or self._legacy == '1.13':
+ if self.floatmode == 'fixed' or self._legacy <= 113:
trim, unique = 'k', False
strs = (dragon4_scientific(x, precision=self.precision,
unique=unique, trim=trim, sign=self.sign == '+')
@@ -934,7 +970,7 @@ class FloatingFormat:
self.unique = unique
# for back-compat with np 1.13, use 2 spaces & sign and full prec
- if self._legacy == '1.13':
+ if self._legacy <= 113:
self.pad_left = 3
else:
# this should be only 1 or 2. Can be calculated from sign.
@@ -951,7 +987,7 @@ class FloatingFormat:
sign=self.sign == '+')
for x in finite_vals)
int_part, frac_part = zip(*(s.split('.') for s in strs))
- if self._legacy == '1.13':
+ if self._legacy <= 113:
self.pad_left = 1 + max(len(s.lstrip('-+')) for s in int_part)
else:
self.pad_left = max(len(s) for s in int_part)
@@ -966,7 +1002,7 @@ class FloatingFormat:
self.trim = '.'
self.min_digits = 0
- if self._legacy != '1.13':
+ if self._legacy > 113:
# account for sign = ' ' by adding one to pad_left
if self.sign == ' ' and not any(np.signbit(finite_vals)):
self.pad_left += 1
@@ -1215,7 +1251,7 @@ class ComplexFloatingFormat:
sign = '+' if sign else '-'
floatmode_real = floatmode_imag = floatmode
- if legacy == '1.13':
+ if legacy <= 113:
floatmode_real = 'maxprec_equal'
floatmode_imag = 'maxprec'
@@ -1286,7 +1322,7 @@ class DatetimeFormat(_TimelikeFormat):
super().__init__(x)
def __call__(self, x):
- if self.legacy == '1.13':
+ if self.legacy <= 113:
return self._format_non_nat(x)
return super().__call__(x)
@@ -1390,7 +1426,7 @@ def dtype_is_implied(dtype):
array([1, 2, 3], dtype=int8)
"""
dtype = np.dtype(dtype)
- if _format_options['legacy'] == '1.13' and dtype.type == bool_:
+ if _format_options['legacy'] <= 113 and dtype.type == bool_:
return False
# not just void types can be structured, and names are not part of the repr
@@ -1445,7 +1481,7 @@ def _array_repr_implementation(
prefix = class_name + "("
suffix = ")" if skipdtype else ","
- if (_format_options['legacy'] == '1.13' and
+ if (_format_options['legacy'] <= 113 and
arr.shape == () and not arr.dtype.names):
lst = repr(arr.item())
elif arr.size > 0 or arr.shape == (0,):
@@ -1466,7 +1502,7 @@ def _array_repr_implementation(
# Note: This line gives the correct result even when rfind returns -1.
last_line_len = len(arr_str) - (arr_str.rfind('\n') + 1)
spacer = " "
- if _format_options['legacy'] == '1.13':
+ if _format_options['legacy'] <= 113:
if issubclass(arr.dtype.type, flexible):
spacer = '\n' + ' '*len(class_name + "(")
elif last_line_len + len(dtype_str) + 1 > max_line_width:
@@ -1540,7 +1576,7 @@ def _array_str_implementation(
a, max_line_width=None, precision=None, suppress_small=None,
array2string=array2string):
"""Internal version of array_str() that allows overriding array2string."""
- if (_format_options['legacy'] == '1.13' and
+ if (_format_options['legacy'] <= 113 and
a.shape == () and not a.dtype.names):
return str(a.item())