blob: 90fa142d86153d5c7a0f23e02c0dcd378e37c158 [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
Cris Luengod400f602017-04-05 16:13:04 -0600206 a1m = a1[::-1, ::-1, ::-1]
207 a2 = wrap(a1m)
208 assert_references(a1m, a2, a1)
209
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200210
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200211def test_numpy_view(capture):
212 from pybind11_tests.array import ArrayClass
213 with capture:
214 ac = ArrayClass()
215 ac_view_1 = ac.numpy_view()
216 ac_view_2 = ac.numpy_view()
217 assert np.all(ac_view_1 == np.array([1, 2], dtype=np.int32))
218 del ac
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100219 pytest.gc_collect()
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200220 assert capture == """
221 ArrayClass()
222 ArrayClass::numpy_view()
223 ArrayClass::numpy_view()
224 """
225 ac_view_1[0] = 4
226 ac_view_1[1] = 3
227 assert ac_view_2[0] == 4
228 assert ac_view_2[1] == 3
229 with capture:
230 del ac_view_1
231 del ac_view_2
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100232 pytest.gc_collect()
233 pytest.gc_collect()
Wenzel Jakobfac7c092016-10-13 10:37:52 +0200234 assert capture == """
235 ~ArrayClass()
236 """
Wenzel Jakob496feac2016-10-28 00:37:07 +0200237
238
Wenzel Jakob1d1f81b2016-12-16 15:00:46 +0100239@pytest.unsupported_on_pypy
Wenzel Jakob496feac2016-10-28 00:37:07 +0200240def test_cast_numpy_int64_to_uint64():
241 from pybind11_tests.array import function_taking_uint64
242 function_taking_uint64(123)
243 function_taking_uint64(np.uint64(123))
Dean Moldovan4de27102016-11-16 01:35:22 +0100244
245
Dean Moldovan4de27102016-11-16 01:35:22 +0100246def test_isinstance():
247 from pybind11_tests.array import isinstance_untyped, isinstance_typed
248
249 assert isinstance_untyped(np.array([1, 2, 3]), "not an array")
250 assert isinstance_typed(np.array([1.0, 2.0, 3.0]))
251
252
Dean Moldovan4de27102016-11-16 01:35:22 +0100253def test_constructors():
254 from pybind11_tests.array import default_constructors, converting_constructors
255
256 defaults = default_constructors()
257 for a in defaults.values():
258 assert a.size == 0
259 assert defaults["array"].dtype == np.array([]).dtype
260 assert defaults["array_t<int32>"].dtype == np.int32
261 assert defaults["array_t<double>"].dtype == np.float64
262
263 results = converting_constructors([1, 2, 3])
264 for a in results.values():
265 np.testing.assert_array_equal(a, [1, 2, 3])
266 assert results["array"].dtype == np.int_
267 assert results["array_t<int32>"].dtype == np.int32
268 assert results["array_t<double>"].dtype == np.float64
Jason Rhinelanderee2e5a52017-02-24 05:33:31 -0500269
270
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500271def test_overload_resolution(msg):
272 from pybind11_tests.array import overloaded, overloaded2, overloaded3, overloaded4, overloaded5
273
274 # Exact overload matches:
275 assert overloaded(np.array([1], dtype='float64')) == 'double'
276 assert overloaded(np.array([1], dtype='float32')) == 'float'
277 assert overloaded(np.array([1], dtype='ushort')) == 'unsigned short'
278 assert overloaded(np.array([1], dtype='intc')) == 'int'
279 assert overloaded(np.array([1], dtype='longlong')) == 'long long'
280 assert overloaded(np.array([1], dtype='complex')) == 'double complex'
281 assert overloaded(np.array([1], dtype='csingle')) == 'float complex'
282
283 # No exact match, should call first convertible version:
284 assert overloaded(np.array([1], dtype='uint8')) == 'double'
285
Dean Moldovan16afbce2017-03-13 19:17:18 +0100286 with pytest.raises(TypeError) as excinfo:
287 overloaded("not an array")
288 assert msg(excinfo.value) == """
289 overloaded(): incompatible function arguments. The following argument types are supported:
290 1. (arg0: numpy.ndarray[float64]) -> str
291 2. (arg0: numpy.ndarray[float32]) -> str
292 3. (arg0: numpy.ndarray[int32]) -> str
293 4. (arg0: numpy.ndarray[uint16]) -> str
294 5. (arg0: numpy.ndarray[int64]) -> str
295 6. (arg0: numpy.ndarray[complex128]) -> str
296 7. (arg0: numpy.ndarray[complex64]) -> str
297
298 Invoked with: 'not an array'
299 """
300
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500301 assert overloaded2(np.array([1], dtype='float64')) == 'double'
302 assert overloaded2(np.array([1], dtype='float32')) == 'float'
303 assert overloaded2(np.array([1], dtype='complex64')) == 'float complex'
304 assert overloaded2(np.array([1], dtype='complex128')) == 'double complex'
305 assert overloaded2(np.array([1], dtype='float32')) == 'float'
306
307 assert overloaded3(np.array([1], dtype='float64')) == 'double'
308 assert overloaded3(np.array([1], dtype='intc')) == 'int'
309 expected_exc = """
310 overloaded3(): incompatible function arguments. The following argument types are supported:
Dean Moldovan16afbce2017-03-13 19:17:18 +0100311 1. (arg0: numpy.ndarray[int32]) -> str
312 2. (arg0: numpy.ndarray[float64]) -> str
Jason Rhinelanderc44fe6f2017-02-26 18:03:00 -0500313
314 Invoked with:"""
315
316 with pytest.raises(TypeError) as excinfo:
317 overloaded3(np.array([1], dtype='uintc'))
318 assert msg(excinfo.value) == expected_exc + " array([1], dtype=uint32)"
319 with pytest.raises(TypeError) as excinfo:
320 overloaded3(np.array([1], dtype='float32'))
321 assert msg(excinfo.value) == expected_exc + " array([ 1.], dtype=float32)"
322 with pytest.raises(TypeError) as excinfo:
323 overloaded3(np.array([1], dtype='complex'))
324 assert msg(excinfo.value) == expected_exc + " array([ 1.+0.j])"
325
326 # Exact matches:
327 assert overloaded4(np.array([1], dtype='double')) == 'double'
328 assert overloaded4(np.array([1], dtype='longlong')) == 'long long'
329 # Non-exact matches requiring conversion. Since float to integer isn't a
330 # save conversion, it should go to the double overload, but short can go to
331 # either (and so should end up on the first-registered, the long long).
332 assert overloaded4(np.array([1], dtype='float32')) == 'double'
333 assert overloaded4(np.array([1], dtype='short')) == 'long long'
334
335 assert overloaded5(np.array([1], dtype='double')) == 'double'
336 assert overloaded5(np.array([1], dtype='uintc')) == 'unsigned int'
337 assert overloaded5(np.array([1], dtype='float32')) == 'unsigned int'
338
339
Jason Rhinelanderee2e5a52017-02-24 05:33:31 -0500340def test_greedy_string_overload(): # issue 685
341 from pybind11_tests.array import issue685
342
343 assert issue685("abc") == "string"
344 assert issue685(np.array([97, 98, 99], dtype='b')) == "array"
345 assert issue685(123) == "other"
Jason Rhinelander423a49b2017-03-19 01:14:23 -0300346
347
Jason Rhinelander773339f2017-03-20 17:48:38 -0300348def test_array_unchecked_fixed_dims(msg):
349 from pybind11_tests.array import (proxy_add2, proxy_init3F, proxy_init3, proxy_squared_L2_norm,
350 proxy_auxiliaries2, array_auxiliaries2)
Jason Rhinelander423a49b2017-03-19 01:14:23 -0300351
352 z1 = np.array([[1, 2], [3, 4]], dtype='float64')
353 proxy_add2(z1, 10)
354 assert np.all(z1 == [[11, 12], [13, 14]])
355
356 with pytest.raises(ValueError) as excinfo:
357 proxy_add2(np.array([1., 2, 3]), 5.0)
358 assert msg(excinfo.value) == "array has incorrect number of dimensions: 1; expected 2"
359
360 expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
361 assert np.all(proxy_init3(3.0) == expect_c)
362 expect_f = np.transpose(expect_c)
363 assert np.all(proxy_init3F(3.0) == expect_f)
364
365 assert proxy_squared_L2_norm(np.array(range(6))) == 55
366 assert proxy_squared_L2_norm(np.array(range(6), dtype="float64")) == 55
Jason Rhinelander773339f2017-03-20 17:48:38 -0300367
368 assert proxy_auxiliaries2(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
369 assert proxy_auxiliaries2(z1) == array_auxiliaries2(z1)
370
371
372def test_array_unchecked_dyn_dims(msg):
373 from pybind11_tests.array import (proxy_add2_dyn, proxy_init3_dyn, proxy_auxiliaries2_dyn,
374 array_auxiliaries2)
375 z1 = np.array([[1, 2], [3, 4]], dtype='float64')
376 proxy_add2_dyn(z1, 10)
377 assert np.all(z1 == [[11, 12], [13, 14]])
378
379 expect_c = np.ndarray(shape=(3, 3, 3), buffer=np.array(range(3, 30)), dtype='int')
380 assert np.all(proxy_init3_dyn(3.0) == expect_c)
381
382 assert proxy_auxiliaries2_dyn(z1) == [11, 11, True, 2, 8, 2, 2, 4, 32]
383 assert proxy_auxiliaries2_dyn(z1) == array_auxiliaries2(z1)
Jason Rhinelander5749b502017-04-10 11:05:26 -0400384
385
386def test_array_failure():
Cris Luengo30d43c42017-04-14 14:33:44 -0600387 from pybind11_tests.array import (array_fail_test, array_t_fail_test,
388 array_fail_test_negative_size)
Jason Rhinelander5749b502017-04-10 11:05:26 -0400389
390 with pytest.raises(ValueError) as excinfo:
391 array_fail_test()
392 assert str(excinfo.value) == 'cannot create a pybind11::array from a nullptr'
393
394 with pytest.raises(ValueError) as excinfo:
395 array_t_fail_test()
396 assert str(excinfo.value) == 'cannot create a pybind11::array_t from a nullptr'
uentity083a0212017-04-13 21:41:55 +0500397
Cris Luengo30d43c42017-04-14 14:33:44 -0600398 with pytest.raises(ValueError) as excinfo:
399 array_fail_test_negative_size()
400 assert str(excinfo.value) == 'negative dimensions are not allowed'
401
uentity083a0212017-04-13 21:41:55 +0500402
403def test_array_resize(msg):
404 from pybind11_tests.array import (array_reshape2, array_resize3)
405
406 a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9], dtype='float64')
407 array_reshape2(a)
408 assert(a.size == 9)
409 assert(np.all(a == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]))
410
411 # total size change should succced with refcheck off
412 array_resize3(a, 4, False)
413 assert(a.size == 64)
414 # ... and fail with refcheck on
415 try:
416 array_resize3(a, 3, True)
417 except ValueError as e:
418 assert(str(e).startswith("cannot resize an array"))
419 # transposed array doesn't own data
420 b = a.transpose()
421 try:
422 array_resize3(b, 3, False)
423 except ValueError as e:
424 assert(str(e).startswith("cannot resize this array: it does not own its data"))
425 # ... but reshape should be fine
426 array_reshape2(b)
427 assert(b.shape == (8, 8))
428
429
430@pytest.unsupported_on_pypy
431def test_array_create_and_resize(msg):
432 from pybind11_tests.array import create_and_resize
433 a = create_and_resize(2)
434 assert(a.size == 4)
435 assert(np.all(a == 42.))