test_numpy_array.py 19.4 KB
Newer Older
1
# -*- coding: utf-8 -*-
2
3
import pytest

4
5
import env  # noqa: F401
from pybind11_tests import numpy_array as m
6

7
np = pytest.importorskip("numpy")
8
9


10
11
12
13
14
15
16
17
18
19
20
def test_dtypes():
    # See issue #1328.
    # - Platform-dependent sizes.
    for size_check in m.get_platform_dtype_size_checks():
        print(size_check)
        assert size_check.size_cpp == size_check.size_numpy, size_check
    # - Concrete sizes.
    for check in m.get_concrete_dtype_checks():
        print(check)
        assert check.numpy == check.pybind11, check
        if check.numpy.num != check.pybind11.num:
21
22
23
24
25
            print(
                "NOTE: typenum mismatch for {}: {} != {}".format(
                    check, check.numpy.num, check.pybind11.num
                )
            )
26
27


28
@pytest.fixture(scope="function")
29
def arr():
30
    return np.array([[1, 2, 3], [4, 5, 6]], "=u2")
31
32


33
def test_array_attributes():
34
    a = np.array(0, "f8")
35
36
37
    assert m.ndim(a) == 0
    assert all(m.shape(a) == [])
    assert all(m.strides(a) == [])
38
    with pytest.raises(IndexError) as excinfo:
39
        m.shape(a, 0)
40
    assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)"
41
    with pytest.raises(IndexError) as excinfo:
42
        m.strides(a, 0)
43
    assert str(excinfo.value) == "invalid axis: 0 (ndim = 0)"
44
45
46
47
48
    assert m.writeable(a)
    assert m.size(a) == 1
    assert m.itemsize(a) == 8
    assert m.nbytes(a) == 8
    assert m.owndata(a)
49

50
    a = np.array([[1, 2, 3], [4, 5, 6]], "u2").view()
51
    a.flags.writeable = False
52
53
54
55
56
57
58
    assert m.ndim(a) == 2
    assert all(m.shape(a) == [2, 3])
    assert m.shape(a, 0) == 2
    assert m.shape(a, 1) == 3
    assert all(m.strides(a) == [6, 2])
    assert m.strides(a, 0) == 6
    assert m.strides(a, 1) == 2
59
    with pytest.raises(IndexError) as excinfo:
60
        m.shape(a, 2)
61
    assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)"
62
    with pytest.raises(IndexError) as excinfo:
63
        m.strides(a, 2)
64
    assert str(excinfo.value) == "invalid axis: 2 (ndim = 2)"
65
66
67
68
69
    assert not m.writeable(a)
    assert m.size(a) == 6
    assert m.itemsize(a) == 2
    assert m.nbytes(a) == 12
    assert not m.owndata(a)
70
71


72
73
74
@pytest.mark.parametrize(
    "args, ret", [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)]
)
75
def test_index_offset(arr, args, ret):
76
77
78
79
    assert m.index_at(arr, *args) == ret
    assert m.index_at_t(arr, *args) == ret
    assert m.offset_at(arr, *args) == ret * arr.dtype.itemsize
    assert m.offset_at_t(arr, *args) == ret * arr.dtype.itemsize
80
81
82


def test_dim_check_fail(arr):
83
84
85
86
87
88
89
90
91
92
    for func in (
        m.index_at,
        m.index_at_t,
        m.offset_at,
        m.offset_at_t,
        m.data,
        m.data_t,
        m.mutate_data,
        m.mutate_data_t,
    ):
93
94
        with pytest.raises(IndexError) as excinfo:
            func(arr, 1, 2, 3)
95
        assert str(excinfo.value) == "too many indices for an array: 3 (ndim = 2)"
96
97


98
99
100
101
102
103
104
105
106
@pytest.mark.parametrize(
    "args, ret",
    [
        ([], [1, 2, 3, 4, 5, 6]),
        ([1], [4, 5, 6]),
        ([0, 1], [2, 3, 4, 5, 6]),
        ([1, 2], [6]),
    ],
)
107
def test_data(arr, args, ret):
108
    from sys import byteorder
109

110
    assert all(m.data_t(arr, *args) == ret)
111
112
    assert all(m.data(arr, *args)[(0 if byteorder == "little" else 1) :: 2] == ret)
    assert all(m.data(arr, *args)[(1 if byteorder == "little" else 0) :: 2] == 0)
113
114


115
@pytest.mark.parametrize("dim", [0, 1, 3])
116
def test_at_fail(arr, dim):
117
    for func in m.at_t, m.mutate_at_t:
118
119
        with pytest.raises(IndexError) as excinfo:
            func(arr, *([0] * dim))
120
121
122
        assert str(excinfo.value) == "index dimension mismatch: {} (ndim = 2)".format(
            dim
        )
123
124
125


def test_at(arr):
126
127
128
129
130
    assert m.at_t(arr, 0, 2) == 3
    assert m.at_t(arr, 1, 0) == 4

    assert all(m.mutate_at_t(arr, 0, 2).ravel() == [1, 2, 4, 4, 5, 6])
    assert all(m.mutate_at_t(arr, 1, 0).ravel() == [1, 2, 4, 5, 5, 6])
131
132


133
134
def test_mutate_readonly(arr):
    arr.flags.writeable = False
135
136
137
138
139
    for func, args in (
        (m.mutate_data, ()),
        (m.mutate_data_t, ()),
        (m.mutate_at_t, (0, 0)),
    ):
140
141
        with pytest.raises(ValueError) as excinfo:
            func(arr, *args)
142
        assert str(excinfo.value) == "array is not writeable"
143
144
145


def test_mutate_data(arr):
146
147
148
149
150
    assert all(m.mutate_data(arr).ravel() == [2, 4, 6, 8, 10, 12])
    assert all(m.mutate_data(arr).ravel() == [4, 8, 12, 16, 20, 24])
    assert all(m.mutate_data(arr, 1).ravel() == [4, 8, 12, 32, 40, 48])
    assert all(m.mutate_data(arr, 0, 1).ravel() == [4, 16, 24, 64, 80, 96])
    assert all(m.mutate_data(arr, 1, 2).ravel() == [4, 16, 24, 64, 80, 192])
151

152
153
154
155
156
    assert all(m.mutate_data_t(arr).ravel() == [5, 17, 25, 65, 81, 193])
    assert all(m.mutate_data_t(arr).ravel() == [6, 18, 26, 66, 82, 194])
    assert all(m.mutate_data_t(arr, 1).ravel() == [6, 18, 26, 67, 83, 195])
    assert all(m.mutate_data_t(arr, 0, 1).ravel() == [6, 19, 27, 68, 84, 196])
    assert all(m.mutate_data_t(arr, 1, 2).ravel() == [6, 19, 27, 68, 84, 197])
157
158
159


def test_bounds_check(arr):
160
161
162
163
164
165
166
167
168
169
    for func in (
        m.index_at,
        m.index_at_t,
        m.data,
        m.data_t,
        m.mutate_data,
        m.mutate_data_t,
        m.at_t,
        m.mutate_at_t,
    ):
170
        with pytest.raises(IndexError) as excinfo:
171
            func(arr, 2, 0)
172
        assert str(excinfo.value) == "index 2 is out of bounds for axis 0 with size 2"
173
        with pytest.raises(IndexError) as excinfo:
174
            func(arr, 0, 4)
175
        assert str(excinfo.value) == "index 4 is out of bounds for axis 1 with size 3"
176

177

178
def test_make_c_f_array():
179
180
181
182
    assert m.make_c_array().flags.c_contiguous
    assert not m.make_c_array().flags.f_contiguous
    assert m.make_f_array().flags.f_contiguous
    assert not m.make_f_array().flags.c_contiguous
183
184


185
186
187
def test_make_empty_shaped_array():
    m.make_empty_shaped_array()

188
189
190
191
192
    # empty shape means numpy scalar, PEP 3118
    assert m.scalar_int().ndim == 0
    assert m.scalar_int().shape == ()
    assert m.scalar_int() == 42

193

194
def test_wrap():
Jason Rhinelander's avatar
Jason Rhinelander committed
195
    def assert_references(a, b, base=None):
196
        from distutils.version import LooseVersion
197

Jason Rhinelander's avatar
Jason Rhinelander committed
198
199
        if base is None:
            base = a
200
        assert a is not b
201
        assert a.__array_interface__["data"][0] == b.__array_interface__["data"][0]
202
203
204
205
206
207
        assert a.shape == b.shape
        assert a.strides == b.strides
        assert a.flags.c_contiguous == b.flags.c_contiguous
        assert a.flags.f_contiguous == b.flags.f_contiguous
        assert a.flags.writeable == b.flags.writeable
        assert a.flags.aligned == b.flags.aligned
208
209
210
211
        if LooseVersion(np.__version__) >= LooseVersion("1.14.0"):
            assert a.flags.writebackifcopy == b.flags.writebackifcopy
        else:
            assert a.flags.updateifcopy == b.flags.updateifcopy
212
213
        assert np.all(a == b)
        assert not b.flags.owndata
Jason Rhinelander's avatar
Jason Rhinelander committed
214
        assert b.base is base
215
216
217
218
219
220
        if a.flags.writeable and a.ndim == 2:
            a[0, 0] = 1234
            assert b[0, 0] == 1234

    a1 = np.array([1, 2], dtype=np.int16)
    assert a1.flags.owndata and a1.base is None
221
    a2 = m.wrap(a1)
222
223
    assert_references(a1, a2)

224
    a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="F")
225
    assert a1.flags.owndata and a1.base is None
226
    a2 = m.wrap(a1)
227
228
    assert_references(a1, a2)

229
    a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order="C")
230
    a1.flags.writeable = False
231
    a2 = m.wrap(a1)
232
233
234
    assert_references(a1, a2)

    a1 = np.random.random((4, 4, 4))
235
    a2 = m.wrap(a1)
236
237
    assert_references(a1, a2)

Jason Rhinelander's avatar
Jason Rhinelander committed
238
    a1t = a1.transpose()
239
    a2 = m.wrap(a1t)
Jason Rhinelander's avatar
Jason Rhinelander committed
240
    assert_references(a1t, a2, a1)
241

Jason Rhinelander's avatar
Jason Rhinelander committed
242
    a1d = a1.diagonal()
243
    a2 = m.wrap(a1d)
Jason Rhinelander's avatar
Jason Rhinelander committed
244
    assert_references(a1d, a2, a1)
245

246
    a1m = a1[::-1, ::-1, ::-1]
247
    a2 = m.wrap(a1m)
248
249
    assert_references(a1m, a2, a1)

250
251
252

def test_numpy_view(capture):
    with capture:
253
        ac = m.ArrayClass()
254
255
256
257
        ac_view_1 = ac.numpy_view()
        ac_view_2 = ac.numpy_view()
        assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32))
        del ac
Wenzel Jakob's avatar
Wenzel Jakob committed
258
        pytest.gc_collect()
259
260
261
    assert (
        capture
        == """
262
263
264
265
        ArrayClass()
        ArrayClass::numpy_view()
        ArrayClass::numpy_view()
    """
266
    )
267
268
269
270
271
272
273
    ac_view_1[0] = 4
    ac_view_1[1] = 3
    assert ac_view_2[0] == 4
    assert ac_view_2[1] == 3
    with capture:
        del ac_view_1
        del ac_view_2
Wenzel Jakob's avatar
Wenzel Jakob committed
274
275
        pytest.gc_collect()
        pytest.gc_collect()
276
277
278
    assert (
        capture
        == """
279
280
        ~ArrayClass()
    """
281
    )
282
283
284


def test_cast_numpy_int64_to_uint64():
285
286
    m.function_taking_uint64(123)
    m.function_taking_uint64(np.uint64(123))
287
288
289


def test_isinstance():
290
291
    assert m.isinstance_untyped(np.array([1, 2, 3]), "not an array")
    assert m.isinstance_typed(np.array([1.0, 2.0, 3.0]))
292
293
294


def test_constructors():
295
    defaults = m.default_constructors()
296
297
298
299
300
301
    for a in defaults.values():
        assert a.size == 0
    assert defaults["array"].dtype == np.array([]).dtype
    assert defaults["array_t<int32>"].dtype == np.int32
    assert defaults["array_t<double>"].dtype == np.float64

302
    results = m.converting_constructors([1, 2, 3])
303
304
305
306
307
    for a in results.values():
        np.testing.assert_array_equal(a, [1, 2, 3])
    assert results["array"].dtype == np.int_
    assert results["array_t<int32>"].dtype == np.int32
    assert results["array_t<double>"].dtype == np.float64
308
309


310
311
def test_overload_resolution(msg):
    # Exact overload matches:
312
313
314
315
316
317
318
    assert m.overloaded(np.array([1], dtype="float64")) == "double"
    assert m.overloaded(np.array([1], dtype="float32")) == "float"
    assert m.overloaded(np.array([1], dtype="ushort")) == "unsigned short"
    assert m.overloaded(np.array([1], dtype="intc")) == "int"
    assert m.overloaded(np.array([1], dtype="longlong")) == "long long"
    assert m.overloaded(np.array([1], dtype="complex")) == "double complex"
    assert m.overloaded(np.array([1], dtype="csingle")) == "float complex"
319
320

    # No exact match, should call first convertible version:
321
    assert m.overloaded(np.array([1], dtype="uint8")) == "double"
322

323
    with pytest.raises(TypeError) as excinfo:
324
        m.overloaded("not an array")
325
326
327
    assert (
        msg(excinfo.value)
        == """
328
        overloaded(): incompatible function arguments. The following argument types are supported:
329
330
331
332
333
334
335
            1. (arg0: numpy.ndarray[numpy.float64]) -> str
            2. (arg0: numpy.ndarray[numpy.float32]) -> str
            3. (arg0: numpy.ndarray[numpy.int32]) -> str
            4. (arg0: numpy.ndarray[numpy.uint16]) -> str
            5. (arg0: numpy.ndarray[numpy.int64]) -> str
            6. (arg0: numpy.ndarray[numpy.complex128]) -> str
            7. (arg0: numpy.ndarray[numpy.complex64]) -> str
336
337
338

        Invoked with: 'not an array'
    """
339
    )
340

341
342
343
344
345
    assert m.overloaded2(np.array([1], dtype="float64")) == "double"
    assert m.overloaded2(np.array([1], dtype="float32")) == "float"
    assert m.overloaded2(np.array([1], dtype="complex64")) == "float complex"
    assert m.overloaded2(np.array([1], dtype="complex128")) == "double complex"
    assert m.overloaded2(np.array([1], dtype="float32")) == "float"
346

347
348
    assert m.overloaded3(np.array([1], dtype="float64")) == "double"
    assert m.overloaded3(np.array([1], dtype="intc")) == "int"
349
350
    expected_exc = """
        overloaded3(): incompatible function arguments. The following argument types are supported:
351
352
            1. (arg0: numpy.ndarray[numpy.int32]) -> str
            2. (arg0: numpy.ndarray[numpy.float64]) -> str
353

354
        Invoked with: """
355
356

    with pytest.raises(TypeError) as excinfo:
357
358
        m.overloaded3(np.array([1], dtype="uintc"))
    assert msg(excinfo.value) == expected_exc + repr(np.array([1], dtype="uint32"))
359
    with pytest.raises(TypeError) as excinfo:
360
361
        m.overloaded3(np.array([1], dtype="float32"))
    assert msg(excinfo.value) == expected_exc + repr(np.array([1.0], dtype="float32"))
362
    with pytest.raises(TypeError) as excinfo:
363
364
        m.overloaded3(np.array([1], dtype="complex"))
    assert msg(excinfo.value) == expected_exc + repr(np.array([1.0 + 0.0j]))
365
366

    # Exact matches:
367
368
    assert m.overloaded4(np.array([1], dtype="double")) == "double"
    assert m.overloaded4(np.array([1], dtype="longlong")) == "long long"
369
370
371
    # Non-exact matches requiring conversion.  Since float to integer isn't a
    # save conversion, it should go to the double overload, but short can go to
    # either (and so should end up on the first-registered, the long long).
372
373
    assert m.overloaded4(np.array([1], dtype="float32")) == "double"
    assert m.overloaded4(np.array([1], dtype="short")) == "long long"
374

375
376
377
    assert m.overloaded5(np.array([1], dtype="double")) == "double"
    assert m.overloaded5(np.array([1], dtype="uintc")) == "unsigned int"
    assert m.overloaded5(np.array([1], dtype="float32")) == "unsigned int"
378
379


380
381
def test_greedy_string_overload():
    """Tests fix for #685 - ndarray shouldn't go to std::string overload"""
382

383
    assert m.issue685("abc") == "string"
384
    assert m.issue685(np.array([97, 98, 99], dtype="b")) == "array"
385
    assert m.issue685(123) == "other"
386
387


388
def test_array_unchecked_fixed_dims(msg):
389
    z1 = np.array([[1, 2], [3, 4]], dtype="float64")
390
    m.proxy_add2(z1, 10)
391
392
393
    assert np.all(z1 == [[11, 12], [13, 14]])

    with pytest.raises(ValueError) as excinfo:
394
395
396
397
        m.proxy_add2(np.array([1.0, 2, 3]), 5.0)
    assert (
        msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2"
    )
398

399
    expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int")
400
    assert np.all(m.proxy_init3(3.0) == expect_c)
401
    expect_f = np.transpose(expect_c)
402
    assert np.all(m.proxy_init3F(3.0) == expect_f)
403

404
405
    assert m.proxy_squared_L2_norm(np.array(range(6))) == 55
    assert m.proxy_squared_L2_norm(np.array(range(6), dtype="float64")) == 55
406

407
408
    assert m.proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
    assert m.proxy_auxiliaries2(z1) == m.array_auxiliaries2(z1)
409

410
411
412
    assert m.proxy_auxiliaries1_const_ref(z1[0, :])
    assert m.proxy_auxiliaries2_const_ref(z1)

413

Nick Cullen's avatar
Nick Cullen committed
414
def test_array_unchecked_dyn_dims():
415
    z1 = np.array([[1, 2], [3, 4]], dtype="float64")
416
    m.proxy_add2_dyn(z1, 10)
417
418
    assert np.all(z1 == [[11, 12], [13, 14]])

419
    expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype="int")
420
    assert np.all(m.proxy_init3_dyn(3.0) == expect_c)
421

422
423
    assert m.proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
    assert m.proxy_auxiliaries2_dyn(z1) == m.array_auxiliaries2(z1)
424
425
426
427


def test_array_failure():
    with pytest.raises(ValueError) as excinfo:
428
        m.array_fail_test()
429
    assert str(excinfo.value) == "cannot create a pybind11::array from a nullptr"
430
431

    with pytest.raises(ValueError) as excinfo:
432
        m.array_t_fail_test()
433
    assert str(excinfo.value) == "cannot create a pybind11::array_t from a nullptr"
uentity's avatar
uentity committed
434

435
    with pytest.raises(ValueError) as excinfo:
436
        m.array_fail_test_negative_size()
437
    assert str(excinfo.value) == "negative dimensions are not allowed"
438

uentity's avatar
uentity committed
439

440
441
442
443
444
445
def test_initializer_list():
    assert m.array_initializer_list1().shape == (1,)
    assert m.array_initializer_list2().shape == (1, 2)
    assert m.array_initializer_list3().shape == (1, 2, 3)
    assert m.array_initializer_list4().shape == (1, 2, 3, 4)

uentity's avatar
uentity committed
446

Nick Cullen's avatar
Nick Cullen committed
447
def test_array_resize():
448
    a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype="float64")
449
    m.array_reshape2(a)
450
451
    assert a.size == 9
    assert np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]])
uentity's avatar
uentity committed
452
453

    # total size change should succced with refcheck off
454
    m.array_resize3(a, 4, False)
455
    assert a.size == 64
uentity's avatar
uentity committed
456
457
    # ... and fail with refcheck on
    try:
458
        m.array_resize3(a, 3, True)
uentity's avatar
uentity committed
459
    except ValueError as e:
460
        assert str(e).startswith("cannot resize an array")
uentity's avatar
uentity committed
461
462
463
    # transposed array doesn't own data
    b = a.transpose()
    try:
464
        m.array_resize3(b, 3, False)
uentity's avatar
uentity committed
465
    except ValueError as e:
466
        assert str(e).startswith("cannot resize this array: it does not own its data")
uentity's avatar
uentity committed
467
    # ... but reshape should be fine
468
    m.array_reshape2(b)
469
    assert b.shape == (8, 8)
uentity's avatar
uentity committed
470
471


472
@pytest.mark.xfail("env.PYPY")
Nick Cullen's avatar
Nick Cullen committed
473
def test_array_create_and_resize():
474
    a = m.create_and_resize(2)
475
476
    assert a.size == 4
    assert np.all(a == 42.0)
477
478


Nick Cullen's avatar
Nick Cullen committed
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
def test_reshape_initializer_list():
    a = np.arange(2 * 7 * 3) + 1
    x = m.reshape_initializer_list(a, 2, 7, 3)
    assert x.shape == (2, 7, 3)
    assert list(x[1][4]) == [34, 35, 36]
    with pytest.raises(ValueError) as excinfo:
        m.reshape_initializer_list(a, 1, 7, 3)
    assert str(excinfo.value) == "cannot reshape array of size 42 into shape (1,7,3)"


def test_reshape_tuple():
    a = np.arange(3 * 7 * 2) + 1
    x = m.reshape_tuple(a, (3, 7, 2))
    assert x.shape == (3, 7, 2)
    assert list(x[1][4]) == [23, 24]
    y = m.reshape_tuple(x, (x.size,))
    assert y.shape == (42,)
    with pytest.raises(ValueError) as excinfo:
        m.reshape_tuple(a, (3, 7, 1))
    assert str(excinfo.value) == "cannot reshape array of size 42 into shape (3,7,1)"
    with pytest.raises(ValueError) as excinfo:
        m.reshape_tuple(a, ())
    assert str(excinfo.value) == "cannot reshape array of size 42 into shape ()"


504
505
506
def test_index_using_ellipsis():
    a = m.index_using_ellipsis(np.zeros((5, 6, 7)))
    assert a.shape == (6,)
507
508


509
510
511
512
513
514
515
516
517
518
519
520
521
@pytest.mark.parametrize(
    "test_func",
    [
        m.test_fmt_desc_float,
        m.test_fmt_desc_double,
        m.test_fmt_desc_const_float,
        m.test_fmt_desc_const_double,
    ],
)
def test_format_descriptors_for_floating_point_types(test_func):
    assert "numpy.ndarray[numpy.float" in test_func.__doc__


522
@pytest.mark.parametrize("forcecast", [False, True])
523
@pytest.mark.parametrize("contiguity", [None, "C", "F"])
524
525
526
527
528
529
@pytest.mark.parametrize("noconvert", [False, True])
@pytest.mark.filterwarnings(
    "ignore:Casting complex values to real discards the imaginary part:numpy.ComplexWarning"
)
def test_argument_conversions(forcecast, contiguity, noconvert):
    function_name = "accept_double"
530
    if contiguity == "C":
531
        function_name += "_c_style"
532
    elif contiguity == "F":
533
534
535
536
537
538
539
        function_name += "_f_style"
    if forcecast:
        function_name += "_forcecast"
    if noconvert:
        function_name += "_noconvert"
    function = getattr(m, function_name)

540
541
    for dtype in [np.dtype("float32"), np.dtype("float64"), np.dtype("complex128")]:
        for order in ["C", "F"]:
542
543
544
545
546
            for shape in [(2, 2), (1, 3, 1, 1), (1, 1, 1), (0,)]:
                if not noconvert:
                    # If noconvert is not passed, only complex128 needs to be truncated and
                    # "cannot be safely obtained". So without `forcecast`, the argument shouldn't
                    # be accepted.
547
                    should_raise = dtype.name == "complex128" and not forcecast
548
549
550
551
552
                else:
                    # If noconvert is passed, only float64 and the matching order is accepted.
                    # If at most one dimension has a size greater than 1, the array is also
                    # trivially contiguous.
                    trivially_contiguous = sum(1 for d in shape if d > 1) <= 1
553
554
555
556
                    should_raise = dtype.name != "float64" or (
                        contiguity is not None
                        and contiguity != order
                        and not trivially_contiguous
557
558
559
560
561
562
                    )

                array = np.zeros(shape, dtype=dtype, order=order)
                if not should_raise:
                    function(array)
                else:
563
564
565
                    with pytest.raises(
                        TypeError, match="incompatible function arguments"
                    ):
566
567
568
                        function(array)


569
@pytest.mark.xfail("env.PYPY")
570
571
def test_dtype_refcount_leak():
    from sys import getrefcount
572

573
574
575
576
577
578
    dtype = np.dtype(np.float_)
    a = np.array([1], dtype=dtype)
    before = getrefcount(dtype)
    m.ndim(a)
    after = getrefcount(dtype)
    assert after == before