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

Code before:
        i4 = np.dtype("i4")
        with pytest.raises(TypeError):
            # May be allowable at some point?
            np.add.resolve_dtypes((i4, i4, i4), reduction=True)

    @pytest.mark.parametrize("dtypes", [
            (np.dtype("i"), np.dtype("i")),
            (None, np.dtype("i"), np.dtype("f")),
            (np.dtype("i"), None, np.dtype("f")),
            ("i4", "i4", None)])
    def test_resolve_dtypes_errors(self, dtypes):
        with pytest.raises(TypeError):
            np.add.resolve_dtypes(dtypes)

    def test_resolve_dtypes_reduction_errors(self):
        i2 = np.dtype("i2")

        with pytest.raises(TypeError):
            np.add.resolve_dtypes((None, i2, i2))

        with pytest.raises(TypeError):
            np.add.signature((None, None, "i4"))

    @pytest.mark.skipif(not hasattr(ct, "pythonapi"),
            reason="`ctypes.pythonapi` required for capsule unpacking.")
    @pytest.mark.thread_unsafe(reason="ctype global state")
    def test_loop_access(self):
        # This is a basic test for the full strided loop access
        data_t = ct.c_char_p * 2
        dim_t = ct.c_ssize_t * 1
        strides_t = ct.c_ssize_t * 2
        strided_loop_t = ct.CFUNCTYPE(
                ct.c_int, ct.c_void_p, data_t, dim_t, strides_t, ct.c_void_p)

        class call_info_t(ct.Structure):
            _fields_ = [
                ("strided_loop", strided_loop_t),
                ("context", ct.c_void_p),
                ("auxdata", ct.c_void_p),
                ("requires_pyapi", ct.c_byte),
                ("no_floatingpoint_errors", ct.c_byte),
            ]

        i4 = np.dtype("i4")
        dt, call_info_obj = np.negative._resolve_dtypes_and_context((i4, i4))
        assert dt == (i4, i4)  # can be used without casting

        # Fill in the rest of the information:
        np.negative._get_strided_loop(call_info_obj)

        ct.pythonapi.PyCapsule_GetPointer.restype = ct.c_void_p

Review comment (suggestion):
```suggestion
    @pytest.mark.thread_unsafe(reason="modifies global object in the ctypes API")
```

Code after:
        i4 = np.dtype("i4")
        with pytest.raises(TypeError):
            # May be allowable at some point?
            np.add.resolve_dtypes((i4, i4, i4), reduction=True)

    @pytest.mark.parametrize("dtypes", [
            (np.dtype("i"), np.dtype("i")),
            (None, np.dtype("i"), np.dtype("f")),
            (np.dtype("i"), None, np.dtype("f")),
            ("i4", "i4", None)])
    def test_resolve_dtypes_errors(self, dtypes):
        with pytest.raises(TypeError):
            np.add.resolve_dtypes(dtypes)

    def test_resolve_dtypes_reduction_errors(self):
        i2 = np.dtype("i2")

        with pytest.raises(TypeError):
            np.add.resolve_dtypes((None, i2, i2))

        with pytest.raises(TypeError):
            np.add.signature((None, None, "i4"))

    @pytest.mark.skipif(not hasattr(ct, "pythonapi"),
            reason="`ctypes.pythonapi` required for capsule unpacking.")
    @pytest.mark.thread_unsafe(reason="modifies global object in the ctypes API")
    def test_loop_access(self):
        # This is a basic test for the full strided loop access
        data_t = ct.c_char_p * 2
        dim_t = ct.c_ssize_t * 1
        strides_t = ct.c_ssize_t * 2
        strided_loop_t = ct.CFUNCTYPE(
                ct.c_int, ct.c_void_p, data_t, dim_t, strides_t, ct.c_void_p)

        class call_info_t(ct.Structure):
            _fields_ = [
                ("strided_loop", strided_loop_t),
                ("context", ct.c_void_p),
                ("auxdata", ct.c_void_p),
                ("requires_pyapi", ct.c_byte),
                ("no_floatingpoint_errors", ct.c_byte),
            ]

        i4 = np.dtype("i4")
        dt, call_info_obj = np.negative._resolve_dtypes_and_context((i4, i4))
        assert dt == (i4, i4)  # can be used without casting

        # Fill in the rest of the information:
        np.negative._get_strided_loop(call_info_obj)

        ct.pythonapi.PyCapsule_GetPointer.restype = ct.c_void_p