import sys import gc from hypothesis import given from hypothesis.extra import numpy as hynp import pytest import numpy as np from numpy.testing import ( assert_, assert_equal, assert_raises, assert_warns, HAS_REFCOUNT, assert_raises_regex, ) from numpy.core.arrayprint import _typelessdata import textwrap class TestArrayRepr: def test_nan_inf(self): x = np.array([np.nan, np.inf]) assert_equal(repr(x), 'array([nan, inf])') def test_subclass(self): class sub(np.ndarray): pass # one dimensional x1d = np.array([1, 2]).view(sub) assert_equal(repr(x1d), 'sub([1, 2])') # two dimensional x2d = np.array([[1, 2], [3, 4]]).view(sub) assert_equal(repr(x2d), 'sub([[1, 2],\n' ' [3, 4]])') # two dimensional with flexible dtype xstruct = np.ones((2,2), dtype=[('a', ' 1) y = sub(None) x[()] = y y[()] = x assert_equal(repr(x), 'sub(sub(sub(..., dtype=object), dtype=object), dtype=object)') assert_equal(str(x), '...') x[()] = 0 # resolve circular references for garbage collector # nested 0d-subclass-object x = sub(None) x[()] = sub(None) assert_equal(repr(x), 'sub(sub(None, dtype=object), dtype=object)') assert_equal(str(x), 'None') # gh-10663 class DuckCounter(np.ndarray): def __getitem__(self, item): result = super().__getitem__(item) if not isinstance(result, DuckCounter): result = result[...].view(DuckCounter) return result def to_string(self): return {0: 'zero', 1: 'one', 2: 'two'}.get(self.item(), 'many') def __str__(self): if self.shape == (): return self.to_string() else: fmt = {'all': lambda x: x.to_string()} return np.array2string(self, formatter=fmt) dc = np.arange(5).view(DuckCounter) assert_equal(str(dc), "[zero one two many many]") assert_equal(str(dc[0]), "zero") def test_self_containing(self): arr0d = np.array(None) arr0d[()] = arr0d assert_equal(repr(arr0d), 'array(array(..., dtype=object), dtype=object)') arr0d[()] = 0 # resolve recursion for garbage collector arr1d = np.array([None, None]) arr1d[1] = arr1d assert_equal(repr(arr1d), 'array([None, array(..., dtype=object)], dtype=object)') arr1d[1] = 0 # resolve recursion for garbage collector first = np.array(None) second = np.array(None) first[()] = second second[()] = first assert_equal(repr(first), 'array(array(array(..., dtype=object), dtype=object), dtype=object)') first[()] = 0 # resolve circular references for garbage collector def test_containing_list(self): # printing square brackets directly would be ambiguuous arr1d = np.array([None, None]) arr1d[0] = [1, 2] arr1d[1] = [3] assert_equal(repr(arr1d), 'array([list([1, 2]), list([3])], dtype=object)') def test_void_scalar_recursion(self): # gh-9345 repr(np.void(b'test')) # RecursionError ? def test_fieldless_structured(self): # gh-10366 no_fields = np.dtype([]) arr_no_fields = np.empty(4, dtype=no_fields) assert_equal(repr(arr_no_fields), 'array([(), (), (), ()], dtype=[])') class TestComplexArray: def test_str(self): rvals = [0, 1, -1, np.inf, -np.inf, np.nan] cvals = [complex(rp, ip) for rp in rvals for ip in rvals] 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.j]', '[0.+1.j]', '[0.+1.j]', '[0.+1.j]', '[0.-1.j]', '[0.-1.j]', '[0.-1.j]', '[0.+infj]', '[0.+infj]', '[0.+infj]', '[0.-infj]', '[0.-infj]', '[0.-infj]', '[0.+nanj]', '[0.+nanj]', '[0.+nanj]', '[1.+0.j]', '[1.+0.j]', '[1.+0.j]', '[1.+1.j]', '[1.+1.j]', '[1.+1.j]', '[1.-1.j]', '[1.-1.j]', '[1.-1.j]', '[1.+infj]', '[1.+infj]', '[1.+infj]', '[1.-infj]', '[1.-infj]', '[1.-infj]', '[1.+nanj]', '[1.+nanj]', '[1.+nanj]', '[-1.+0.j]', '[-1.+0.j]', '[-1.+0.j]', '[-1.+1.j]', '[-1.+1.j]', '[-1.+1.j]', '[-1.-1.j]', '[-1.-1.j]', '[-1.-1.j]', '[-1.+infj]', '[-1.+infj]', '[-1.+infj]', '[-1.-infj]', '[-1.-infj]', '[-1.-infj]', '[-1.+nanj]', '[-1.+nanj]', '[-1.+nanj]', '[inf+0.j]', '[inf+0.j]', '[inf+0.j]', '[inf+1.j]', '[inf+1.j]', '[inf+1.j]', '[inf-1.j]', '[inf-1.j]', '[inf-1.j]', '[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.j]', '[-inf+1.j]', '[-inf+1.j]', '[-inf+1.j]', '[-inf-1.j]', '[-inf-1.j]', '[-inf-1.j]', '[-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.j]', '[nan+1.j]', '[nan+1.j]', '[nan+1.j]', '[nan-1.j]', '[nan-1.j]', '[nan-1.j]', '[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_equal(res, val) class TestArray2String: def test_basic(self): """Basic test of array2string.""" a = np.arange(3) assert_(np.array2string(a) == '[0 1 2]') assert_(np.array2string(a, max_line_width=4, legacy='1.13') == '[0 1\n 2]') assert_(np.array2string(a, max_line_width=4) == '[0\n 1\n 2]') def test_unexpected_kwarg(self): # ensure than an appropriate TypeError # is raised when array2string receives # an unexpected kwarg with assert_raises_regex(TypeError, 'nonsense'): np.array2string(np.array([1, 2, 3]), nonsense=None) def test_format_function(self): """Test custom format function for each element in array.""" def _format_function(x): if np.abs(x) < 1: return '.' elif np.abs(x) < 2: return 'o' else: return 'O' x = np.arange(3) x_hex = "[0x0 0x1 0x2]" x_oct = "[0o0 0o1 0o2]" assert_(np.array2string(x, formatter={'all':_format_function}) == "[. o O]") assert_(np.array2string(x, formatter={'int_kind':_format_function}) == "[. o O]") assert_(np.array2string(x, formatter={'all':lambda x: "%.4f" % x}) == "[0.0000 1.0000 2.0000]") assert_equal(np.array2string(x, formatter={'int':lambda x: hex(x)}), x_hex) assert_equal(np.array2string(x, formatter={'int':lambda x: oct(x)}), x_oct) x = np.arange(3.) assert_(np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) == "[0.00 1.00 2.00]") assert_(np.array2string(x, formatter={'float':lambda x: "%.2f" % x}) == "[0.00 1.00 2.00]") s = np.array(['abc', 'def']) assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) == '[abcabc defdef]') def test_structure_format_mixed(self): 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.])]") np.set_printoptions(legacy='1.13') try: # for issue #5692 A = np.zeros(shape=10, dtype=[("A", "M8[s]")]) A[5:].fill(np.datetime64('NaT')) assert_equal( np.array2string(A), textwrap.dedent("""\ [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('NaT',) ('NaT',) ('NaT',) ('NaT',) ('NaT',)]""") ) finally: np.set_printoptions(legacy=False) # same again, but with non-legacy behavior assert_equal( np.array2string(A), textwrap.dedent("""\ [('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ('1970-01-01T00:00:00',) ( 'NaT',) ( 'NaT',) ( 'NaT',) ( 'NaT',) ( 'NaT',)]""") ) # and again, with timedeltas A = np.full(10, 123456, dtype=[("A", "m8[s]")]) A[5:].fill(np.datetime64('NaT')) assert_equal( np.array2string(A), textwrap.dedent("""\ [(123456,) (123456,) (123456,) (123456,) (123456,) ( 'NaT',) ( 'NaT',) ( 'NaT',) ( 'NaT',) ( 'NaT',)]""") ) def test_structure_format_int(self): # See #8160 struct_int = np.array([([1, -1],), ([123, 1],)], dtype=[('B', 'i4', 2)]) assert_equal(np.array2string(struct_int), "[([ 1, -1],) ([123, 1],)]") struct_2dint = np.array([([[0, 1], [2, 3]],), ([[12, 0], [0, 0]],)], dtype=[('B', 'i4', (2, 2))]) assert_equal(np.array2string(struct_2dint), "[([[ 0, 1], [ 2, 3]],) ([[12, 0], [ 0, 0]],)]") def test_structure_format_float(self): # See #8172 array_scalar = np.array( (1., 2.1234567890123456789, 3.), dtype=('f8,f8,f8')) assert_equal(np.array2string(array_scalar), "(1., 2.12345679, 3.)") def test_unstructured_void_repr(self): a = np.array([27, 91, 50, 75, 7, 65, 10, 8, 27, 91, 51, 49,109, 82,101,100], dtype='u1').view('V8') assert_equal(repr(a[0]), r"void(b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08')") assert_equal(str(a[0]), r"b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'") assert_equal(repr(a), r"array([b'\x1B\x5B\x32\x4B\x07\x41\x0A\x08'," "\n" r" b'\x1B\x5B\x33\x31\x6D\x52\x65\x64'], dtype='|V8')") assert_equal(eval(repr(a), vars(np)), a) assert_equal(eval(repr(a[0]), vars(np)), a[0]) def test_edgeitems_kwarg(self): # previously the global print options would be taken over the kwarg arr = np.zeros(3, int) assert_equal( np.array2string(arr, edgeitems=1, threshold=0), "[0 ... 0]" ) def test_summarize_1d(self): A = np.arange(1001) strA = '[ 0 1 2 ... 998 999 1000]' assert_equal(str(A), strA) reprA = 'array([ 0, 1, 2, ..., 998, 999, 1000])' assert_equal(repr(A), reprA) def test_summarize_2d(self): A = np.arange(1002).reshape(2, 501) strA = '[[ 0 1 2 ... 498 499 500]\n' \ ' [ 501 502 503 ... 999 1000 1001]]' assert_equal(str(A), strA) reprA = 'array([[ 0, 1, 2, ..., 498, 499, 500],\n' \ ' [ 501, 502, 503, ..., 999, 1000, 1001]])' assert_equal(repr(A), reprA) def test_summarize_structure(self): A = (np.arange(2002, dtype="i8", (2, 1001))]) strB = "[([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)]" assert_equal(str(B), strB) reprB = ( "array([([[1, 1, 1, ..., 1, 1, 1], [1, 1, 1, ..., 1, 1, 1]],)],\n" " dtype=[('i', '>i8', (2, 1001))])" ) assert_equal(repr(B), reprB) C = (np.arange(22, dtype=" 1: # if the type is >1 byte, the non-native endian version # must show endianness. assert non_native_repr != native_repr assert f"dtype='{non_native_dtype.byteorder}" in non_native_repr def test_linewidth_repr(self): a = np.full(7, fill_value=2) np.set_printoptions(linewidth=17) assert_equal( repr(a), textwrap.dedent("""\ array([2, 2, 2, 2, 2, 2, 2])""") ) np.set_printoptions(linewidth=17, legacy='1.13') assert_equal( repr(a), textwrap.dedent("""\ array([2, 2, 2, 2, 2, 2, 2])""") ) a = np.full(8, fill_value=2) np.set_printoptions(linewidth=18, legacy=False) assert_equal( repr(a), textwrap.dedent("""\ array([2, 2, 2, 2, 2, 2, 2, 2])""") ) np.set_printoptions(linewidth=18, legacy='1.13') assert_equal( repr(a), textwrap.dedent("""\ array([2, 2, 2, 2, 2, 2, 2, 2])""") ) def test_linewidth_str(self): a = np.full(18, fill_value=2) np.set_printoptions(linewidth=18) assert_equal( str(a), textwrap.dedent("""\ [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]""") ) np.set_printoptions(linewidth=18, legacy='1.13') assert_equal( str(a), textwrap.dedent("""\ [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2]""") ) def test_edgeitems(self): np.set_printoptions(edgeitems=1, threshold=1) a = np.arange(27).reshape((3, 3, 3)) assert_equal( repr(a), textwrap.dedent("""\ array([[[ 0, ..., 2], ..., [ 6, ..., 8]], ..., [[18, ..., 20], ..., [24, ..., 26]]])""") ) b = np.zeros((3, 3, 1, 1)) assert_equal( repr(b), textwrap.dedent("""\ array([[[[0.]], ..., [[0.]]], ..., [[[0.]], ..., [[0.]]]])""") ) # 1.13 had extra trailing spaces, and was missing newlines np.set_printoptions(legacy='1.13') assert_equal( repr(a), textwrap.dedent("""\ array([[[ 0, ..., 2], ..., [ 6, ..., 8]], ..., [[18, ..., 20], ..., [24, ..., 26]]])""") ) assert_equal( repr(b), textwrap.dedent("""\ array([[[[ 0.]], ..., [[ 0.]]], ..., [[[ 0.]], ..., [[ 0.]]]])""") ) def test_edgeitems_structured(self): np.set_printoptions(edgeitems=1, threshold=1) A = np.arange(5*2*3, dtype="