blob: 10af7486a163e6a23dc9307f64de4e8ec71ce366 [file] [log] [blame]
Ivan Smirnov91b3d682016-08-29 02:41:05 +01001import pytest
2
Jason Rhinelander2a757842017-01-24 11:26:51 -05003pytestmark = pytest.requires_numpy
4
Ivan Smirnov91b3d682016-08-29 02:41:05 +01005with pytest.suppress(ImportError):
6 import numpy as np
7
8
Ivan Smirnovaca6bca2016-09-08 23:03:35 +01009@pytest.fixture(scope='function')
10def arr():
Jason Rhinelander0861be02017-02-25 16:43:01 -050011 return np.array([[1, 2, 3], [4, 5, 6]], '=u2')
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010012
13
Ivan Smirnov91b3d682016-08-29 02:41:05 +010014def test_array_attributes():
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010015 from pybind11_tests.array import (
16 ndim, shape, strides, writeable, size, itemsize, nbytes, owndata
17 )
Ivan Smirnov91b3d682016-08-29 02:41:05 +010018
19 a = np.array(0, 'f8')
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010020 assert ndim(a) == 0
21 assert all(shape(a) == [])
22 assert all(strides(a) == [])
23 with pytest.raises(IndexError) as excinfo:
24 shape(a, 0)
25 assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)'
26 with pytest.raises(IndexError) as excinfo:
27 strides(a, 0)
28 assert str(excinfo.value) == 'invalid axis: 0 (ndim = 0)'
29 assert writeable(a)
30 assert size(a) == 1
31 assert itemsize(a) == 8
32 assert nbytes(a) == 8
33 assert owndata(a)
Ivan Smirnov91b3d682016-08-29 02:41:05 +010034
35 a = np.array([[1, 2, 3], [4, 5, 6]], 'u2').view()
36 a.flags.writeable = False
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010037 assert ndim(a) == 2
38 assert all(shape(a) == [2, 3])
39 assert shape(a, 0) == 2
40 assert shape(a, 1) == 3
41 assert all(strides(a) == [6, 2])
42 assert strides(a, 0) == 6
43 assert strides(a, 1) == 2
44 with pytest.raises(IndexError) as excinfo:
45 shape(a, 2)
46 assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)'
47 with pytest.raises(IndexError) as excinfo:
48 strides(a, 2)
49 assert str(excinfo.value) == 'invalid axis: 2 (ndim = 2)'
50 assert not writeable(a)
51 assert size(a) == 6
52 assert itemsize(a) == 2
53 assert nbytes(a) == 12
54 assert not owndata(a)
55
56
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010057@pytest.mark.parametrize('args, ret', [([], 0), ([0], 0), ([1], 3), ([0, 1], 1), ([1, 2], 5)])
58def test_index_offset(arr, args, ret):
59 from pybind11_tests.array import index_at, index_at_t, offset_at, offset_at_t
60 assert index_at(arr, *args) == ret
61 assert index_at_t(arr, *args) == ret
62 assert offset_at(arr, *args) == ret * arr.dtype.itemsize
63 assert offset_at_t(arr, *args) == ret * arr.dtype.itemsize
64
65
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010066def test_dim_check_fail(arr):
67 from pybind11_tests.array import (index_at, index_at_t, offset_at, offset_at_t, data, data_t,
68 mutate_data, mutate_data_t)
69 for func in (index_at, index_at_t, offset_at, offset_at_t, data, data_t,
70 mutate_data, mutate_data_t):
71 with pytest.raises(IndexError) as excinfo:
72 func(arr, 1, 2, 3)
73 assert str(excinfo.value) == 'too many indices for an array: 3 (ndim = 2)'
74
75
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010076@pytest.mark.parametrize('args, ret',
77 [([], [1, 2, 3, 4, 5, 6]),
78 ([1], [4, 5, 6]),
79 ([0, 1], [2, 3, 4, 5, 6]),
80 ([1, 2], [6])])
81def test_data(arr, args, ret):
82 from pybind11_tests.array import data, data_t
Jason Rhinelander0861be02017-02-25 16:43:01 -050083 from sys import byteorder
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010084 assert all(data_t(arr, *args) == ret)
Jason Rhinelander0861be02017-02-25 16:43:01 -050085 assert all(data(arr, *args)[(0 if byteorder == 'little' else 1)::2] == ret)
86 assert all(data(arr, *args)[(1 if byteorder == 'little' else 0)::2] == 0)
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010087
88
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010089def test_mutate_readonly(arr):
90 from pybind11_tests.array import mutate_data, mutate_data_t, mutate_at_t
91 arr.flags.writeable = False
92 for func, args in (mutate_data, ()), (mutate_data_t, ()), (mutate_at_t, (0, 0)):
Jason Rhinelanderfd751702017-01-20 13:50:07 -050093 with pytest.raises(ValueError) as excinfo:
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010094 func(arr, *args)
95 assert str(excinfo.value) == 'array is not writeable'
96
97
Ivan Smirnovaca6bca2016-09-08 23:03:35 +010098@pytest.mark.parametrize('dim', [0, 1, 3])
99def test_at_fail(arr, dim):
100 from pybind11_tests.array import at_t, mutate_at_t
101 for func in at_t, mutate_at_t:
102 with pytest.raises(IndexError) as excinfo:
103 func(arr, *([0] * dim))
104 assert str(excinfo.value) == 'index dimension mismatch: {} (ndim = 2)'.format(dim)
105
106
Ivan Smirnovaca6bca2016-09-08 23:03:35 +0100107def test_at(arr):
108 from pybind11_tests.array import at_t, mutate_at_t
109
110 assert at_t(arr, 0, 2) == 3
111 assert at_t(arr, 1, 0) == 4
112
113 assert all(mutate_at_t(arr, 0, 2).ravel() == [1, 2, 4, 4, 5, 6])
114 assert all(mutate_at_t(arr, 1, 0).ravel() == [1, 2, 4, 5, 5, 6])
115
116
Ivan Smirnovaca6bca2016-09-08 23:03:35 +0100117def test_mutate_data(arr):
118 from pybind11_tests.array import mutate_data, mutate_data_t
119
120 assert all(mutate_data(arr).ravel() == [2, 4, 6, 8, 10, 12])
121 assert all(mutate_data(arr).ravel() == [4, 8, 12, 16, 20, 24])
122 assert all(mutate_data(arr, 1).ravel() == [4, 8, 12, 32, 40, 48])
123 assert all(mutate_data(arr, 0, 1).ravel() == [4, 16, 24, 64, 80, 96])
124 assert all(mutate_data(arr, 1, 2).ravel() == [4, 16, 24, 64, 80, 192])
125
126 assert all(mutate_data_t(arr).ravel() == [5, 17, 25, 65, 81, 193])
127 assert all(mutate_data_t(arr).ravel() == [6, 18, 26, 66, 82, 194])
128 assert all(mutate_data_t(arr, 1).ravel() == [6, 18, 26, 67, 83, 195])
129 assert all(mutate_data_t(arr, 0, 1).ravel() == [6, 19, 27, 68, 84, 196])
130 assert all(mutate_data_t(arr, 1, 2).ravel() == [6, 19, 27, 68, 84, 197])
131
132
Ivan Smirnovaca6bca2016-09-08 23:03:35 +0100133def test_bounds_check(arr):
134 from pybind11_tests.array import (index_at, index_at_t, data, data_t,
135 mutate_data, mutate_data_t, at_t, mutate_at_t)
136 funcs = (index_at, index_at_t, data, data_t,
137 mutate_data, mutate_data_t, at_t, mutate_at_t)
138 for func in funcs:
139 with pytest.raises(IndexError) as excinfo:
Dean Moldovanbad17402016-11-20 21:21:54 +0100140 func(arr, 2, 0)
Ivan Smirnovaca6bca2016-09-08 23:03:35 +0100141 assert str(excinfo.value) == 'index 2 is out of bounds for axis 0 with size 2'
142 with pytest.raises(IndexError) as excinfo:
Dean Moldovanbad17402016-11-20 21:21:54 +0100143 func(arr, 0, 4)
Ivan Smirnovaca6bca2016-09-08 23:03:35 +0100144 assert str(excinfo.value) == 'index 4 is out of bounds for axis 1 with size 3'
Wenzel Jakob43f6aa62016-10-12 23:34:06 +0200145
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200146
Wenzel Jakob43f6aa62016-10-12 23:34:06 +0200147def test_make_c_f_array():
148 from pybind11_tests.array import (
149 make_c_array, make_f_array
150 )
151 assert make_c_array().flags.c_contiguous
152 assert not make_c_array().flags.f_contiguous
153 assert make_f_array().flags.f_contiguous
154 assert not make_f_array().flags.c_contiguous
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200155
156
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200157def test_wrap():
158 from pybind11_tests.array import wrap
159
Jason Rhinelanderf86dddf2017-01-16 20:22:00 -0500160 def assert_references(a, b, base=None):
161 if base is None:
162 base = a
Dean Moldovanbad17402016-11-20 21:21:54 +0100163 assert a is not b
164 assert a.__array_interface__['data'][0] == b.__array_interface__['data'][0]
165 assert a.shape == b.shape
166 assert a.strides == b.strides
167 assert a.flags.c_contiguous == b.flags.c_contiguous
168 assert a.flags.f_contiguous == b.flags.f_contiguous
169 assert a.flags.writeable == b.flags.writeable
170 assert a.flags.aligned == b.flags.aligned
171 assert a.flags.updateifcopy == b.flags.updateifcopy
172 assert np.all(a == b)
173 assert not b.flags.owndata
Jason Rhinelanderf86dddf2017-01-16 20:22:00 -0500174 assert b.base is base
Dean Moldovanbad17402016-11-20 21:21:54 +0100175 if a.flags.writeable and a.ndim == 2:
176 a[0, 0] = 1234
177 assert b[0, 0] == 1234
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200178
Dean Moldovanbad17402016-11-20 21:21:54 +0100179 a1 = np.array([1, 2], dtype=np.int16)
180 assert a1.flags.owndata and a1.base is None
181 a2 = wrap(a1)
182 assert_references(a1, a2)
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200183
Dean Moldovanbad17402016-11-20 21:21:54 +0100184 a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='F')
185 assert a1.flags.owndata and a1.base is None
186 a2 = wrap(a1)
187 assert_references(a1, a2)
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200188
Dean Moldovanbad17402016-11-20 21:21:54 +0100189 a1 = np.array([[1, 2], [3, 4]], dtype=np.float32, order='C')
190 a1.flags.writeable = False
191 a2 = wrap(a1)
192 assert_references(a1, a2)
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200193
Dean Moldovanbad17402016-11-20 21:21:54 +0100194 a1 = np.random.random((4, 4, 4))
195 a2 = wrap(a1)
196 assert_references(a1, a2)
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200197
Jason Rhinelanderf86dddf2017-01-16 20:22:00 -0500198 a1t = a1.transpose()
199 a2 = wrap(a1t)
200 assert_references(a1t, a2, a1)
Wenzel Jakob369e9b32016-10-13 00:57:42 +0200201
Jason Rhinelanderf86dddf2017-01-16 20:22:00 -0500202 a1d = a1.diagonal()
203 a2 = wrap(a1d)
204 assert_references(a1d, a2, a1)
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200205
206
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200207def test_numpy_view(capture):
208 from pybind11_tests.array import ArrayClass
209 with capture:
210 ac = ArrayClass()
211 ac_view_1 = ac.numpy_view()
212 ac_view_2 = ac.numpy_view()
213 assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32))
214 del ac
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100215 pytest.gc_collect()
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200216 assert capture == """
217 ArrayClass()
218 ArrayClass::numpy_view()
219 ArrayClass::numpy_view()
220 """
221 ac_view_1[0] = 4
222 ac_view_1[1] = 3
223 assert ac_view_2[0] == 4
224 assert ac_view_2[1] == 3
225 with capture:
226 del ac_view_1
227 del ac_view_2
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100228 pytest.gc_collect()
229 pytest.gc_collect()
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200230 assert capture == """
231 ~ArrayClass()
232 """
Wenzel Jakob496feac2016-10-28 00:37:07 +0200233
234
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100235@pytest.unsupported_on_pypy
Wenzel Jakob496feac2016-10-28 00:37:07 +0200236def test_cast_numpy_int64_to_uint64():
237 from pybind11_tests.array import function_taking_uint64
238 function_taking_uint64(123)
239 function_taking_uint64(np.uint64(123))
Dean Moldovan4de27102016-11-16 01:35:22 +0100240
241
Dean Moldovan4de27102016-11-16 01:35:22 +0100242def test_isinstance():
243 from pybind11_tests.array import isinstance_untyped, isinstance_typed
244
245 assert isinstance_untyped(np.array([1, 2, 3]), "not an array")
246 assert isinstance_typed(np.array([1.0, 2.0, 3.0]))
247
248
Dean Moldovan4de27102016-11-16 01:35:22 +0100249def test_constructors():
250 from pybind11_tests.array import default_constructors, converting_constructors
251
252 defaults = default_constructors()
253 for a in defaults.values():
254 assert a.size == 0
255 assert defaults["array"].dtype == np.array([]).dtype
256 assert defaults["array_t<int32>"].dtype == np.int32
257 assert defaults["array_t<double>"].dtype == np.float64
258
259 results = converting_constructors([1, 2, 3])
260 for a in results.values():
261 np.testing.assert_array_equal(a, [1, 2, 3])
262 assert results["array"].dtype == np.int_
263 assert results["array_t<int32>"].dtype == np.int32
264 assert results["array_t<double>"].dtype == np.float64
Jason Rhinelanderee2e5a52017-02-24 05:33:31 -0500265
266
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500267def test_overload_resolution(msg):
268 from pybind11_tests.array import overloaded, overloaded2, overloaded3, overloaded4, overloaded5
269
270 # Exact overload matches:
271 assert overloaded(np.array([1], dtype='float64')) == 'double'
272 assert overloaded(np.array([1], dtype='float32')) == 'float'
273 assert overloaded(np.array([1], dtype='ushort')) == 'unsigned short'
274 assert overloaded(np.array([1], dtype='intc')) == 'int'
275 assert overloaded(np.array([1], dtype='longlong')) == 'long long'
276 assert overloaded(np.array([1], dtype='complex')) == 'double complex'
277 assert overloaded(np.array([1], dtype='csingle')) == 'float complex'
278
279 # No exact match, should call first convertible version:
280 assert overloaded(np.array([1], dtype='uint8')) == 'double'
281
Dean Moldovan16afbce2017-03-13 19:17:18 +0100282 with pytest.raises(TypeError) as excinfo:
283 overloaded("not an array")
284 assert msg(excinfo.value) == """
285 overloaded(): incompatible function arguments. The following argument types are supported:
286 1. (arg0: numpy.ndarray[float64]) -> str
287 2. (arg0: numpy.ndarray[float32]) -> str
288 3. (arg0: numpy.ndarray[int32]) -> str
289 4. (arg0: numpy.ndarray[uint16]) -> str
290 5. (arg0: numpy.ndarray[int64]) -> str
291 6. (arg0: numpy.ndarray[complex128]) -> str
292 7. (arg0: numpy.ndarray[complex64]) -> str
293
294 Invoked with: 'not an array'
295 """
296
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500297 assert overloaded2(np.array([1], dtype='float64')) == 'double'
298 assert overloaded2(np.array([1], dtype='float32')) == 'float'
299 assert overloaded2(np.array([1], dtype='complex64')) == 'float complex'
300 assert overloaded2(np.array([1], dtype='complex128')) == 'double complex'
301 assert overloaded2(np.array([1], dtype='float32')) == 'float'
302
303 assert overloaded3(np.array([1], dtype='float64')) == 'double'
304 assert overloaded3(np.array([1], dtype='intc')) == 'int'
305 expected_exc = """
306 overloaded3(): incompatible function arguments. The following argument types are supported:
Dean Moldovan16afbce2017-03-13 19:17:18 +0100307 1. (arg0: numpy.ndarray[int32]) -> str
308 2. (arg0: numpy.ndarray[float64]) -> str
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500309
310 Invoked with:"""
311
312 with pytest.raises(TypeError) as excinfo:
313 overloaded3(np.array([1], dtype='uintc'))
314 assert msg(excinfo.value) == expected_exc + " array([1], dtype=uint32)"
315 with pytest.raises(TypeError) as excinfo:
316 overloaded3(np.array([1], dtype='float32'))
317 assert msg(excinfo.value) == expected_exc + " array([ 1.], dtype=float32)"
318 with pytest.raises(TypeError) as excinfo:
319 overloaded3(np.array([1], dtype='complex'))
320 assert msg(excinfo.value) == expected_exc + " array([ 1.+0.j])"
321
322 # Exact matches:
323 assert overloaded4(np.array([1], dtype='double')) == 'double'
324 assert overloaded4(np.array([1], dtype='longlong')) == 'long long'
325 # Non-exact matches requiring conversion. Since float to integer isn't a
326 # save conversion, it should go to the double overload, but short can go to
327 # either (and so should end up on the first-registered, the long long).
328 assert overloaded4(np.array([1], dtype='float32')) == 'double'
329 assert overloaded4(np.array([1], dtype='short')) == 'long long'
330
331 assert overloaded5(np.array([1], dtype='double')) == 'double'
332 assert overloaded5(np.array([1], dtype='uintc')) == 'unsigned int'
333 assert overloaded5(np.array([1], dtype='float32')) == 'unsigned int'
334
335
Jason Rhinelanderee2e5a52017-02-24 05:33:31 -0500336def test_greedy_string_overload(): # issue 685
337 from pybind11_tests.array import issue685
338
339 assert issue685("abc") == "string"
340 assert issue685(np.array([97, 98, 99], dtype='b')) == "array"
341 assert issue685(123) == "other"
Jason Rhinelander423a49b2017-03-19 01:14:23 -0300342
343
Jason Rhinelander773339f2017-03-20 17:48:38 -0300344def test_array_unchecked_fixed_dims(msg):
345 from pybind11_tests.array import (proxy_add2, proxy_init3F, proxy_init3, proxy_squared_L2_norm,
346 proxy_auxiliaries2, array_auxiliaries2)
Jason Rhinelander423a49b2017-03-19 01:14:23 -0300347
348 z1 = np.array([[1, 2], [3, 4]], dtype='float64')
349 proxy_add2(z1, 10)
350 assert np.all(z1 == [[11, 12], [13, 14]])
351
352 with pytest.raises(ValueError) as excinfo:
353 proxy_add2(np.array([1., 2, 3]), 5.0)
354 assert msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2"
355
356 expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
357 assert np.all(proxy_init3(3.0) == expect_c)
358 expect_f = np.transpose(expect_c)
359 assert np.all(proxy_init3F(3.0) == expect_f)
360
361 assert proxy_squared_L2_norm(np.array(range(6))) == 55
362 assert proxy_squared_L2_norm(np.array(range(6), dtype="float64")) == 55
Jason Rhinelander773339f2017-03-20 17:48:38 -0300363
364 assert proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
365 assert proxy_auxiliaries2(z1) == array_auxiliaries2(z1)
366
367
368def test_array_unchecked_dyn_dims(msg):
369 from pybind11_tests.array import (proxy_add2_dyn, proxy_init3_dyn, proxy_auxiliaries2_dyn,
370 array_auxiliaries2)
371 z1 = np.array([[1, 2], [3, 4]], dtype='float64')
372 proxy_add2_dyn(z1, 10)
373 assert np.all(z1 == [[11, 12], [13, 14]])
374
375 expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
376 assert np.all(proxy_init3_dyn(3.0) == expect_c)
377
378 assert proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
379 assert proxy_auxiliaries2_dyn(z1) == array_auxiliaries2(z1)
Jason Rhinelander5749b502017-04-10 11:05:26 -0400380
381
382def test_array_failure():
383 from pybind11_tests.array import array_fail_test, array_t_fail_test
384
385 with pytest.raises(ValueError) as excinfo:
386 array_fail_test()
387 assert str(excinfo.value) == 'cannot create a pybind11::array from a nullptr'
388
389 with pytest.raises(ValueError) as excinfo:
390 array_t_fail_test()
391 assert str(excinfo.value) == 'cannot create a pybind11::array_t from a nullptr'
uentity083a0212017-04-13 21:41:55 +0500392
393
394def test_array_resize(msg):
395 from pybind11_tests.array import (array_reshape2, array_resize3)
396
397 a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='float64')
398 array_reshape2(a)
399 assert(a.size == 9)
400 assert(np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
401
402 # total size change should succced with refcheck off
403 array_resize3(a, 4, False)
404 assert(a.size == 64)
405 # ... and fail with refcheck on
406 try:
407 array_resize3(a, 3, True)
408 except ValueError as e:
409 assert(str(e).startswith("cannot resize an array"))
410 # transposed array doesn't own data
411 b = a.transpose()
412 try:
413 array_resize3(b, 3, False)
414 except ValueError as e:
415 assert(str(e).startswith("cannot resize this array: it does not own its data"))
416 # ... but reshape should be fine
417 array_reshape2(b)
418 assert(b.shape == (8, 8))
419
420
421@pytest.unsupported_on_pypy
422def test_array_create_and_resize(msg):
423 from pybind11_tests.array import create_and_resize
424 a = create_and_resize(2)
425 assert(a.size == 4)
426 assert(np.all(a == 42.))