blob: d440bcf7e0faa1faf7b00e9763d6a9f02d06a239 [file] [log] [blame]
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001#
2# The ndarray object from _testbuffer.c is a complete implementation of
3# a PEP-3118 buffer provider. It is independent from NumPy's ndarray
4# and the tests don't require NumPy.
5#
6# If NumPy is present, some tests check both ndarray implementations
7# against each other.
8#
9# Most ndarray tests also check that memoryview(ndarray) behaves in
10# the same way as the original. Thus, a substantial part of the
11# memoryview tests is now in this module.
12#
Stefan Krahb942ba02020-02-24 12:24:43 +010013# Written and designed by Stefan Krah for Python 3.3.
14#
Stefan Krah9a2d99e2012-02-25 12:24:21 +010015
Antoine Pitrou31084ba2015-03-19 23:29:36 +010016import contextlib
Stefan Krah9a2d99e2012-02-25 12:24:21 +010017import unittest
18from test import support
19from itertools import permutations, product
20from random import randrange, sample, choice
Stefan Krah9a2d99e2012-02-25 12:24:21 +010021import warnings
Serhiy Storchaka676db4b2017-10-16 10:38:14 +030022import sys, array, io, os
Stefan Krah9a2d99e2012-02-25 12:24:21 +010023from decimal import Decimal
24from fractions import Fraction
25
26try:
27 from _testbuffer import *
28except ImportError:
29 ndarray = None
30
31try:
32 import struct
33except ImportError:
34 struct = None
35
36try:
Nick Coghlan06e1ab02012-08-25 17:59:50 +100037 import ctypes
38except ImportError:
39 ctypes = None
40
41try:
Serhiy Storchaka676db4b2017-10-16 10:38:14 +030042 with support.EnvironmentVarGuard() as os.environ, \
43 warnings.catch_warnings():
Stefan Krah9a2d99e2012-02-25 12:24:21 +010044 from numpy import ndarray as numpy_array
45except ImportError:
46 numpy_array = None
47
Joannah Nanjekye9e66aba2019-08-20 11:46:36 -030048try:
49 import _testcapi
50except ImportError:
51 _testcapi = None
52
Stefan Krah9a2d99e2012-02-25 12:24:21 +010053
54SHORT_TEST = True
55
56
57# ======================================================================
58# Random lists by format specifier
59# ======================================================================
60
61# Native format chars and their ranges.
62NATIVE = {
63 '?':0, 'c':0, 'b':0, 'B':0,
64 'h':0, 'H':0, 'i':0, 'I':0,
65 'l':0, 'L':0, 'n':0, 'N':0,
66 'f':0, 'd':0, 'P':0
67}
68
Stefan Krah7d12d9d2012-07-28 12:25:55 +020069# NumPy does not have 'n' or 'N':
70if numpy_array:
71 del NATIVE['n']
72 del NATIVE['N']
73
Stefan Krah9a2d99e2012-02-25 12:24:21 +010074if struct:
75 try:
76 # Add "qQ" if present in native mode.
77 struct.pack('Q', 2**64-1)
78 NATIVE['q'] = 0
79 NATIVE['Q'] = 0
80 except struct.error:
81 pass
82
83# Standard format chars and their ranges.
84STANDARD = {
85 '?':(0, 2), 'c':(0, 1<<8),
86 'b':(-(1<<7), 1<<7), 'B':(0, 1<<8),
87 'h':(-(1<<15), 1<<15), 'H':(0, 1<<16),
88 'i':(-(1<<31), 1<<31), 'I':(0, 1<<32),
89 'l':(-(1<<31), 1<<31), 'L':(0, 1<<32),
90 'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64),
91 'f':(-(1<<63), 1<<63), 'd':(-(1<<1023), 1<<1023)
92}
93
94def native_type_range(fmt):
95 """Return range of a native type."""
96 if fmt == 'c':
97 lh = (0, 256)
98 elif fmt == '?':
99 lh = (0, 2)
100 elif fmt == 'f':
101 lh = (-(1<<63), 1<<63)
102 elif fmt == 'd':
103 lh = (-(1<<1023), 1<<1023)
104 else:
105 for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7):
106 try:
107 struct.pack(fmt, (1<<exp)-1)
108 break
109 except struct.error:
110 pass
111 lh = (-(1<<exp), 1<<exp) if exp & 1 else (0, 1<<exp)
112 return lh
113
114fmtdict = {
115 '':NATIVE,
116 '@':NATIVE,
117 '<':STANDARD,
118 '>':STANDARD,
119 '=':STANDARD,
120 '!':STANDARD
121}
122
123if struct:
124 for fmt in fmtdict['@']:
125 fmtdict['@'][fmt] = native_type_range(fmt)
126
127MEMORYVIEW = NATIVE.copy()
128ARRAY = NATIVE.copy()
129for k in NATIVE:
130 if not k in "bBhHiIlLfd":
131 del ARRAY[k]
132
133BYTEFMT = NATIVE.copy()
134for k in NATIVE:
135 if not k in "Bbc":
136 del BYTEFMT[k]
137
138fmtdict['m'] = MEMORYVIEW
139fmtdict['@m'] = MEMORYVIEW
140fmtdict['a'] = ARRAY
141fmtdict['b'] = BYTEFMT
142fmtdict['@b'] = BYTEFMT
143
144# Capabilities of the test objects:
145MODE = 0
146MULT = 1
147cap = { # format chars # multiplier
148 'ndarray': (['', '@', '<', '>', '=', '!'], ['', '1', '2', '3']),
149 'array': (['a'], ['']),
150 'numpy': ([''], ['']),
151 'memoryview': (['@m', 'm'], ['']),
152 'bytefmt': (['@b', 'b'], ['']),
153}
154
155def randrange_fmt(mode, char, obj):
156 """Return random item for a type specified by a mode and a single
157 format character."""
158 x = randrange(*fmtdict[mode][char])
159 if char == 'c':
Serhiy Storchaka74a49ac2015-03-20 16:46:19 +0200160 x = bytes([x])
161 if obj == 'numpy' and x == b'\x00':
162 # http://projects.scipy.org/numpy/ticket/1925
163 x = b'\x01'
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100164 if char == '?':
165 x = bool(x)
166 if char == 'f' or char == 'd':
167 x = struct.pack(char, x)
168 x = struct.unpack(char, x)[0]
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100169 return x
170
171def gen_item(fmt, obj):
172 """Return single random item."""
173 mode, chars = fmt.split('#')
174 x = []
175 for c in chars:
176 x.append(randrange_fmt(mode, c, obj))
177 return x[0] if len(x) == 1 else tuple(x)
178
179def gen_items(n, fmt, obj):
180 """Return a list of random items (or a scalar)."""
181 if n == 0:
182 return gen_item(fmt, obj)
183 lst = [0] * n
184 for i in range(n):
185 lst[i] = gen_item(fmt, obj)
186 return lst
187
188def struct_items(n, obj):
189 mode = choice(cap[obj][MODE])
190 xfmt = mode + '#'
191 fmt = mode.strip('amb')
192 nmemb = randrange(2, 10) # number of struct members
193 for _ in range(nmemb):
194 char = choice(tuple(fmtdict[mode]))
195 multiplier = choice(cap[obj][MULT])
196 xfmt += (char * int(multiplier if multiplier else 1))
197 fmt += (multiplier + char)
198 items = gen_items(n, xfmt, obj)
199 item = gen_item(xfmt, obj)
200 return fmt, items, item
201
202def randitems(n, obj='ndarray', mode=None, char=None):
203 """Return random format, items, item."""
204 if mode is None:
205 mode = choice(cap[obj][MODE])
206 if char is None:
207 char = choice(tuple(fmtdict[mode]))
208 multiplier = choice(cap[obj][MULT])
209 fmt = mode + '#' + char * int(multiplier if multiplier else 1)
210 items = gen_items(n, fmt, obj)
211 item = gen_item(fmt, obj)
212 fmt = mode.strip('amb') + multiplier + char
213 return fmt, items, item
214
215def iter_mode(n, obj='ndarray'):
216 """Iterate through supported mode/char combinations."""
217 for mode in cap[obj][MODE]:
218 for char in fmtdict[mode]:
219 yield randitems(n, obj, mode, char)
220
221def iter_format(nitems, testobj='ndarray'):
222 """Yield (format, items, item) for all possible modes and format
223 characters plus one random compound format string."""
224 for t in iter_mode(nitems, testobj):
225 yield t
226 if testobj != 'ndarray':
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -0800227 return
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100228 yield struct_items(nitems, testobj)
229
230
231def is_byte_format(fmt):
232 return 'c' in fmt or 'b' in fmt or 'B' in fmt
233
234def is_memoryview_format(fmt):
235 """format suitable for memoryview"""
236 x = len(fmt)
237 return ((x == 1 or (x == 2 and fmt[0] == '@')) and
238 fmt[x-1] in MEMORYVIEW)
239
240NON_BYTE_FORMAT = [c for c in fmtdict['@'] if not is_byte_format(c)]
241
242
243# ======================================================================
244# Multi-dimensional tolist(), slicing and slice assignments
245# ======================================================================
246
247def atomp(lst):
248 """Tuple items (representing structs) are regarded as atoms."""
249 return not isinstance(lst, list)
250
251def listp(lst):
252 return isinstance(lst, list)
253
254def prod(lst):
255 """Product of list elements."""
256 if len(lst) == 0:
257 return 0
258 x = lst[0]
259 for v in lst[1:]:
260 x *= v
261 return x
262
263def strides_from_shape(ndim, shape, itemsize, layout):
264 """Calculate strides of a contiguous array. Layout is 'C' or
265 'F' (Fortran)."""
266 if ndim == 0:
267 return ()
268 if layout == 'C':
269 strides = list(shape[1:]) + [itemsize]
270 for i in range(ndim-2, -1, -1):
271 strides[i] *= strides[i+1]
272 else:
273 strides = [itemsize] + list(shape[:-1])
274 for i in range(1, ndim):
275 strides[i] *= strides[i-1]
276 return strides
277
278def _ca(items, s):
279 """Convert flat item list to the nested list representation of a
280 multidimensional C array with shape 's'."""
281 if atomp(items):
282 return items
283 if len(s) == 0:
284 return items[0]
285 lst = [0] * s[0]
286 stride = len(items) // s[0] if s[0] else 0
287 for i in range(s[0]):
288 start = i*stride
289 lst[i] = _ca(items[start:start+stride], s[1:])
290 return lst
291
292def _fa(items, s):
293 """Convert flat item list to the nested list representation of a
294 multidimensional Fortran array with shape 's'."""
295 if atomp(items):
296 return items
297 if len(s) == 0:
298 return items[0]
299 lst = [0] * s[0]
300 stride = s[0]
301 for i in range(s[0]):
302 lst[i] = _fa(items[i::stride], s[1:])
303 return lst
304
305def carray(items, shape):
306 if listp(items) and not 0 in shape and prod(shape) != len(items):
307 raise ValueError("prod(shape) != len(items)")
308 return _ca(items, shape)
309
310def farray(items, shape):
311 if listp(items) and not 0 in shape and prod(shape) != len(items):
312 raise ValueError("prod(shape) != len(items)")
313 return _fa(items, shape)
314
315def indices(shape):
316 """Generate all possible tuples of indices."""
317 iterables = [range(v) for v in shape]
318 return product(*iterables)
319
320def getindex(ndim, ind, strides):
321 """Convert multi-dimensional index to the position in the flat list."""
322 ret = 0
323 for i in range(ndim):
324 ret += strides[i] * ind[i]
325 return ret
326
327def transpose(src, shape):
328 """Transpose flat item list that is regarded as a multi-dimensional
329 matrix defined by shape: dest...[k][j][i] = src[i][j][k]... """
330 if not shape:
331 return src
332 ndim = len(shape)
333 sstrides = strides_from_shape(ndim, shape, 1, 'C')
334 dstrides = strides_from_shape(ndim, shape[::-1], 1, 'C')
335 dest = [0] * len(src)
336 for ind in indices(shape):
337 fr = getindex(ndim, ind, sstrides)
338 to = getindex(ndim, ind[::-1], dstrides)
339 dest[to] = src[fr]
340 return dest
341
342def _flatten(lst):
343 """flatten list"""
344 if lst == []:
345 return lst
346 if atomp(lst):
347 return [lst]
348 return _flatten(lst[0]) + _flatten(lst[1:])
349
350def flatten(lst):
351 """flatten list or return scalar"""
352 if atomp(lst): # scalar
353 return lst
354 return _flatten(lst)
355
356def slice_shape(lst, slices):
357 """Get the shape of lst after slicing: slices is a list of slice
358 objects."""
359 if atomp(lst):
360 return []
361 return [len(lst[slices[0]])] + slice_shape(lst[0], slices[1:])
362
363def multislice(lst, slices):
364 """Multi-dimensional slicing: slices is a list of slice objects."""
365 if atomp(lst):
366 return lst
367 return [multislice(sublst, slices[1:]) for sublst in lst[slices[0]]]
368
369def m_assign(llst, rlst, lslices, rslices):
370 """Multi-dimensional slice assignment: llst and rlst are the operands,
371 lslices and rslices are lists of slice objects. llst and rlst must
372 have the same structure.
373
374 For a two-dimensional example, this is not implemented in Python:
375
376 llst[0:3:2, 0:3:2] = rlst[1:3:1, 1:3:1]
377
378 Instead we write:
379
380 lslices = [slice(0,3,2), slice(0,3,2)]
381 rslices = [slice(1,3,1), slice(1,3,1)]
382 multislice_assign(llst, rlst, lslices, rslices)
383 """
384 if atomp(rlst):
385 return rlst
386 rlst = [m_assign(l, r, lslices[1:], rslices[1:])
387 for l, r in zip(llst[lslices[0]], rlst[rslices[0]])]
388 llst[lslices[0]] = rlst
389 return llst
390
391def cmp_structure(llst, rlst, lslices, rslices):
392 """Compare the structure of llst[lslices] and rlst[rslices]."""
393 lshape = slice_shape(llst, lslices)
394 rshape = slice_shape(rlst, rslices)
395 if (len(lshape) != len(rshape)):
396 return -1
397 for i in range(len(lshape)):
398 if lshape[i] != rshape[i]:
399 return -1
400 if lshape[i] == 0:
401 return 0
402 return 0
403
404def multislice_assign(llst, rlst, lslices, rslices):
405 """Return llst after assigning: llst[lslices] = rlst[rslices]"""
406 if cmp_structure(llst, rlst, lslices, rslices) < 0:
407 raise ValueError("lvalue and rvalue have different structures")
408 return m_assign(llst, rlst, lslices, rslices)
409
410
411# ======================================================================
412# Random structures
413# ======================================================================
414
415#
416# PEP-3118 is very permissive with respect to the contents of a
417# Py_buffer. In particular:
418#
419# - shape can be zero
420# - strides can be any integer, including zero
421# - offset can point to any location in the underlying
422# memory block, provided that it is a multiple of
423# itemsize.
424#
425# The functions in this section test and verify random structures
426# in full generality. A structure is valid iff it fits in the
427# underlying memory block.
428#
429# The structure 't' (short for 'tuple') is fully defined by:
430#
431# t = (memlen, itemsize, ndim, shape, strides, offset)
432#
433
434def verify_structure(memlen, itemsize, ndim, shape, strides, offset):
435 """Verify that the parameters represent a valid array within
436 the bounds of the allocated memory:
437 char *mem: start of the physical memory block
438 memlen: length of the physical memory block
439 offset: (char *)buf - mem
440 """
441 if offset % itemsize:
442 return False
443 if offset < 0 or offset+itemsize > memlen:
444 return False
445 if any(v % itemsize for v in strides):
446 return False
447
448 if ndim <= 0:
449 return ndim == 0 and not shape and not strides
450 if 0 in shape:
451 return True
452
453 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
454 if strides[j] <= 0)
455 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
456 if strides[j] > 0)
457
458 return 0 <= offset+imin and offset+imax+itemsize <= memlen
459
460def get_item(lst, indices):
461 for i in indices:
462 lst = lst[i]
463 return lst
464
465def memory_index(indices, t):
466 """Location of an item in the underlying memory."""
467 memlen, itemsize, ndim, shape, strides, offset = t
468 p = offset
469 for i in range(ndim):
470 p += strides[i]*indices[i]
471 return p
472
473def is_overlapping(t):
474 """The structure 't' is overlapping if at least one memory location
475 is visited twice while iterating through all possible tuples of
476 indices."""
477 memlen, itemsize, ndim, shape, strides, offset = t
478 visited = 1<<memlen
479 for ind in indices(shape):
480 i = memory_index(ind, t)
481 bit = 1<<i
482 if visited & bit:
483 return True
484 visited |= bit
485 return False
486
487def rand_structure(itemsize, valid, maxdim=5, maxshape=16, shape=()):
488 """Return random structure:
489 (memlen, itemsize, ndim, shape, strides, offset)
490 If 'valid' is true, the returned structure is valid, otherwise invalid.
491 If 'shape' is given, use that instead of creating a random shape.
492 """
493 if not shape:
494 ndim = randrange(maxdim+1)
495 if (ndim == 0):
496 if valid:
497 return itemsize, itemsize, ndim, (), (), 0
498 else:
499 nitems = randrange(1, 16+1)
500 memlen = nitems * itemsize
501 offset = -itemsize if randrange(2) == 0 else memlen
502 return memlen, itemsize, ndim, (), (), offset
503
504 minshape = 2
505 n = randrange(100)
506 if n >= 95 and valid:
507 minshape = 0
508 elif n >= 90:
509 minshape = 1
510 shape = [0] * ndim
511
512 for i in range(ndim):
513 shape[i] = randrange(minshape, maxshape+1)
514 else:
515 ndim = len(shape)
516
517 maxstride = 5
518 n = randrange(100)
519 zero_stride = True if n >= 95 and n & 1 else False
520
521 strides = [0] * ndim
522 strides[ndim-1] = itemsize * randrange(-maxstride, maxstride+1)
523 if not zero_stride and strides[ndim-1] == 0:
524 strides[ndim-1] = itemsize
525
526 for i in range(ndim-2, -1, -1):
527 maxstride *= shape[i+1] if shape[i+1] else 1
528 if zero_stride:
529 strides[i] = itemsize * randrange(-maxstride, maxstride+1)
530 else:
531 strides[i] = ((1,-1)[randrange(2)] *
532 itemsize * randrange(1, maxstride+1))
533
534 imin = imax = 0
535 if not 0 in shape:
536 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
537 if strides[j] <= 0)
538 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
539 if strides[j] > 0)
540
541 nitems = imax - imin
542 if valid:
543 offset = -imin * itemsize
544 memlen = offset + (imax+1) * itemsize
545 else:
546 memlen = (-imin + imax) * itemsize
547 offset = -imin-itemsize if randrange(2) == 0 else memlen
548 return memlen, itemsize, ndim, shape, strides, offset
549
550def randslice_from_slicelen(slicelen, listlen):
551 """Create a random slice of len slicelen that fits into listlen."""
552 maxstart = listlen - slicelen
553 start = randrange(maxstart+1)
554 maxstep = (listlen - start) // slicelen if slicelen else 1
555 step = randrange(1, maxstep+1)
556 stop = start + slicelen * step
557 s = slice(start, stop, step)
558 _, _, _, control = slice_indices(s, listlen)
559 if control != slicelen:
560 raise RuntimeError
561 return s
562
563def randslice_from_shape(ndim, shape):
564 """Create two sets of slices for an array x with shape 'shape'
565 such that shapeof(x[lslices]) == shapeof(x[rslices])."""
566 lslices = [0] * ndim
567 rslices = [0] * ndim
568 for n in range(ndim):
569 l = shape[n]
570 slicelen = randrange(1, l+1) if l > 0 else 0
571 lslices[n] = randslice_from_slicelen(slicelen, l)
572 rslices[n] = randslice_from_slicelen(slicelen, l)
573 return tuple(lslices), tuple(rslices)
574
575def rand_aligned_slices(maxdim=5, maxshape=16):
576 """Create (lshape, rshape, tuple(lslices), tuple(rslices)) such that
577 shapeof(x[lslices]) == shapeof(y[rslices]), where x is an array
578 with shape 'lshape' and y is an array with shape 'rshape'."""
579 ndim = randrange(1, maxdim+1)
580 minshape = 2
581 n = randrange(100)
582 if n >= 95:
583 minshape = 0
584 elif n >= 90:
585 minshape = 1
586 all_random = True if randrange(100) >= 80 else False
587 lshape = [0]*ndim; rshape = [0]*ndim
588 lslices = [0]*ndim; rslices = [0]*ndim
589
590 for n in range(ndim):
591 small = randrange(minshape, maxshape+1)
592 big = randrange(minshape, maxshape+1)
593 if big < small:
594 big, small = small, big
595
596 # Create a slice that fits the smaller value.
597 if all_random:
598 start = randrange(-small, small+1)
599 stop = randrange(-small, small+1)
600 step = (1,-1)[randrange(2)] * randrange(1, small+2)
601 s_small = slice(start, stop, step)
602 _, _, _, slicelen = slice_indices(s_small, small)
603 else:
604 slicelen = randrange(1, small+1) if small > 0 else 0
605 s_small = randslice_from_slicelen(slicelen, small)
606
607 # Create a slice of the same length for the bigger value.
608 s_big = randslice_from_slicelen(slicelen, big)
609 if randrange(2) == 0:
610 rshape[n], lshape[n] = big, small
611 rslices[n], lslices[n] = s_big, s_small
612 else:
613 rshape[n], lshape[n] = small, big
614 rslices[n], lslices[n] = s_small, s_big
615
616 return lshape, rshape, tuple(lslices), tuple(rslices)
617
618def randitems_from_structure(fmt, t):
619 """Return a list of random items for structure 't' with format
620 'fmtchar'."""
621 memlen, itemsize, _, _, _, _ = t
622 return gen_items(memlen//itemsize, '#'+fmt, 'numpy')
623
624def ndarray_from_structure(items, fmt, t, flags=0):
625 """Return ndarray from the tuple returned by rand_structure()"""
626 memlen, itemsize, ndim, shape, strides, offset = t
627 return ndarray(items, shape=shape, strides=strides, format=fmt,
628 offset=offset, flags=ND_WRITABLE|flags)
629
630def numpy_array_from_structure(items, fmt, t):
631 """Return numpy_array from the tuple returned by rand_structure()"""
632 memlen, itemsize, ndim, shape, strides, offset = t
633 buf = bytearray(memlen)
634 for j, v in enumerate(items):
635 struct.pack_into(fmt, buf, j*itemsize, v)
636 return numpy_array(buffer=buf, shape=shape, strides=strides,
637 dtype=fmt, offset=offset)
638
639
640# ======================================================================
641# memoryview casts
642# ======================================================================
643
644def cast_items(exporter, fmt, itemsize, shape=None):
645 """Interpret the raw memory of 'exporter' as a list of items with
646 size 'itemsize'. If shape=None, the new structure is assumed to
647 be 1-D with n * itemsize = bytelen. If shape is given, the usual
648 constraint for contiguous arrays prod(shape) * itemsize = bytelen
649 applies. On success, return (items, shape). If the constraints
650 cannot be met, return (None, None). If a chunk of bytes is interpreted
651 as NaN as a result of float conversion, return ('nan', None)."""
652 bytelen = exporter.nbytes
653 if shape:
654 if prod(shape) * itemsize != bytelen:
655 return None, shape
656 elif shape == []:
657 if exporter.ndim == 0 or itemsize != bytelen:
658 return None, shape
659 else:
660 n, r = divmod(bytelen, itemsize)
661 shape = [n]
662 if r != 0:
663 return None, shape
664
665 mem = exporter.tobytes()
666 byteitems = [mem[i:i+itemsize] for i in range(0, len(mem), itemsize)]
667
668 items = []
669 for v in byteitems:
670 item = struct.unpack(fmt, v)[0]
671 if item != item:
672 return 'nan', shape
673 items.append(item)
674
675 return (items, shape) if shape != [] else (items[0], shape)
676
677def gencastshapes():
678 """Generate shapes to test casting."""
679 for n in range(32):
680 yield [n]
681 ndim = randrange(4, 6)
682 minshape = 1 if randrange(100) > 80 else 2
683 yield [randrange(minshape, 5) for _ in range(ndim)]
684 ndim = randrange(2, 4)
685 minshape = 1 if randrange(100) > 80 else 2
686 yield [randrange(minshape, 5) for _ in range(ndim)]
687
688
689# ======================================================================
690# Actual tests
691# ======================================================================
692
693def genslices(n):
694 """Generate all possible slices for a single dimension."""
695 return product(range(-n, n+1), range(-n, n+1), range(-n, n+1))
696
697def genslices_ndim(ndim, shape):
698 """Generate all possible slice tuples for 'shape'."""
699 iterables = [genslices(shape[n]) for n in range(ndim)]
700 return product(*iterables)
701
702def rslice(n, allow_empty=False):
703 """Generate random slice for a single dimension of length n.
704 If zero=True, the slices may be empty, otherwise they will
705 be non-empty."""
706 minlen = 0 if allow_empty or n == 0 else 1
707 slicelen = randrange(minlen, n+1)
708 return randslice_from_slicelen(slicelen, n)
709
710def rslices(n, allow_empty=False):
711 """Generate random slices for a single dimension."""
712 for _ in range(5):
713 yield rslice(n, allow_empty)
714
715def rslices_ndim(ndim, shape, iterations=5):
716 """Generate random slice tuples for 'shape'."""
717 # non-empty slices
718 for _ in range(iterations):
719 yield tuple(rslice(shape[n]) for n in range(ndim))
720 # possibly empty slices
721 for _ in range(iterations):
722 yield tuple(rslice(shape[n], allow_empty=True) for n in range(ndim))
723 # invalid slices
724 yield tuple(slice(0,1,0) for _ in range(ndim))
725
726def rpermutation(iterable, r=None):
727 pool = tuple(iterable)
728 r = len(pool) if r is None else r
729 yield tuple(sample(pool, r))
730
731def ndarray_print(nd):
732 """Print ndarray for debugging."""
733 try:
734 x = nd.tolist()
735 except (TypeError, NotImplementedError):
736 x = nd.tobytes()
737 if isinstance(nd, ndarray):
738 offset = nd.offset
739 flags = nd.flags
740 else:
741 offset = 'unknown'
742 flags = 'unknown'
743 print("ndarray(%s, shape=%s, strides=%s, suboffsets=%s, offset=%s, "
744 "format='%s', itemsize=%s, flags=%s)" %
745 (x, nd.shape, nd.strides, nd.suboffsets, offset,
746 nd.format, nd.itemsize, flags))
747 sys.stdout.flush()
748
749
750ITERATIONS = 100
751MAXDIM = 5
752MAXSHAPE = 10
753
754if SHORT_TEST:
755 ITERATIONS = 10
756 MAXDIM = 3
757 MAXSHAPE = 4
758 genslices = rslices
759 genslices_ndim = rslices_ndim
760 permutations = rpermutation
761
762
763@unittest.skipUnless(struct, 'struct module required for this test.')
764@unittest.skipUnless(ndarray, 'ndarray object required for this test')
765class TestBufferProtocol(unittest.TestCase):
766
767 def setUp(self):
Stefan Krah5d953182012-05-16 20:41:56 +0200768 # The suboffsets tests need sizeof(void *).
769 self.sizeof_void_p = get_sizeof_void_p()
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100770
Serhiy Storchakae0d67f12018-07-26 13:23:03 +0300771 def verify(self, result, *, obj,
772 itemsize, fmt, readonly,
773 ndim, shape, strides,
774 lst, sliced=False, cast=False):
Serhiy Storchaka3b5342c2018-07-26 17:34:07 +0300775 # Verify buffer contents against expected values.
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100776 if shape:
777 expected_len = prod(shape)*itemsize
778 else:
779 if not fmt: # array has been implicitly cast to unsigned bytes
780 expected_len = len(lst)
781 else: # ndim = 0
782 expected_len = itemsize
783
784 # Reconstruct suboffsets from strides. Support for slicing
785 # could be added, but is currently only needed for test_getbuf().
786 suboffsets = ()
787 if result.suboffsets:
788 self.assertGreater(ndim, 0)
789
790 suboffset0 = 0
791 for n in range(1, ndim):
792 if shape[n] == 0:
793 break
794 if strides[n] <= 0:
795 suboffset0 += -strides[n] * (shape[n]-1)
796
797 suboffsets = [suboffset0] + [-1 for v in range(ndim-1)]
798
799 # Not correct if slicing has occurred in the first dimension.
800 stride0 = self.sizeof_void_p
801 if strides[0] < 0:
802 stride0 = -stride0
803 strides = [stride0] + list(strides[1:])
804
805 self.assertIs(result.obj, obj)
806 self.assertEqual(result.nbytes, expected_len)
807 self.assertEqual(result.itemsize, itemsize)
808 self.assertEqual(result.format, fmt)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +0300809 self.assertIs(result.readonly, readonly)
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100810 self.assertEqual(result.ndim, ndim)
811 self.assertEqual(result.shape, tuple(shape))
812 if not (sliced and suboffsets):
813 self.assertEqual(result.strides, tuple(strides))
814 self.assertEqual(result.suboffsets, tuple(suboffsets))
815
816 if isinstance(result, ndarray) or is_memoryview_format(fmt):
817 rep = result.tolist() if fmt else result.tobytes()
818 self.assertEqual(rep, lst)
819
820 if not fmt: # array has been cast to unsigned bytes,
821 return # the remaining tests won't work.
822
823 # PyBuffer_GetPointer() is the definition how to access an item.
824 # If PyBuffer_GetPointer(indices) is correct for all possible
825 # combinations of indices, the buffer is correct.
826 #
827 # Also test tobytes() against the flattened 'lst', with all items
828 # packed to bytes.
829 if not cast: # casts chop up 'lst' in different ways
830 b = bytearray()
831 buf_err = None
832 for ind in indices(shape):
833 try:
834 item1 = get_pointer(result, ind)
835 item2 = get_item(lst, ind)
836 if isinstance(item2, tuple):
837 x = struct.pack(fmt, *item2)
838 else:
839 x = struct.pack(fmt, item2)
840 b.extend(x)
841 except BufferError:
842 buf_err = True # re-exporter does not provide full buffer
843 break
844 self.assertEqual(item1, item2)
845
846 if not buf_err:
847 # test tobytes()
848 self.assertEqual(result.tobytes(), b)
849
Stefan Krah0ce5b6e2015-11-10 18:17:22 +0100850 # test hex()
851 m = memoryview(result)
852 h = "".join("%02x" % c for c in b)
853 self.assertEqual(m.hex(), h)
854
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100855 # lst := expected multi-dimensional logical representation
856 # flatten(lst) := elements in C-order
857 ff = fmt if fmt else 'B'
858 flattened = flatten(lst)
859
860 # Rules for 'A': if the array is already contiguous, return
861 # the array unaltered. Otherwise, return a contiguous 'C'
862 # representation.
863 for order in ['C', 'F', 'A']:
864 expected = result
865 if order == 'F':
866 if not is_contiguous(result, 'A') or \
867 is_contiguous(result, 'C'):
868 # For constructing the ndarray, convert the
869 # flattened logical representation to Fortran order.
870 trans = transpose(flattened, shape)
871 expected = ndarray(trans, shape=shape, format=ff,
872 flags=ND_FORTRAN)
873 else: # 'C', 'A'
874 if not is_contiguous(result, 'A') or \
875 is_contiguous(result, 'F') and order == 'C':
876 # The flattened list is already in C-order.
877 expected = ndarray(flattened, shape=shape, format=ff)
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200878
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100879 contig = get_contiguous(result, PyBUF_READ, order)
880 self.assertEqual(contig.tobytes(), b)
881 self.assertTrue(cmp_contig(contig, expected))
882
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200883 if ndim == 0:
884 continue
885
886 nmemb = len(flattened)
887 ro = 0 if readonly else ND_WRITABLE
888
889 ### See comment in test_py_buffer_to_contiguous for an
890 ### explanation why these tests are valid.
891
892 # To 'C'
893 contig = py_buffer_to_contiguous(result, 'C', PyBUF_FULL_RO)
894 self.assertEqual(len(contig), nmemb * itemsize)
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000895 initlst = [struct.unpack_from(fmt, contig, n*itemsize)
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200896 for n in range(nmemb)]
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000897 if len(initlst[0]) == 1:
898 initlst = [v[0] for v in initlst]
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200899
900 y = ndarray(initlst, shape=shape, flags=ro, format=fmt)
901 self.assertEqual(memoryview(y), memoryview(result))
902
Stefan Krahd08ea702019-02-02 18:57:41 +0100903 contig_bytes = memoryview(result).tobytes()
904 self.assertEqual(contig_bytes, contig)
905
906 contig_bytes = memoryview(result).tobytes(order=None)
907 self.assertEqual(contig_bytes, contig)
908
909 contig_bytes = memoryview(result).tobytes(order='C')
910 self.assertEqual(contig_bytes, contig)
911
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200912 # To 'F'
913 contig = py_buffer_to_contiguous(result, 'F', PyBUF_FULL_RO)
914 self.assertEqual(len(contig), nmemb * itemsize)
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000915 initlst = [struct.unpack_from(fmt, contig, n*itemsize)
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200916 for n in range(nmemb)]
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000917 if len(initlst[0]) == 1:
918 initlst = [v[0] for v in initlst]
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200919
920 y = ndarray(initlst, shape=shape, flags=ro|ND_FORTRAN,
921 format=fmt)
922 self.assertEqual(memoryview(y), memoryview(result))
923
Stefan Krahd08ea702019-02-02 18:57:41 +0100924 contig_bytes = memoryview(result).tobytes(order='F')
925 self.assertEqual(contig_bytes, contig)
926
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200927 # To 'A'
928 contig = py_buffer_to_contiguous(result, 'A', PyBUF_FULL_RO)
929 self.assertEqual(len(contig), nmemb * itemsize)
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000930 initlst = [struct.unpack_from(fmt, contig, n*itemsize)
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200931 for n in range(nmemb)]
Nick Coghlan06e1ab02012-08-25 17:59:50 +1000932 if len(initlst[0]) == 1:
933 initlst = [v[0] for v in initlst]
Stefan Krah7d12d9d2012-07-28 12:25:55 +0200934
935 f = ND_FORTRAN if is_contiguous(result, 'F') else 0
936 y = ndarray(initlst, shape=shape, flags=f|ro, format=fmt)
937 self.assertEqual(memoryview(y), memoryview(result))
938
Stefan Krahd08ea702019-02-02 18:57:41 +0100939 contig_bytes = memoryview(result).tobytes(order='A')
940 self.assertEqual(contig_bytes, contig)
941
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100942 if is_memoryview_format(fmt):
943 try:
944 m = memoryview(result)
945 except BufferError: # re-exporter does not provide full information
946 return
947 ex = result.obj if isinstance(result, memoryview) else result
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100948
Antoine Pitrou480ab052018-04-14 19:49:21 +0200949 def check_memoryview(m, expected_readonly=readonly):
950 self.assertIs(m.obj, ex)
951 self.assertEqual(m.nbytes, expected_len)
952 self.assertEqual(m.itemsize, itemsize)
953 self.assertEqual(m.format, fmt)
954 self.assertEqual(m.readonly, expected_readonly)
955 self.assertEqual(m.ndim, ndim)
956 self.assertEqual(m.shape, tuple(shape))
957 if not (sliced and suboffsets):
958 self.assertEqual(m.strides, tuple(strides))
959 self.assertEqual(m.suboffsets, tuple(suboffsets))
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100960
Antoine Pitrou480ab052018-04-14 19:49:21 +0200961 n = 1 if ndim == 0 else len(lst)
962 self.assertEqual(len(m), n)
963
964 rep = result.tolist() if fmt else result.tobytes()
965 self.assertEqual(rep, lst)
966 self.assertEqual(m, result)
967
968 check_memoryview(m)
969 with m.toreadonly() as mm:
970 check_memoryview(mm, expected_readonly=True)
971 m.tobytes() # Releasing mm didn't release m
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100972
973 def verify_getbuf(self, orig_ex, ex, req, sliced=False):
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100974 def match(req, flag):
975 return ((req&flag) == flag)
976
977 if (# writable request to read-only exporter
978 (ex.readonly and match(req, PyBUF_WRITABLE)) or
979 # cannot match explicit contiguity request
980 (match(req, PyBUF_C_CONTIGUOUS) and not ex.c_contiguous) or
981 (match(req, PyBUF_F_CONTIGUOUS) and not ex.f_contiguous) or
982 (match(req, PyBUF_ANY_CONTIGUOUS) and not ex.contiguous) or
983 # buffer needs suboffsets
984 (not match(req, PyBUF_INDIRECT) and ex.suboffsets) or
985 # buffer without strides must be C-contiguous
986 (not match(req, PyBUF_STRIDES) and not ex.c_contiguous) or
987 # PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT
988 (not match(req, PyBUF_ND) and match(req, PyBUF_FORMAT))):
989
990 self.assertRaises(BufferError, ndarray, ex, getbuf=req)
991 return
992
993 if isinstance(ex, ndarray) or is_memoryview_format(ex.format):
994 lst = ex.tolist()
995 else:
996 nd = ndarray(ex, getbuf=PyBUF_FULL_RO)
997 lst = nd.tolist()
998
999 # The consumer may have requested default values or a NULL format.
Serhiy Storchaka3b5342c2018-07-26 17:34:07 +03001000 ro = False if match(req, PyBUF_WRITABLE) else ex.readonly
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001001 fmt = ex.format
1002 itemsize = ex.itemsize
1003 ndim = ex.ndim
1004 if not match(req, PyBUF_FORMAT):
1005 # itemsize refers to the original itemsize before the cast.
1006 # The equality product(shape) * itemsize = len still holds.
1007 # The equality calcsize(format) = itemsize does _not_ hold.
1008 fmt = ''
1009 lst = orig_ex.tobytes() # Issue 12834
1010 if not match(req, PyBUF_ND):
1011 ndim = 1
1012 shape = orig_ex.shape if match(req, PyBUF_ND) else ()
1013 strides = orig_ex.strides if match(req, PyBUF_STRIDES) else ()
1014
1015 nd = ndarray(ex, getbuf=req)
1016 self.verify(nd, obj=ex,
1017 itemsize=itemsize, fmt=fmt, readonly=ro,
1018 ndim=ndim, shape=shape, strides=strides,
1019 lst=lst, sliced=sliced)
1020
1021 def test_ndarray_getbuf(self):
1022 requests = (
1023 # distinct flags
1024 PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE,
1025 PyBUF_C_CONTIGUOUS, PyBUF_F_CONTIGUOUS, PyBUF_ANY_CONTIGUOUS,
1026 # compound requests
1027 PyBUF_FULL, PyBUF_FULL_RO,
1028 PyBUF_RECORDS, PyBUF_RECORDS_RO,
1029 PyBUF_STRIDED, PyBUF_STRIDED_RO,
1030 PyBUF_CONTIG, PyBUF_CONTIG_RO,
1031 )
1032 # items and format
1033 items_fmt = (
1034 ([True if x % 2 else False for x in range(12)], '?'),
1035 ([1,2,3,4,5,6,7,8,9,10,11,12], 'b'),
1036 ([1,2,3,4,5,6,7,8,9,10,11,12], 'B'),
1037 ([(2**31-x) if x % 2 else (-2**31+x) for x in range(12)], 'l')
1038 )
1039 # shape, strides, offset
1040 structure = (
1041 ([], [], 0),
Stefan Krah363af442015-02-01 14:53:54 +01001042 ([1,3,1], [], 0),
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001043 ([12], [], 0),
1044 ([12], [-1], 11),
1045 ([6], [2], 0),
1046 ([6], [-2], 11),
1047 ([3, 4], [], 0),
1048 ([3, 4], [-4, -1], 11),
1049 ([2, 2], [4, 1], 4),
1050 ([2, 2], [-4, -1], 8)
1051 )
1052 # ndarray creation flags
1053 ndflags = (
1054 0, ND_WRITABLE, ND_FORTRAN, ND_FORTRAN|ND_WRITABLE,
1055 ND_PIL, ND_PIL|ND_WRITABLE
1056 )
1057 # flags that can actually be used as flags
1058 real_flags = (0, PyBUF_WRITABLE, PyBUF_FORMAT,
1059 PyBUF_WRITABLE|PyBUF_FORMAT)
1060
1061 for items, fmt in items_fmt:
1062 itemsize = struct.calcsize(fmt)
1063 for shape, strides, offset in structure:
1064 strides = [v * itemsize for v in strides]
1065 offset *= itemsize
1066 for flags in ndflags:
1067
1068 if strides and (flags&ND_FORTRAN):
1069 continue
1070 if not shape and (flags&ND_PIL):
1071 continue
1072
1073 _items = items if shape else items[0]
1074 ex1 = ndarray(_items, format=fmt, flags=flags,
1075 shape=shape, strides=strides, offset=offset)
1076 ex2 = ex1[::-2] if shape else None
1077
1078 m1 = memoryview(ex1)
1079 if ex2:
1080 m2 = memoryview(ex2)
1081 if ex1.ndim == 0 or (ex1.ndim == 1 and shape and strides):
1082 self.assertEqual(m1, ex1)
1083 if ex2 and ex2.ndim == 1 and shape and strides:
1084 self.assertEqual(m2, ex2)
1085
1086 for req in requests:
1087 for bits in real_flags:
1088 self.verify_getbuf(ex1, ex1, req|bits)
1089 self.verify_getbuf(ex1, m1, req|bits)
1090 if ex2:
1091 self.verify_getbuf(ex2, ex2, req|bits,
1092 sliced=True)
1093 self.verify_getbuf(ex2, m2, req|bits,
1094 sliced=True)
1095
1096 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1097
1098 # ND_GETBUF_FAIL
1099 ex = ndarray(items, shape=[12], flags=ND_GETBUF_FAIL)
1100 self.assertRaises(BufferError, ndarray, ex)
1101
1102 # Request complex structure from a simple exporter. In this
1103 # particular case the test object is not PEP-3118 compliant.
1104 base = ndarray([9], [1])
1105 ex = ndarray(base, getbuf=PyBUF_SIMPLE)
1106 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_WRITABLE)
1107 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ND)
1108 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_STRIDES)
1109 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_C_CONTIGUOUS)
1110 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_F_CONTIGUOUS)
1111 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ANY_CONTIGUOUS)
1112 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1113
Stefan Krah363af442015-02-01 14:53:54 +01001114 # Issue #22445: New precise contiguity definition.
1115 for shape in [1,12,1], [7,0,7]:
1116 for order in 0, ND_FORTRAN:
1117 ex = ndarray(items, shape=shape, flags=order|ND_WRITABLE)
1118 self.assertTrue(is_contiguous(ex, 'F'))
1119 self.assertTrue(is_contiguous(ex, 'C'))
1120
1121 for flags in requests:
1122 nd = ndarray(ex, getbuf=flags)
1123 self.assertTrue(is_contiguous(nd, 'F'))
1124 self.assertTrue(is_contiguous(nd, 'C'))
1125
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001126 def test_ndarray_exceptions(self):
1127 nd = ndarray([9], [1])
1128 ndm = ndarray([9], [1], flags=ND_VAREXPORT)
1129
1130 # Initialization of a new ndarray or mutation of an existing array.
1131 for c in (ndarray, nd.push, ndm.push):
1132 # Invalid types.
1133 self.assertRaises(TypeError, c, {1,2,3})
1134 self.assertRaises(TypeError, c, [1,2,'3'])
1135 self.assertRaises(TypeError, c, [1,2,(3,4)])
1136 self.assertRaises(TypeError, c, [1,2,3], shape={3})
1137 self.assertRaises(TypeError, c, [1,2,3], shape=[3], strides={1})
1138 self.assertRaises(TypeError, c, [1,2,3], shape=[3], offset=[])
1139 self.assertRaises(TypeError, c, [1], shape=[1], format={})
1140 self.assertRaises(TypeError, c, [1], shape=[1], flags={})
1141 self.assertRaises(TypeError, c, [1], shape=[1], getbuf={})
1142
1143 # ND_FORTRAN flag is only valid without strides.
1144 self.assertRaises(TypeError, c, [1], shape=[1], strides=[1],
1145 flags=ND_FORTRAN)
1146
1147 # ND_PIL flag is only valid with ndim > 0.
1148 self.assertRaises(TypeError, c, [1], shape=[], flags=ND_PIL)
1149
1150 # Invalid items.
1151 self.assertRaises(ValueError, c, [], shape=[1])
1152 self.assertRaises(ValueError, c, ['XXX'], shape=[1], format="L")
1153 # Invalid combination of items and format.
1154 self.assertRaises(struct.error, c, [1000], shape=[1], format="B")
1155 self.assertRaises(ValueError, c, [1,(2,3)], shape=[2], format="B")
1156 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="QL")
1157
1158 # Invalid ndim.
1159 n = ND_MAX_NDIM+1
1160 self.assertRaises(ValueError, c, [1]*n, shape=[1]*n)
1161
1162 # Invalid shape.
1163 self.assertRaises(ValueError, c, [1], shape=[-1])
1164 self.assertRaises(ValueError, c, [1,2,3], shape=['3'])
1165 self.assertRaises(OverflowError, c, [1], shape=[2**128])
1166 # prod(shape) * itemsize != len(items)
1167 self.assertRaises(ValueError, c, [1,2,3,4,5], shape=[2,2], offset=3)
1168
1169 # Invalid strides.
1170 self.assertRaises(ValueError, c, [1,2,3], shape=[3], strides=['1'])
1171 self.assertRaises(OverflowError, c, [1], shape=[1],
1172 strides=[2**128])
1173
1174 # Invalid combination of strides and shape.
1175 self.assertRaises(ValueError, c, [1,2], shape=[2,1], strides=[1])
1176 # Invalid combination of strides and format.
1177 self.assertRaises(ValueError, c, [1,2,3,4], shape=[2], strides=[3],
1178 format="L")
1179
1180 # Invalid offset.
1181 self.assertRaises(ValueError, c, [1,2,3], shape=[3], offset=4)
1182 self.assertRaises(ValueError, c, [1,2,3], shape=[1], offset=3,
1183 format="L")
1184
1185 # Invalid format.
1186 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="")
1187 self.assertRaises(struct.error, c, [(1,2,3)], shape=[1],
1188 format="@#$")
1189
1190 # Striding out of the memory bounds.
1191 items = [1,2,3,4,5,6,7,8,9,10]
1192 self.assertRaises(ValueError, c, items, shape=[2,3],
1193 strides=[-3, -2], offset=5)
1194
1195 # Constructing consumer: format argument invalid.
1196 self.assertRaises(TypeError, c, bytearray(), format="Q")
1197
1198 # Constructing original base object: getbuf argument invalid.
1199 self.assertRaises(TypeError, c, [1], shape=[1], getbuf=PyBUF_FULL)
1200
1201 # Shape argument is mandatory for original base objects.
1202 self.assertRaises(TypeError, c, [1])
1203
1204
1205 # PyBUF_WRITABLE request to read-only provider.
1206 self.assertRaises(BufferError, ndarray, b'123', getbuf=PyBUF_WRITABLE)
1207
1208 # ND_VAREXPORT can only be specified during construction.
1209 nd = ndarray([9], [1], flags=ND_VAREXPORT)
1210 self.assertRaises(ValueError, nd.push, [1], [1], flags=ND_VAREXPORT)
1211
1212 # Invalid operation for consumers: push/pop
1213 nd = ndarray(b'123')
1214 self.assertRaises(BufferError, nd.push, [1], [1])
1215 self.assertRaises(BufferError, nd.pop)
1216
1217 # ND_VAREXPORT not set: push/pop fail with exported buffers
1218 nd = ndarray([9], [1])
1219 nd.push([1], [1])
1220 m = memoryview(nd)
1221 self.assertRaises(BufferError, nd.push, [1], [1])
1222 self.assertRaises(BufferError, nd.pop)
1223 m.release()
1224 nd.pop()
1225
1226 # Single remaining buffer: pop fails
1227 self.assertRaises(BufferError, nd.pop)
1228 del nd
1229
1230 # get_pointer()
1231 self.assertRaises(TypeError, get_pointer, {}, [1,2,3])
1232 self.assertRaises(TypeError, get_pointer, b'123', {})
1233
1234 nd = ndarray(list(range(100)), shape=[1]*100)
1235 self.assertRaises(ValueError, get_pointer, nd, [5])
1236
1237 nd = ndarray(list(range(12)), shape=[3,4])
1238 self.assertRaises(ValueError, get_pointer, nd, [2,3,4])
1239 self.assertRaises(ValueError, get_pointer, nd, [3,3])
1240 self.assertRaises(ValueError, get_pointer, nd, [-3,3])
1241 self.assertRaises(OverflowError, get_pointer, nd, [1<<64,3])
1242
1243 # tolist() needs format
1244 ex = ndarray([1,2,3], shape=[3], format='L')
1245 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1246 self.assertRaises(ValueError, nd.tolist)
1247
1248 # memoryview_from_buffer()
1249 ex1 = ndarray([1,2,3], shape=[3], format='L')
1250 ex2 = ndarray(ex1)
1251 nd = ndarray(ex2)
1252 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1253
1254 nd = ndarray([(1,)*200], shape=[1], format='L'*200)
1255 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1256
1257 n = ND_MAX_NDIM
1258 nd = ndarray(list(range(n)), shape=[1]*n)
1259 self.assertRaises(ValueError, nd.memoryview_from_buffer)
1260
1261 # get_contiguous()
1262 nd = ndarray([1], shape=[1])
1263 self.assertRaises(TypeError, get_contiguous, 1, 2, 3, 4, 5)
1264 self.assertRaises(TypeError, get_contiguous, nd, "xyz", 'C')
1265 self.assertRaises(OverflowError, get_contiguous, nd, 2**64, 'C')
1266 self.assertRaises(TypeError, get_contiguous, nd, PyBUF_READ, 961)
1267 self.assertRaises(UnicodeEncodeError, get_contiguous, nd, PyBUF_READ,
1268 '\u2007')
Stefan Krah66e63172012-08-23 15:53:45 +02001269 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'Z')
1270 self.assertRaises(ValueError, get_contiguous, nd, 255, 'A')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001271
1272 # cmp_contig()
1273 nd = ndarray([1], shape=[1])
1274 self.assertRaises(TypeError, cmp_contig, 1, 2, 3, 4, 5)
1275 self.assertRaises(TypeError, cmp_contig, {}, nd)
1276 self.assertRaises(TypeError, cmp_contig, nd, {})
1277
1278 # is_contiguous()
1279 nd = ndarray([1], shape=[1])
1280 self.assertRaises(TypeError, is_contiguous, 1, 2, 3, 4, 5)
1281 self.assertRaises(TypeError, is_contiguous, {}, 'A')
1282 self.assertRaises(TypeError, is_contiguous, nd, 201)
1283
1284 def test_ndarray_linked_list(self):
1285 for perm in permutations(range(5)):
1286 m = [0]*5
1287 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
1288 m[0] = memoryview(nd)
1289
1290 for i in range(1, 5):
1291 nd.push([1,2,3], shape=[3])
1292 m[i] = memoryview(nd)
1293
1294 for i in range(5):
1295 m[perm[i]].release()
1296
1297 self.assertRaises(BufferError, nd.pop)
1298 del nd
1299
1300 def test_ndarray_format_scalar(self):
1301 # ndim = 0: scalar
1302 for fmt, scalar, _ in iter_format(0):
1303 itemsize = struct.calcsize(fmt)
1304 nd = ndarray(scalar, shape=(), format=fmt)
1305 self.verify(nd, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001306 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001307 ndim=0, shape=(), strides=(),
1308 lst=scalar)
1309
1310 def test_ndarray_format_shape(self):
1311 # ndim = 1, shape = [n]
1312 nitems = randrange(1, 10)
1313 for fmt, items, _ in iter_format(nitems):
1314 itemsize = struct.calcsize(fmt)
1315 for flags in (0, ND_PIL):
1316 nd = ndarray(items, shape=[nitems], format=fmt, flags=flags)
1317 self.verify(nd, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001318 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001319 ndim=1, shape=(nitems,), strides=(itemsize,),
1320 lst=items)
1321
1322 def test_ndarray_format_strides(self):
1323 # ndim = 1, strides
1324 nitems = randrange(1, 30)
1325 for fmt, items, _ in iter_format(nitems):
1326 itemsize = struct.calcsize(fmt)
1327 for step in range(-5, 5):
1328 if step == 0:
1329 continue
1330
1331 shape = [len(items[::step])]
1332 strides = [step*itemsize]
1333 offset = itemsize*(nitems-1) if step < 0 else 0
1334
1335 for flags in (0, ND_PIL):
1336 nd = ndarray(items, shape=shape, strides=strides,
1337 format=fmt, offset=offset, flags=flags)
1338 self.verify(nd, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001339 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001340 ndim=1, shape=shape, strides=strides,
1341 lst=items[::step])
1342
1343 def test_ndarray_fortran(self):
1344 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1345 ex = ndarray(items, shape=(3, 4), strides=(1, 3))
1346 nd = ndarray(ex, getbuf=PyBUF_F_CONTIGUOUS|PyBUF_FORMAT)
1347 self.assertEqual(nd.tolist(), farray(items, (3, 4)))
1348
1349 def test_ndarray_multidim(self):
1350 for ndim in range(5):
1351 shape_t = [randrange(2, 10) for _ in range(ndim)]
1352 nitems = prod(shape_t)
1353 for shape in permutations(shape_t):
1354
1355 fmt, items, _ = randitems(nitems)
1356 itemsize = struct.calcsize(fmt)
1357
1358 for flags in (0, ND_PIL):
1359 if ndim == 0 and flags == ND_PIL:
1360 continue
1361
1362 # C array
1363 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1364
1365 strides = strides_from_shape(ndim, shape, itemsize, 'C')
1366 lst = carray(items, shape)
1367 self.verify(nd, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001368 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001369 ndim=ndim, shape=shape, strides=strides,
1370 lst=lst)
1371
1372 if is_memoryview_format(fmt):
1373 # memoryview: reconstruct strides
1374 ex = ndarray(items, shape=shape, format=fmt)
1375 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
1376 self.assertTrue(nd.strides == ())
1377 mv = nd.memoryview_from_buffer()
1378 self.verify(mv, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001379 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001380 ndim=ndim, shape=shape, strides=strides,
1381 lst=lst)
1382
1383 # Fortran array
1384 nd = ndarray(items, shape=shape, format=fmt,
1385 flags=flags|ND_FORTRAN)
1386
1387 strides = strides_from_shape(ndim, shape, itemsize, 'F')
1388 lst = farray(items, shape)
1389 self.verify(nd, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001390 itemsize=itemsize, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001391 ndim=ndim, shape=shape, strides=strides,
1392 lst=lst)
1393
1394 def test_ndarray_index_invalid(self):
1395 # not writable
1396 nd = ndarray([1], shape=[1])
1397 self.assertRaises(TypeError, nd.__setitem__, 1, 8)
1398 mv = memoryview(nd)
1399 self.assertEqual(mv, nd)
1400 self.assertRaises(TypeError, mv.__setitem__, 1, 8)
1401
1402 # cannot be deleted
1403 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1404 self.assertRaises(TypeError, nd.__delitem__, 1)
1405 mv = memoryview(nd)
1406 self.assertEqual(mv, nd)
1407 self.assertRaises(TypeError, mv.__delitem__, 1)
1408
1409 # overflow
1410 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1411 self.assertRaises(OverflowError, nd.__getitem__, 1<<64)
1412 self.assertRaises(OverflowError, nd.__setitem__, 1<<64, 8)
1413 mv = memoryview(nd)
1414 self.assertEqual(mv, nd)
1415 self.assertRaises(IndexError, mv.__getitem__, 1<<64)
1416 self.assertRaises(IndexError, mv.__setitem__, 1<<64, 8)
1417
1418 # format
1419 items = [1,2,3,4,5,6,7,8]
1420 nd = ndarray(items, shape=[len(items)], format="B", flags=ND_WRITABLE)
1421 self.assertRaises(struct.error, nd.__setitem__, 2, 300)
1422 self.assertRaises(ValueError, nd.__setitem__, 1, (100, 200))
1423 mv = memoryview(nd)
1424 self.assertEqual(mv, nd)
1425 self.assertRaises(ValueError, mv.__setitem__, 2, 300)
1426 self.assertRaises(TypeError, mv.__setitem__, 1, (100, 200))
1427
1428 items = [(1,2), (3,4), (5,6)]
1429 nd = ndarray(items, shape=[len(items)], format="LQ", flags=ND_WRITABLE)
1430 self.assertRaises(ValueError, nd.__setitem__, 2, 300)
1431 self.assertRaises(struct.error, nd.__setitem__, 1, (b'\x001', 200))
1432
1433 def test_ndarray_index_scalar(self):
1434 # scalar
1435 nd = ndarray(1, shape=(), flags=ND_WRITABLE)
1436 mv = memoryview(nd)
1437 self.assertEqual(mv, nd)
1438
1439 x = nd[()]; self.assertEqual(x, 1)
1440 x = nd[...]; self.assertEqual(x.tolist(), nd.tolist())
1441
1442 x = mv[()]; self.assertEqual(x, 1)
1443 x = mv[...]; self.assertEqual(x.tolist(), nd.tolist())
1444
1445 self.assertRaises(TypeError, nd.__getitem__, 0)
1446 self.assertRaises(TypeError, mv.__getitem__, 0)
1447 self.assertRaises(TypeError, nd.__setitem__, 0, 8)
1448 self.assertRaises(TypeError, mv.__setitem__, 0, 8)
1449
1450 self.assertEqual(nd.tolist(), 1)
1451 self.assertEqual(mv.tolist(), 1)
1452
1453 nd[()] = 9; self.assertEqual(nd.tolist(), 9)
1454 mv[()] = 9; self.assertEqual(mv.tolist(), 9)
1455
1456 nd[...] = 5; self.assertEqual(nd.tolist(), 5)
1457 mv[...] = 5; self.assertEqual(mv.tolist(), 5)
1458
1459 def test_ndarray_index_null_strides(self):
1460 ex = ndarray(list(range(2*4)), shape=[2, 4], flags=ND_WRITABLE)
1461 nd = ndarray(ex, getbuf=PyBUF_CONTIG)
1462
1463 # Sub-views are only possible for full exporters.
1464 self.assertRaises(BufferError, nd.__getitem__, 1)
1465 # Same for slices.
1466 self.assertRaises(BufferError, nd.__getitem__, slice(3,5,1))
1467
1468 def test_ndarray_index_getitem_single(self):
1469 # getitem
1470 for fmt, items, _ in iter_format(5):
1471 nd = ndarray(items, shape=[5], format=fmt)
1472 for i in range(-5, 5):
1473 self.assertEqual(nd[i], items[i])
1474
1475 self.assertRaises(IndexError, nd.__getitem__, -6)
1476 self.assertRaises(IndexError, nd.__getitem__, 5)
1477
1478 if is_memoryview_format(fmt):
1479 mv = memoryview(nd)
1480 self.assertEqual(mv, nd)
1481 for i in range(-5, 5):
1482 self.assertEqual(mv[i], items[i])
1483
1484 self.assertRaises(IndexError, mv.__getitem__, -6)
1485 self.assertRaises(IndexError, mv.__getitem__, 5)
1486
1487 # getitem with null strides
1488 for fmt, items, _ in iter_format(5):
1489 ex = ndarray(items, shape=[5], flags=ND_WRITABLE, format=fmt)
1490 nd = ndarray(ex, getbuf=PyBUF_CONTIG|PyBUF_FORMAT)
1491
1492 for i in range(-5, 5):
1493 self.assertEqual(nd[i], items[i])
1494
1495 if is_memoryview_format(fmt):
1496 mv = nd.memoryview_from_buffer()
1497 self.assertIs(mv.__eq__(nd), NotImplemented)
1498 for i in range(-5, 5):
1499 self.assertEqual(mv[i], items[i])
1500
1501 # getitem with null format
1502 items = [1,2,3,4,5]
1503 ex = ndarray(items, shape=[5])
1504 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO)
1505 for i in range(-5, 5):
1506 self.assertEqual(nd[i], items[i])
1507
1508 # getitem with null shape/strides/format
1509 items = [1,2,3,4,5]
1510 ex = ndarray(items, shape=[5])
1511 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1512
1513 for i in range(-5, 5):
1514 self.assertEqual(nd[i], items[i])
1515
1516 def test_ndarray_index_setitem_single(self):
1517 # assign single value
1518 for fmt, items, single_item in iter_format(5):
1519 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1520 for i in range(5):
1521 items[i] = single_item
1522 nd[i] = single_item
1523 self.assertEqual(nd.tolist(), items)
1524
1525 self.assertRaises(IndexError, nd.__setitem__, -6, single_item)
1526 self.assertRaises(IndexError, nd.__setitem__, 5, single_item)
1527
1528 if not is_memoryview_format(fmt):
1529 continue
1530
1531 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1532 mv = memoryview(nd)
1533 self.assertEqual(mv, nd)
1534 for i in range(5):
1535 items[i] = single_item
1536 mv[i] = single_item
1537 self.assertEqual(mv.tolist(), items)
1538
1539 self.assertRaises(IndexError, mv.__setitem__, -6, single_item)
1540 self.assertRaises(IndexError, mv.__setitem__, 5, single_item)
1541
1542
1543 # assign single value: lobject = robject
1544 for fmt, items, single_item in iter_format(5):
1545 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1546 for i in range(-5, 4):
1547 items[i] = items[i+1]
1548 nd[i] = nd[i+1]
1549 self.assertEqual(nd.tolist(), items)
1550
1551 if not is_memoryview_format(fmt):
1552 continue
1553
1554 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1555 mv = memoryview(nd)
1556 self.assertEqual(mv, nd)
1557 for i in range(-5, 4):
1558 items[i] = items[i+1]
1559 mv[i] = mv[i+1]
1560 self.assertEqual(mv.tolist(), items)
1561
1562 def test_ndarray_index_getitem_multidim(self):
1563 shape_t = (2, 3, 5)
1564 nitems = prod(shape_t)
1565 for shape in permutations(shape_t):
1566
1567 fmt, items, _ = randitems(nitems)
1568
1569 for flags in (0, ND_PIL):
1570 # C array
1571 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1572 lst = carray(items, shape)
1573
1574 for i in range(-shape[0], shape[0]):
1575 self.assertEqual(lst[i], nd[i].tolist())
1576 for j in range(-shape[1], shape[1]):
1577 self.assertEqual(lst[i][j], nd[i][j].tolist())
1578 for k in range(-shape[2], shape[2]):
1579 self.assertEqual(lst[i][j][k], nd[i][j][k])
1580
1581 # Fortran array
1582 nd = ndarray(items, shape=shape, format=fmt,
1583 flags=flags|ND_FORTRAN)
1584 lst = farray(items, shape)
1585
1586 for i in range(-shape[0], shape[0]):
1587 self.assertEqual(lst[i], nd[i].tolist())
1588 for j in range(-shape[1], shape[1]):
1589 self.assertEqual(lst[i][j], nd[i][j].tolist())
1590 for k in range(shape[2], shape[2]):
1591 self.assertEqual(lst[i][j][k], nd[i][j][k])
1592
1593 def test_ndarray_sequence(self):
1594 nd = ndarray(1, shape=())
1595 self.assertRaises(TypeError, eval, "1 in nd", locals())
1596 mv = memoryview(nd)
1597 self.assertEqual(mv, nd)
1598 self.assertRaises(TypeError, eval, "1 in mv", locals())
1599
1600 for fmt, items, _ in iter_format(5):
1601 nd = ndarray(items, shape=[5], format=fmt)
1602 for i, v in enumerate(nd):
1603 self.assertEqual(v, items[i])
1604 self.assertTrue(v in nd)
1605
1606 if is_memoryview_format(fmt):
1607 mv = memoryview(nd)
1608 for i, v in enumerate(mv):
1609 self.assertEqual(v, items[i])
1610 self.assertTrue(v in mv)
1611
1612 def test_ndarray_slice_invalid(self):
1613 items = [1,2,3,4,5,6,7,8]
1614
1615 # rvalue is not an exporter
1616 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1617 ml = memoryview(xl)
1618 self.assertRaises(TypeError, xl.__setitem__, slice(0,8,1), items)
1619 self.assertRaises(TypeError, ml.__setitem__, slice(0,8,1), items)
1620
1621 # rvalue is not a full exporter
1622 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1623 ex = ndarray(items, shape=[8], flags=ND_WRITABLE)
1624 xr = ndarray(ex, getbuf=PyBUF_ND)
1625 self.assertRaises(BufferError, xl.__setitem__, slice(0,8,1), xr)
1626
1627 # zero step
1628 nd = ndarray(items, shape=[8], format="L", flags=ND_WRITABLE)
1629 mv = memoryview(nd)
1630 self.assertRaises(ValueError, nd.__getitem__, slice(0,1,0))
1631 self.assertRaises(ValueError, mv.__getitem__, slice(0,1,0))
1632
1633 nd = ndarray(items, shape=[2,4], format="L", flags=ND_WRITABLE)
1634 mv = memoryview(nd)
1635
1636 self.assertRaises(ValueError, nd.__getitem__,
1637 (slice(0,1,1), slice(0,1,0)))
1638 self.assertRaises(ValueError, nd.__getitem__,
1639 (slice(0,1,0), slice(0,1,1)))
1640 self.assertRaises(TypeError, nd.__getitem__, "@%$")
1641 self.assertRaises(TypeError, nd.__getitem__, ("@%$", slice(0,1,1)))
1642 self.assertRaises(TypeError, nd.__getitem__, (slice(0,1,1), {}))
1643
1644 # memoryview: not implemented
1645 self.assertRaises(NotImplementedError, mv.__getitem__,
1646 (slice(0,1,1), slice(0,1,0)))
1647 self.assertRaises(TypeError, mv.__getitem__, "@%$")
1648
1649 # differing format
1650 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1651 xr = ndarray(items, shape=[8], format="b")
1652 ml = memoryview(xl)
1653 mr = memoryview(xr)
1654 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1655 self.assertEqual(xl.tolist(), items)
1656 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1657 self.assertEqual(ml.tolist(), items)
1658
1659 # differing itemsize
1660 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1661 yr = ndarray(items, shape=[8], format="L")
1662 ml = memoryview(xl)
1663 mr = memoryview(xr)
1664 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1665 self.assertEqual(xl.tolist(), items)
1666 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1667 self.assertEqual(ml.tolist(), items)
1668
1669 # differing ndim
1670 xl = ndarray(items, shape=[2, 4], format="b", flags=ND_WRITABLE)
1671 xr = ndarray(items, shape=[8], format="b")
1672 ml = memoryview(xl)
1673 mr = memoryview(xr)
1674 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1675 self.assertEqual(xl.tolist(), [[1,2,3,4], [5,6,7,8]])
1676 self.assertRaises(NotImplementedError, ml.__setitem__, slice(0,1,1),
1677 mr[7:8])
1678
1679 # differing shape
1680 xl = ndarray(items, shape=[8], format="b", flags=ND_WRITABLE)
1681 xr = ndarray(items, shape=[8], format="b")
1682 ml = memoryview(xl)
1683 mr = memoryview(xr)
1684 self.assertRaises(ValueError, xl.__setitem__, slice(0,2,1), xr[7:8])
1685 self.assertEqual(xl.tolist(), items)
1686 self.assertRaises(ValueError, ml.__setitem__, slice(0,2,1), mr[7:8])
1687 self.assertEqual(ml.tolist(), items)
1688
1689 # _testbuffer.c module functions
1690 self.assertRaises(TypeError, slice_indices, slice(0,1,2), {})
1691 self.assertRaises(TypeError, slice_indices, "###########", 1)
1692 self.assertRaises(ValueError, slice_indices, slice(0,1,0), 4)
1693
1694 x = ndarray(items, shape=[8], format="b", flags=ND_PIL)
1695 self.assertRaises(TypeError, x.add_suboffsets)
1696
1697 ex = ndarray(items, shape=[8], format="B")
1698 x = ndarray(ex, getbuf=PyBUF_SIMPLE)
1699 self.assertRaises(TypeError, x.add_suboffsets)
1700
1701 def test_ndarray_slice_zero_shape(self):
1702 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1703
1704 x = ndarray(items, shape=[12], format="L", flags=ND_WRITABLE)
1705 y = ndarray(items, shape=[12], format="L")
1706 x[4:4] = y[9:9]
1707 self.assertEqual(x.tolist(), items)
1708
1709 ml = memoryview(x)
1710 mr = memoryview(y)
1711 self.assertEqual(ml, x)
1712 self.assertEqual(ml, y)
1713 ml[4:4] = mr[9:9]
1714 self.assertEqual(ml.tolist(), items)
1715
1716 x = ndarray(items, shape=[3, 4], format="L", flags=ND_WRITABLE)
1717 y = ndarray(items, shape=[4, 3], format="L")
1718 x[1:2, 2:2] = y[1:2, 3:3]
1719 self.assertEqual(x.tolist(), carray(items, [3, 4]))
1720
1721 def test_ndarray_slice_multidim(self):
1722 shape_t = (2, 3, 5)
1723 ndim = len(shape_t)
1724 nitems = prod(shape_t)
1725 for shape in permutations(shape_t):
1726
1727 fmt, items, _ = randitems(nitems)
1728 itemsize = struct.calcsize(fmt)
1729
1730 for flags in (0, ND_PIL):
1731 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1732 lst = carray(items, shape)
1733
1734 for slices in rslices_ndim(ndim, shape):
1735
1736 listerr = None
1737 try:
1738 sliced = multislice(lst, slices)
1739 except Exception as e:
1740 listerr = e.__class__
1741
1742 nderr = None
1743 try:
1744 ndsliced = nd[slices]
1745 except Exception as e:
1746 nderr = e.__class__
1747
1748 if nderr or listerr:
1749 self.assertIs(nderr, listerr)
1750 else:
1751 self.assertEqual(ndsliced.tolist(), sliced)
1752
1753 def test_ndarray_slice_redundant_suboffsets(self):
1754 shape_t = (2, 3, 5, 2)
1755 ndim = len(shape_t)
1756 nitems = prod(shape_t)
1757 for shape in permutations(shape_t):
1758
1759 fmt, items, _ = randitems(nitems)
1760 itemsize = struct.calcsize(fmt)
1761
1762 nd = ndarray(items, shape=shape, format=fmt)
1763 nd.add_suboffsets()
1764 ex = ndarray(items, shape=shape, format=fmt)
1765 ex.add_suboffsets()
1766 mv = memoryview(ex)
1767 lst = carray(items, shape)
1768
1769 for slices in rslices_ndim(ndim, shape):
1770
1771 listerr = None
1772 try:
1773 sliced = multislice(lst, slices)
1774 except Exception as e:
1775 listerr = e.__class__
1776
1777 nderr = None
1778 try:
1779 ndsliced = nd[slices]
1780 except Exception as e:
1781 nderr = e.__class__
1782
1783 if nderr or listerr:
1784 self.assertIs(nderr, listerr)
1785 else:
1786 self.assertEqual(ndsliced.tolist(), sliced)
1787
1788 def test_ndarray_slice_assign_single(self):
1789 for fmt, items, _ in iter_format(5):
1790 for lslice in genslices(5):
1791 for rslice in genslices(5):
1792 for flags in (0, ND_PIL):
1793
1794 f = flags|ND_WRITABLE
1795 nd = ndarray(items, shape=[5], format=fmt, flags=f)
1796 ex = ndarray(items, shape=[5], format=fmt, flags=f)
1797 mv = memoryview(ex)
1798
1799 lsterr = None
1800 diff_structure = None
1801 lst = items[:]
1802 try:
1803 lval = lst[lslice]
1804 rval = lst[rslice]
1805 lst[lslice] = lst[rslice]
1806 diff_structure = len(lval) != len(rval)
1807 except Exception as e:
1808 lsterr = e.__class__
1809
1810 nderr = None
1811 try:
1812 nd[lslice] = nd[rslice]
1813 except Exception as e:
1814 nderr = e.__class__
1815
1816 if diff_structure: # ndarray cannot change shape
1817 self.assertIs(nderr, ValueError)
1818 else:
1819 self.assertEqual(nd.tolist(), lst)
1820 self.assertIs(nderr, lsterr)
1821
1822 if not is_memoryview_format(fmt):
1823 continue
1824
1825 mverr = None
1826 try:
1827 mv[lslice] = mv[rslice]
1828 except Exception as e:
1829 mverr = e.__class__
1830
1831 if diff_structure: # memoryview cannot change shape
1832 self.assertIs(mverr, ValueError)
1833 else:
1834 self.assertEqual(mv.tolist(), lst)
1835 self.assertEqual(mv, nd)
1836 self.assertIs(mverr, lsterr)
1837 self.verify(mv, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001838 itemsize=nd.itemsize, fmt=fmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001839 ndim=nd.ndim, shape=nd.shape, strides=nd.strides,
1840 lst=nd.tolist())
1841
1842 def test_ndarray_slice_assign_multidim(self):
1843 shape_t = (2, 3, 5)
1844 ndim = len(shape_t)
1845 nitems = prod(shape_t)
1846 for shape in permutations(shape_t):
1847
1848 fmt, items, _ = randitems(nitems)
1849
1850 for flags in (0, ND_PIL):
1851 for _ in range(ITERATIONS):
1852 lslices, rslices = randslice_from_shape(ndim, shape)
1853
1854 nd = ndarray(items, shape=shape, format=fmt,
1855 flags=flags|ND_WRITABLE)
1856 lst = carray(items, shape)
1857
1858 listerr = None
1859 try:
1860 result = multislice_assign(lst, lst, lslices, rslices)
1861 except Exception as e:
1862 listerr = e.__class__
1863
1864 nderr = None
1865 try:
1866 nd[lslices] = nd[rslices]
1867 except Exception as e:
1868 nderr = e.__class__
1869
1870 if nderr or listerr:
1871 self.assertIs(nderr, listerr)
1872 else:
1873 self.assertEqual(nd.tolist(), result)
1874
1875 def test_ndarray_random(self):
1876 # construction of valid arrays
1877 for _ in range(ITERATIONS):
1878 for fmt in fmtdict['@']:
1879 itemsize = struct.calcsize(fmt)
1880
1881 t = rand_structure(itemsize, True, maxdim=MAXDIM,
1882 maxshape=MAXSHAPE)
1883 self.assertTrue(verify_structure(*t))
1884 items = randitems_from_structure(fmt, t)
1885
1886 x = ndarray_from_structure(items, fmt, t)
1887 xlist = x.tolist()
1888
1889 mv = memoryview(x)
1890 if is_memoryview_format(fmt):
1891 mvlist = mv.tolist()
1892 self.assertEqual(mvlist, xlist)
1893
1894 if t[2] > 0:
1895 # ndim > 0: test against suboffsets representation.
1896 y = ndarray_from_structure(items, fmt, t, flags=ND_PIL)
1897 ylist = y.tolist()
1898 self.assertEqual(xlist, ylist)
1899
1900 mv = memoryview(y)
1901 if is_memoryview_format(fmt):
1902 self.assertEqual(mv, y)
1903 mvlist = mv.tolist()
1904 self.assertEqual(mvlist, ylist)
1905
1906 if numpy_array:
1907 shape = t[3]
1908 if 0 in shape:
1909 continue # http://projects.scipy.org/numpy/ticket/1910
1910 z = numpy_array_from_structure(items, fmt, t)
1911 self.verify(x, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001912 itemsize=z.itemsize, fmt=fmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001913 ndim=z.ndim, shape=z.shape, strides=z.strides,
1914 lst=z.tolist())
1915
1916 def test_ndarray_random_invalid(self):
1917 # exceptions during construction of invalid arrays
1918 for _ in range(ITERATIONS):
1919 for fmt in fmtdict['@']:
1920 itemsize = struct.calcsize(fmt)
1921
1922 t = rand_structure(itemsize, False, maxdim=MAXDIM,
1923 maxshape=MAXSHAPE)
1924 self.assertFalse(verify_structure(*t))
1925 items = randitems_from_structure(fmt, t)
1926
1927 nderr = False
1928 try:
1929 x = ndarray_from_structure(items, fmt, t)
1930 except Exception as e:
1931 nderr = e.__class__
1932 self.assertTrue(nderr)
1933
1934 if numpy_array:
1935 numpy_err = False
1936 try:
1937 y = numpy_array_from_structure(items, fmt, t)
1938 except Exception as e:
1939 numpy_err = e.__class__
1940
1941 if 0: # http://projects.scipy.org/numpy/ticket/1910
1942 self.assertTrue(numpy_err)
1943
1944 def test_ndarray_random_slice_assign(self):
1945 # valid slice assignments
1946 for _ in range(ITERATIONS):
1947 for fmt in fmtdict['@']:
1948 itemsize = struct.calcsize(fmt)
1949
1950 lshape, rshape, lslices, rslices = \
1951 rand_aligned_slices(maxdim=MAXDIM, maxshape=MAXSHAPE)
1952 tl = rand_structure(itemsize, True, shape=lshape)
1953 tr = rand_structure(itemsize, True, shape=rshape)
1954 self.assertTrue(verify_structure(*tl))
1955 self.assertTrue(verify_structure(*tr))
1956 litems = randitems_from_structure(fmt, tl)
1957 ritems = randitems_from_structure(fmt, tr)
1958
1959 xl = ndarray_from_structure(litems, fmt, tl)
1960 xr = ndarray_from_structure(ritems, fmt, tr)
1961 xl[lslices] = xr[rslices]
1962 xllist = xl.tolist()
1963 xrlist = xr.tolist()
1964
1965 ml = memoryview(xl)
1966 mr = memoryview(xr)
1967 self.assertEqual(ml.tolist(), xllist)
1968 self.assertEqual(mr.tolist(), xrlist)
1969
1970 if tl[2] > 0 and tr[2] > 0:
1971 # ndim > 0: test against suboffsets representation.
1972 yl = ndarray_from_structure(litems, fmt, tl, flags=ND_PIL)
1973 yr = ndarray_from_structure(ritems, fmt, tr, flags=ND_PIL)
1974 yl[lslices] = yr[rslices]
1975 yllist = yl.tolist()
1976 yrlist = yr.tolist()
1977 self.assertEqual(xllist, yllist)
1978 self.assertEqual(xrlist, yrlist)
1979
1980 ml = memoryview(yl)
1981 mr = memoryview(yr)
1982 self.assertEqual(ml.tolist(), yllist)
1983 self.assertEqual(mr.tolist(), yrlist)
1984
1985 if numpy_array:
1986 if 0 in lshape or 0 in rshape:
1987 continue # http://projects.scipy.org/numpy/ticket/1910
1988
1989 zl = numpy_array_from_structure(litems, fmt, tl)
1990 zr = numpy_array_from_structure(ritems, fmt, tr)
1991 zl[lslices] = zr[rslices]
1992
1993 if not is_overlapping(tl) and not is_overlapping(tr):
1994 # Slice assignment of overlapping structures
1995 # is undefined in NumPy.
1996 self.verify(xl, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03001997 itemsize=zl.itemsize, fmt=fmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001998 ndim=zl.ndim, shape=zl.shape,
1999 strides=zl.strides, lst=zl.tolist())
2000
2001 self.verify(xr, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002002 itemsize=zr.itemsize, fmt=fmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002003 ndim=zr.ndim, shape=zr.shape,
2004 strides=zr.strides, lst=zr.tolist())
2005
2006 def test_ndarray_re_export(self):
2007 items = [1,2,3,4,5,6,7,8,9,10,11,12]
2008
2009 nd = ndarray(items, shape=[3,4], flags=ND_PIL)
2010 ex = ndarray(nd)
2011
2012 self.assertTrue(ex.flags & ND_PIL)
2013 self.assertIs(ex.obj, nd)
2014 self.assertEqual(ex.suboffsets, (0, -1))
2015 self.assertFalse(ex.c_contiguous)
2016 self.assertFalse(ex.f_contiguous)
2017 self.assertFalse(ex.contiguous)
2018
2019 def test_ndarray_zero_shape(self):
2020 # zeros in shape
2021 for flags in (0, ND_PIL):
2022 nd = ndarray([1,2,3], shape=[0], flags=flags)
2023 mv = memoryview(nd)
2024 self.assertEqual(mv, nd)
2025 self.assertEqual(nd.tolist(), [])
2026 self.assertEqual(mv.tolist(), [])
2027
2028 nd = ndarray([1,2,3], shape=[0,3,3], flags=flags)
2029 self.assertEqual(nd.tolist(), [])
2030
2031 nd = ndarray([1,2,3], shape=[3,0,3], flags=flags)
2032 self.assertEqual(nd.tolist(), [[], [], []])
2033
2034 nd = ndarray([1,2,3], shape=[3,3,0], flags=flags)
2035 self.assertEqual(nd.tolist(),
2036 [[[], [], []], [[], [], []], [[], [], []]])
2037
2038 def test_ndarray_zero_strides(self):
2039 # zero strides
2040 for flags in (0, ND_PIL):
2041 nd = ndarray([1], shape=[5], strides=[0], flags=flags)
2042 mv = memoryview(nd)
2043 self.assertEqual(mv, nd)
2044 self.assertEqual(nd.tolist(), [1, 1, 1, 1, 1])
2045 self.assertEqual(mv.tolist(), [1, 1, 1, 1, 1])
2046
2047 def test_ndarray_offset(self):
2048 nd = ndarray(list(range(20)), shape=[3], offset=7)
2049 self.assertEqual(nd.offset, 7)
2050 self.assertEqual(nd.tolist(), [7,8,9])
2051
2052 def test_ndarray_memoryview_from_buffer(self):
2053 for flags in (0, ND_PIL):
2054 nd = ndarray(list(range(3)), shape=[3], flags=flags)
2055 m = nd.memoryview_from_buffer()
2056 self.assertEqual(m, nd)
2057
2058 def test_ndarray_get_pointer(self):
2059 for flags in (0, ND_PIL):
2060 nd = ndarray(list(range(3)), shape=[3], flags=flags)
2061 for i in range(3):
2062 self.assertEqual(nd[i], get_pointer(nd, [i]))
2063
2064 def test_ndarray_tolist_null_strides(self):
2065 ex = ndarray(list(range(20)), shape=[2,2,5])
2066
2067 nd = ndarray(ex, getbuf=PyBUF_ND|PyBUF_FORMAT)
2068 self.assertEqual(nd.tolist(), ex.tolist())
2069
2070 m = memoryview(ex)
2071 self.assertEqual(m.tolist(), ex.tolist())
2072
2073 def test_ndarray_cmp_contig(self):
2074
2075 self.assertFalse(cmp_contig(b"123", b"456"))
2076
2077 x = ndarray(list(range(12)), shape=[3,4])
2078 y = ndarray(list(range(12)), shape=[4,3])
2079 self.assertFalse(cmp_contig(x, y))
2080
2081 x = ndarray([1], shape=[1], format="B")
2082 self.assertTrue(cmp_contig(x, b'\x01'))
2083 self.assertTrue(cmp_contig(b'\x01', x))
2084
2085 def test_ndarray_hash(self):
2086
2087 a = array.array('L', [1,2,3])
2088 nd = ndarray(a)
2089 self.assertRaises(ValueError, hash, nd)
2090
2091 # one-dimensional
2092 b = bytes(list(range(12)))
2093
2094 nd = ndarray(list(range(12)), shape=[12])
2095 self.assertEqual(hash(nd), hash(b))
2096
2097 # C-contiguous
2098 nd = ndarray(list(range(12)), shape=[3,4])
2099 self.assertEqual(hash(nd), hash(b))
2100
2101 nd = ndarray(list(range(12)), shape=[3,2,2])
2102 self.assertEqual(hash(nd), hash(b))
2103
2104 # Fortran contiguous
2105 b = bytes(transpose(list(range(12)), shape=[4,3]))
2106 nd = ndarray(list(range(12)), shape=[3,4], flags=ND_FORTRAN)
2107 self.assertEqual(hash(nd), hash(b))
2108
2109 b = bytes(transpose(list(range(12)), shape=[2,3,2]))
2110 nd = ndarray(list(range(12)), shape=[2,3,2], flags=ND_FORTRAN)
2111 self.assertEqual(hash(nd), hash(b))
2112
2113 # suboffsets
2114 b = bytes(list(range(12)))
2115 nd = ndarray(list(range(12)), shape=[2,2,3], flags=ND_PIL)
2116 self.assertEqual(hash(nd), hash(b))
2117
2118 # non-byte formats
2119 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
2120 self.assertEqual(hash(nd), hash(nd.tobytes()))
2121
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002122 def test_py_buffer_to_contiguous(self):
2123
2124 # The requests are used in _testbuffer.c:py_buffer_to_contiguous
2125 # to generate buffers without full information for testing.
2126 requests = (
2127 # distinct flags
2128 PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE,
2129 # compound requests
2130 PyBUF_FULL, PyBUF_FULL_RO,
2131 PyBUF_RECORDS, PyBUF_RECORDS_RO,
2132 PyBUF_STRIDED, PyBUF_STRIDED_RO,
2133 PyBUF_CONTIG, PyBUF_CONTIG_RO,
2134 )
2135
2136 # no buffer interface
2137 self.assertRaises(TypeError, py_buffer_to_contiguous, {}, 'F',
2138 PyBUF_FULL_RO)
2139
2140 # scalar, read-only request
2141 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
2142 for order in ['C', 'F', 'A']:
2143 for request in requests:
2144 b = py_buffer_to_contiguous(nd, order, request)
2145 self.assertEqual(b, nd.tobytes())
2146
2147 # zeros in shape
2148 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
2149 for order in ['C', 'F', 'A']:
2150 for request in requests:
2151 b = py_buffer_to_contiguous(nd, order, request)
2152 self.assertEqual(b, b'')
2153
2154 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
2155 flags=ND_WRITABLE)
2156 for order in ['C', 'F', 'A']:
2157 for request in requests:
2158 b = py_buffer_to_contiguous(nd, order, request)
2159 self.assertEqual(b, b'')
2160
2161 ### One-dimensional arrays are trivial, since Fortran and C order
2162 ### are the same.
2163
2164 # one-dimensional
2165 for f in [0, ND_FORTRAN]:
2166 nd = ndarray([1], shape=[1], format="h", flags=f|ND_WRITABLE)
2167 ndbytes = nd.tobytes()
2168 for order in ['C', 'F', 'A']:
2169 for request in requests:
2170 b = py_buffer_to_contiguous(nd, order, request)
2171 self.assertEqual(b, ndbytes)
2172
2173 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=f|ND_WRITABLE)
2174 ndbytes = nd.tobytes()
2175 for order in ['C', 'F', 'A']:
2176 for request in requests:
2177 b = py_buffer_to_contiguous(nd, order, request)
2178 self.assertEqual(b, ndbytes)
2179
2180 # one-dimensional, non-contiguous input
2181 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
2182 ndbytes = nd.tobytes()
2183 for order in ['C', 'F', 'A']:
2184 for request in [PyBUF_STRIDES, PyBUF_FULL]:
2185 b = py_buffer_to_contiguous(nd, order, request)
2186 self.assertEqual(b, ndbytes)
2187
2188 nd = nd[::-1]
2189 ndbytes = nd.tobytes()
2190 for order in ['C', 'F', 'A']:
2191 for request in requests:
2192 try:
2193 b = py_buffer_to_contiguous(nd, order, request)
2194 except BufferError:
2195 continue
2196 self.assertEqual(b, ndbytes)
2197
2198 ###
2199 ### Multi-dimensional arrays:
2200 ###
2201 ### The goal here is to preserve the logical representation of the
2202 ### input array but change the physical representation if necessary.
2203 ###
2204 ### _testbuffer example:
2205 ### ====================
2206 ###
2207 ### C input array:
2208 ### --------------
2209 ### >>> nd = ndarray(list(range(12)), shape=[3, 4])
2210 ### >>> nd.tolist()
2211 ### [[0, 1, 2, 3],
2212 ### [4, 5, 6, 7],
2213 ### [8, 9, 10, 11]]
2214 ###
2215 ### Fortran output:
2216 ### ---------------
2217 ### >>> py_buffer_to_contiguous(nd, 'F', PyBUF_FULL_RO)
2218 ### >>> b'\x00\x04\x08\x01\x05\t\x02\x06\n\x03\x07\x0b'
2219 ###
2220 ### The return value corresponds to this input list for
2221 ### _testbuffer's ndarray:
2222 ### >>> nd = ndarray([0,4,8,1,5,9,2,6,10,3,7,11], shape=[3,4],
2223 ### flags=ND_FORTRAN)
2224 ### >>> nd.tolist()
2225 ### [[0, 1, 2, 3],
2226 ### [4, 5, 6, 7],
2227 ### [8, 9, 10, 11]]
2228 ###
2229 ### The logical array is the same, but the values in memory are now
2230 ### in Fortran order.
2231 ###
2232 ### NumPy example:
2233 ### ==============
2234 ### _testbuffer's ndarray takes lists to initialize the memory.
2235 ### Here's the same sequence in NumPy:
2236 ###
2237 ### C input:
2238 ### --------
2239 ### >>> nd = ndarray(buffer=bytearray(list(range(12))),
2240 ### shape=[3, 4], dtype='B')
2241 ### >>> nd
2242 ### array([[ 0, 1, 2, 3],
2243 ### [ 4, 5, 6, 7],
2244 ### [ 8, 9, 10, 11]], dtype=uint8)
2245 ###
2246 ### Fortran output:
2247 ### ---------------
2248 ### >>> fortran_buf = nd.tostring(order='F')
2249 ### >>> fortran_buf
2250 ### b'\x00\x04\x08\x01\x05\t\x02\x06\n\x03\x07\x0b'
2251 ###
2252 ### >>> nd = ndarray(buffer=fortran_buf, shape=[3, 4],
2253 ### dtype='B', order='F')
2254 ###
2255 ### >>> nd
2256 ### array([[ 0, 1, 2, 3],
2257 ### [ 4, 5, 6, 7],
2258 ### [ 8, 9, 10, 11]], dtype=uint8)
2259 ###
2260
2261 # multi-dimensional, contiguous input
2262 lst = list(range(12))
2263 for f in [0, ND_FORTRAN]:
2264 nd = ndarray(lst, shape=[3, 4], flags=f|ND_WRITABLE)
2265 if numpy_array:
2266 na = numpy_array(buffer=bytearray(lst),
2267 shape=[3, 4], dtype='B',
2268 order='C' if f == 0 else 'F')
2269
2270 # 'C' request
2271 if f == ND_FORTRAN: # 'F' to 'C'
2272 x = ndarray(transpose(lst, [4, 3]), shape=[3, 4],
2273 flags=ND_WRITABLE)
2274 expected = x.tobytes()
2275 else:
2276 expected = nd.tobytes()
2277 for request in requests:
2278 try:
2279 b = py_buffer_to_contiguous(nd, 'C', request)
2280 except BufferError:
2281 continue
2282
2283 self.assertEqual(b, expected)
2284
2285 # Check that output can be used as the basis for constructing
2286 # a C array that is logically identical to the input array.
2287 y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE)
2288 self.assertEqual(memoryview(y), memoryview(nd))
2289
2290 if numpy_array:
2291 self.assertEqual(b, na.tostring(order='C'))
2292
2293 # 'F' request
2294 if f == 0: # 'C' to 'F'
2295 x = ndarray(transpose(lst, [3, 4]), shape=[4, 3],
2296 flags=ND_WRITABLE)
2297 else:
2298 x = ndarray(lst, shape=[3, 4], flags=ND_WRITABLE)
2299 expected = x.tobytes()
2300 for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT,
2301 PyBUF_STRIDES, PyBUF_ND]:
2302 try:
2303 b = py_buffer_to_contiguous(nd, 'F', request)
2304 except BufferError:
2305 continue
2306 self.assertEqual(b, expected)
2307
2308 # Check that output can be used as the basis for constructing
2309 # a Fortran array that is logically identical to the input array.
2310 y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE)
2311 self.assertEqual(memoryview(y), memoryview(nd))
2312
2313 if numpy_array:
2314 self.assertEqual(b, na.tostring(order='F'))
2315
2316 # 'A' request
2317 if f == ND_FORTRAN:
2318 x = ndarray(lst, shape=[3, 4], flags=ND_WRITABLE)
2319 expected = x.tobytes()
2320 else:
2321 expected = nd.tobytes()
2322 for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT,
2323 PyBUF_STRIDES, PyBUF_ND]:
2324 try:
2325 b = py_buffer_to_contiguous(nd, 'A', request)
2326 except BufferError:
2327 continue
2328
2329 self.assertEqual(b, expected)
2330
2331 # Check that output can be used as the basis for constructing
2332 # an array with order=f that is logically identical to the input
2333 # array.
2334 y = ndarray([v for v in b], shape=[3, 4], flags=f|ND_WRITABLE)
2335 self.assertEqual(memoryview(y), memoryview(nd))
2336
2337 if numpy_array:
2338 self.assertEqual(b, na.tostring(order='A'))
2339
2340 # multi-dimensional, non-contiguous input
2341 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
2342
2343 # 'C'
2344 b = py_buffer_to_contiguous(nd, 'C', PyBUF_FULL_RO)
2345 self.assertEqual(b, nd.tobytes())
2346 y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE)
2347 self.assertEqual(memoryview(y), memoryview(nd))
2348
2349 # 'F'
2350 b = py_buffer_to_contiguous(nd, 'F', PyBUF_FULL_RO)
2351 x = ndarray(transpose(lst, [3, 4]), shape=[4, 3], flags=ND_WRITABLE)
2352 self.assertEqual(b, x.tobytes())
2353 y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE)
2354 self.assertEqual(memoryview(y), memoryview(nd))
2355
2356 # 'A'
2357 b = py_buffer_to_contiguous(nd, 'A', PyBUF_FULL_RO)
2358 self.assertEqual(b, nd.tobytes())
2359 y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE)
2360 self.assertEqual(memoryview(y), memoryview(nd))
2361
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002362 def test_memoryview_construction(self):
2363
2364 items_shape = [(9, []), ([1,2,3], [3]), (list(range(2*3*5)), [2,3,5])]
2365
2366 # NumPy style, C-contiguous:
2367 for items, shape in items_shape:
2368
2369 # From PEP-3118 compliant exporter:
2370 ex = ndarray(items, shape=shape)
2371 m = memoryview(ex)
2372 self.assertTrue(m.c_contiguous)
2373 self.assertTrue(m.contiguous)
2374
2375 ndim = len(shape)
2376 strides = strides_from_shape(ndim, shape, 1, 'C')
2377 lst = carray(items, shape)
2378
2379 self.verify(m, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002380 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002381 ndim=ndim, shape=shape, strides=strides,
2382 lst=lst)
2383
2384 # From memoryview:
2385 m2 = memoryview(m)
2386 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002387 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002388 ndim=ndim, shape=shape, strides=strides,
2389 lst=lst)
2390
2391 # PyMemoryView_FromBuffer(): no strides
2392 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2393 self.assertEqual(nd.strides, ())
2394 m = nd.memoryview_from_buffer()
2395 self.verify(m, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002396 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002397 ndim=ndim, shape=shape, strides=strides,
2398 lst=lst)
2399
2400 # PyMemoryView_FromBuffer(): no format, shape, strides
2401 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2402 self.assertEqual(nd.format, '')
2403 self.assertEqual(nd.shape, ())
2404 self.assertEqual(nd.strides, ())
2405 m = nd.memoryview_from_buffer()
2406
2407 lst = [items] if ndim == 0 else items
2408 self.verify(m, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002409 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002410 ndim=1, shape=[ex.nbytes], strides=(1,),
2411 lst=lst)
2412
2413 # NumPy style, Fortran contiguous:
2414 for items, shape in items_shape:
2415
2416 # From PEP-3118 compliant exporter:
2417 ex = ndarray(items, shape=shape, flags=ND_FORTRAN)
2418 m = memoryview(ex)
2419 self.assertTrue(m.f_contiguous)
2420 self.assertTrue(m.contiguous)
2421
2422 ndim = len(shape)
2423 strides = strides_from_shape(ndim, shape, 1, 'F')
2424 lst = farray(items, shape)
2425
2426 self.verify(m, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002427 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002428 ndim=ndim, shape=shape, strides=strides,
2429 lst=lst)
2430
2431 # From memoryview:
2432 m2 = memoryview(m)
2433 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002434 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002435 ndim=ndim, shape=shape, strides=strides,
2436 lst=lst)
2437
2438 # PIL style:
2439 for items, shape in items_shape[1:]:
2440
2441 # From PEP-3118 compliant exporter:
2442 ex = ndarray(items, shape=shape, flags=ND_PIL)
2443 m = memoryview(ex)
2444
2445 ndim = len(shape)
2446 lst = carray(items, shape)
2447
2448 self.verify(m, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002449 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002450 ndim=ndim, shape=shape, strides=ex.strides,
2451 lst=lst)
2452
2453 # From memoryview:
2454 m2 = memoryview(m)
2455 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002456 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002457 ndim=ndim, shape=shape, strides=ex.strides,
2458 lst=lst)
2459
2460 # Invalid number of arguments:
2461 self.assertRaises(TypeError, memoryview, b'9', 'x')
2462 # Not a buffer provider:
2463 self.assertRaises(TypeError, memoryview, {})
2464 # Non-compliant buffer provider:
2465 ex = ndarray([1,2,3], shape=[3])
2466 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2467 self.assertRaises(BufferError, memoryview, nd)
2468 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2469 self.assertRaises(BufferError, memoryview, nd)
2470
2471 # ndim > 64
2472 nd = ndarray([1]*128, shape=[1]*128, format='L')
2473 self.assertRaises(ValueError, memoryview, nd)
2474 self.assertRaises(ValueError, nd.memoryview_from_buffer)
2475 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'C')
2476 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'F')
2477 self.assertRaises(ValueError, get_contiguous, nd[::-1], PyBUF_READ, 'C')
2478
2479 def test_memoryview_cast_zero_shape(self):
Antoine Pitrou60b18342013-10-03 19:55:41 +02002480 # Casts are undefined if buffer is multidimensional and shape
2481 # contains zeros. These arrays are regarded as C-contiguous by
2482 # Numpy and PyBuffer_GetContiguous(), so they are not caught by
2483 # the test for C-contiguity in memory_cast().
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002484 items = [1,2,3]
2485 for shape in ([0,3,3], [3,0,3], [0,3,3]):
2486 ex = ndarray(items, shape=shape)
2487 self.assertTrue(ex.c_contiguous)
2488 msrc = memoryview(ex)
2489 self.assertRaises(TypeError, msrc.cast, 'c')
Antoine Pitrou60b18342013-10-03 19:55:41 +02002490 # Monodimensional empty view can be cast (issue #19014).
2491 for fmt, _, _ in iter_format(1, 'memoryview'):
2492 msrc = memoryview(b'')
2493 m = msrc.cast(fmt)
2494 self.assertEqual(m.tobytes(), b'')
2495 self.assertEqual(m.tolist(), [])
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002496
Antoine Pitroua6545102015-03-10 22:32:00 +01002497 check_sizeof = support.check_sizeof
2498
2499 def test_memoryview_sizeof(self):
2500 check = self.check_sizeof
2501 vsize = support.calcvobjsize
Antoine Pitrou63afdaa2015-03-10 22:35:24 +01002502 base_struct = 'Pnin 2P2n2i5P P'
Antoine Pitroua6545102015-03-10 22:32:00 +01002503 per_dim = '3n'
2504
2505 items = list(range(8))
2506 check(memoryview(b''), vsize(base_struct + 1 * per_dim))
2507 a = ndarray(items, shape=[2, 4], format="b")
2508 check(memoryview(a), vsize(base_struct + 2 * per_dim))
2509 a = ndarray(items, shape=[2, 2, 2], format="b")
2510 check(memoryview(a), vsize(base_struct + 3 * per_dim))
2511
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002512 def test_memoryview_struct_module(self):
2513
2514 class INT(object):
2515 def __init__(self, val):
2516 self.val = val
2517 def __int__(self):
2518 return self.val
2519
2520 class IDX(object):
2521 def __init__(self, val):
2522 self.val = val
2523 def __index__(self):
2524 return self.val
2525
2526 def f(): return 7
2527
2528 values = [INT(9), IDX(9),
2529 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2),
2530 [1,2,3], {4,5,6}, {7:8}, (), (9,),
MojoVampire469325c2020-03-03 18:50:17 +00002531 True, False, None, Ellipsis,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002532 b'a', b'abc', bytearray(b'a'), bytearray(b'abc'),
2533 'a', 'abc', r'a', r'abc',
2534 f, lambda x: x]
2535
2536 for fmt, items, item in iter_format(10, 'memoryview'):
2537 ex = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2538 nd = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2539 m = memoryview(ex)
2540
2541 struct.pack_into(fmt, nd, 0, item)
2542 m[0] = item
2543 self.assertEqual(m[0], nd[0])
2544
2545 itemsize = struct.calcsize(fmt)
2546 if 'P' in fmt:
2547 continue
2548
2549 for v in values:
2550 struct_err = None
2551 try:
2552 struct.pack_into(fmt, nd, itemsize, v)
2553 except struct.error:
2554 struct_err = struct.error
2555
2556 mv_err = None
2557 try:
2558 m[1] = v
2559 except (TypeError, ValueError) as e:
2560 mv_err = e.__class__
2561
2562 if struct_err or mv_err:
2563 self.assertIsNot(struct_err, None)
2564 self.assertIsNot(mv_err, None)
2565 else:
2566 self.assertEqual(m[1], nd[1])
2567
2568 def test_memoryview_cast_zero_strides(self):
2569 # Casts are undefined if strides contains zeros. These arrays are
2570 # (sometimes!) regarded as C-contiguous by Numpy, but not by
2571 # PyBuffer_GetContiguous().
2572 ex = ndarray([1,2,3], shape=[3], strides=[0])
2573 self.assertFalse(ex.c_contiguous)
2574 msrc = memoryview(ex)
2575 self.assertRaises(TypeError, msrc.cast, 'c')
2576
2577 def test_memoryview_cast_invalid(self):
2578 # invalid format
2579 for sfmt in NON_BYTE_FORMAT:
2580 sformat = '@' + sfmt if randrange(2) else sfmt
2581 ssize = struct.calcsize(sformat)
2582 for dfmt in NON_BYTE_FORMAT:
2583 dformat = '@' + dfmt if randrange(2) else dfmt
2584 dsize = struct.calcsize(dformat)
2585 ex = ndarray(list(range(32)), shape=[32//ssize], format=sformat)
2586 msrc = memoryview(ex)
2587 self.assertRaises(TypeError, msrc.cast, dfmt, [32//dsize])
2588
2589 for sfmt, sitems, _ in iter_format(1):
2590 ex = ndarray(sitems, shape=[1], format=sfmt)
2591 msrc = memoryview(ex)
2592 for dfmt, _, _ in iter_format(1):
Stefan Krah0c515952015-08-08 13:38:10 +02002593 if not is_memoryview_format(dfmt):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002594 self.assertRaises(ValueError, msrc.cast, dfmt,
2595 [32//dsize])
2596 else:
2597 if not is_byte_format(sfmt) and not is_byte_format(dfmt):
2598 self.assertRaises(TypeError, msrc.cast, dfmt,
2599 [32//dsize])
2600
2601 # invalid shape
2602 size_h = struct.calcsize('h')
2603 size_d = struct.calcsize('d')
2604 ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h')
2605 msrc = memoryview(ex)
2606 self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d')
2607
2608 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2609 m = memoryview(ex)
2610
2611 # incorrect number of args
2612 self.assertRaises(TypeError, m.cast)
2613 self.assertRaises(TypeError, m.cast, 1, 2, 3)
2614
2615 # incorrect dest format type
2616 self.assertRaises(TypeError, m.cast, {})
2617
2618 # incorrect dest format
2619 self.assertRaises(ValueError, m.cast, "X")
2620 self.assertRaises(ValueError, m.cast, "@X")
2621 self.assertRaises(ValueError, m.cast, "@XY")
2622
2623 # dest format not implemented
2624 self.assertRaises(ValueError, m.cast, "=B")
2625 self.assertRaises(ValueError, m.cast, "!L")
2626 self.assertRaises(ValueError, m.cast, "<P")
2627 self.assertRaises(ValueError, m.cast, ">l")
2628 self.assertRaises(ValueError, m.cast, "BI")
2629 self.assertRaises(ValueError, m.cast, "xBI")
2630
2631 # src format not implemented
2632 ex = ndarray([(1,2), (3,4)], shape=[2], format="II")
2633 m = memoryview(ex)
2634 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2635 self.assertRaises(NotImplementedError, m.__setitem__, 0, 8)
2636 self.assertRaises(NotImplementedError, m.tolist)
2637
2638 # incorrect shape type
2639 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2640 m = memoryview(ex)
2641 self.assertRaises(TypeError, m.cast, "B", shape={})
2642
2643 # incorrect shape elements
2644 ex = ndarray(list(range(120)), shape=[2*3*4*5])
2645 m = memoryview(ex)
2646 self.assertRaises(OverflowError, m.cast, "B", shape=[2**64])
2647 self.assertRaises(ValueError, m.cast, "B", shape=[-1])
2648 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1])
2649 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0])
2650 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x'])
2651
2652 # N-D -> N-D cast
2653 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11])
2654 m = memoryview(ex)
2655 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2656
2657 # cast with ndim > 64
2658 nd = ndarray(list(range(128)), shape=[128], format='I')
2659 m = memoryview(nd)
2660 self.assertRaises(ValueError, m.cast, 'I', [1]*128)
2661
2662 # view->len not a multiple of itemsize
2663 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2664 m = memoryview(ex)
2665 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2666
2667 # product(shape) * itemsize != buffer size
2668 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2669 m = memoryview(ex)
2670 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5])
2671
2672 # product(shape) * itemsize overflow
2673 nd = ndarray(list(range(128)), shape=[128], format='I')
2674 m1 = memoryview(nd)
2675 nd = ndarray(list(range(128)), shape=[128], format='B')
2676 m2 = memoryview(nd)
2677 if sys.maxsize == 2**63-1:
2678 self.assertRaises(TypeError, m1.cast, 'B',
2679 [7, 7, 73, 127, 337, 92737, 649657])
2680 self.assertRaises(ValueError, m1.cast, 'B',
2681 [2**20, 2**20, 2**10, 2**10, 2**3])
2682 self.assertRaises(ValueError, m2.cast, 'I',
2683 [2**20, 2**20, 2**10, 2**10, 2**1])
2684 else:
2685 self.assertRaises(TypeError, m1.cast, 'B',
2686 [1, 2147483647])
2687 self.assertRaises(ValueError, m1.cast, 'B',
2688 [2**10, 2**10, 2**5, 2**5, 2**1])
2689 self.assertRaises(ValueError, m2.cast, 'I',
2690 [2**10, 2**10, 2**5, 2**3, 2**1])
2691
2692 def test_memoryview_cast(self):
2693 bytespec = (
2694 ('B', lambda ex: list(ex.tobytes())),
2695 ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]),
2696 ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]),
2697 )
2698
2699 def iter_roundtrip(ex, m, items, fmt):
2700 srcsize = struct.calcsize(fmt)
2701 for bytefmt, to_bytelist in bytespec:
2702
2703 m2 = m.cast(bytefmt)
2704 lst = to_bytelist(ex)
2705 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002706 itemsize=1, fmt=bytefmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002707 ndim=1, shape=[31*srcsize], strides=(1,),
2708 lst=lst, cast=True)
2709
2710 m3 = m2.cast(fmt)
2711 self.assertEqual(m3, ex)
2712 lst = ex.tolist()
2713 self.verify(m3, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002714 itemsize=srcsize, fmt=fmt, readonly=False,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002715 ndim=1, shape=[31], strides=(srcsize,),
2716 lst=lst, cast=True)
2717
2718 # cast from ndim = 0 to ndim = 1
2719 srcsize = struct.calcsize('I')
2720 ex = ndarray(9, shape=[], format='I')
2721 destitems, destshape = cast_items(ex, 'B', 1)
2722 m = memoryview(ex)
2723 m2 = m.cast('B')
2724 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002725 itemsize=1, fmt='B', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002726 ndim=1, shape=destshape, strides=(1,),
2727 lst=destitems, cast=True)
2728
2729 # cast from ndim = 1 to ndim = 0
2730 destsize = struct.calcsize('I')
2731 ex = ndarray([9]*destsize, shape=[destsize], format='B')
2732 destitems, destshape = cast_items(ex, 'I', destsize, shape=[])
2733 m = memoryview(ex)
2734 m2 = m.cast('I', shape=[])
2735 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002736 itemsize=destsize, fmt='I', readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002737 ndim=0, shape=(), strides=(),
2738 lst=destitems, cast=True)
2739
2740 # array.array: roundtrip to/from bytes
2741 for fmt, items, _ in iter_format(31, 'array'):
2742 ex = array.array(fmt, items)
2743 m = memoryview(ex)
2744 iter_roundtrip(ex, m, items, fmt)
2745
2746 # ndarray: roundtrip to/from bytes
2747 for fmt, items, _ in iter_format(31, 'memoryview'):
2748 ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE)
2749 m = memoryview(ex)
2750 iter_roundtrip(ex, m, items, fmt)
2751
2752 def test_memoryview_cast_1D_ND(self):
2753 # Cast between C-contiguous buffers. At least one buffer must
2754 # be 1D, at least one format must be 'c', 'b' or 'B'.
2755 for _tshape in gencastshapes():
2756 for char in fmtdict['@']:
Stefan Krah1ae9cde2020-03-12 19:35:38 +01002757 # Casts to _Bool are undefined if the source contains values
2758 # other than 0 or 1.
2759 if char == "?":
2760 continue
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002761 tfmt = ('', '@')[randrange(2)] + char
2762 tsize = struct.calcsize(tfmt)
2763 n = prod(_tshape) * tsize
2764 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2765 for fmt, items, _ in iter_format(n, obj):
2766 size = struct.calcsize(fmt)
2767 shape = [n] if n > 0 else []
2768 tshape = _tshape + [size]
2769
2770 ex = ndarray(items, shape=shape, format=fmt)
2771 m = memoryview(ex)
2772
2773 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2774
2775 if titems is None:
2776 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2777 continue
2778 if titems == 'nan':
2779 continue # NaNs in lists are a recipe for trouble.
2780
2781 # 1D -> ND
2782 nd = ndarray(titems, shape=tshape, format=tfmt)
2783
2784 m2 = m.cast(tfmt, shape=tshape)
2785 ndim = len(tshape)
2786 strides = nd.strides
2787 lst = nd.tolist()
2788 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002789 itemsize=tsize, fmt=tfmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002790 ndim=ndim, shape=tshape, strides=strides,
2791 lst=lst, cast=True)
2792
2793 # ND -> 1D
2794 m3 = m2.cast(fmt)
2795 m4 = m2.cast(fmt, shape=shape)
2796 ndim = len(shape)
2797 strides = ex.strides
2798 lst = ex.tolist()
2799
2800 self.verify(m3, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002801 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002802 ndim=ndim, shape=shape, strides=strides,
2803 lst=lst, cast=True)
2804
2805 self.verify(m4, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002806 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002807 ndim=ndim, shape=shape, strides=strides,
2808 lst=lst, cast=True)
2809
Stefan Krah0c515952015-08-08 13:38:10 +02002810 if ctypes:
2811 # format: "T{>l:x:>d:y:}"
2812 class BEPoint(ctypes.BigEndianStructure):
2813 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)]
2814 point = BEPoint(100, 200.1)
2815 m1 = memoryview(point)
2816 m2 = m1.cast('B')
2817 self.assertEqual(m2.obj, point)
2818 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002819 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002820 self.assertEqual(m2.ndim, 1)
2821 self.assertEqual(m2.shape, (m2.nbytes,))
2822 self.assertEqual(m2.strides, (1,))
2823 self.assertEqual(m2.suboffsets, ())
2824
2825 x = ctypes.c_double(1.2)
2826 m1 = memoryview(x)
2827 m2 = m1.cast('c')
2828 self.assertEqual(m2.obj, x)
2829 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002830 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002831 self.assertEqual(m2.ndim, 1)
2832 self.assertEqual(m2.shape, (m2.nbytes,))
2833 self.assertEqual(m2.strides, (1,))
2834 self.assertEqual(m2.suboffsets, ())
2835
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002836 def test_memoryview_tolist(self):
2837
2838 # Most tolist() tests are in self.verify() etc.
2839
2840 a = array.array('h', list(range(-6, 6)))
2841 m = memoryview(a)
2842 self.assertEqual(m, a)
2843 self.assertEqual(m.tolist(), a.tolist())
2844
2845 a = a[2::3]
2846 m = m[2::3]
2847 self.assertEqual(m, a)
2848 self.assertEqual(m.tolist(), a.tolist())
2849
2850 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2851 m = memoryview(ex)
2852 self.assertEqual(m.tolist(), ex.tolist())
2853
2854 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2855 m = memoryview(ex)
2856 self.assertRaises(NotImplementedError, m.tolist)
2857
2858 ex = ndarray([b'12345'], shape=[1], format="s")
2859 m = memoryview(ex)
2860 self.assertRaises(NotImplementedError, m.tolist)
2861
2862 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2863 m = memoryview(ex)
2864 self.assertRaises(NotImplementedError, m.tolist)
2865
2866 def test_memoryview_repr(self):
2867 m = memoryview(bytearray(9))
2868 r = m.__repr__()
2869 self.assertTrue(r.startswith("<memory"))
2870
2871 m.release()
2872 r = m.__repr__()
2873 self.assertTrue(r.startswith("<released"))
2874
2875 def test_memoryview_sequence(self):
2876
2877 for fmt in ('d', 'f'):
2878 inf = float(3e400)
2879 ex = array.array(fmt, [1.0, inf, 3.0])
2880 m = memoryview(ex)
2881 self.assertIn(1.0, m)
2882 self.assertIn(5e700, m)
2883 self.assertIn(3.0, m)
2884
2885 ex = ndarray(9.0, [], format='f')
2886 m = memoryview(ex)
2887 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2888
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002889 @contextlib.contextmanager
2890 def assert_out_of_bounds_error(self, dim):
2891 with self.assertRaises(IndexError) as cm:
2892 yield
2893 self.assertEqual(str(cm.exception),
2894 "index out of bounds on dimension %d" % (dim,))
2895
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002896 def test_memoryview_index(self):
2897
2898 # ndim = 0
2899 ex = ndarray(12.5, shape=[], format='d')
2900 m = memoryview(ex)
2901 self.assertEqual(m[()], 12.5)
2902 self.assertEqual(m[...], m)
2903 self.assertEqual(m[...], ex)
2904 self.assertRaises(TypeError, m.__getitem__, 0)
2905
2906 ex = ndarray((1,2,3), shape=[], format='iii')
2907 m = memoryview(ex)
2908 self.assertRaises(NotImplementedError, m.__getitem__, ())
2909
2910 # range
2911 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2912 m = memoryview(ex)
2913
2914 self.assertRaises(IndexError, m.__getitem__, 2**64)
2915 self.assertRaises(TypeError, m.__getitem__, 2.0)
2916 self.assertRaises(TypeError, m.__getitem__, 0.0)
2917
2918 # out of bounds
2919 self.assertRaises(IndexError, m.__getitem__, -8)
2920 self.assertRaises(IndexError, m.__getitem__, 8)
2921
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002922 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002923 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2924 m = memoryview(ex)
2925
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002926 self.assertEqual(m[0, 0], 0)
2927 self.assertEqual(m[2, 0], 8)
2928 self.assertEqual(m[2, 3], 11)
2929 self.assertEqual(m[-1, -1], 11)
2930 self.assertEqual(m[-3, -4], 0)
2931
2932 # out of bounds
2933 for index in (3, -4):
2934 with self.assert_out_of_bounds_error(dim=1):
2935 m[index, 0]
2936 for index in (4, -5):
2937 with self.assert_out_of_bounds_error(dim=2):
2938 m[0, index]
2939 self.assertRaises(IndexError, m.__getitem__, (2**64, 0))
2940 self.assertRaises(IndexError, m.__getitem__, (0, 2**64))
2941
2942 self.assertRaises(TypeError, m.__getitem__, (0, 0, 0))
2943 self.assertRaises(TypeError, m.__getitem__, (0.0, 0.0))
2944
2945 # Not implemented: multidimensional sub-views
2946 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002947 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2948
2949 def test_memoryview_assign(self):
2950
2951 # ndim = 0
2952 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2953 m = memoryview(ex)
2954 m[()] = 22.5
2955 self.assertEqual(m[()], 22.5)
2956 m[...] = 23.5
2957 self.assertEqual(m[()], 23.5)
2958 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2959
2960 # read-only
2961 ex = ndarray(list(range(7)), shape=[7])
2962 m = memoryview(ex)
2963 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2964
2965 # range
2966 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2967 m = memoryview(ex)
2968
2969 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2970 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2971 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2972
2973 # out of bounds
2974 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2975 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2976
2977 # pack_single() success:
2978 for fmt in fmtdict['@']:
2979 if fmt == 'c' or fmt == '?':
2980 continue
2981 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2982 m = memoryview(ex)
2983 i = randrange(-3, 3)
2984 m[i] = 8
2985 self.assertEqual(m[i], 8)
2986 self.assertEqual(m[i], ex[i])
2987
2988 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2989 flags=ND_WRITABLE)
2990 m = memoryview(ex)
2991 m[2] = b'9'
2992 self.assertEqual(m[2], b'9')
2993
2994 ex = ndarray([True, False, True], shape=[3], format='?',
2995 flags=ND_WRITABLE)
2996 m = memoryview(ex)
2997 m[1] = True
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002998 self.assertIs(m[1], True)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002999
3000 # pack_single() exceptions:
3001 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
3002 m = memoryview(nd)
3003 self.assertRaises(TypeError, m.__setitem__, 0, 100)
3004
3005 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
3006 m1 = memoryview(ex)
3007
3008 for fmt, _range in fmtdict['@'].items():
3009 if (fmt == '?'): # PyObject_IsTrue() accepts anything
3010 continue
3011 if fmt == 'c': # special case tested above
3012 continue
3013 m2 = m1.cast(fmt)
3014 lo, hi = _range
3015 if fmt == 'd' or fmt == 'f':
3016 lo, hi = -2**1024, 2**1024
3017 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
3018 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
3019 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
3020 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
3021
3022 # invalid item
3023 m2 = m1.cast('c')
3024 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
3025
3026 # format not implemented
3027 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
3028 m = memoryview(ex)
3029 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3030
3031 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
3032 m = memoryview(ex)
3033 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3034
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003035 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003036 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
3037 m = memoryview(ex)
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003038 m[0,1] = 42
3039 self.assertEqual(ex[0][1], 42)
3040 m[-1,-1] = 43
3041 self.assertEqual(ex[2][3], 43)
3042 # errors
3043 for index in (3, -4):
3044 with self.assert_out_of_bounds_error(dim=1):
3045 m[index, 0] = 0
3046 for index in (4, -5):
3047 with self.assert_out_of_bounds_error(dim=2):
3048 m[0, index] = 0
3049 self.assertRaises(IndexError, m.__setitem__, (2**64, 0), 0)
3050 self.assertRaises(IndexError, m.__setitem__, (0, 2**64), 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003051
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003052 self.assertRaises(TypeError, m.__setitem__, (0, 0, 0), 0)
3053 self.assertRaises(TypeError, m.__setitem__, (0.0, 0.0), 0)
3054
3055 # Not implemented: multidimensional sub-views
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003056 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
3057
3058 def test_memoryview_slice(self):
3059
3060 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3061 m = memoryview(ex)
3062
3063 # zero step
3064 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
3065 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
3066 bytearray([1,2]))
3067
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003068 # 0-dim slicing (identity function)
3069 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003070
3071 # multidimensional slices
3072 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3073 m = memoryview(ex)
3074
3075 self.assertRaises(NotImplementedError, m.__getitem__,
3076 (slice(0,2,1), slice(0,2,1)))
3077 self.assertRaises(NotImplementedError, m.__setitem__,
3078 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
3079
3080 # invalid slice tuple
3081 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
3082 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
3083 bytearray([1,2]))
3084
3085 # rvalue is not an exporter
3086 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
3087
3088 # non-contiguous slice assignment
3089 for flags in (0, ND_PIL):
3090 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
3091 flags=ND_WRITABLE|flags)
3092 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
3093 m1 = memoryview(ex1)
3094 m2 = memoryview(ex2)
3095
3096 ex1[2:5] = ex1[2:5]
3097 m1[2:5] = m2[2:5]
3098
3099 self.assertEqual(m1, ex1)
3100 self.assertEqual(m2, ex2)
3101
3102 ex1[1:3][::-1] = ex2[0:2][::1]
3103 m1[1:3][::-1] = m2[0:2][::1]
3104
3105 self.assertEqual(m1, ex1)
3106 self.assertEqual(m2, ex2)
3107
3108 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
3109 m1[4:1:-2][::-1] = m1[1:4:2][::1]
3110
3111 self.assertEqual(m1, ex1)
3112 self.assertEqual(m2, ex2)
3113
3114 def test_memoryview_array(self):
3115
3116 def cmptest(testcase, a, b, m, singleitem):
3117 for i, _ in enumerate(a):
3118 ai = a[i]
3119 mi = m[i]
3120 testcase.assertEqual(ai, mi)
3121 a[i] = singleitem
3122 if singleitem != ai:
3123 testcase.assertNotEqual(a, m)
3124 testcase.assertNotEqual(a, b)
3125 else:
3126 testcase.assertEqual(a, m)
3127 testcase.assertEqual(a, b)
3128 m[i] = singleitem
3129 testcase.assertEqual(a, m)
3130 testcase.assertEqual(b, m)
3131 a[i] = ai
3132 m[i] = mi
3133
3134 for n in range(1, 5):
3135 for fmt, items, singleitem in iter_format(n, 'array'):
3136 for lslice in genslices(n):
3137 for rslice in genslices(n):
3138
3139 a = array.array(fmt, items)
3140 b = array.array(fmt, items)
3141 m = memoryview(b)
3142
3143 self.assertEqual(m, a)
3144 self.assertEqual(m.tolist(), a.tolist())
3145 self.assertEqual(m.tobytes(), a.tobytes())
3146 self.assertEqual(len(m), len(a))
3147
3148 cmptest(self, a, b, m, singleitem)
3149
3150 array_err = None
3151 have_resize = None
3152 try:
3153 al = a[lslice]
3154 ar = a[rslice]
3155 a[lslice] = a[rslice]
3156 have_resize = len(al) != len(ar)
3157 except Exception as e:
3158 array_err = e.__class__
3159
3160 m_err = None
3161 try:
3162 m[lslice] = m[rslice]
3163 except Exception as e:
3164 m_err = e.__class__
3165
3166 if have_resize: # memoryview cannot change shape
3167 self.assertIs(m_err, ValueError)
3168 elif m_err or array_err:
3169 self.assertIs(m_err, array_err)
3170 else:
3171 self.assertEqual(m, a)
3172 self.assertEqual(m.tolist(), a.tolist())
3173 self.assertEqual(m.tobytes(), a.tobytes())
3174 cmptest(self, a, b, m, singleitem)
3175
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003176 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003177
3178 a = array.array('L', [1, 2, 3])
3179 b = array.array('L', [1, 2, 7])
3180
3181 # Ordering comparisons raise:
3182 v = memoryview(a)
3183 w = memoryview(b)
3184 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3185 self.assertIs(getattr(v, attr)(w), NotImplemented)
3186 self.assertIs(getattr(a, attr)(v), NotImplemented)
3187
3188 # Released views compare equal to themselves:
3189 v = memoryview(a)
3190 v.release()
3191 self.assertEqual(v, v)
3192 self.assertNotEqual(v, a)
3193 self.assertNotEqual(a, v)
3194
3195 v = memoryview(a)
3196 w = memoryview(a)
3197 w.release()
3198 self.assertNotEqual(v, w)
3199 self.assertNotEqual(w, v)
3200
3201 # Operand does not implement the buffer protocol:
3202 v = memoryview(a)
3203 self.assertNotEqual(v, [1, 2, 3])
3204
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003205 # NaNs
3206 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3207 nd[0] = (-1, float('nan'))
3208 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003209
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003210 # Depends on issue #15625: the struct module does not understand 'u'.
3211 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003212 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003213 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003214 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003215
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003216 # Some ctypes format strings are unknown to the struct module.
3217 if ctypes:
3218 # format: "T{>l:x:>l:y:}"
3219 class BEPoint(ctypes.BigEndianStructure):
3220 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3221 point = BEPoint(100, 200)
3222 a = memoryview(point)
3223 b = memoryview(point)
3224 self.assertNotEqual(a, b)
3225 self.assertNotEqual(a, point)
3226 self.assertNotEqual(point, a)
3227 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003228
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003229 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003230
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003231 nd1 = ndarray(1729, shape=[], format='@L')
3232 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
3233 v = memoryview(nd1)
3234 w = memoryview(nd2)
3235 self.assertEqual(v, w)
3236 self.assertEqual(w, v)
3237 self.assertEqual(v, nd2)
3238 self.assertEqual(nd2, v)
3239 self.assertEqual(w, nd1)
3240 self.assertEqual(nd1, w)
3241
3242 self.assertFalse(v.__ne__(w))
3243 self.assertFalse(w.__ne__(v))
3244
3245 w[()] = 1728
3246 self.assertNotEqual(v, w)
3247 self.assertNotEqual(w, v)
3248 self.assertNotEqual(v, nd2)
3249 self.assertNotEqual(nd2, v)
3250 self.assertNotEqual(w, nd1)
3251 self.assertNotEqual(nd1, w)
3252
3253 self.assertFalse(v.__eq__(w))
3254 self.assertFalse(w.__eq__(v))
3255
3256 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3257 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3258 m = memoryview(ex)
3259
3260 self.assertEqual(m, nd)
3261 m[9] = 100
3262 self.assertNotEqual(m, nd)
3263
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003264 # struct module: equal
3265 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3266 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3267 flags=ND_WRITABLE)
3268 v = memoryview(nd1)
3269 w = memoryview(nd2)
3270 self.assertEqual(v, w)
3271 self.assertEqual(w, v)
3272 self.assertEqual(v, nd2)
3273 self.assertEqual(nd2, v)
3274 self.assertEqual(w, nd1)
3275 self.assertEqual(nd1, w)
3276
3277 # struct module: not equal
3278 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3279 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3280 flags=ND_WRITABLE)
3281 v = memoryview(nd1)
3282 w = memoryview(nd2)
3283 self.assertNotEqual(v, w)
3284 self.assertNotEqual(w, v)
3285 self.assertNotEqual(v, nd2)
3286 self.assertNotEqual(nd2, v)
3287 self.assertNotEqual(w, nd1)
3288 self.assertNotEqual(nd1, w)
3289 self.assertEqual(v, nd1)
3290 self.assertEqual(w, nd2)
3291
3292 def test_memoryview_compare_ndim_one(self):
3293
3294 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003295 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3296 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3297 v = memoryview(nd1)
3298 w = memoryview(nd2)
3299
3300 self.assertEqual(v, nd1)
3301 self.assertEqual(w, nd2)
3302 self.assertNotEqual(v, nd2)
3303 self.assertNotEqual(w, nd1)
3304 self.assertNotEqual(v, w)
3305
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003306 # contiguous, struct module
3307 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3308 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3309 v = memoryview(nd1)
3310 w = memoryview(nd2)
3311
3312 self.assertEqual(v, nd1)
3313 self.assertEqual(w, nd2)
3314 self.assertNotEqual(v, nd2)
3315 self.assertNotEqual(w, nd1)
3316 self.assertNotEqual(v, w)
3317
3318 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003319 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3320 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3321 v = memoryview(nd1)
3322 w = memoryview(nd2)
3323
3324 self.assertEqual(v, nd2[::2])
3325 self.assertEqual(w[::2], nd1)
3326 self.assertEqual(v, w[::2])
3327 self.assertEqual(v[::-1], w[::-2])
3328
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003329 # non-contiguous, struct module
3330 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3331 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3332 v = memoryview(nd1)
3333 w = memoryview(nd2)
3334
3335 self.assertEqual(v, nd2[::2])
3336 self.assertEqual(w[::2], nd1)
3337 self.assertEqual(v, w[::2])
3338 self.assertEqual(v[::-1], w[::-2])
3339
3340 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003341 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3342 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3343 flags=ND_PIL)
3344 v = memoryview(nd1)
3345 w = memoryview(nd2)
3346
3347 self.assertEqual(v, nd2[::2])
3348 self.assertEqual(w[::2], nd1)
3349 self.assertEqual(v, w[::2])
3350 self.assertEqual(v[::-1], w[::-2])
3351
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003352 # non-contiguous, suboffsets, struct module
3353 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3354 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3355 flags=ND_PIL)
3356 v = memoryview(nd1)
3357 w = memoryview(nd2)
3358
3359 self.assertEqual(v, nd2[::2])
3360 self.assertEqual(w[::2], nd1)
3361 self.assertEqual(v, w[::2])
3362 self.assertEqual(v[::-1], w[::-2])
3363
3364 def test_memoryview_compare_zero_shape(self):
3365
3366 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003367 nd1 = ndarray([900, 961], shape=[0], format='@h')
3368 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3369 v = memoryview(nd1)
3370 w = memoryview(nd2)
3371
3372 self.assertEqual(v, nd1)
3373 self.assertEqual(w, nd2)
3374 self.assertEqual(v, nd2)
3375 self.assertEqual(w, nd1)
3376 self.assertEqual(v, w)
3377
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003378 # zeros in shape, struct module
3379 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3380 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3381 v = memoryview(nd1)
3382 w = memoryview(nd2)
3383
3384 self.assertEqual(v, nd1)
3385 self.assertEqual(w, nd2)
3386 self.assertEqual(v, nd2)
3387 self.assertEqual(w, nd1)
3388 self.assertEqual(v, w)
3389
3390 def test_memoryview_compare_zero_strides(self):
3391
3392 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003393 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3394 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3395 v = memoryview(nd1)
3396 w = memoryview(nd2)
3397
3398 self.assertEqual(v, nd1)
3399 self.assertEqual(w, nd2)
3400 self.assertEqual(v, nd2)
3401 self.assertEqual(w, nd1)
3402 self.assertEqual(v, w)
3403
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003404 # zero strides, struct module
3405 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3406 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3407 v = memoryview(nd1)
3408 w = memoryview(nd2)
3409
3410 self.assertEqual(v, nd1)
3411 self.assertEqual(w, nd2)
3412 self.assertEqual(v, nd2)
3413 self.assertEqual(w, nd1)
3414 self.assertEqual(v, w)
3415
3416 def test_memoryview_compare_random_formats(self):
3417
3418 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003419 n = 10
3420 for char in fmtdict['@m']:
3421 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3422 for flags in (0, ND_PIL):
3423 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3424 m = memoryview(nd)
3425 self.assertEqual(m, nd)
3426
3427 nd = nd[::-3]
3428 m = memoryview(nd)
3429 self.assertEqual(m, nd)
3430
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003431 # random formats
3432 n = 10
3433 for _ in range(100):
3434 fmt, items, singleitem = randitems(n)
3435 for flags in (0, ND_PIL):
3436 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3437 m = memoryview(nd)
3438 self.assertEqual(m, nd)
3439
3440 nd = nd[::-3]
3441 m = memoryview(nd)
3442 self.assertEqual(m, nd)
3443
3444 def test_memoryview_compare_multidim_c(self):
3445
3446 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003447 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3448 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3449 v = memoryview(nd1)
3450 w = memoryview(nd2)
3451
3452 self.assertEqual(v, nd1)
3453 self.assertEqual(w, nd2)
3454 self.assertNotEqual(v, nd2)
3455 self.assertNotEqual(w, nd1)
3456 self.assertNotEqual(v, w)
3457
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003458 # C-contiguous, different values, struct module
3459 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3460 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3461 v = memoryview(nd1)
3462 w = memoryview(nd2)
3463
3464 self.assertEqual(v, nd1)
3465 self.assertEqual(w, nd2)
3466 self.assertNotEqual(v, nd2)
3467 self.assertNotEqual(w, nd1)
3468 self.assertNotEqual(v, w)
3469
3470 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003471 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3472 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3473 v = memoryview(nd1)
3474 w = memoryview(nd2)
3475
3476 self.assertEqual(v, nd1)
3477 self.assertEqual(w, nd2)
3478 self.assertNotEqual(v, nd2)
3479 self.assertNotEqual(w, nd1)
3480 self.assertNotEqual(v, w)
3481
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003482 # C-contiguous, different shape, struct module
3483 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3484 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003485 v = memoryview(nd1)
3486 w = memoryview(nd2)
3487
3488 self.assertEqual(v, nd1)
3489 self.assertEqual(w, nd2)
3490 self.assertNotEqual(v, nd2)
3491 self.assertNotEqual(w, nd1)
3492 self.assertNotEqual(v, w)
3493
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003494 # C-contiguous, different format, struct module
3495 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3496 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3497 v = memoryview(nd1)
3498 w = memoryview(nd2)
3499
3500 self.assertEqual(v, nd1)
3501 self.assertEqual(w, nd2)
3502 self.assertEqual(v, nd2)
3503 self.assertEqual(w, nd1)
3504 self.assertEqual(v, w)
3505
3506 def test_memoryview_compare_multidim_fortran(self):
3507
3508 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003509 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3510 flags=ND_FORTRAN)
3511 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3512 flags=ND_FORTRAN)
3513 v = memoryview(nd1)
3514 w = memoryview(nd2)
3515
3516 self.assertEqual(v, nd1)
3517 self.assertEqual(w, nd2)
3518 self.assertNotEqual(v, nd2)
3519 self.assertNotEqual(w, nd1)
3520 self.assertNotEqual(v, w)
3521
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003522 # Fortran-contiguous, different values, struct module
3523 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3524 flags=ND_FORTRAN)
3525 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3526 flags=ND_FORTRAN)
3527 v = memoryview(nd1)
3528 w = memoryview(nd2)
3529
3530 self.assertEqual(v, nd1)
3531 self.assertEqual(w, nd2)
3532 self.assertNotEqual(v, nd2)
3533 self.assertNotEqual(w, nd1)
3534 self.assertNotEqual(v, w)
3535
3536 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003537 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3538 flags=ND_FORTRAN)
3539 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3540 flags=ND_FORTRAN)
3541 v = memoryview(nd1)
3542 w = memoryview(nd2)
3543
3544 self.assertEqual(v, nd1)
3545 self.assertEqual(w, nd2)
3546 self.assertNotEqual(v, nd2)
3547 self.assertNotEqual(w, nd1)
3548 self.assertNotEqual(v, w)
3549
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003550 # Fortran-contiguous, different shape, struct module
3551 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003552 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003553 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003554 flags=ND_FORTRAN)
3555 v = memoryview(nd1)
3556 w = memoryview(nd2)
3557
3558 self.assertEqual(v, nd1)
3559 self.assertEqual(w, nd2)
3560 self.assertNotEqual(v, nd2)
3561 self.assertNotEqual(w, nd1)
3562 self.assertNotEqual(v, w)
3563
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003564 # Fortran-contiguous, different format, struct module
3565 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3566 flags=ND_FORTRAN)
3567 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3568 flags=ND_FORTRAN)
3569 v = memoryview(nd1)
3570 w = memoryview(nd2)
3571
3572 self.assertEqual(v, nd1)
3573 self.assertEqual(w, nd2)
3574 self.assertEqual(v, nd2)
3575 self.assertEqual(w, nd1)
3576 self.assertEqual(v, w)
3577
3578 def test_memoryview_compare_multidim_mixed(self):
3579
3580 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003581 lst1 = list(range(-15, 15))
3582 lst2 = transpose(lst1, [3, 2, 5])
3583 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3584 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3585 v = memoryview(nd1)
3586 w = memoryview(nd2)
3587
3588 self.assertEqual(v, nd1)
3589 self.assertEqual(w, nd2)
3590 self.assertEqual(v, w)
3591
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003592 # mixed C/Fortran contiguous, struct module
3593 lst1 = [(-3.3, -22, b'x')]*30
3594 lst1[5] = (-2.2, -22, b'x')
3595 lst2 = transpose(lst1, [3, 2, 5])
3596 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3597 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3598 v = memoryview(nd1)
3599 w = memoryview(nd2)
3600
3601 self.assertEqual(v, nd1)
3602 self.assertEqual(w, nd2)
3603 self.assertEqual(v, w)
3604
3605 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003606 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3607 nd1 = ex1[3:1:-1, ::-2]
3608 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3609 nd2 = ex2[1:3:1, ::-2]
3610 v = memoryview(nd1)
3611 w = memoryview(nd2)
3612
3613 self.assertEqual(v, nd1)
3614 self.assertEqual(w, nd2)
3615 self.assertNotEqual(v, nd2)
3616 self.assertNotEqual(w, nd1)
3617 self.assertNotEqual(v, w)
3618
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003619 # same values, non-contiguous, struct module
3620 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3621 nd1 = ex1[3:1:-1, ::-2]
3622 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3623 nd2 = ex2[1:3:1, ::-2]
3624 v = memoryview(nd1)
3625 w = memoryview(nd2)
3626
3627 self.assertEqual(v, nd1)
3628 self.assertEqual(w, nd2)
3629 self.assertEqual(v, nd2)
3630 self.assertEqual(w, nd1)
3631 self.assertEqual(v, w)
3632
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003633 # different shape
3634 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3635 nd1 = ex1[1:3:, ::-2]
3636 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3637 nd2 = ex2[1:3:, ::-2]
3638 v = memoryview(nd1)
3639 w = memoryview(nd2)
3640
3641 self.assertEqual(v, nd1)
3642 self.assertEqual(w, nd2)
3643 self.assertNotEqual(v, nd2)
3644 self.assertNotEqual(w, nd1)
3645 self.assertNotEqual(v, w)
3646
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003647 # different shape, struct module
3648 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003649 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003650 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003651 nd2 = ex2[1:3:, ::-2]
3652 v = memoryview(nd1)
3653 w = memoryview(nd2)
3654
3655 self.assertEqual(v, nd1)
3656 self.assertEqual(w, nd2)
3657 self.assertNotEqual(v, nd2)
3658 self.assertNotEqual(w, nd1)
3659 self.assertNotEqual(v, w)
3660
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003661 # different format, struct module
3662 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3663 nd1 = ex1[1:3:, ::-2]
3664 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3665 nd2 = ex2[1:3:, ::-2]
3666 v = memoryview(nd1)
3667 w = memoryview(nd2)
3668
3669 self.assertEqual(v, nd1)
3670 self.assertEqual(w, nd2)
3671 self.assertNotEqual(v, nd2)
3672 self.assertNotEqual(w, nd1)
3673 self.assertNotEqual(v, w)
3674
3675 def test_memoryview_compare_multidim_zero_shape(self):
3676
3677 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003678 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3679 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3680 v = memoryview(nd1)
3681 w = memoryview(nd2)
3682
3683 self.assertEqual(v, nd1)
3684 self.assertEqual(w, nd2)
3685 self.assertNotEqual(v, nd2)
3686 self.assertNotEqual(w, nd1)
3687 self.assertNotEqual(v, w)
3688
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003689 # zeros in shape, struct module
3690 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3691 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3692 v = memoryview(nd1)
3693 w = memoryview(nd2)
3694
3695 self.assertEqual(v, nd1)
3696 self.assertEqual(w, nd2)
3697 self.assertNotEqual(v, nd2)
3698 self.assertNotEqual(w, nd1)
3699 self.assertNotEqual(v, w)
3700
3701 def test_memoryview_compare_multidim_zero_strides(self):
3702
3703 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003704 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3705 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3706 v = memoryview(nd1)
3707 w = memoryview(nd2)
3708
3709 self.assertEqual(v, nd1)
3710 self.assertEqual(w, nd2)
3711 self.assertEqual(v, nd2)
3712 self.assertEqual(w, nd1)
3713 self.assertEqual(v, w)
3714 self.assertEqual(v.tolist(), w.tolist())
3715
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003716 # zero strides, struct module
3717 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3718 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3719 v = memoryview(nd1)
3720 w = memoryview(nd2)
3721
3722 self.assertEqual(v, nd1)
3723 self.assertEqual(w, nd2)
3724 self.assertEqual(v, nd2)
3725 self.assertEqual(w, nd1)
3726 self.assertEqual(v, w)
3727
3728 def test_memoryview_compare_multidim_suboffsets(self):
3729
3730 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003731 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3732 nd1 = ex1[3:1:-1, ::-2]
3733 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3734 nd2 = ex2[1:3:1, ::-2]
3735 v = memoryview(nd1)
3736 w = memoryview(nd2)
3737
3738 self.assertEqual(v, nd1)
3739 self.assertEqual(w, nd2)
3740 self.assertNotEqual(v, nd2)
3741 self.assertNotEqual(w, nd1)
3742 self.assertNotEqual(v, w)
3743
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003744 # suboffsets, struct module
3745 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3746 flags=ND_WRITABLE)
3747 ex1[2][7] = (1, -2)
3748 nd1 = ex1[3:1:-1, ::-2]
3749
3750 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3751 flags=ND_PIL|ND_WRITABLE)
3752 ex2[2][7] = (1, -2)
3753 nd2 = ex2[1:3:1, ::-2]
3754
3755 v = memoryview(nd1)
3756 w = memoryview(nd2)
3757
3758 self.assertEqual(v, nd1)
3759 self.assertEqual(w, nd2)
3760 self.assertEqual(v, nd2)
3761 self.assertEqual(w, nd1)
3762 self.assertEqual(v, w)
3763
3764 # suboffsets, different shape
3765 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3766 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003767 nd1 = ex1[1:3:, ::-2]
3768 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3769 nd2 = ex2[1:3:, ::-2]
3770 v = memoryview(nd1)
3771 w = memoryview(nd2)
3772
3773 self.assertEqual(v, nd1)
3774 self.assertEqual(w, nd2)
3775 self.assertNotEqual(v, nd2)
3776 self.assertNotEqual(w, nd1)
3777 self.assertNotEqual(v, w)
3778
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003779 # suboffsets, different shape, struct module
3780 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3781 flags=ND_PIL|ND_WRITABLE)
3782 nd1 = ex1[1:2:, ::-2]
3783
3784 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3785 nd2 = ex2[1:2:, ::-2]
3786
3787 v = memoryview(nd1)
3788 w = memoryview(nd2)
3789
3790 self.assertEqual(v, nd1)
3791 self.assertEqual(w, nd2)
3792 self.assertNotEqual(v, nd2)
3793 self.assertNotEqual(w, nd1)
3794 self.assertNotEqual(v, w)
3795
3796 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003797 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3798 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003799 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003800 nd2 = ex2[1:3:, ::-2]
3801 v = memoryview(nd1)
3802 w = memoryview(nd2)
3803
3804 self.assertEqual(v, nd1)
3805 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003806 self.assertEqual(v, nd2)
3807 self.assertEqual(w, nd1)
3808 self.assertEqual(v, w)
3809
3810 # suboffsets, different format, struct module
3811 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3812 flags=ND_PIL|ND_WRITABLE)
3813 ex1[1][2][2] = (b'sushi', b'', 1)
3814 nd1 = ex1[1:3:, ::-2]
3815
3816 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3817 flags=ND_PIL|ND_WRITABLE)
3818 ex1[1][2][2] = (b'sushi', b'', 1)
3819 nd2 = ex2[1:3:, ::-2]
3820
3821 v = memoryview(nd1)
3822 w = memoryview(nd2)
3823
3824 self.assertEqual(v, nd1)
3825 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003826 self.assertNotEqual(v, nd2)
3827 self.assertNotEqual(w, nd1)
3828 self.assertNotEqual(v, w)
3829
3830 # initialize mixed C/Fortran + suboffsets
3831 lst1 = list(range(-15, 15))
3832 lst2 = transpose(lst1, [3, 2, 5])
3833 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3834 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3835 v = memoryview(nd1)
3836 w = memoryview(nd2)
3837
3838 self.assertEqual(v, nd1)
3839 self.assertEqual(w, nd2)
3840 self.assertEqual(v, w)
3841
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003842 # initialize mixed C/Fortran + suboffsets, struct module
3843 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3844 lst1[11] = (b'ramen', b'spicy', 9.45)
3845 lst2 = transpose(lst1, [3, 2, 5])
3846
3847 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3848 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3849 flags=ND_FORTRAN|ND_PIL)
3850 v = memoryview(nd1)
3851 w = memoryview(nd2)
3852
3853 self.assertEqual(v, nd1)
3854 self.assertEqual(w, nd2)
3855 self.assertEqual(v, w)
3856
3857 def test_memoryview_compare_not_equal(self):
3858
3859 # items not equal
3860 for byteorder in ['=', '<', '>', '!']:
3861 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3862 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3863 flags=ND_WRITABLE|ND_FORTRAN)
3864 y[2][3][1][1][1] = 1
3865 a = memoryview(x)
3866 b = memoryview(y)
3867 self.assertEqual(a, x)
3868 self.assertEqual(b, y)
3869 self.assertNotEqual(a, b)
3870 self.assertNotEqual(a, y)
3871 self.assertNotEqual(b, x)
3872
3873 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3874 format=byteorder+'QLH')
3875 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3876 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3877 y[2][3][1][1][1] = (1, 1, 1)
3878 a = memoryview(x)
3879 b = memoryview(y)
3880 self.assertEqual(a, x)
3881 self.assertEqual(b, y)
3882 self.assertNotEqual(a, b)
3883 self.assertNotEqual(a, y)
3884 self.assertNotEqual(b, x)
3885
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003886 def test_memoryview_check_released(self):
3887
3888 a = array.array('d', [1.1, 2.2, 3.3])
3889
3890 m = memoryview(a)
3891 m.release()
3892
3893 # PyMemoryView_FromObject()
3894 self.assertRaises(ValueError, memoryview, m)
3895 # memoryview.cast()
3896 self.assertRaises(ValueError, m.cast, 'c')
3897 # getbuffer()
3898 self.assertRaises(ValueError, ndarray, m)
3899 # memoryview.tolist()
3900 self.assertRaises(ValueError, m.tolist)
3901 # memoryview.tobytes()
3902 self.assertRaises(ValueError, m.tobytes)
3903 # sequence
3904 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3905 # subscript
3906 self.assertRaises(ValueError, m.__getitem__, 0)
3907 # assignment
3908 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3909
3910 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3911 'shape', 'strides', 'suboffsets', 'c_contiguous',
3912 'f_contiguous', 'contiguous'):
3913 self.assertRaises(ValueError, m.__getattribute__, attr)
3914
3915 # richcompare
3916 b = array.array('d', [1.1, 2.2, 3.3])
3917 m1 = memoryview(a)
3918 m2 = memoryview(b)
3919
3920 self.assertEqual(m1, m2)
3921 m1.release()
3922 self.assertNotEqual(m1, m2)
3923 self.assertNotEqual(m1, a)
3924 self.assertEqual(m1, m1)
3925
3926 def test_memoryview_tobytes(self):
3927 # Many implicit tests are already in self.verify().
3928
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003929 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003930
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003931 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003932 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003933 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003934 self.assertEqual(m.tobytes(), nd.tobytes())
3935
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003936 nd = ndarray([t], shape=[1], format='>hQiLl')
3937 m = memoryview(nd)
3938 self.assertEqual(m, nd)
3939 self.assertEqual(m.tobytes(), nd.tobytes())
3940
3941 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3942 m = memoryview(nd)
3943 self.assertEqual(m, nd)
3944 self.assertEqual(m.tobytes(), nd.tobytes())
3945
3946 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3947 format='<hQiLl')
3948 m = memoryview(nd)
3949 self.assertEqual(m, nd)
3950 self.assertEqual(m.tobytes(), nd.tobytes())
3951
3952 # Unknown formats are handled: tobytes() purely depends on itemsize.
3953 if ctypes:
3954 # format: "T{>l:x:>l:y:}"
3955 class BEPoint(ctypes.BigEndianStructure):
3956 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3957 point = BEPoint(100, 200)
3958 a = memoryview(point)
3959 self.assertEqual(a.tobytes(), bytes(point))
3960
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003961 def test_memoryview_get_contiguous(self):
3962 # Many implicit tests are already in self.verify().
3963
3964 # no buffer interface
3965 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3966
3967 # writable request to read-only object
3968 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3969
3970 # writable request to non-contiguous object
3971 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3972 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3973
3974 # scalar, read-only request from read-only exporter
3975 nd = ndarray(9, shape=(), format="L")
3976 for order in ['C', 'F', 'A']:
3977 m = get_contiguous(nd, PyBUF_READ, order)
3978 self.assertEqual(m, nd)
3979 self.assertEqual(m[()], 9)
3980
3981 # scalar, read-only request from writable exporter
3982 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3983 for order in ['C', 'F', 'A']:
3984 m = get_contiguous(nd, PyBUF_READ, order)
3985 self.assertEqual(m, nd)
3986 self.assertEqual(m[()], 9)
3987
3988 # scalar, writable request
3989 for order in ['C', 'F', 'A']:
3990 nd[()] = 9
3991 m = get_contiguous(nd, PyBUF_WRITE, order)
3992 self.assertEqual(m, nd)
3993 self.assertEqual(m[()], 9)
3994
3995 m[()] = 10
3996 self.assertEqual(m[()], 10)
3997 self.assertEqual(nd[()], 10)
3998
3999 # zeros in shape
4000 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
4001 for order in ['C', 'F', 'A']:
4002 m = get_contiguous(nd, PyBUF_READ, order)
4003 self.assertRaises(IndexError, m.__getitem__, 0)
4004 self.assertEqual(m, nd)
4005 self.assertEqual(m.tolist(), [])
4006
4007 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
4008 flags=ND_WRITABLE)
4009 for order in ['C', 'F', 'A']:
4010 m = get_contiguous(nd, PyBUF_READ, order)
4011 self.assertEqual(ndarray(m).tolist(), [[], []])
4012
4013 # one-dimensional
4014 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
4015 for order in ['C', 'F', 'A']:
4016 m = get_contiguous(nd, PyBUF_WRITE, order)
4017 self.assertEqual(m, nd)
4018 self.assertEqual(m.tolist(), nd.tolist())
4019
4020 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
4021 for order in ['C', 'F', 'A']:
4022 m = get_contiguous(nd, PyBUF_WRITE, order)
4023 self.assertEqual(m, nd)
4024 self.assertEqual(m.tolist(), nd.tolist())
4025
4026 # one-dimensional, non-contiguous
4027 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
4028 for order in ['C', 'F', 'A']:
4029 m = get_contiguous(nd, PyBUF_READ, order)
4030 self.assertEqual(m, nd)
4031 self.assertEqual(m.tolist(), nd.tolist())
4032 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4033 self.assertEqual(m[1], 3)
4034 self.assertEqual(nd[1], 3)
4035
4036 nd = nd[::-1]
4037 for order in ['C', 'F', 'A']:
4038 m = get_contiguous(nd, PyBUF_READ, order)
4039 self.assertEqual(m, nd)
4040 self.assertEqual(m.tolist(), nd.tolist())
4041 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4042 self.assertEqual(m[1], 1)
4043 self.assertEqual(nd[1], 1)
4044
4045 # multi-dimensional, contiguous input
4046 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
4047 for order in ['C', 'A']:
4048 m = get_contiguous(nd, PyBUF_WRITE, order)
4049 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4050
4051 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
4052 m = get_contiguous(nd, PyBUF_READ, order)
4053 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4054
4055 nd = ndarray(list(range(12)), shape=[3, 4],
4056 flags=ND_WRITABLE|ND_FORTRAN)
4057 for order in ['F', 'A']:
4058 m = get_contiguous(nd, PyBUF_WRITE, order)
4059 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4060
4061 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
4062 m = get_contiguous(nd, PyBUF_READ, order)
4063 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4064
4065 # multi-dimensional, non-contiguous input
4066 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
4067 for order in ['C', 'F', 'A']:
4068 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
4069 order)
4070 m = get_contiguous(nd, PyBUF_READ, order)
4071 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4072
4073 # flags
4074 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
4075 m = get_contiguous(nd, PyBUF_READ, 'C')
4076 self.assertTrue(m.c_contiguous)
4077
4078 def test_memoryview_serializing(self):
4079
4080 # C-contiguous
4081 size = struct.calcsize('i')
4082 a = array.array('i', [1,2,3,4,5])
4083 m = memoryview(a)
4084 buf = io.BytesIO(m)
4085 b = bytearray(5*size)
4086 buf.readinto(b)
4087 self.assertEqual(m.tobytes(), b)
4088
4089 # C-contiguous, multi-dimensional
4090 size = struct.calcsize('L')
4091 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
4092 m = memoryview(nd)
4093 buf = io.BytesIO(m)
4094 b = bytearray(2*3*2*size)
4095 buf.readinto(b)
4096 self.assertEqual(m.tobytes(), b)
4097
4098 # Fortran contiguous, multi-dimensional
4099 #size = struct.calcsize('L')
4100 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
4101 # flags=ND_FORTRAN)
4102 #m = memoryview(nd)
4103 #buf = io.BytesIO(m)
4104 #b = bytearray(2*3*2*size)
4105 #buf.readinto(b)
4106 #self.assertEqual(m.tobytes(), b)
4107
4108 def test_memoryview_hash(self):
4109
4110 # bytes exporter
4111 b = bytes(list(range(12)))
4112 m = memoryview(b)
4113 self.assertEqual(hash(b), hash(m))
4114
4115 # C-contiguous
4116 mc = m.cast('c', shape=[3,4])
4117 self.assertEqual(hash(mc), hash(b))
4118
4119 # non-contiguous
4120 mx = m[::-2]
4121 b = bytes(list(range(12))[::-2])
4122 self.assertEqual(hash(mx), hash(b))
4123
4124 # Fortran contiguous
4125 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
4126 m = memoryview(nd)
4127 self.assertEqual(hash(m), hash(nd))
4128
4129 # multi-dimensional slice
4130 nd = ndarray(list(range(30)), shape=[3,2,5])
4131 x = nd[::2, ::, ::-1]
4132 m = memoryview(x)
4133 self.assertEqual(hash(m), hash(x))
4134
4135 # multi-dimensional slice with suboffsets
4136 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
4137 x = nd[::2, ::, ::-1]
4138 m = memoryview(x)
4139 self.assertEqual(hash(m), hash(x))
4140
Stefan Krah4af77a02012-11-02 17:49:22 +01004141 # equality-hash invariant
4142 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004143 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004144
4145 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004146 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004147
Stefan Krahb716f842012-11-04 20:53:50 +01004148 self.assertEqual(a, b)
4149 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004150
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004151 # non-byte formats
4152 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4153 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004154 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004155
4156 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4157 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004158 self.assertRaises(ValueError, m.__hash__)
4159
4160 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4161 m = memoryview(nd)
4162 self.assertRaises(ValueError, m.__hash__)
4163
4164 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4165 m = memoryview(nd)
4166 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004167
4168 def test_memoryview_release(self):
4169
4170 # Create re-exporter from getbuffer(memoryview), then release the view.
4171 a = bytearray([1,2,3])
4172 m = memoryview(a)
4173 nd = ndarray(m) # re-exporter
4174 self.assertRaises(BufferError, m.release)
4175 del nd
4176 m.release()
4177
Stefan Krah4e99a312012-03-05 09:30:47 +01004178 a = bytearray([1,2,3])
4179 m = memoryview(a)
4180 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4181 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4182 self.assertIs(nd2.obj, m)
4183 self.assertRaises(BufferError, m.release)
4184 del nd1, nd2
4185 m.release()
4186
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004187 # chained views
4188 a = bytearray([1,2,3])
4189 m1 = memoryview(a)
4190 m2 = memoryview(m1)
4191 nd = ndarray(m2) # re-exporter
4192 m1.release()
4193 self.assertRaises(BufferError, m2.release)
4194 del nd
4195 m2.release()
4196
Stefan Krah4e99a312012-03-05 09:30:47 +01004197 a = bytearray([1,2,3])
4198 m1 = memoryview(a)
4199 m2 = memoryview(m1)
4200 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4201 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4202 self.assertIs(nd2.obj, m2)
4203 m1.release()
4204 self.assertRaises(BufferError, m2.release)
4205 del nd1, nd2
4206 m2.release()
4207
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004208 # Allow changing layout while buffers are exported.
4209 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4210 m1 = memoryview(nd)
4211
4212 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4213 m2 = memoryview(nd)
4214
4215 x = memoryview(m1)
4216 self.assertEqual(x.tolist(), m1.tolist())
4217
4218 y = memoryview(m2)
4219 self.assertEqual(y.tolist(), m2.tolist())
4220 self.assertEqual(y.tolist(), nd.tolist())
4221 m2.release()
4222 y.release()
4223
4224 nd.pop() # pop the current view
4225 self.assertEqual(x.tolist(), nd.tolist())
4226
4227 del nd
4228 m1.release()
4229 x.release()
4230
4231 # If multiple memoryviews share the same managed buffer, implicit
4232 # release() in the context manager's __exit__() method should still
4233 # work.
4234 def catch22(b):
4235 with memoryview(b) as m2:
4236 pass
4237
4238 x = bytearray(b'123')
4239 with memoryview(x) as m1:
4240 catch22(m1)
4241 self.assertEqual(m1[0], ord(b'1'))
4242
Stefan Krah4e99a312012-03-05 09:30:47 +01004243 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4244 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4245 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4246 self.assertIs(z.obj, x)
4247 with memoryview(z) as m:
4248 catch22(m)
4249 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4250
4251 # Test garbage collection.
4252 for flags in (0, ND_REDIRECT):
4253 x = bytearray(b'123')
4254 with memoryview(x) as m1:
4255 del x
4256 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4257 with memoryview(y) as m2:
4258 del y
4259 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4260 with memoryview(z) as m3:
4261 del z
4262 catch22(m3)
4263 catch22(m2)
4264 catch22(m1)
4265 self.assertEqual(m1[0], ord(b'1'))
4266 self.assertEqual(m2[1], ord(b'2'))
4267 self.assertEqual(m3[2], ord(b'3'))
4268 del m3
4269 del m2
4270 del m1
4271
4272 x = bytearray(b'123')
4273 with memoryview(x) as m1:
4274 del x
4275 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4276 with memoryview(y) as m2:
4277 del y
4278 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4279 with memoryview(z) as m3:
4280 del z
4281 catch22(m1)
4282 catch22(m2)
4283 catch22(m3)
4284 self.assertEqual(m1[0], ord(b'1'))
4285 self.assertEqual(m2[1], ord(b'2'))
4286 self.assertEqual(m3[2], ord(b'3'))
4287 del m1, m2, m3
4288
Stefan Krahfcbb4162012-03-05 10:45:31 +01004289 # memoryview.release() fails if the view has exported buffers.
4290 x = bytearray(b'123')
4291 with self.assertRaises(BufferError):
4292 with memoryview(x) as m:
4293 ex = ndarray(m)
4294 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004295
Stefan Krah4e99a312012-03-05 09:30:47 +01004296 def test_memoryview_redirect(self):
4297
4298 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4299 a = array.array('d', [1.0 * x for x in range(12)])
4300
4301 for x in (nd, a):
4302 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4303 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4304 m = memoryview(z)
4305
4306 self.assertIs(y.obj, x)
4307 self.assertIs(z.obj, x)
4308 self.assertIs(m.obj, x)
4309
4310 self.assertEqual(m, x)
4311 self.assertEqual(m, y)
4312 self.assertEqual(m, z)
4313
4314 self.assertEqual(m[1:3], x[1:3])
4315 self.assertEqual(m[1:3], y[1:3])
4316 self.assertEqual(m[1:3], z[1:3])
4317 del y, z
4318 self.assertEqual(m[1:3], x[1:3])
4319
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004320 def test_memoryview_from_static_exporter(self):
4321
4322 fmt = 'B'
4323 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4324
4325 # exceptions
4326 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4327
4328 # view.obj==x
4329 x = staticarray()
4330 y = memoryview(x)
4331 self.verify(y, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004332 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004333 ndim=1, shape=[12], strides=[1],
4334 lst=lst)
4335 for i in range(12):
4336 self.assertEqual(y[i], i)
4337 del x
4338 del y
4339
4340 x = staticarray()
4341 y = memoryview(x)
4342 del y
4343 del x
4344
4345 x = staticarray()
4346 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4347 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4348 m = memoryview(z)
4349 self.assertIs(y.obj, x)
4350 self.assertIs(m.obj, z)
4351 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004352 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004353 ndim=1, shape=[12], strides=[1],
4354 lst=lst)
4355 del x, y, z, m
4356
4357 x = staticarray()
4358 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4359 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4360 m = memoryview(z)
4361 self.assertIs(y.obj, x)
4362 self.assertIs(z.obj, x)
4363 self.assertIs(m.obj, x)
4364 self.verify(m, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004365 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004366 ndim=1, shape=[12], strides=[1],
4367 lst=lst)
4368 del x, y, z, m
4369
4370 # view.obj==NULL
4371 x = staticarray(legacy_mode=True)
4372 y = memoryview(x)
4373 self.verify(y, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004374 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004375 ndim=1, shape=[12], strides=[1],
4376 lst=lst)
4377 for i in range(12):
4378 self.assertEqual(y[i], i)
4379 del x
4380 del y
4381
4382 x = staticarray(legacy_mode=True)
4383 y = memoryview(x)
4384 del y
4385 del x
4386
4387 x = staticarray(legacy_mode=True)
4388 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4389 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4390 m = memoryview(z)
4391 self.assertIs(y.obj, None)
4392 self.assertIs(m.obj, z)
4393 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004394 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004395 ndim=1, shape=[12], strides=[1],
4396 lst=lst)
4397 del x, y, z, m
4398
4399 x = staticarray(legacy_mode=True)
4400 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4401 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4402 m = memoryview(z)
4403 # Clearly setting view.obj==NULL is inferior, since it
4404 # messes up the redirection chain:
4405 self.assertIs(y.obj, None)
4406 self.assertIs(z.obj, y)
4407 self.assertIs(m.obj, y)
4408 self.verify(m, obj=y,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004409 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004410 ndim=1, shape=[12], strides=[1],
4411 lst=lst)
4412 del x, y, z, m
4413
Stefan Krah1649c1b2012-03-05 17:45:17 +01004414 def test_memoryview_getbuffer_undefined(self):
4415
4416 # getbufferproc does not adhere to the new documentation
4417 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4418 self.assertRaises(BufferError, memoryview, nd)
4419
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004420 def test_issue_7385(self):
4421 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4422 self.assertRaises(BufferError, memoryview, x)
4423
Joannah Nanjekye9e66aba2019-08-20 11:46:36 -03004424 @support.cpython_only
4425 def test_pybuffer_size_from_format(self):
4426 # basic tests
4427 for format in ('', 'ii', '3s'):
4428 self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format),
4429 struct.calcsize(format))
4430
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004431
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004432if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004433 unittest.main()