codekingpro/portable-devtools
115k
1import copy
2import platform
3import sys
4from pathlib import Path
5
6import pytest
7
8import numpy as np
9from numpy._core._type_aliases import c_names_dict as _c_names_dict
10
11from . import util
12
13wrap = None
14
15# Extend core typeinfo with CHARACTER to test dtype('c')
16c_names_dict = dict(
17 CHARACTER=np.dtype("c"),
18 **_c_names_dict
19)
20
21
22def get_testdir():
23 testroot = Path(__file__).resolve().parent / "src"
24 return testroot / "array_from_pyobj"
25
26def setup_module():
27 """
28 Build the required testing extension module
29
30 """
31 global wrap
32
33 if wrap is None:
34 src = [
35 get_testdir() / "wrapmodule.c",
36 ]
37 wrap = util.build_meson(src, module_name="test_array_from_pyobj_ext")
38
39
40def flags_info(arr):
41 flags = wrap.array_attrs(arr)[6]
42 return flags2names(flags)
43
44
45def flags2names(flags):
46 info = []
47 for flagname in [
48 "CONTIGUOUS",
49 "FORTRAN",
50 "OWNDATA",
51 "ENSURECOPY",
52 "ENSUREARRAY",
53 "ALIGNED",
54 "NOTSWAPPED",
55 "WRITEABLE",
56 "WRITEBACKIFCOPY",
57 "UPDATEIFCOPY",
58 "BEHAVED",
59 "BEHAVED_RO",
60 "CARRAY",
61 "FARRAY",
62 ]:
63 if abs(flags) & getattr(wrap, flagname, 0):
64 info.append(flagname)
65 return info
66
67
68class Intent:
69 def __init__(self, intent_list=[]):
70 self.intent_list = intent_list[:]
71 flags = 0
72 for i in intent_list:
73 if i == "optional":
74 flags |= wrap.F2PY_OPTIONAL
75 else:
76 flags |= getattr(wrap, "F2PY_INTENT_" + i.upper())
77 self.flags = flags
78
79 def __getattr__(self, name):
80 name = name.lower()
81 if name == "in_":
82 name = "in"
83 return self.__class__(self.intent_list + [name])
84
85 def __str__(self):
86 return f"intent({','.join(self.intent_list)})"
87
88 def __repr__(self):
89 return f"Intent({self.intent_list!r})"
90
91 def is_intent(self, *names):
92 return all(name in self.intent_list for name in names)
93
94 def is_intent_exact(self, *names):
95 return len(self.intent_list) == len(names) and self.is_intent(*names)
96
97
98intent = Intent()
99
100_type_names = [
101 "BOOL",
102 "BYTE",
103 "UBYTE",
104 "SHORT",
105 "USHORT",
106 "INT",
107 "UINT",
108 "LONG",
109 "ULONG",
110 "LONGLONG",
111 "ULONGLONG",
112 "FLOAT",
113 "DOUBLE",
114 "CFLOAT",
115 "STRING1",
116 "STRING5",
117 "CHARACTER",
118]
119
120_cast_dict = {"BOOL": ["BOOL"]}
121_cast_dict["BYTE"] = _cast_dict["BOOL"] + ["BYTE"]
122_cast_dict["UBYTE"] = _cast_dict["BOOL"] + ["UBYTE"]
123_cast_dict["BYTE"] = ["BYTE"]
124_cast_dict["UBYTE"] = ["UBYTE"]
125_cast_dict["SHORT"] = _cast_dict["BYTE"] + ["UBYTE", "SHORT"]
126_cast_dict["USHORT"] = _cast_dict["UBYTE"] + ["BYTE", "USHORT"]
127_cast_dict["INT"] = _cast_dict["SHORT"] + ["USHORT", "INT"]
128_cast_dict["UINT"] = _cast_dict["USHORT"] + ["SHORT", "UINT"]
129
130_cast_dict["LONG"] = _cast_dict["INT"] + ["LONG"]
131_cast_dict["ULONG"] = _cast_dict["UINT"] + ["ULONG"]
132
133_cast_dict["LONGLONG"] = _cast_dict["LONG"] + ["LONGLONG"]
134_cast_dict["ULONGLONG"] = _cast_dict["ULONG"] + ["ULONGLONG"]
135
136_cast_dict["FLOAT"] = _cast_dict["SHORT"] + ["USHORT", "FLOAT"]
137_cast_dict["DOUBLE"] = _cast_dict["INT"] + ["UINT", "FLOAT", "DOUBLE"]
138
139_cast_dict["CFLOAT"] = _cast_dict["FLOAT"] + ["CFLOAT"]
140
141_cast_dict['STRING1'] = ['STRING1']
142_cast_dict['STRING5'] = ['STRING5']
143_cast_dict['CHARACTER'] = ['CHARACTER']
144
145# 32 bit system malloc typically does not provide the alignment required by
146# 16 byte long double types this means the inout intent cannot be satisfied
147# and several tests fail as the alignment flag can be randomly true or false
148# when numpy gains an aligned allocator the tests could be enabled again
149#
150# Furthermore, on macOS ARM64 and AIX, LONGDOUBLE is an alias for DOUBLE.
151if ((np.intp().dtype.itemsize != 4 or np.clongdouble().dtype.alignment <= 8)
152 and sys.platform not in ["win32", "aix"]
153 and (platform.system(), platform.processor()) != ("Darwin", "arm")):
154 _type_names.extend(["LONGDOUBLE", "CDOUBLE", "CLONGDOUBLE"])
155 _cast_dict["LONGDOUBLE"] = _cast_dict["LONG"] + [
156 "ULONG",
157 "FLOAT",
158 "DOUBLE",
159 "LONGDOUBLE",
160 ]
161 _cast_dict["CLONGDOUBLE"] = _cast_dict["LONGDOUBLE"] + [
162 "CFLOAT",
163 "CDOUBLE",
164 "CLONGDOUBLE",
165 ]
166 _cast_dict["CDOUBLE"] = _cast_dict["DOUBLE"] + ["CFLOAT", "CDOUBLE"]
167
168
169class Type:
170 _type_cache = {}
171
172 def __new__(cls, name):
173 if isinstance(name, np.dtype):
174 dtype0 = name
175 name = None
176 for n, i in c_names_dict.items():
177 if not isinstance(i, type) and dtype0.type is i.type:
178 name = n
179 break
180 obj = cls._type_cache.get(name.upper(), None)
181 if obj is not None:
182 return obj
183 obj = object.__new__(cls)
184 obj._init(name)
185 cls._type_cache[name.upper()] = obj
186 return obj
187
188 def _init(self, name):
189 self.NAME = name.upper()
190
191 if self.NAME == 'CHARACTER':
192 info = c_names_dict[self.NAME]
193 self.type_num = wrap.NPY_STRING
194 self.elsize = 1
195 self.dtype = np.dtype('c')
196 elif self.NAME.startswith('STRING'):
197 info = c_names_dict[self.NAME[:6]]
198 self.type_num = wrap.NPY_STRING
199 self.elsize = int(self.NAME[6:] or 0)
200 self.dtype = np.dtype(f'S{self.elsize}')
201 else:
202 info = c_names_dict[self.NAME]
203 self.type_num = getattr(wrap, 'NPY_' + self.NAME)
204 self.elsize = info.itemsize
205 self.dtype = np.dtype(info.type)
206
207 assert self.type_num == info.num
208 self.type = info.type
209 self.dtypechar = info.char
210
211 def __repr__(self):
212 return (f"Type({self.NAME})|type_num={self.type_num},"
213 f" dtype={self.dtype},"
214 f" type={self.type}, elsize={self.elsize},"
215 f" dtypechar={self.dtypechar}")
216
217 def cast_types(self):
218 return [self.__class__(_m) for _m in _cast_dict[self.NAME]]
219
220 def all_types(self):
221 return [self.__class__(_m) for _m in _type_names]
222
223 def smaller_types(self):
224 bits = c_names_dict[self.NAME].alignment
225 types = []
226 for name in _type_names:
227 if c_names_dict[name].alignment < bits:
228 types.append(Type(name))
229 return types
230
231 def equal_types(self):
232 bits = c_names_dict[self.NAME].alignment
233 types = []
234 for name in _type_names:
235 if name == self.NAME:
236 continue
237 if c_names_dict[name].alignment == bits:
238 types.append(Type(name))
239 return types
240
241 def larger_types(self):
242 bits = c_names_dict[self.NAME].alignment
243 types = []
244 for name in _type_names:
245 if c_names_dict[name].alignment > bits:
246 types.append(Type(name))
247 return types
248
249
250class Array:
251
252 def __repr__(self):
253 return (f'Array({self.type}, {self.dims}, {self.intent},'
254 f' {self.obj})|arr={self.arr}')
255
256 def __init__(self, typ, dims, intent, obj):
257 self.type = typ
258 self.dims = dims
259 self.intent = intent
260 self.obj_copy = copy.deepcopy(obj)
261 self.obj = obj
262
263 # arr.dtypechar may be different from typ.dtypechar
264 self.arr = wrap.call(typ.type_num,
265 typ.elsize,
266 dims, intent.flags, obj)
267
268 assert isinstance(self.arr, np.ndarray)
269
270 self.arr_attr = wrap.array_attrs(self.arr)
271
272 if len(dims) > 1:
273 if self.intent.is_intent("c"):
274 assert (intent.flags & wrap.F2PY_INTENT_C)
275 assert not self.arr.flags["FORTRAN"]
276 assert self.arr.flags["CONTIGUOUS"]
277 assert (not self.arr_attr[6] & wrap.FORTRAN)
278 else:
279 assert (not intent.flags & wrap.F2PY_INTENT_C)
280 assert self.arr.flags["FORTRAN"]
281 assert not self.arr.flags["CONTIGUOUS"]
282 assert (self.arr_attr[6] & wrap.FORTRAN)
283
284 if obj is None:
285 self.pyarr = None
286 self.pyarr_attr = None
287 return
288
289 if intent.is_intent("cache"):
290 assert isinstance(obj, np.ndarray), repr(type(obj))
291 self.pyarr = np.array(obj).reshape(*dims).copy()
292 else:
293 self.pyarr = np.array(
294 np.array(obj, dtype=typ.dtypechar).reshape(*dims),
295 order=(self.intent.is_intent("c") and "C") or "F",
296 )
297 assert self.pyarr.dtype == typ
298 self.pyarr.setflags(write=self.arr.flags["WRITEABLE"])
299 assert self.pyarr.flags["OWNDATA"], (obj, intent)
300 self.pyarr_attr = wrap.array_attrs(self.pyarr)
301
302 if len(dims) > 1:
303 if self.intent.is_intent("c"):
304 assert not self.pyarr.flags["FORTRAN"]
305 assert self.pyarr.flags["CONTIGUOUS"]
306 assert (not self.pyarr_attr[6] & wrap.FORTRAN)
307 else:
308 assert self.pyarr.flags["FORTRAN"]
309 assert not self.pyarr.flags["CONTIGUOUS"]
310 assert (self.pyarr_attr[6] & wrap.FORTRAN)
311
312 assert self.arr_attr[1] == self.pyarr_attr[1] # nd
313 assert self.arr_attr[2] == self.pyarr_attr[2] # dimensions
314 if self.arr_attr[1] <= 1:
315 assert self.arr_attr[3] == self.pyarr_attr[3], repr((
316 self.arr_attr[3],
317 self.pyarr_attr[3],
318 self.arr.tobytes(),
319 self.pyarr.tobytes(),
320 )) # strides
321 assert self.arr_attr[5][-2:] == self.pyarr_attr[5][-2:], repr((
322 self.arr_attr[5], self.pyarr_attr[5]
323 )) # descr
324 assert self.arr_attr[6] == self.pyarr_attr[6], repr((
325 self.arr_attr[6],
326 self.pyarr_attr[6],
327 flags2names(0 * self.arr_attr[6] - self.pyarr_attr[6]),
328 flags2names(self.arr_attr[6]),
329 intent,
330 )) # flags
331
332 if intent.is_intent("cache"):
333 assert self.arr_attr[5][3] >= self.type.elsize
334 else:
335 assert self.arr_attr[5][3] == self.type.elsize
336 assert (self.arr_equal(self.pyarr, self.arr))
337
338 if isinstance(self.obj, np.ndarray):
339 if typ.elsize == Type(obj.dtype).elsize:
340 if not intent.is_intent("copy") and self.arr_attr[1] <= 1:
341 assert self.has_shared_memory()
342
343 def arr_equal(self, arr1, arr2):
344 if arr1.shape != arr2.shape:
345 return False
346 return (arr1 == arr2).all()
347
348 def __str__(self):
349 return str(self.arr)
350
351 def has_shared_memory(self):
352 """Check that created array shares data with input array."""
353 if self.obj is self.arr:
354 return True
355 if not isinstance(self.obj, np.ndarray):
356 return False
357 obj_attr = wrap.array_attrs(self.obj)
358 return obj_attr[0] == self.arr_attr[0]
359
360
361class TestIntent:
362 def test_in_out(self):
363 assert str(intent.in_.out) == "intent(in,out)"
364 assert intent.in_.c.is_intent("c")
365 assert not intent.in_.c.is_intent_exact("c")
366 assert intent.in_.c.is_intent_exact("c", "in")
367 assert intent.in_.c.is_intent_exact("in", "c")
368 assert not intent.in_.is_intent("c")
369
370
371class TestSharedMemory:
372
373 @pytest.fixture(autouse=True, scope="class", params=_type_names)
374 def setup_type(self, request):
375 request.cls.type = Type(request.param)
376 request.cls.array = lambda self, dims, intent, obj: Array(
377 Type(request.param), dims, intent, obj)
378
379 @property
380 def num2seq(self):
381 if self.type.NAME.startswith('STRING'):
382 elsize = self.type.elsize
383 return ['1' * elsize, '2' * elsize]
384 return [1, 2]
385
386 @property
387 def num23seq(self):
388 if self.type.NAME.startswith('STRING'):
389 elsize = self.type.elsize
390 return [['1' * elsize, '2' * elsize, '3' * elsize],
391 ['4' * elsize, '5' * elsize, '6' * elsize]]
392 return [[1, 2, 3], [4, 5, 6]]
393
394 def test_in_from_2seq(self):
395 a = self.array([2], intent.in_, self.num2seq)
396 assert not a.has_shared_memory()
397
398 def test_in_from_2casttype(self):
399 for t in self.type.cast_types():
400 obj = np.array(self.num2seq, dtype=t.dtype)
401 a = self.array([len(self.num2seq)], intent.in_, obj)
402 if t.elsize == self.type.elsize:
403 assert a.has_shared_memory(), repr((self.type.dtype, t.dtype))
404 else:
405 assert not a.has_shared_memory()
406
407 @pytest.mark.parametrize("write", ["w", "ro"])
408 @pytest.mark.parametrize("order", ["C", "F"])
409 @pytest.mark.parametrize("inp", ["2seq", "23seq"])
410 def test_in_nocopy(self, write, order, inp):
411 """Test if intent(in) array can be passed without copies"""
412 seq = getattr(self, "num" + inp)
413 obj = np.array(seq, dtype=self.type.dtype, order=order)
414 obj.setflags(write=(write == 'w'))
415 a = self.array(obj.shape,
416 ((order == 'C' and intent.in_.c) or intent.in_), obj)
417 assert a.has_shared_memory()
418
419 def test_inout_2seq(self):
420 obj = np.array(self.num2seq, dtype=self.type.dtype)
421 a = self.array([len(self.num2seq)], intent.inout, obj)
422 assert a.has_shared_memory()
423
424 try:
425 a = self.array([2], intent.in_.inout, self.num2seq)
426 except TypeError as msg:
427 if not str(msg).startswith(
428 "failed to initialize intent(inout|inplace|cache) array"):
429 raise
430 else:
431 raise SystemError("intent(inout) should have failed on sequence")
432
433 def test_f_inout_23seq(self):
434 obj = np.array(self.num23seq, dtype=self.type.dtype, order="F")
435 shape = (len(self.num23seq), len(self.num23seq[0]))
436 a = self.array(shape, intent.in_.inout, obj)
437 assert a.has_shared_memory()
438
439 obj = np.array(self.num23seq, dtype=self.type.dtype, order="C")
440 shape = (len(self.num23seq), len(self.num23seq[0]))
441 try:
442 a = self.array(shape, intent.in_.inout, obj)
443 except ValueError as msg:
444 if not str(msg).startswith(
445 "failed to initialize intent(inout) array"):
446 raise
447 else:
448 raise SystemError(
449 "intent(inout) should have failed on improper array")
450
451 def test_c_inout_23seq(self):
452 obj = np.array(self.num23seq, dtype=self.type.dtype)
453 shape = (len(self.num23seq), len(self.num23seq[0]))
454 a = self.array(shape, intent.in_.c.inout, obj)
455 assert a.has_shared_memory()
456
457 def test_in_copy_from_2casttype(self):
458 for t in self.type.cast_types():
459 obj = np.array(self.num2seq, dtype=t.dtype)
460 a = self.array([len(self.num2seq)], intent.in_.copy, obj)
461 assert not a.has_shared_memory()
462
463 def test_c_in_from_23seq(self):
464 a = self.array(
465 [len(self.num23seq), len(self.num23seq[0])], intent.in_,
466 self.num23seq)
467 assert not a.has_shared_memory()
468
469 def test_in_from_23casttype(self):
470 for t in self.type.cast_types():
471 obj = np.array(self.num23seq, dtype=t.dtype)
472 a = self.array(
473 [len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
474 assert not a.has_shared_memory()
475
476 def test_f_in_from_23casttype(self):
477 for t in self.type.cast_types():
478 obj = np.array(self.num23seq, dtype=t.dtype, order="F")
479 a = self.array(
480 [len(self.num23seq), len(self.num23seq[0])], intent.in_, obj)
481 if t.elsize == self.type.elsize:
482 assert a.has_shared_memory()
483 else:
484 assert not a.has_shared_memory()
485
486 def test_c_in_from_23casttype(self):
487 for t in self.type.cast_types():
488 obj = np.array(self.num23seq, dtype=t.dtype)
489 a = self.array(
490 [len(self.num23seq), len(self.num23seq[0])], intent.in_.c, obj)
491 if t.elsize == self.type.elsize:
492 assert a.has_shared_memory()
493 else:
494 assert not a.has_shared_memory()
495
496 def test_f_copy_in_from_23casttype(self):
497 for t in self.type.cast_types():
498 obj = np.array(self.num23seq, dtype=t.dtype, order="F")
499 a = self.array(
500 [len(self.num23seq), len(self.num23seq[0])], intent.in_.copy,
501 obj)
502 assert not a.has_shared_memory()
503
504 def test_c_copy_in_from_23casttype(self):
505 for t in self.type.cast_types():
506 obj = np.array(self.num23seq, dtype=t.dtype)
507 a = self.array(
508 [len(self.num23seq), len(self.num23seq[0])], intent.in_.c.copy,
509 obj)
510 assert not a.has_shared_memory()
511
512 def test_in_cache_from_2casttype(self):
513 for t in self.type.all_types():
514 if t.elsize != self.type.elsize:
515 continue
516 obj = np.array(self.num2seq, dtype=t.dtype)
517 shape = (len(self.num2seq), )
518 a = self.array(shape, intent.in_.c.cache, obj)
519 assert a.has_shared_memory()
520
521 a = self.array(shape, intent.in_.cache, obj)
522 assert a.has_shared_memory()
523
524 obj = np.array(self.num2seq, dtype=t.dtype, order="F")
525 a = self.array(shape, intent.in_.c.cache, obj)
526 assert a.has_shared_memory()
527
528 a = self.array(shape, intent.in_.cache, obj)
529 assert a.has_shared_memory(), repr(t.dtype)
530
531 try:
532 a = self.array(shape, intent.in_.cache, obj[::-1])
533 except ValueError as msg:
534 if not str(msg).startswith(
535 "failed to initialize intent(cache) array"):
536 raise
537 else:
538 raise SystemError(
539 "intent(cache) should have failed on multisegmented array")
540
541 def test_in_cache_from_2casttype_failure(self):
542 for t in self.type.all_types():
543 if t.NAME == 'STRING':
544 # string elsize is 0, so skipping the test
545 continue
546 if t.elsize >= self.type.elsize:
547 continue
548 is_int = np.issubdtype(t.dtype, np.integer)
549 if is_int and int(self.num2seq[0]) > np.iinfo(t.dtype).max:
550 # skip test if num2seq would trigger an overflow error
551 continue
552 obj = np.array(self.num2seq, dtype=t.dtype)
553 shape = (len(self.num2seq), )
554 try:
555 self.array(shape, intent.in_.cache, obj) # Should succeed
556 except ValueError as msg:
557 if not str(msg).startswith(
558 "failed to initialize intent(cache) array"):
559 raise
560 else:
561 raise SystemError(
562 "intent(cache) should have failed on smaller array")
563
564 def test_cache_hidden(self):
565 shape = (2, )
566 a = self.array(shape, intent.cache.hide, None)
567 assert a.arr.shape == shape
568
569 shape = (2, 3)
570 a = self.array(shape, intent.cache.hide, None)
571 assert a.arr.shape == shape
572
573 shape = (-1, 3)
574 try:
575 a = self.array(shape, intent.cache.hide, None)
576 except ValueError as msg:
577 if not str(msg).startswith(
578 "failed to create intent(cache|hide)|optional array"):
579 raise
580 else:
581 raise SystemError(
582 "intent(cache) should have failed on undefined dimensions")
583
584 def test_hidden(self):
585 shape = (2, )
586 a = self.array(shape, intent.hide, None)
587 assert a.arr.shape == shape
588 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
589
590 shape = (2, 3)
591 a = self.array(shape, intent.hide, None)
592 assert a.arr.shape == shape
593 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
594 assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
595
596 shape = (2, 3)
597 a = self.array(shape, intent.c.hide, None)
598 assert a.arr.shape == shape
599 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
600 assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
601
602 shape = (-1, 3)
603 try:
604 a = self.array(shape, intent.hide, None)
605 except ValueError as msg:
606 if not str(msg).startswith(
607 "failed to create intent(cache|hide)|optional array"):
608 raise
609 else:
610 raise SystemError(
611 "intent(hide) should have failed on undefined dimensions")
612
613 def test_optional_none(self):
614 shape = (2, )
615 a = self.array(shape, intent.optional, None)
616 assert a.arr.shape == shape
617 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
618
619 shape = (2, 3)
620 a = self.array(shape, intent.optional, None)
621 assert a.arr.shape == shape
622 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
623 assert a.arr.flags["FORTRAN"] and not a.arr.flags["CONTIGUOUS"]
624
625 shape = (2, 3)
626 a = self.array(shape, intent.c.optional, None)
627 assert a.arr.shape == shape
628 assert a.arr_equal(a.arr, np.zeros(shape, dtype=self.type.dtype))
629 assert not a.arr.flags["FORTRAN"] and a.arr.flags["CONTIGUOUS"]
630
631 def test_optional_from_2seq(self):
632 obj = self.num2seq
633 shape = (len(obj), )
634 a = self.array(shape, intent.optional, obj)
635 assert a.arr.shape == shape
636 assert not a.has_shared_memory()
637
638 def test_optional_from_23seq(self):
639 obj = self.num23seq
640 shape = (len(obj), len(obj[0]))
641 a = self.array(shape, intent.optional, obj)
642 assert a.arr.shape == shape
643 assert not a.has_shared_memory()
644
645 a = self.array(shape, intent.optional.c, obj)
646 assert a.arr.shape == shape
647 assert not a.has_shared_memory()
648
649 def test_inplace(self):
650 obj = np.array(self.num23seq, dtype=self.type.dtype)
651 assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
652 shape = obj.shape
653 a = self.array(shape, intent.inplace, obj)
654 assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
655 a.arr[1][2] = 54
656 assert obj[1][2] == a.arr[1][2] == np.array(54, dtype=self.type.dtype)
657 assert a.arr is obj
658 assert obj.flags["FORTRAN"] # obj attributes are changed inplace!
659 assert not obj.flags["CONTIGUOUS"]
660
661 def test_inplace_from_casttype(self):
662 for t in self.type.cast_types():
663 if t is self.type:
664 continue
665 obj = np.array(self.num23seq, dtype=t.dtype)
666 assert obj.dtype.type == t.type
667 assert obj.dtype.type is not self.type.type
668 assert not obj.flags["FORTRAN"] and obj.flags["CONTIGUOUS"]
669 shape = obj.shape
670 a = self.array(shape, intent.inplace, obj)
671 assert obj[1][2] == a.arr[1][2], repr((obj, a.arr))
672 a.arr[1][2] = 54
673 assert obj[1][2] == a.arr[1][2] == np.array(54,
674 dtype=self.type.dtype)
675 assert a.arr is obj
676 assert obj.flags["FORTRAN"] # obj attributes changed inplace!
677 assert not obj.flags["CONTIGUOUS"]
678 assert obj.dtype.type is self.type.type # obj changed inplace!
679 