summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/release/1.14.0-notes.rst20
-rw-r--r--numpy/core/arrayprint.py367
-rw-r--r--numpy/core/tests/test_arrayprint.py136
-rw-r--r--numpy/core/tests/test_regression.py2
-rw-r--r--numpy/polynomial/tests/test_printing.py24
-rw-r--r--numpy/testing/tests/test_utils.py24
6 files changed, 338 insertions, 235 deletions
diff --git a/doc/release/1.14.0-notes.rst b/doc/release/1.14.0-notes.rst
index 73d2bf6a3..c9f1cec76 100644
--- a/doc/release/1.14.0-notes.rst
+++ b/doc/release/1.14.0-notes.rst
@@ -304,3 +304,23 @@ source to the destination.
Using field "titles" in multiple-field indexing is now disallowed, as is
repeating a field name in a multiple-field index.
+``sign`` option added to ``np.setprintoptions`` and ``np.array2string``
+-----------------------------------------------------------------------
+This option controls printing of the sign of floating-point types, and may be
+one of the characters '-', '+' or ' ', or the string 'legacy'. With '+' numpy
+always prints the sign of positive values, with ' ' it always prints a space
+(whitespace character) in the sign position of positive values, and with '-' it
+will omit the sign character for positive values, and with 'legacy' it will
+behave like ' ' except no space is printed in 0d arrays. The new default is '-'.
+
+Unneeded whitespace in float array printing removed
+---------------------------------------------------
+The new default of ``sign='-'`` (see last note) means that the ``repr`` of
+float arrays now often omits the whitespace characters previously used to
+display the sign. This new behavior can be disabled to mostly reproduce numpy
+1.13 behavior by calling ``np.set_printoptions(sign='legacy')``.
+
+``threshold`` and ``edgeitems`` options added to ``np.array2string``
+-----------------------------------------------------------------
+These options could previously be controlled using ``np.set_printoptions``, but
+now can be changed on a per-call basis as arguments to ``np.array2string``.
diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py
index b8e60562f..e0da9f81e 100644
--- a/numpy/core/arrayprint.py
+++ b/numpy/core/arrayprint.py
@@ -38,7 +38,7 @@ else:
import numpy as np
from . import numerictypes as _nt
-from .umath import maximum, minimum, absolute, not_equal, isnan, isinf
+from .umath import absolute, not_equal, isnan, isinf
from . import multiarray
from .multiarray import (array, format_longfloat, datetime_as_string,
datetime_data, dtype, ndarray)
@@ -55,24 +55,36 @@ else:
_MAXINT = sys.maxint
_MININT = -sys.maxint - 1
-def product(x, y):
- return x*y
+_format_options = {
+ 'edgeitems': 3, # repr N leading and trailing items of each dimension
+ 'threshold': 1000, # total items > triggers array summarization
+ 'precision': 8, # precision of floating point representations
+ 'suppress': False, # suppress printing small floating values in exp format
+ 'linewidth': 75,
+ 'nanstr': 'nan',
+ 'infstr': 'inf',
+ 'sign': '-',
+ 'formatter': None }
-_summaryEdgeItems = 3 # repr N leading and trailing items of each dimension
-_summaryThreshold = 1000 # total items > triggers array summarization
+def _make_options_dict(precision=None, threshold=None, edgeitems=None,
+ linewidth=None, suppress=None, nanstr=None, infstr=None,
+ sign=None, formatter=None):
+ """ make a dictionary out of the non-None arguments, plus sanity checks """
-_float_output_precision = 8
-_float_output_suppress_small = False
-_line_width = 75
-_nan_str = 'nan'
-_inf_str = 'inf'
-_formatter = None # formatting function for array elements
+ options = {k: v for k, v in locals().items() if v is not None}
+ if suppress is not None:
+ options['suppress'] = bool(suppress)
+
+ if sign not in [None, '-', '+', ' ', 'legacy']:
+ raise ValueError("sign option must be one of "
+ "' ', '+', '-', or 'legacy'")
+
+ return options
def set_printoptions(precision=None, threshold=None, edgeitems=None,
- linewidth=None, suppress=None,
- nanstr=None, infstr=None,
- formatter=None):
+ linewidth=None, suppress=None, nanstr=None, infstr=None,
+ formatter=None, sign=None):
"""
Set printing options.
@@ -102,6 +114,12 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
String representation of floating point not-a-number (default nan).
infstr : str, optional
String representation of floating point infinity (default inf).
+ sign : string, either '-', '+', ' ' or 'legacy', optional
+ Controls printing of the sign of floating-point types. If '+', always
+ print the sign of positive values. If ' ', always prints a space
+ (whitespace character) in the sign position of positive values. If
+ '-', omit the sign character of positive values. If 'legacy', print a
+ space for positive values except in 0d arrays. (default '-')
formatter : dict of callables, optional
If not None, the keys should indicate the type(s) that the respective
formatting function applies to. Callables should return a string.
@@ -177,26 +195,12 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
... linewidth=75, nanstr='nan', precision=8,
... suppress=False, threshold=1000, formatter=None)
"""
+ opt = _make_options_dict(precision, threshold, edgeitems, linewidth,
+ suppress, nanstr, infstr, sign, formatter)
+ # formatter is always reset
+ opt['formatter'] = formatter
+ _format_options.update(opt)
- global _summaryThreshold, _summaryEdgeItems, _float_output_precision
- global _line_width, _float_output_suppress_small, _nan_str, _inf_str
- global _formatter
-
- if linewidth is not None:
- _line_width = linewidth
- if threshold is not None:
- _summaryThreshold = threshold
- if edgeitems is not None:
- _summaryEdgeItems = edgeitems
- if precision is not None:
- _float_output_precision = precision
- if suppress is not None:
- _float_output_suppress_small = not not suppress
- if nanstr is not None:
- _nan_str = nanstr
- if infstr is not None:
- _inf_str = infstr
- _formatter = formatter
def get_printoptions():
"""
@@ -215,6 +219,7 @@ def get_printoptions():
- nanstr : str
- infstr : str
- formatter : dict of callables
+ - sign : str
For a full description of these options, see `set_printoptions`.
@@ -223,40 +228,25 @@ def get_printoptions():
set_printoptions, set_string_function
"""
- d = dict(precision=_float_output_precision,
- threshold=_summaryThreshold,
- edgeitems=_summaryEdgeItems,
- linewidth=_line_width,
- suppress=_float_output_suppress_small,
- nanstr=_nan_str,
- infstr=_inf_str,
- formatter=_formatter)
- return d
+ return _format_options.copy()
def _leading_trailing(a):
+ edgeitems = _format_options['edgeitems']
if a.ndim == 1:
- if len(a) > 2*_summaryEdgeItems:
- b = concatenate((a[:_summaryEdgeItems],
- a[-_summaryEdgeItems:]))
+ if len(a) > 2*edgeitems:
+ b = concatenate((a[:edgeitems], a[-edgeitems:]))
else:
b = a
else:
- if len(a) > 2*_summaryEdgeItems:
- l = [_leading_trailing(a[i]) for i in range(
- min(len(a), _summaryEdgeItems))]
+ if len(a) > 2*edgeitems:
+ l = [_leading_trailing(a[i]) for i in range(min(len(a), edgeitems))]
l.extend([_leading_trailing(a[-i]) for i in range(
- min(len(a), _summaryEdgeItems), 0, -1)])
+ min(len(a), edgeitems), 0, -1)])
else:
l = [_leading_trailing(a[i]) for i in range(0, len(a))]
b = concatenate(tuple(l))
return b
-def _boolFormatter(x):
- if x:
- return ' True'
- else:
- return 'False'
-
def _object_format(o):
""" Object arrays containing lists should be printed unambiguously """
if type(o) is list:
@@ -268,15 +258,16 @@ def _object_format(o):
def repr_format(x):
return repr(x)
-def _get_formatdict(data, precision, suppress_small, formatter):
+def _get_formatdict(data, **opt):
+ prec, supp, sign = opt['precision'], opt['suppress'], opt['sign']
+
# wrapped in lambdas to avoid taking a code path with the wrong type of data
- formatdict = {'bool': lambda: _boolFormatter,
+ formatdict = {'bool': lambda: BoolFormat(data),
'int': lambda: IntegerFormat(data),
- 'float': lambda: FloatFormat(data, precision, suppress_small),
- 'longfloat': lambda: LongFloatFormat(precision),
- 'complexfloat': lambda: ComplexFormat(data, precision,
- suppress_small),
- 'longcomplexfloat': lambda: LongComplexFormat(precision),
+ 'float': lambda: FloatFormat(data, prec, supp, sign),
+ 'longfloat': lambda: LongFloatFormat(prec),
+ 'complexfloat': lambda: ComplexFormat(data, prec, supp, sign),
+ 'longcomplexfloat': lambda: LongComplexFormat(prec),
'datetime': lambda: DatetimeFormat(data),
'timedelta': lambda: TimedeltaFormat(data),
'object': lambda: _object_format,
@@ -288,6 +279,7 @@ def _get_formatdict(data, precision, suppress_small, formatter):
def indirect(x):
return lambda: x
+ formatter = opt['formatter']
if formatter is not None:
fkeys = [k for k in formatter.keys() if formatter[k] is not None]
if 'all' in fkeys:
@@ -311,7 +303,7 @@ def _get_formatdict(data, precision, suppress_small, formatter):
return formatdict
-def _get_format_function(data, precision, suppress_small, formatter):
+def _get_format_function(data, **options):
"""
find the right formatting function for the dtype_
"""
@@ -319,16 +311,14 @@ def _get_format_function(data, precision, suppress_small, formatter):
if dtype_.fields is not None:
format_functions = []
for field_name in dtype_.names:
- field_values = data[field_name]
- format_function = _get_format_function(
- ravel(field_values), precision, suppress_small, formatter)
+ format_function = _get_format_function(data[field_name], **options)
if dtype_[field_name].shape != ():
format_function = SubArrayFormat(format_function)
format_functions.append(format_function)
return StructureFormat(format_functions)
dtypeobj = dtype_.type
- formatdict = _get_formatdict(data, precision, suppress_small, formatter)
+ formatdict = _get_formatdict(data, **options)
if issubclass(dtypeobj, _nt.bool_):
return formatdict['bool']()
elif issubclass(dtypeobj, _nt.integer):
@@ -355,30 +345,6 @@ def _get_format_function(data, precision, suppress_small, formatter):
else:
return formatdict['numpystr']()
-def _array2string(a, max_line_width, precision, suppress_small, separator=' ',
- prefix="", formatter=None):
-
- if a.size > _summaryThreshold:
- summary_insert = "..., "
- data = _leading_trailing(a)
- else:
- summary_insert = ""
- data = ravel(asarray(a))
-
- # find the right formatting function for the array
- format_function = _get_format_function(data, precision,
- suppress_small, formatter)
-
- # skip over "["
- next_line_prefix = " "
- # skip over array(
- next_line_prefix += " "*len(prefix)
-
- lst = _formatArray(a, format_function, a.ndim, max_line_width,
- next_line_prefix, separator,
- _summaryEdgeItems, summary_insert)[:-1]
- return lst
-
def _recursive_guard(fillvalue='...'):
"""
@@ -409,12 +375,34 @@ def _recursive_guard(fillvalue='...'):
return decorating_function
-# gracefully handle recursive calls - this comes up when object arrays contain
-# themselves
+# gracefully handle recursive calls, when object arrays contain themselves
@_recursive_guard()
+def _array2string(a, options, separator=' ', prefix=""):
+ if a.size > options['threshold']:
+ summary_insert = "..., "
+ data = _leading_trailing(a)
+ else:
+ summary_insert = ""
+ data = asarray(a)
+
+ # find the right formatting function for the array
+ format_function = _get_format_function(data, **options)
+
+ # skip over "["
+ next_line_prefix = " "
+ # skip over array(
+ next_line_prefix += " "*len(prefix)
+
+ lst = _formatArray(a, format_function, a.ndim, options['linewidth'],
+ next_line_prefix, separator,
+ options['edgeitems'], summary_insert)[:-1]
+ return lst
+
+
def array2string(a, max_line_width=None, precision=None,
suppress_small=None, separator=' ', prefix="",
- style=np._NoValue, formatter=None):
+ style=np._NoValue, formatter=None, threshold=None,
+ edgeitems=None, sign=None):
"""
Return a string representation of an array.
@@ -469,6 +457,18 @@ def array2string(a, max_line_width=None, precision=None,
- 'float_kind' : sets 'float' and 'longfloat'
- 'complex_kind' : sets 'complexfloat' and 'longcomplexfloat'
- 'str_kind' : sets 'str' and 'numpystr'
+ threshold : int, optional
+ Total number of array elements which trigger summarization
+ rather than full repr.
+ edgeitems : int, optional
+ Number of array items in summary at beginning and end of
+ each dimension.
+ sign : string, either '-', '+', ' ' or 'legacy', optional
+ Controls printing of the sign of floating-point types. If '+', always
+ print the sign of positive values. If ' ', always prints a space
+ (whitespace character) in the sign position of positive values. If
+ '-', omit the sign character of positive values. If 'legacy', print a
+ space for positive values except in 0d arrays.
Returns
-------
@@ -509,30 +509,22 @@ def array2string(a, max_line_width=None, precision=None,
'[0x0L 0x1L 0x2L]'
"""
-
# Deprecation 05-16-2017 v1.14
if style is not np._NoValue:
warnings.warn("'style' argument is deprecated and no longer functional",
DeprecationWarning, stacklevel=3)
- if max_line_width is None:
- max_line_width = _line_width
-
- if precision is None:
- precision = _float_output_precision
-
- if suppress_small is None:
- suppress_small = _float_output_suppress_small
-
- if formatter is None:
- formatter = _formatter
+ overrides = _make_options_dict(precision, threshold, edgeitems,
+ max_line_width, suppress_small, None, None,
+ sign, formatter)
+ options = _format_options.copy()
+ options.update(overrides)
if a.size == 0:
# treat as a null array if any of shape elements == 0
lst = "[]"
else:
- lst = _array2string(a, max_line_width, precision, suppress_small,
- separator, prefix, formatter=formatter)
+ lst = _array2string(a, options, separator, prefix)
return lst
@@ -613,30 +605,38 @@ def _formatArray(a, format_function, rank, max_line_len,
class FloatFormat(object):
def __init__(self, data, precision, suppress_small, sign=False):
+ # for backcompatibility, accept bools
+ if isinstance(sign, bool):
+ sign = '+' if sign else '-'
+
+ self._legacy = False
+ if sign == 'legacy':
+ self._legacy = True
+ sign = '-' if data.shape == () else ' '
+
self.precision = precision
self.suppress_small = suppress_small
self.sign = sign
self.exp_format = False
self.large_exponent = False
- self.max_str_len = 0
- try:
- self.fillFormat(data)
- except (TypeError, NotImplementedError):
- # if reduce(data) fails, this instance will not be called, just
- # instantiated in formatdict.
- pass
+
+ self.fillFormat(data)
def fillFormat(self, data):
with errstate(all='ignore'):
- special = isnan(data) | isinf(data)
+ hasinf = isinf(data)
+ special = isnan(data) | hasinf
valid = not_equal(data, 0) & ~special
- non_zero = absolute(data.compress(valid))
+ non_zero = data[valid]
+ abs_non_zero = absolute(non_zero)
if len(non_zero) == 0:
max_val = 0.
min_val = 0.
+ min_val_sgn = 0.
else:
- max_val = maximum.reduce(non_zero)
- min_val = minimum.reduce(non_zero)
+ max_val = np.max(abs_non_zero)
+ min_val = np.min(abs_non_zero)
+ min_val_sgn = np.min(non_zero)
if max_val >= 1.e8:
self.exp_format = True
if not self.suppress_small and (min_val < 0.0001
@@ -645,51 +645,57 @@ class FloatFormat(object):
if self.exp_format:
self.large_exponent = 0 < min_val < 1e-99 or max_val >= 1e100
- self.max_str_len = 8 + self.precision
- if self.large_exponent:
- self.max_str_len += 1
- if self.sign:
- format = '%+'
- else:
- format = '%'
- format = format + '%d.%de' % (self.max_str_len, self.precision)
+
+ signpos = self.sign != '-' or any(non_zero < 0)
+ # for back-compatibility with np 1.13, use two spaces
+ if self._legacy:
+ signpos = 2
+ max_str_len = signpos + 6 + self.precision + self.large_exponent
+
+ conversion = '' if self.sign == '-' else self.sign
+ format = '%' + conversion + '%d.%de' % (max_str_len, self.precision)
else:
- format = '%%.%df' % (self.precision,)
- if len(non_zero):
- precision = max([_digits(x, self.precision, format)
- for x in non_zero])
+ if len(non_zero) and self.precision > 0:
+ precision = self.precision
+ trim_zero = lambda s: precision - (len(s) - len(s.rstrip('0')))
+ fmt = '%%.%df' % (precision,)
+ precision = max(trim_zero(fmt % x) for x in abs_non_zero)
else:
precision = 0
- precision = min(self.precision, precision)
- self.max_str_len = len(str(int(max_val))) + precision + 2
+
+ int_len = len(str(int(max_val)))
+ signpos = self.sign != '-' or (len(str(int(min_val_sgn))) > int_len)
+ max_str_len = signpos + int_len + 1 + precision
+
if any(special):
- self.max_str_len = max(self.max_str_len,
- len(_nan_str),
- len(_inf_str)+1)
- if self.sign:
- format = '%#+'
- else:
- format = '%#'
- format = format + '%d.%df' % (self.max_str_len, precision)
+ neginf = self.sign != '-' or any(data[hasinf] < 0)
+ nanlen = len(_format_options['nanstr'])
+ inflen = len(_format_options['infstr']) + neginf
+ max_str_len = max(max_str_len, nanlen, inflen)
- self.special_fmt = '%%%ds' % (self.max_str_len,)
+ conversion = '' if self.sign == '-' else self.sign
+ format = '%#' + conversion + '%d.%df' % (max_str_len, precision)
+
+ self.special_fmt = '%%%ds' % (max_str_len,)
self.format = format
def __call__(self, x, strip_zeros=True):
with errstate(invalid='ignore'):
if isnan(x):
- if self.sign:
- return self.special_fmt % ('+' + _nan_str,)
+ nan_str = _format_options['nanstr']
+ if self.sign == '+':
+ return self.special_fmt % ('+' + nan_str,)
else:
- return self.special_fmt % (_nan_str,)
+ return self.special_fmt % (nan_str,)
elif isinf(x):
+ inf_str = _format_options['infstr']
if x > 0:
- if self.sign:
- return self.special_fmt % ('+' + _inf_str,)
+ if self.sign == '+':
+ return self.special_fmt % ('+' + inf_str,)
else:
- return self.special_fmt % (_inf_str,)
+ return self.special_fmt % (inf_str,)
else:
- return self.special_fmt % ('-' + _inf_str,)
+ return self.special_fmt % ('-' + inf_str,)
s = self.format % x
if self.large_exponent:
@@ -706,21 +712,11 @@ class FloatFormat(object):
s = z + ' '*(len(s)-len(z))
return s
-
-def _digits(x, precision, format):
- if precision > 0:
- s = format % x
- z = s.rstrip('0')
- return precision - len(s) + len(z)
- else:
- return 0
-
-
class IntegerFormat(object):
def __init__(self, data):
try:
- max_str_len = max(len(str(maximum.reduce(data))),
- len(str(minimum.reduce(data))))
+ max_str_len = max(len(str(np.max(data))),
+ len(str(np.min(data))))
self.format = '%' + str(max_str_len) + 'd'
except (TypeError, NotImplementedError):
# if reduce(data) fails, this instance will not be called, just
@@ -736,29 +732,45 @@ class IntegerFormat(object):
else:
return "%s" % x
+class BoolFormat(object):
+ def __init__(self, data, **kwargs):
+ # add an extra space so " True" and "False" have the same length and
+ # array elements align nicely when printed, except in 0d arrays
+ self.truestr = ' True' if data.shape != () else 'True'
+
+ def __call__(self, x):
+ return self.truestr if x else "False"
+
+
class LongFloatFormat(object):
# XXX Have to add something to determine the width to use a la FloatFormat
# Right now, things won't line up properly
def __init__(self, precision, sign=False):
+ # for backcompatibility, accept bools
+ if isinstance(sign, bool):
+ sign = '+' if sign else '-'
+
self.precision = precision
self.sign = sign
def __call__(self, x):
if isnan(x):
- if self.sign:
- return '+' + _nan_str
+ nan_str = _format_options['nanstr']
+ if self.sign == '+':
+ return '+' + nan_str
else:
- return ' ' + _nan_str
+ return ' ' + nan_str
elif isinf(x):
+ inf_str = _format_options['infstr']
if x > 0:
- if self.sign:
- return '+' + _inf_str
+ if self.sign == '+':
+ return '+' + inf_str
else:
- return ' ' + _inf_str
+ return ' ' + inf_str
else:
- return '-' + _inf_str
+ return '-' + inf_str
elif x >= 0:
- if self.sign:
+ if self.sign == '+':
return '+' + format_longfloat(x, self.precision)
else:
return ' ' + format_longfloat(x, self.precision)
@@ -769,7 +781,7 @@ class LongFloatFormat(object):
class LongComplexFormat(object):
def __init__(self, precision):
self.real_format = LongFloatFormat(precision)
- self.imag_format = LongFloatFormat(precision, sign=True)
+ self.imag_format = LongFloatFormat(precision, sign='+')
def __call__(self, x):
r = self.real_format(x.real)
@@ -778,10 +790,15 @@ class LongComplexFormat(object):
class ComplexFormat(object):
- def __init__(self, x, precision, suppress_small):
- self.real_format = FloatFormat(x.real, precision, suppress_small)
+ def __init__(self, x, precision, suppress_small, sign=False):
+ # for backcompatibility, accept bools
+ if isinstance(sign, bool):
+ sign = '+' if sign else '-'
+
+ self.real_format = FloatFormat(x.real, precision, suppress_small,
+ sign=sign)
self.imag_format = FloatFormat(x.imag, precision, suppress_small,
- sign=True)
+ sign='+')
def __call__(self, x):
r = self.real_format(x.real, strip_zeros=False)
@@ -823,8 +840,8 @@ class TimedeltaFormat(object):
v = int_view[not_equal(int_view, nat_value.view(int_dtype))]
if len(v) > 0:
# Max str length of non-NaT elements
- max_str_len = max(len(str(maximum.reduce(v))),
- len(str(minimum.reduce(v))))
+ max_str_len = max(len(str(np.max(v))),
+ len(str(np.min(v))))
else:
max_str_len = 0
if len(v) < len(data):
diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py
index 7d4acd35d..b03229447 100644
--- a/numpy/core/tests/test_arrayprint.py
+++ b/numpy/core/tests/test_arrayprint.py
@@ -11,7 +11,7 @@ from numpy.testing import (
class TestArrayRepr(object):
def test_nan_inf(self):
x = np.array([np.nan, np.inf])
- assert_equal(repr(x), 'array([ nan, inf])')
+ assert_equal(repr(x), 'array([nan, inf])')
def test_subclass(self):
class sub(np.ndarray): pass
@@ -68,45 +68,45 @@ class TestComplexArray(object):
dtypes = [np.complex64, np.cdouble, np.clongdouble]
actual = [str(np.array([c], dt)) for c in cvals for dt in dtypes]
wanted = [
- '[ 0.+0.j]', '[ 0.+0.j]', '[ 0.0+0.0j]',
- '[ 0.+1.j]', '[ 0.+1.j]', '[ 0.0+1.0j]',
- '[ 0.-1.j]', '[ 0.-1.j]', '[ 0.0-1.0j]',
- '[ 0.+infj]', '[ 0.+infj]', '[ 0.0+infj]',
- '[ 0.-infj]', '[ 0.-infj]', '[ 0.0-infj]',
- '[ 0.+nanj]', '[ 0.+nanj]', '[ 0.0+nanj]',
- '[ 1.+0.j]', '[ 1.+0.j]', '[ 1.0+0.0j]',
- '[ 1.+1.j]', '[ 1.+1.j]', '[ 1.0+1.0j]',
- '[ 1.-1.j]', '[ 1.-1.j]', '[ 1.0-1.0j]',
- '[ 1.+infj]', '[ 1.+infj]', '[ 1.0+infj]',
- '[ 1.-infj]', '[ 1.-infj]', '[ 1.0-infj]',
- '[ 1.+nanj]', '[ 1.+nanj]', '[ 1.0+nanj]',
+ '[0.+0.j]', '[0.+0.j]', '[ 0.0+0.0j]',
+ '[0.+1.j]', '[0.+1.j]', '[ 0.0+1.0j]',
+ '[0.-1.j]', '[0.-1.j]', '[ 0.0-1.0j]',
+ '[0.+infj]', '[0.+infj]', '[ 0.0+infj]',
+ '[0.-infj]', '[0.-infj]', '[ 0.0-infj]',
+ '[0.+nanj]', '[0.+nanj]', '[ 0.0+nanj]',
+ '[1.+0.j]', '[1.+0.j]', '[ 1.0+0.0j]',
+ '[1.+1.j]', '[1.+1.j]', '[ 1.0+1.0j]',
+ '[1.-1.j]', '[1.-1.j]', '[ 1.0-1.0j]',
+ '[1.+infj]', '[1.+infj]', '[ 1.0+infj]',
+ '[1.-infj]', '[1.-infj]', '[ 1.0-infj]',
+ '[1.+nanj]', '[1.+nanj]', '[ 1.0+nanj]',
'[-1.+0.j]', '[-1.+0.j]', '[-1.0+0.0j]',
'[-1.+1.j]', '[-1.+1.j]', '[-1.0+1.0j]',
'[-1.-1.j]', '[-1.-1.j]', '[-1.0-1.0j]',
'[-1.+infj]', '[-1.+infj]', '[-1.0+infj]',
'[-1.-infj]', '[-1.-infj]', '[-1.0-infj]',
'[-1.+nanj]', '[-1.+nanj]', '[-1.0+nanj]',
- '[ inf+0.j]', '[ inf+0.j]', '[ inf+0.0j]',
- '[ inf+1.j]', '[ inf+1.j]', '[ inf+1.0j]',
- '[ inf-1.j]', '[ inf-1.j]', '[ inf-1.0j]',
- '[ inf+infj]', '[ inf+infj]', '[ inf+infj]',
- '[ inf-infj]', '[ inf-infj]', '[ inf-infj]',
- '[ inf+nanj]', '[ inf+nanj]', '[ inf+nanj]',
+ '[inf+0.j]', '[inf+0.j]', '[ inf+0.0j]',
+ '[inf+1.j]', '[inf+1.j]', '[ inf+1.0j]',
+ '[inf-1.j]', '[inf-1.j]', '[ inf-1.0j]',
+ '[inf+infj]', '[inf+infj]', '[ inf+infj]',
+ '[inf-infj]', '[inf-infj]', '[ inf-infj]',
+ '[inf+nanj]', '[inf+nanj]', '[ inf+nanj]',
'[-inf+0.j]', '[-inf+0.j]', '[-inf+0.0j]',
'[-inf+1.j]', '[-inf+1.j]', '[-inf+1.0j]',
'[-inf-1.j]', '[-inf-1.j]', '[-inf-1.0j]',
'[-inf+infj]', '[-inf+infj]', '[-inf+infj]',
'[-inf-infj]', '[-inf-infj]', '[-inf-infj]',
'[-inf+nanj]', '[-inf+nanj]', '[-inf+nanj]',
- '[ nan+0.j]', '[ nan+0.j]', '[ nan+0.0j]',
- '[ nan+1.j]', '[ nan+1.j]', '[ nan+1.0j]',
- '[ nan-1.j]', '[ nan-1.j]', '[ nan-1.0j]',
- '[ nan+infj]', '[ nan+infj]', '[ nan+infj]',
- '[ nan-infj]', '[ nan-infj]', '[ nan-infj]',
- '[ nan+nanj]', '[ nan+nanj]', '[ nan+nanj]']
+ '[nan+0.j]', '[nan+0.j]', '[ nan+0.0j]',
+ '[nan+1.j]', '[nan+1.j]', '[ nan+1.0j]',
+ '[nan-1.j]', '[nan-1.j]', '[ nan-1.0j]',
+ '[nan+infj]', '[nan+infj]', '[ nan+infj]',
+ '[nan-infj]', '[nan-infj]', '[ nan-infj]',
+ '[nan+nanj]', '[nan+nanj]', '[ nan+nanj]']
for res, val in zip(actual, wanted):
- assert_(res == val)
+ assert_equal(res, val)
class TestArray2String(object):
def test_basic(self):
@@ -157,7 +157,7 @@ class TestArray2String(object):
dt = np.dtype([('name', np.str_, 16), ('grades', np.float64, (2,))])
x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
assert_equal(np.array2string(x),
- "[('Sarah', [ 8., 7.]) ('John', [ 6., 7.])]")
+ "[('Sarah', [8., 7.]) ('John', [6., 7.])]")
# for issue #5692
A = np.zeros(shape=10, dtype=[("A", "M8[s]")])
@@ -180,7 +180,7 @@ class TestArray2String(object):
# See #8172
array_scalar = np.array(
(1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8'))
- assert_equal(np.array2string(array_scalar), "( 1., 2.12345679, 3.)")
+ assert_equal(np.array2string(array_scalar), "(1., 2.12345679, 3.)")
class TestPrintOptions(object):
@@ -194,17 +194,17 @@ class TestPrintOptions(object):
def test_basic(self):
x = np.array([1.5, 0, 1.234567890])
- assert_equal(repr(x), "array([ 1.5 , 0. , 1.23456789])")
+ assert_equal(repr(x), "array([1.5 , 0. , 1.23456789])")
np.set_printoptions(precision=4)
- assert_equal(repr(x), "array([ 1.5 , 0. , 1.2346])")
+ assert_equal(repr(x), "array([1.5 , 0. , 1.2346])")
def test_precision_zero(self):
np.set_printoptions(precision=0)
for values, string in (
- ([0.], " 0."), ([.3], " 0."), ([-.3], "-0."), ([.7], " 1."),
- ([1.5], " 2."), ([-1.5], "-2."), ([-15.34], "-15."),
- ([100.], " 100."), ([.2, -1, 122.51], " 0., -1., 123."),
- ([0], "0"), ([-12], "-12"), ([complex(.3, -.7)], " 0.-1.j")):
+ ([0.], "0."), ([.3], "0."), ([-.3], "-0."), ([.7], "1."),
+ ([1.5], "2."), ([-1.5], "-2."), ([-15.34], "-15."),
+ ([100.], "100."), ([.2, -1, 122.51], " 0., -1., 123."),
+ ([0], "0"), ([-12], "-12"), ([complex(.3, -.7)], "0.-1.j")):
x = np.array(values)
assert_equal(repr(x), "array([%s])" % string)
@@ -234,7 +234,7 @@ class TestPrintOptions(object):
np.set_printoptions(formatter={'float':lambda x: str(x-1)})
assert_equal(repr(x), "array([-1.0, 0.0, 1.0])")
np.set_printoptions(formatter={'float_kind':None})
- assert_equal(repr(x), "array([ 0., 1., 2.])")
+ assert_equal(repr(x), "array([0., 1., 2.])")
def test_0d_arrays(self):
assert_equal(repr(np.datetime64('2005-02-25')[...]),
@@ -244,6 +244,72 @@ class TestPrintOptions(object):
np.set_printoptions(formatter={'all':lambda x: "test"})
assert_equal(repr(x), "array(test)")
+ def test_float_spacing(self):
+ x = np.array([1., 2., 3.])
+ y = np.array([1., 2., -10.])
+ z = np.array([100., 2., -1.])
+ w = np.array([-100., 2., 1.])
+
+ assert_equal(repr(x), 'array([1., 2., 3.])')
+ assert_equal(repr(y), 'array([ 1., 2., -10.])')
+ assert_equal(repr(np.array(y[0])), 'array(1.)')
+ assert_equal(repr(np.array(y[-1])), 'array(-10.)')
+ assert_equal(repr(z), 'array([100., 2., -1.])')
+ assert_equal(repr(w), 'array([-100., 2., 1.])')
+
+ assert_equal(repr(np.array([np.nan, np.inf])), 'array([nan, inf])')
+ assert_equal(repr(np.array([np.nan, -np.inf])), 'array([ nan, -inf])')
+
+ x = np.array([np.inf, 100000, 1.1234])
+ y = np.array([np.inf, 100000, -1.1234])
+ z = np.array([np.inf, 1.1234, -1e120])
+ np.set_printoptions(precision=2)
+ assert_equal(repr(x), 'array([ inf, 1.00e+05, 1.12e+00])')
+ assert_equal(repr(y), 'array([ inf, 1.00e+05, -1.12e+00])')
+ assert_equal(repr(z), 'array([ inf, 1.12e+000, -1.00e+120])')
+
+ def test_bool_spacing(self):
+ assert_equal(repr(np.array([True, True])),
+ 'array([ True, True], dtype=bool)')
+ assert_equal(repr(np.array([True, False])),
+ 'array([ True, False], dtype=bool)')
+ assert_equal(repr(np.array([True])),
+ 'array([ True], dtype=bool)')
+ assert_equal(repr(np.array(True)),
+ 'array(True, dtype=bool)')
+ assert_equal(repr(np.array(False)),
+ 'array(False, dtype=bool)')
+
+ def test_sign_spacing(self):
+ a = np.arange(4.)
+ b = np.array([1.234e9])
+
+ assert_equal(repr(a), 'array([0., 1., 2., 3.])')
+ assert_equal(repr(np.array(1.)), 'array(1.)')
+ assert_equal(repr(b), 'array([1.23400000e+09])')
+
+ np.set_printoptions(sign=' ')
+ assert_equal(repr(a), 'array([ 0., 1., 2., 3.])')
+ assert_equal(repr(np.array(1.)), 'array( 1.)')
+ assert_equal(repr(b), 'array([ 1.23400000e+09])')
+
+ np.set_printoptions(sign='+')
+ assert_equal(repr(a), 'array([+0., +1., +2., +3.])')
+ assert_equal(repr(np.array(1.)), 'array(+1.)')
+ assert_equal(repr(b), 'array([+1.23400000e+09])')
+
+ np.set_printoptions(sign='legacy')
+ assert_equal(repr(a), 'array([ 0., 1., 2., 3.])')
+ assert_equal(repr(np.array(1.)), 'array(1.)')
+ assert_equal(repr(b), 'array([ 1.23400000e+09])')
+
+ def test_sign_spacing_structured(self):
+ a = np.ones(2, dtype='f,f')
+ assert_equal(repr(a), "array([(1., 1.), (1., 1.)],\n"
+ " dtype=[('f0', '<f4'), ('f1', '<f4')])")
+ assert_equal(repr(a[0]), "(1., 1.)")
+
+
def test_unicode_object_array():
import sys
if sys.version_info[0] >= 3:
diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py
index 84469d03b..34f9080fb 100644
--- a/numpy/core/tests/test_regression.py
+++ b/numpy/core/tests/test_regression.py
@@ -858,7 +858,7 @@ class TestRegression(object):
def test_sign_bit(self):
x = np.array([0, -0.0, 0])
- assert_equal(str(np.abs(x)), '[ 0. 0. 0.]')
+ assert_equal(str(np.abs(x)), '[0. 0. 0.]')
def test_flat_index_byteswap(self):
for dt in (np.dtype('<i4'), np.dtype('>i4')):
diff --git a/numpy/polynomial/tests/test_printing.py b/numpy/polynomial/tests/test_printing.py
index f403812c9..939d48a86 100644
--- a/numpy/polynomial/tests/test_printing.py
+++ b/numpy/polynomial/tests/test_printing.py
@@ -7,64 +7,64 @@ from numpy.testing import run_module_suite, assert_equal
class TestStr(object):
def test_polynomial_str(self):
res = str(poly.Polynomial([0, 1]))
- tgt = 'poly([ 0. 1.])'
+ tgt = 'poly([0. 1.])'
assert_equal(res, tgt)
def test_chebyshev_str(self):
res = str(poly.Chebyshev([0, 1]))
- tgt = 'cheb([ 0. 1.])'
+ tgt = 'cheb([0. 1.])'
assert_equal(res, tgt)
def test_legendre_str(self):
res = str(poly.Legendre([0, 1]))
- tgt = 'leg([ 0. 1.])'
+ tgt = 'leg([0. 1.])'
assert_equal(res, tgt)
def test_hermite_str(self):
res = str(poly.Hermite([0, 1]))
- tgt = 'herm([ 0. 1.])'
+ tgt = 'herm([0. 1.])'
assert_equal(res, tgt)
def test_hermiteE_str(self):
res = str(poly.HermiteE([0, 1]))
- tgt = 'herme([ 0. 1.])'
+ tgt = 'herme([0. 1.])'
assert_equal(res, tgt)
def test_laguerre_str(self):
res = str(poly.Laguerre([0, 1]))
- tgt = 'lag([ 0. 1.])'
+ tgt = 'lag([0. 1.])'
assert_equal(res, tgt)
class TestRepr(object):
def test_polynomial_str(self):
res = repr(poly.Polynomial([0, 1]))
- tgt = 'Polynomial([ 0., 1.], domain=[-1, 1], window=[-1, 1])'
+ tgt = 'Polynomial([0., 1.], domain=[-1, 1], window=[-1, 1])'
assert_equal(res, tgt)
def test_chebyshev_str(self):
res = repr(poly.Chebyshev([0, 1]))
- tgt = 'Chebyshev([ 0., 1.], domain=[-1, 1], window=[-1, 1])'
+ tgt = 'Chebyshev([0., 1.], domain=[-1, 1], window=[-1, 1])'
assert_equal(res, tgt)
def test_legendre_repr(self):
res = repr(poly.Legendre([0, 1]))
- tgt = 'Legendre([ 0., 1.], domain=[-1, 1], window=[-1, 1])'
+ tgt = 'Legendre([0., 1.], domain=[-1, 1], window=[-1, 1])'
assert_equal(res, tgt)
def test_hermite_repr(self):
res = repr(poly.Hermite([0, 1]))
- tgt = 'Hermite([ 0., 1.], domain=[-1, 1], window=[-1, 1])'
+ tgt = 'Hermite([0., 1.], domain=[-1, 1], window=[-1, 1])'
assert_equal(res, tgt)
def test_hermiteE_repr(self):
res = repr(poly.HermiteE([0, 1]))
- tgt = 'HermiteE([ 0., 1.], domain=[-1, 1], window=[-1, 1])'
+ tgt = 'HermiteE([0., 1.], domain=[-1, 1], window=[-1, 1])'
assert_equal(res, tgt)
def test_laguerre_repr(self):
res = repr(poly.Laguerre([0, 1]))
- tgt = 'Laguerre([ 0., 1.], domain=[0, 1], window=[0, 1])'
+ tgt = 'Laguerre([0., 1.], domain=[0, 1], window=[0, 1])'
assert_equal(res, tgt)
diff --git a/numpy/testing/tests/test_utils.py b/numpy/testing/tests/test_utils.py
index 493c538af..1a2a621ea 100644
--- a/numpy/testing/tests/test_utils.py
+++ b/numpy/testing/tests/test_utils.py
@@ -159,9 +159,9 @@ class TestBuildErrorMessage(unittest.TestCase):
err_msg = 'There is a mismatch'
a = build_err_msg([x, y], err_msg)
- b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array([ '
- '1.00001, 2.00002, 3.00003])\n DESIRED: array([ 1.00002, '
- '2.00003, 3.00004])')
+ b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array(['
+ '1.00001, 2.00002, 3.00003])\n DESIRED: array([1.00002, '
+ '2.00003, 3.00004])')
self.assertEqual(a, b)
def test_build_err_msg_no_verbose(self):
@@ -179,8 +179,8 @@ class TestBuildErrorMessage(unittest.TestCase):
err_msg = 'There is a mismatch'
a = build_err_msg([x, y], err_msg, names=('FOO', 'BAR'))
- b = ('\nItems are not equal: There is a mismatch\n FOO: array([ '
- '1.00001, 2.00002, 3.00003])\n BAR: array([ 1.00002, 2.00003, '
+ b = ('\nItems are not equal: There is a mismatch\n FOO: array(['
+ '1.00001, 2.00002, 3.00003])\n BAR: array([1.00002, 2.00003, '
'3.00004])')
self.assertEqual(a, b)
@@ -190,9 +190,9 @@ class TestBuildErrorMessage(unittest.TestCase):
err_msg = 'There is a mismatch'
a = build_err_msg([x, y], err_msg, precision=10)
- b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array([ '
- '1.000000001, 2.00002 , 3.00003 ])\n DESIRED: array([ '
- '1.000000002, 2.00003 , 3.00004 ])')
+ b = ('\nItems are not equal: There is a mismatch\n ACTUAL: array(['
+ '1.000000001, 2.00002 , 3.00003 ])\n DESIRED: array(['
+ '1.000000002, 2.00003 , 3.00004 ])')
self.assertEqual(a, b)
@@ -433,8 +433,8 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
# test with a different amount of decimal digits
# note that we only check for the formatting of the arrays themselves
- b = ('x: array([ 1.00000000001, 2.00000000002, 3.00003 '
- ' ])\n y: array([ 1.00000000002, 2.00000000003, 3.00004 ])')
+ b = ('x: array([1.00000000001, 2.00000000002, 3.00003 '
+ ' ])\n y: array([1.00000000002, 2.00000000003, 3.00004 ])')
try:
self._assert_func(x, y, decimal=12)
except AssertionError as e:
@@ -443,8 +443,8 @@ class TestAlmostEqual(_GenericTest, unittest.TestCase):
# with the default value of decimal digits, only the 3rd element differs
# note that we only check for the formatting of the arrays themselves
- b = ('x: array([ 1. , 2. , 3.00003])\n y: array([ 1. , '
- '2. , 3.00004])')
+ b = ('x: array([1. , 2. , 3.00003])\n y: array([1. , '
+ '2. , 3.00004])')
try:
self._assert_func(x, y)
except AssertionError as e: