Repository: numpy/numpy
File: numpy/_core/tests/test_nditer.py (Python)

Code before:
def test_arbitrary_number_of_ops_nested():
    # 2*16 + 1 is still just a few kiB, so should be fast and easy to deal with
    # but larger than any small custom integer.
    ops = [np.arange(10) for a in range(2**16 + 1)]

    it = np.nested_iters(ops, [[0], []])
    for i, vals in enumerate(it):
        assert all(v == i for v in vals)


@pytest.mark.slow
@requires_memory(9 * np.iinfo(np.intc).max)
@pytest.mark.thread_unsafe(reason="crashes with low memory")
def test_arbitrary_number_of_ops_error():
    # A different error may happen for more than integer operands, but that
    # is too large to test nicely.
    a = np.ones(1)
    args = [a] * (np.iinfo(np.intc).max + 1)
    with pytest.raises(ValueError, match="Too many operands to nditer"):
        np.nditer(args)

    with pytest.raises(ValueError, match="Too many operands to nditer"):
        np.nested_iters(args, [[0], []])


@pytest.mark.thread_unsafe(reason="capfd is thread-unsafe?")
def test_debug_print(capfd):
    """
    Matches the expected output of a debug print with the actual output.
    Note that the iterator dump should not be considered stable API,
    this test is mainly to ensure the print does not crash.

    Currently uses a subprocess to avoid dealing with the C level `printf`s.
    """
    # the expected output with all addresses and sizes stripped (they vary
    # and/or are platform dependent).
    expected = """
    ------ BEGIN ITERATOR DUMP ------
    | Iterator Address:
    | ItFlags: BUFFER REDUCE
    | NDim: 2
    | NOp: 2
    | IterSize: 50
    | IterStart: 0
    | IterEnd: 50
    | IterIndex: 0
    | Iterator SizeOf:
    | BufferData SizeOf:
    | AxisData SizeOf:
    |
    | Perm: 0 1

Review comment (suggestion):
```suggestion
@pytest.mark.thread_unsafe(reason="capfd is thread-unsafe")
```

No need to be uncertain - it's thread-unsafe. It's reading from stdout and stderr and there's only one of each stream globally.

Code after:
def test_arbitrary_number_of_ops_nested():
    # 2*16 + 1 is still just a few kiB, so should be fast and easy to deal with
    # but larger than any small custom integer.
    ops = [np.arange(10) for a in range(2**16 + 1)]

    it = np.nested_iters(ops, [[0], []])
    for i, vals in enumerate(it):
        assert all(v == i for v in vals)


@pytest.mark.slow
@requires_memory(9 * np.iinfo(np.intc).max)
@pytest.mark.thread_unsafe(reason="crashes with low memory")
def test_arbitrary_number_of_ops_error():
    # A different error may happen for more than integer operands, but that
    # is too large to test nicely.
    a = np.ones(1)
    args = [a] * (np.iinfo(np.intc).max + 1)
    with pytest.raises(ValueError, match="Too many operands to nditer"):
        np.nditer(args)

    with pytest.raises(ValueError, match="Too many operands to nditer"):
        np.nested_iters(args, [[0], []])


@pytest.mark.thread_unsafe(reason="capfd is thread-unsafe")
def test_debug_print(capfd):
    """
    Matches the expected output of a debug print with the actual output.
    Note that the iterator dump should not be considered stable API,
    this test is mainly to ensure the print does not crash.

    Currently uses a subprocess to avoid dealing with the C level `printf`s.
    """
    # the expected output with all addresses and sizes stripped (they vary
    # and/or are platform dependent).
    expected = """
    ------ BEGIN ITERATOR DUMP ------
    | Iterator Address:
    | ItFlags: BUFFER REDUCE
    | NDim: 2
    | NOp: 2
    | IterSize: 50
    | IterStart: 0
    | IterEnd: 50
    | IterIndex: 0
    | Iterator SizeOf:
    | BufferData SizeOf:
    | AxisData SizeOf:
    |
    | Perm: 0 1