blob: 2ddca06b8b568a1e2e3ac2d666dd2b7550c8d3e0 [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['@']:
2757 tfmt = ('', '@')[randrange(2)] + char
2758 tsize = struct.calcsize(tfmt)
2759 n = prod(_tshape) * tsize
2760 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2761 for fmt, items, _ in iter_format(n, obj):
2762 size = struct.calcsize(fmt)
2763 shape = [n] if n > 0 else []
2764 tshape = _tshape + [size]
2765
2766 ex = ndarray(items, shape=shape, format=fmt)
2767 m = memoryview(ex)
2768
2769 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2770
2771 if titems is None:
2772 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2773 continue
2774 if titems == 'nan':
2775 continue # NaNs in lists are a recipe for trouble.
2776
2777 # 1D -> ND
2778 nd = ndarray(titems, shape=tshape, format=tfmt)
2779
2780 m2 = m.cast(tfmt, shape=tshape)
2781 ndim = len(tshape)
2782 strides = nd.strides
2783 lst = nd.tolist()
2784 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002785 itemsize=tsize, fmt=tfmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002786 ndim=ndim, shape=tshape, strides=strides,
2787 lst=lst, cast=True)
2788
2789 # ND -> 1D
2790 m3 = m2.cast(fmt)
2791 m4 = m2.cast(fmt, shape=shape)
2792 ndim = len(shape)
2793 strides = ex.strides
2794 lst = ex.tolist()
2795
2796 self.verify(m3, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002797 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002798 ndim=ndim, shape=shape, strides=strides,
2799 lst=lst, cast=True)
2800
2801 self.verify(m4, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002802 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002803 ndim=ndim, shape=shape, strides=strides,
2804 lst=lst, cast=True)
2805
Stefan Krah0c515952015-08-08 13:38:10 +02002806 if ctypes:
2807 # format: "T{>l:x:>d:y:}"
2808 class BEPoint(ctypes.BigEndianStructure):
2809 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)]
2810 point = BEPoint(100, 200.1)
2811 m1 = memoryview(point)
2812 m2 = m1.cast('B')
2813 self.assertEqual(m2.obj, point)
2814 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002815 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002816 self.assertEqual(m2.ndim, 1)
2817 self.assertEqual(m2.shape, (m2.nbytes,))
2818 self.assertEqual(m2.strides, (1,))
2819 self.assertEqual(m2.suboffsets, ())
2820
2821 x = ctypes.c_double(1.2)
2822 m1 = memoryview(x)
2823 m2 = m1.cast('c')
2824 self.assertEqual(m2.obj, x)
2825 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002826 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002827 self.assertEqual(m2.ndim, 1)
2828 self.assertEqual(m2.shape, (m2.nbytes,))
2829 self.assertEqual(m2.strides, (1,))
2830 self.assertEqual(m2.suboffsets, ())
2831
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002832 def test_memoryview_tolist(self):
2833
2834 # Most tolist() tests are in self.verify() etc.
2835
2836 a = array.array('h', list(range(-6, 6)))
2837 m = memoryview(a)
2838 self.assertEqual(m, a)
2839 self.assertEqual(m.tolist(), a.tolist())
2840
2841 a = a[2::3]
2842 m = m[2::3]
2843 self.assertEqual(m, a)
2844 self.assertEqual(m.tolist(), a.tolist())
2845
2846 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2847 m = memoryview(ex)
2848 self.assertEqual(m.tolist(), ex.tolist())
2849
2850 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2851 m = memoryview(ex)
2852 self.assertRaises(NotImplementedError, m.tolist)
2853
2854 ex = ndarray([b'12345'], shape=[1], format="s")
2855 m = memoryview(ex)
2856 self.assertRaises(NotImplementedError, m.tolist)
2857
2858 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2859 m = memoryview(ex)
2860 self.assertRaises(NotImplementedError, m.tolist)
2861
2862 def test_memoryview_repr(self):
2863 m = memoryview(bytearray(9))
2864 r = m.__repr__()
2865 self.assertTrue(r.startswith("<memory"))
2866
2867 m.release()
2868 r = m.__repr__()
2869 self.assertTrue(r.startswith("<released"))
2870
2871 def test_memoryview_sequence(self):
2872
2873 for fmt in ('d', 'f'):
2874 inf = float(3e400)
2875 ex = array.array(fmt, [1.0, inf, 3.0])
2876 m = memoryview(ex)
2877 self.assertIn(1.0, m)
2878 self.assertIn(5e700, m)
2879 self.assertIn(3.0, m)
2880
2881 ex = ndarray(9.0, [], format='f')
2882 m = memoryview(ex)
2883 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2884
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002885 @contextlib.contextmanager
2886 def assert_out_of_bounds_error(self, dim):
2887 with self.assertRaises(IndexError) as cm:
2888 yield
2889 self.assertEqual(str(cm.exception),
2890 "index out of bounds on dimension %d" % (dim,))
2891
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002892 def test_memoryview_index(self):
2893
2894 # ndim = 0
2895 ex = ndarray(12.5, shape=[], format='d')
2896 m = memoryview(ex)
2897 self.assertEqual(m[()], 12.5)
2898 self.assertEqual(m[...], m)
2899 self.assertEqual(m[...], ex)
2900 self.assertRaises(TypeError, m.__getitem__, 0)
2901
2902 ex = ndarray((1,2,3), shape=[], format='iii')
2903 m = memoryview(ex)
2904 self.assertRaises(NotImplementedError, m.__getitem__, ())
2905
2906 # range
2907 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2908 m = memoryview(ex)
2909
2910 self.assertRaises(IndexError, m.__getitem__, 2**64)
2911 self.assertRaises(TypeError, m.__getitem__, 2.0)
2912 self.assertRaises(TypeError, m.__getitem__, 0.0)
2913
2914 # out of bounds
2915 self.assertRaises(IndexError, m.__getitem__, -8)
2916 self.assertRaises(IndexError, m.__getitem__, 8)
2917
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002918 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002919 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2920 m = memoryview(ex)
2921
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002922 self.assertEqual(m[0, 0], 0)
2923 self.assertEqual(m[2, 0], 8)
2924 self.assertEqual(m[2, 3], 11)
2925 self.assertEqual(m[-1, -1], 11)
2926 self.assertEqual(m[-3, -4], 0)
2927
2928 # out of bounds
2929 for index in (3, -4):
2930 with self.assert_out_of_bounds_error(dim=1):
2931 m[index, 0]
2932 for index in (4, -5):
2933 with self.assert_out_of_bounds_error(dim=2):
2934 m[0, index]
2935 self.assertRaises(IndexError, m.__getitem__, (2**64, 0))
2936 self.assertRaises(IndexError, m.__getitem__, (0, 2**64))
2937
2938 self.assertRaises(TypeError, m.__getitem__, (0, 0, 0))
2939 self.assertRaises(TypeError, m.__getitem__, (0.0, 0.0))
2940
2941 # Not implemented: multidimensional sub-views
2942 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002943 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2944
2945 def test_memoryview_assign(self):
2946
2947 # ndim = 0
2948 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2949 m = memoryview(ex)
2950 m[()] = 22.5
2951 self.assertEqual(m[()], 22.5)
2952 m[...] = 23.5
2953 self.assertEqual(m[()], 23.5)
2954 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2955
2956 # read-only
2957 ex = ndarray(list(range(7)), shape=[7])
2958 m = memoryview(ex)
2959 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2960
2961 # range
2962 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2963 m = memoryview(ex)
2964
2965 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2966 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2967 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2968
2969 # out of bounds
2970 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2971 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2972
2973 # pack_single() success:
2974 for fmt in fmtdict['@']:
2975 if fmt == 'c' or fmt == '?':
2976 continue
2977 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2978 m = memoryview(ex)
2979 i = randrange(-3, 3)
2980 m[i] = 8
2981 self.assertEqual(m[i], 8)
2982 self.assertEqual(m[i], ex[i])
2983
2984 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2985 flags=ND_WRITABLE)
2986 m = memoryview(ex)
2987 m[2] = b'9'
2988 self.assertEqual(m[2], b'9')
2989
2990 ex = ndarray([True, False, True], shape=[3], format='?',
2991 flags=ND_WRITABLE)
2992 m = memoryview(ex)
2993 m[1] = True
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002994 self.assertIs(m[1], True)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002995
2996 # pack_single() exceptions:
2997 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2998 m = memoryview(nd)
2999 self.assertRaises(TypeError, m.__setitem__, 0, 100)
3000
3001 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
3002 m1 = memoryview(ex)
3003
3004 for fmt, _range in fmtdict['@'].items():
3005 if (fmt == '?'): # PyObject_IsTrue() accepts anything
3006 continue
3007 if fmt == 'c': # special case tested above
3008 continue
3009 m2 = m1.cast(fmt)
3010 lo, hi = _range
3011 if fmt == 'd' or fmt == 'f':
3012 lo, hi = -2**1024, 2**1024
3013 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
3014 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
3015 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
3016 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
3017
3018 # invalid item
3019 m2 = m1.cast('c')
3020 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
3021
3022 # format not implemented
3023 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
3024 m = memoryview(ex)
3025 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3026
3027 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
3028 m = memoryview(ex)
3029 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3030
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003031 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003032 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
3033 m = memoryview(ex)
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003034 m[0,1] = 42
3035 self.assertEqual(ex[0][1], 42)
3036 m[-1,-1] = 43
3037 self.assertEqual(ex[2][3], 43)
3038 # errors
3039 for index in (3, -4):
3040 with self.assert_out_of_bounds_error(dim=1):
3041 m[index, 0] = 0
3042 for index in (4, -5):
3043 with self.assert_out_of_bounds_error(dim=2):
3044 m[0, index] = 0
3045 self.assertRaises(IndexError, m.__setitem__, (2**64, 0), 0)
3046 self.assertRaises(IndexError, m.__setitem__, (0, 2**64), 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003047
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003048 self.assertRaises(TypeError, m.__setitem__, (0, 0, 0), 0)
3049 self.assertRaises(TypeError, m.__setitem__, (0.0, 0.0), 0)
3050
3051 # Not implemented: multidimensional sub-views
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003052 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
3053
3054 def test_memoryview_slice(self):
3055
3056 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3057 m = memoryview(ex)
3058
3059 # zero step
3060 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
3061 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
3062 bytearray([1,2]))
3063
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003064 # 0-dim slicing (identity function)
3065 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003066
3067 # multidimensional slices
3068 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3069 m = memoryview(ex)
3070
3071 self.assertRaises(NotImplementedError, m.__getitem__,
3072 (slice(0,2,1), slice(0,2,1)))
3073 self.assertRaises(NotImplementedError, m.__setitem__,
3074 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
3075
3076 # invalid slice tuple
3077 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
3078 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
3079 bytearray([1,2]))
3080
3081 # rvalue is not an exporter
3082 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
3083
3084 # non-contiguous slice assignment
3085 for flags in (0, ND_PIL):
3086 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
3087 flags=ND_WRITABLE|flags)
3088 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
3089 m1 = memoryview(ex1)
3090 m2 = memoryview(ex2)
3091
3092 ex1[2:5] = ex1[2:5]
3093 m1[2:5] = m2[2:5]
3094
3095 self.assertEqual(m1, ex1)
3096 self.assertEqual(m2, ex2)
3097
3098 ex1[1:3][::-1] = ex2[0:2][::1]
3099 m1[1:3][::-1] = m2[0:2][::1]
3100
3101 self.assertEqual(m1, ex1)
3102 self.assertEqual(m2, ex2)
3103
3104 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
3105 m1[4:1:-2][::-1] = m1[1:4:2][::1]
3106
3107 self.assertEqual(m1, ex1)
3108 self.assertEqual(m2, ex2)
3109
3110 def test_memoryview_array(self):
3111
3112 def cmptest(testcase, a, b, m, singleitem):
3113 for i, _ in enumerate(a):
3114 ai = a[i]
3115 mi = m[i]
3116 testcase.assertEqual(ai, mi)
3117 a[i] = singleitem
3118 if singleitem != ai:
3119 testcase.assertNotEqual(a, m)
3120 testcase.assertNotEqual(a, b)
3121 else:
3122 testcase.assertEqual(a, m)
3123 testcase.assertEqual(a, b)
3124 m[i] = singleitem
3125 testcase.assertEqual(a, m)
3126 testcase.assertEqual(b, m)
3127 a[i] = ai
3128 m[i] = mi
3129
3130 for n in range(1, 5):
3131 for fmt, items, singleitem in iter_format(n, 'array'):
3132 for lslice in genslices(n):
3133 for rslice in genslices(n):
3134
3135 a = array.array(fmt, items)
3136 b = array.array(fmt, items)
3137 m = memoryview(b)
3138
3139 self.assertEqual(m, a)
3140 self.assertEqual(m.tolist(), a.tolist())
3141 self.assertEqual(m.tobytes(), a.tobytes())
3142 self.assertEqual(len(m), len(a))
3143
3144 cmptest(self, a, b, m, singleitem)
3145
3146 array_err = None
3147 have_resize = None
3148 try:
3149 al = a[lslice]
3150 ar = a[rslice]
3151 a[lslice] = a[rslice]
3152 have_resize = len(al) != len(ar)
3153 except Exception as e:
3154 array_err = e.__class__
3155
3156 m_err = None
3157 try:
3158 m[lslice] = m[rslice]
3159 except Exception as e:
3160 m_err = e.__class__
3161
3162 if have_resize: # memoryview cannot change shape
3163 self.assertIs(m_err, ValueError)
3164 elif m_err or array_err:
3165 self.assertIs(m_err, array_err)
3166 else:
3167 self.assertEqual(m, a)
3168 self.assertEqual(m.tolist(), a.tolist())
3169 self.assertEqual(m.tobytes(), a.tobytes())
3170 cmptest(self, a, b, m, singleitem)
3171
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003172 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003173
3174 a = array.array('L', [1, 2, 3])
3175 b = array.array('L', [1, 2, 7])
3176
3177 # Ordering comparisons raise:
3178 v = memoryview(a)
3179 w = memoryview(b)
3180 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3181 self.assertIs(getattr(v, attr)(w), NotImplemented)
3182 self.assertIs(getattr(a, attr)(v), NotImplemented)
3183
3184 # Released views compare equal to themselves:
3185 v = memoryview(a)
3186 v.release()
3187 self.assertEqual(v, v)
3188 self.assertNotEqual(v, a)
3189 self.assertNotEqual(a, v)
3190
3191 v = memoryview(a)
3192 w = memoryview(a)
3193 w.release()
3194 self.assertNotEqual(v, w)
3195 self.assertNotEqual(w, v)
3196
3197 # Operand does not implement the buffer protocol:
3198 v = memoryview(a)
3199 self.assertNotEqual(v, [1, 2, 3])
3200
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003201 # NaNs
3202 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3203 nd[0] = (-1, float('nan'))
3204 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003205
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003206 # Depends on issue #15625: the struct module does not understand 'u'.
3207 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003208 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003209 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003210 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003211
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003212 # Some ctypes format strings are unknown to the struct module.
3213 if ctypes:
3214 # format: "T{>l:x:>l:y:}"
3215 class BEPoint(ctypes.BigEndianStructure):
3216 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3217 point = BEPoint(100, 200)
3218 a = memoryview(point)
3219 b = memoryview(point)
3220 self.assertNotEqual(a, b)
3221 self.assertNotEqual(a, point)
3222 self.assertNotEqual(point, a)
3223 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003224
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003225 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003226
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003227 nd1 = ndarray(1729, shape=[], format='@L')
3228 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
3229 v = memoryview(nd1)
3230 w = memoryview(nd2)
3231 self.assertEqual(v, w)
3232 self.assertEqual(w, v)
3233 self.assertEqual(v, nd2)
3234 self.assertEqual(nd2, v)
3235 self.assertEqual(w, nd1)
3236 self.assertEqual(nd1, w)
3237
3238 self.assertFalse(v.__ne__(w))
3239 self.assertFalse(w.__ne__(v))
3240
3241 w[()] = 1728
3242 self.assertNotEqual(v, w)
3243 self.assertNotEqual(w, v)
3244 self.assertNotEqual(v, nd2)
3245 self.assertNotEqual(nd2, v)
3246 self.assertNotEqual(w, nd1)
3247 self.assertNotEqual(nd1, w)
3248
3249 self.assertFalse(v.__eq__(w))
3250 self.assertFalse(w.__eq__(v))
3251
3252 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3253 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3254 m = memoryview(ex)
3255
3256 self.assertEqual(m, nd)
3257 m[9] = 100
3258 self.assertNotEqual(m, nd)
3259
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003260 # struct module: equal
3261 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3262 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3263 flags=ND_WRITABLE)
3264 v = memoryview(nd1)
3265 w = memoryview(nd2)
3266 self.assertEqual(v, w)
3267 self.assertEqual(w, v)
3268 self.assertEqual(v, nd2)
3269 self.assertEqual(nd2, v)
3270 self.assertEqual(w, nd1)
3271 self.assertEqual(nd1, w)
3272
3273 # struct module: not equal
3274 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3275 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3276 flags=ND_WRITABLE)
3277 v = memoryview(nd1)
3278 w = memoryview(nd2)
3279 self.assertNotEqual(v, w)
3280 self.assertNotEqual(w, v)
3281 self.assertNotEqual(v, nd2)
3282 self.assertNotEqual(nd2, v)
3283 self.assertNotEqual(w, nd1)
3284 self.assertNotEqual(nd1, w)
3285 self.assertEqual(v, nd1)
3286 self.assertEqual(w, nd2)
3287
3288 def test_memoryview_compare_ndim_one(self):
3289
3290 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003291 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3292 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3293 v = memoryview(nd1)
3294 w = memoryview(nd2)
3295
3296 self.assertEqual(v, nd1)
3297 self.assertEqual(w, nd2)
3298 self.assertNotEqual(v, nd2)
3299 self.assertNotEqual(w, nd1)
3300 self.assertNotEqual(v, w)
3301
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003302 # contiguous, struct module
3303 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3304 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3305 v = memoryview(nd1)
3306 w = memoryview(nd2)
3307
3308 self.assertEqual(v, nd1)
3309 self.assertEqual(w, nd2)
3310 self.assertNotEqual(v, nd2)
3311 self.assertNotEqual(w, nd1)
3312 self.assertNotEqual(v, w)
3313
3314 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003315 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3316 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3317 v = memoryview(nd1)
3318 w = memoryview(nd2)
3319
3320 self.assertEqual(v, nd2[::2])
3321 self.assertEqual(w[::2], nd1)
3322 self.assertEqual(v, w[::2])
3323 self.assertEqual(v[::-1], w[::-2])
3324
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003325 # non-contiguous, struct module
3326 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3327 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3328 v = memoryview(nd1)
3329 w = memoryview(nd2)
3330
3331 self.assertEqual(v, nd2[::2])
3332 self.assertEqual(w[::2], nd1)
3333 self.assertEqual(v, w[::2])
3334 self.assertEqual(v[::-1], w[::-2])
3335
3336 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003337 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3338 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3339 flags=ND_PIL)
3340 v = memoryview(nd1)
3341 w = memoryview(nd2)
3342
3343 self.assertEqual(v, nd2[::2])
3344 self.assertEqual(w[::2], nd1)
3345 self.assertEqual(v, w[::2])
3346 self.assertEqual(v[::-1], w[::-2])
3347
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003348 # non-contiguous, suboffsets, struct module
3349 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3350 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3351 flags=ND_PIL)
3352 v = memoryview(nd1)
3353 w = memoryview(nd2)
3354
3355 self.assertEqual(v, nd2[::2])
3356 self.assertEqual(w[::2], nd1)
3357 self.assertEqual(v, w[::2])
3358 self.assertEqual(v[::-1], w[::-2])
3359
3360 def test_memoryview_compare_zero_shape(self):
3361
3362 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003363 nd1 = ndarray([900, 961], shape=[0], format='@h')
3364 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3365 v = memoryview(nd1)
3366 w = memoryview(nd2)
3367
3368 self.assertEqual(v, nd1)
3369 self.assertEqual(w, nd2)
3370 self.assertEqual(v, nd2)
3371 self.assertEqual(w, nd1)
3372 self.assertEqual(v, w)
3373
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003374 # zeros in shape, struct module
3375 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3376 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3377 v = memoryview(nd1)
3378 w = memoryview(nd2)
3379
3380 self.assertEqual(v, nd1)
3381 self.assertEqual(w, nd2)
3382 self.assertEqual(v, nd2)
3383 self.assertEqual(w, nd1)
3384 self.assertEqual(v, w)
3385
3386 def test_memoryview_compare_zero_strides(self):
3387
3388 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003389 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3390 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3391 v = memoryview(nd1)
3392 w = memoryview(nd2)
3393
3394 self.assertEqual(v, nd1)
3395 self.assertEqual(w, nd2)
3396 self.assertEqual(v, nd2)
3397 self.assertEqual(w, nd1)
3398 self.assertEqual(v, w)
3399
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003400 # zero strides, struct module
3401 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3402 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3403 v = memoryview(nd1)
3404 w = memoryview(nd2)
3405
3406 self.assertEqual(v, nd1)
3407 self.assertEqual(w, nd2)
3408 self.assertEqual(v, nd2)
3409 self.assertEqual(w, nd1)
3410 self.assertEqual(v, w)
3411
3412 def test_memoryview_compare_random_formats(self):
3413
3414 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003415 n = 10
3416 for char in fmtdict['@m']:
3417 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3418 for flags in (0, ND_PIL):
3419 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3420 m = memoryview(nd)
3421 self.assertEqual(m, nd)
3422
3423 nd = nd[::-3]
3424 m = memoryview(nd)
3425 self.assertEqual(m, nd)
3426
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003427 # random formats
3428 n = 10
3429 for _ in range(100):
3430 fmt, items, singleitem = randitems(n)
3431 for flags in (0, ND_PIL):
3432 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3433 m = memoryview(nd)
3434 self.assertEqual(m, nd)
3435
3436 nd = nd[::-3]
3437 m = memoryview(nd)
3438 self.assertEqual(m, nd)
3439
3440 def test_memoryview_compare_multidim_c(self):
3441
3442 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003443 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3444 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3445 v = memoryview(nd1)
3446 w = memoryview(nd2)
3447
3448 self.assertEqual(v, nd1)
3449 self.assertEqual(w, nd2)
3450 self.assertNotEqual(v, nd2)
3451 self.assertNotEqual(w, nd1)
3452 self.assertNotEqual(v, w)
3453
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003454 # C-contiguous, different values, struct module
3455 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3456 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3457 v = memoryview(nd1)
3458 w = memoryview(nd2)
3459
3460 self.assertEqual(v, nd1)
3461 self.assertEqual(w, nd2)
3462 self.assertNotEqual(v, nd2)
3463 self.assertNotEqual(w, nd1)
3464 self.assertNotEqual(v, w)
3465
3466 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003467 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3468 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3469 v = memoryview(nd1)
3470 w = memoryview(nd2)
3471
3472 self.assertEqual(v, nd1)
3473 self.assertEqual(w, nd2)
3474 self.assertNotEqual(v, nd2)
3475 self.assertNotEqual(w, nd1)
3476 self.assertNotEqual(v, w)
3477
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003478 # C-contiguous, different shape, struct module
3479 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3480 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003481 v = memoryview(nd1)
3482 w = memoryview(nd2)
3483
3484 self.assertEqual(v, nd1)
3485 self.assertEqual(w, nd2)
3486 self.assertNotEqual(v, nd2)
3487 self.assertNotEqual(w, nd1)
3488 self.assertNotEqual(v, w)
3489
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003490 # C-contiguous, different format, struct module
3491 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3492 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3493 v = memoryview(nd1)
3494 w = memoryview(nd2)
3495
3496 self.assertEqual(v, nd1)
3497 self.assertEqual(w, nd2)
3498 self.assertEqual(v, nd2)
3499 self.assertEqual(w, nd1)
3500 self.assertEqual(v, w)
3501
3502 def test_memoryview_compare_multidim_fortran(self):
3503
3504 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003505 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3506 flags=ND_FORTRAN)
3507 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3508 flags=ND_FORTRAN)
3509 v = memoryview(nd1)
3510 w = memoryview(nd2)
3511
3512 self.assertEqual(v, nd1)
3513 self.assertEqual(w, nd2)
3514 self.assertNotEqual(v, nd2)
3515 self.assertNotEqual(w, nd1)
3516 self.assertNotEqual(v, w)
3517
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003518 # Fortran-contiguous, different values, struct module
3519 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3520 flags=ND_FORTRAN)
3521 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3522 flags=ND_FORTRAN)
3523 v = memoryview(nd1)
3524 w = memoryview(nd2)
3525
3526 self.assertEqual(v, nd1)
3527 self.assertEqual(w, nd2)
3528 self.assertNotEqual(v, nd2)
3529 self.assertNotEqual(w, nd1)
3530 self.assertNotEqual(v, w)
3531
3532 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003533 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3534 flags=ND_FORTRAN)
3535 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3536 flags=ND_FORTRAN)
3537 v = memoryview(nd1)
3538 w = memoryview(nd2)
3539
3540 self.assertEqual(v, nd1)
3541 self.assertEqual(w, nd2)
3542 self.assertNotEqual(v, nd2)
3543 self.assertNotEqual(w, nd1)
3544 self.assertNotEqual(v, w)
3545
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003546 # Fortran-contiguous, different shape, struct module
3547 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003548 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003549 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003550 flags=ND_FORTRAN)
3551 v = memoryview(nd1)
3552 w = memoryview(nd2)
3553
3554 self.assertEqual(v, nd1)
3555 self.assertEqual(w, nd2)
3556 self.assertNotEqual(v, nd2)
3557 self.assertNotEqual(w, nd1)
3558 self.assertNotEqual(v, w)
3559
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003560 # Fortran-contiguous, different format, struct module
3561 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3562 flags=ND_FORTRAN)
3563 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3564 flags=ND_FORTRAN)
3565 v = memoryview(nd1)
3566 w = memoryview(nd2)
3567
3568 self.assertEqual(v, nd1)
3569 self.assertEqual(w, nd2)
3570 self.assertEqual(v, nd2)
3571 self.assertEqual(w, nd1)
3572 self.assertEqual(v, w)
3573
3574 def test_memoryview_compare_multidim_mixed(self):
3575
3576 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003577 lst1 = list(range(-15, 15))
3578 lst2 = transpose(lst1, [3, 2, 5])
3579 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3580 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3581 v = memoryview(nd1)
3582 w = memoryview(nd2)
3583
3584 self.assertEqual(v, nd1)
3585 self.assertEqual(w, nd2)
3586 self.assertEqual(v, w)
3587
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003588 # mixed C/Fortran contiguous, struct module
3589 lst1 = [(-3.3, -22, b'x')]*30
3590 lst1[5] = (-2.2, -22, b'x')
3591 lst2 = transpose(lst1, [3, 2, 5])
3592 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3593 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3594 v = memoryview(nd1)
3595 w = memoryview(nd2)
3596
3597 self.assertEqual(v, nd1)
3598 self.assertEqual(w, nd2)
3599 self.assertEqual(v, w)
3600
3601 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003602 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3603 nd1 = ex1[3:1:-1, ::-2]
3604 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3605 nd2 = ex2[1:3:1, ::-2]
3606 v = memoryview(nd1)
3607 w = memoryview(nd2)
3608
3609 self.assertEqual(v, nd1)
3610 self.assertEqual(w, nd2)
3611 self.assertNotEqual(v, nd2)
3612 self.assertNotEqual(w, nd1)
3613 self.assertNotEqual(v, w)
3614
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003615 # same values, non-contiguous, struct module
3616 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3617 nd1 = ex1[3:1:-1, ::-2]
3618 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3619 nd2 = ex2[1:3:1, ::-2]
3620 v = memoryview(nd1)
3621 w = memoryview(nd2)
3622
3623 self.assertEqual(v, nd1)
3624 self.assertEqual(w, nd2)
3625 self.assertEqual(v, nd2)
3626 self.assertEqual(w, nd1)
3627 self.assertEqual(v, w)
3628
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003629 # different shape
3630 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3631 nd1 = ex1[1:3:, ::-2]
3632 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3633 nd2 = ex2[1:3:, ::-2]
3634 v = memoryview(nd1)
3635 w = memoryview(nd2)
3636
3637 self.assertEqual(v, nd1)
3638 self.assertEqual(w, nd2)
3639 self.assertNotEqual(v, nd2)
3640 self.assertNotEqual(w, nd1)
3641 self.assertNotEqual(v, w)
3642
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003643 # different shape, struct module
3644 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003645 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003646 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003647 nd2 = ex2[1:3:, ::-2]
3648 v = memoryview(nd1)
3649 w = memoryview(nd2)
3650
3651 self.assertEqual(v, nd1)
3652 self.assertEqual(w, nd2)
3653 self.assertNotEqual(v, nd2)
3654 self.assertNotEqual(w, nd1)
3655 self.assertNotEqual(v, w)
3656
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003657 # different format, struct module
3658 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3659 nd1 = ex1[1:3:, ::-2]
3660 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3661 nd2 = ex2[1:3:, ::-2]
3662 v = memoryview(nd1)
3663 w = memoryview(nd2)
3664
3665 self.assertEqual(v, nd1)
3666 self.assertEqual(w, nd2)
3667 self.assertNotEqual(v, nd2)
3668 self.assertNotEqual(w, nd1)
3669 self.assertNotEqual(v, w)
3670
3671 def test_memoryview_compare_multidim_zero_shape(self):
3672
3673 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003674 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3675 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3676 v = memoryview(nd1)
3677 w = memoryview(nd2)
3678
3679 self.assertEqual(v, nd1)
3680 self.assertEqual(w, nd2)
3681 self.assertNotEqual(v, nd2)
3682 self.assertNotEqual(w, nd1)
3683 self.assertNotEqual(v, w)
3684
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003685 # zeros in shape, struct module
3686 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3687 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3688 v = memoryview(nd1)
3689 w = memoryview(nd2)
3690
3691 self.assertEqual(v, nd1)
3692 self.assertEqual(w, nd2)
3693 self.assertNotEqual(v, nd2)
3694 self.assertNotEqual(w, nd1)
3695 self.assertNotEqual(v, w)
3696
3697 def test_memoryview_compare_multidim_zero_strides(self):
3698
3699 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003700 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3701 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3702 v = memoryview(nd1)
3703 w = memoryview(nd2)
3704
3705 self.assertEqual(v, nd1)
3706 self.assertEqual(w, nd2)
3707 self.assertEqual(v, nd2)
3708 self.assertEqual(w, nd1)
3709 self.assertEqual(v, w)
3710 self.assertEqual(v.tolist(), w.tolist())
3711
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003712 # zero strides, struct module
3713 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3714 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3715 v = memoryview(nd1)
3716 w = memoryview(nd2)
3717
3718 self.assertEqual(v, nd1)
3719 self.assertEqual(w, nd2)
3720 self.assertEqual(v, nd2)
3721 self.assertEqual(w, nd1)
3722 self.assertEqual(v, w)
3723
3724 def test_memoryview_compare_multidim_suboffsets(self):
3725
3726 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003727 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3728 nd1 = ex1[3:1:-1, ::-2]
3729 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3730 nd2 = ex2[1:3:1, ::-2]
3731 v = memoryview(nd1)
3732 w = memoryview(nd2)
3733
3734 self.assertEqual(v, nd1)
3735 self.assertEqual(w, nd2)
3736 self.assertNotEqual(v, nd2)
3737 self.assertNotEqual(w, nd1)
3738 self.assertNotEqual(v, w)
3739
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003740 # suboffsets, struct module
3741 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3742 flags=ND_WRITABLE)
3743 ex1[2][7] = (1, -2)
3744 nd1 = ex1[3:1:-1, ::-2]
3745
3746 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3747 flags=ND_PIL|ND_WRITABLE)
3748 ex2[2][7] = (1, -2)
3749 nd2 = ex2[1:3:1, ::-2]
3750
3751 v = memoryview(nd1)
3752 w = memoryview(nd2)
3753
3754 self.assertEqual(v, nd1)
3755 self.assertEqual(w, nd2)
3756 self.assertEqual(v, nd2)
3757 self.assertEqual(w, nd1)
3758 self.assertEqual(v, w)
3759
3760 # suboffsets, different shape
3761 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3762 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003763 nd1 = ex1[1:3:, ::-2]
3764 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3765 nd2 = ex2[1:3:, ::-2]
3766 v = memoryview(nd1)
3767 w = memoryview(nd2)
3768
3769 self.assertEqual(v, nd1)
3770 self.assertEqual(w, nd2)
3771 self.assertNotEqual(v, nd2)
3772 self.assertNotEqual(w, nd1)
3773 self.assertNotEqual(v, w)
3774
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003775 # suboffsets, different shape, struct module
3776 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3777 flags=ND_PIL|ND_WRITABLE)
3778 nd1 = ex1[1:2:, ::-2]
3779
3780 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3781 nd2 = ex2[1:2:, ::-2]
3782
3783 v = memoryview(nd1)
3784 w = memoryview(nd2)
3785
3786 self.assertEqual(v, nd1)
3787 self.assertEqual(w, nd2)
3788 self.assertNotEqual(v, nd2)
3789 self.assertNotEqual(w, nd1)
3790 self.assertNotEqual(v, w)
3791
3792 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003793 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3794 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003795 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003796 nd2 = ex2[1:3:, ::-2]
3797 v = memoryview(nd1)
3798 w = memoryview(nd2)
3799
3800 self.assertEqual(v, nd1)
3801 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003802 self.assertEqual(v, nd2)
3803 self.assertEqual(w, nd1)
3804 self.assertEqual(v, w)
3805
3806 # suboffsets, different format, struct module
3807 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3808 flags=ND_PIL|ND_WRITABLE)
3809 ex1[1][2][2] = (b'sushi', b'', 1)
3810 nd1 = ex1[1:3:, ::-2]
3811
3812 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3813 flags=ND_PIL|ND_WRITABLE)
3814 ex1[1][2][2] = (b'sushi', b'', 1)
3815 nd2 = ex2[1:3:, ::-2]
3816
3817 v = memoryview(nd1)
3818 w = memoryview(nd2)
3819
3820 self.assertEqual(v, nd1)
3821 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003822 self.assertNotEqual(v, nd2)
3823 self.assertNotEqual(w, nd1)
3824 self.assertNotEqual(v, w)
3825
3826 # initialize mixed C/Fortran + suboffsets
3827 lst1 = list(range(-15, 15))
3828 lst2 = transpose(lst1, [3, 2, 5])
3829 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3830 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3831 v = memoryview(nd1)
3832 w = memoryview(nd2)
3833
3834 self.assertEqual(v, nd1)
3835 self.assertEqual(w, nd2)
3836 self.assertEqual(v, w)
3837
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003838 # initialize mixed C/Fortran + suboffsets, struct module
3839 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3840 lst1[11] = (b'ramen', b'spicy', 9.45)
3841 lst2 = transpose(lst1, [3, 2, 5])
3842
3843 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3844 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3845 flags=ND_FORTRAN|ND_PIL)
3846 v = memoryview(nd1)
3847 w = memoryview(nd2)
3848
3849 self.assertEqual(v, nd1)
3850 self.assertEqual(w, nd2)
3851 self.assertEqual(v, w)
3852
3853 def test_memoryview_compare_not_equal(self):
3854
3855 # items not equal
3856 for byteorder in ['=', '<', '>', '!']:
3857 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3858 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3859 flags=ND_WRITABLE|ND_FORTRAN)
3860 y[2][3][1][1][1] = 1
3861 a = memoryview(x)
3862 b = memoryview(y)
3863 self.assertEqual(a, x)
3864 self.assertEqual(b, y)
3865 self.assertNotEqual(a, b)
3866 self.assertNotEqual(a, y)
3867 self.assertNotEqual(b, x)
3868
3869 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3870 format=byteorder+'QLH')
3871 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3872 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3873 y[2][3][1][1][1] = (1, 1, 1)
3874 a = memoryview(x)
3875 b = memoryview(y)
3876 self.assertEqual(a, x)
3877 self.assertEqual(b, y)
3878 self.assertNotEqual(a, b)
3879 self.assertNotEqual(a, y)
3880 self.assertNotEqual(b, x)
3881
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003882 def test_memoryview_check_released(self):
3883
3884 a = array.array('d', [1.1, 2.2, 3.3])
3885
3886 m = memoryview(a)
3887 m.release()
3888
3889 # PyMemoryView_FromObject()
3890 self.assertRaises(ValueError, memoryview, m)
3891 # memoryview.cast()
3892 self.assertRaises(ValueError, m.cast, 'c')
3893 # getbuffer()
3894 self.assertRaises(ValueError, ndarray, m)
3895 # memoryview.tolist()
3896 self.assertRaises(ValueError, m.tolist)
3897 # memoryview.tobytes()
3898 self.assertRaises(ValueError, m.tobytes)
3899 # sequence
3900 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3901 # subscript
3902 self.assertRaises(ValueError, m.__getitem__, 0)
3903 # assignment
3904 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3905
3906 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3907 'shape', 'strides', 'suboffsets', 'c_contiguous',
3908 'f_contiguous', 'contiguous'):
3909 self.assertRaises(ValueError, m.__getattribute__, attr)
3910
3911 # richcompare
3912 b = array.array('d', [1.1, 2.2, 3.3])
3913 m1 = memoryview(a)
3914 m2 = memoryview(b)
3915
3916 self.assertEqual(m1, m2)
3917 m1.release()
3918 self.assertNotEqual(m1, m2)
3919 self.assertNotEqual(m1, a)
3920 self.assertEqual(m1, m1)
3921
3922 def test_memoryview_tobytes(self):
3923 # Many implicit tests are already in self.verify().
3924
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003925 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003926
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003927 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003928 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003929 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003930 self.assertEqual(m.tobytes(), nd.tobytes())
3931
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003932 nd = ndarray([t], shape=[1], format='>hQiLl')
3933 m = memoryview(nd)
3934 self.assertEqual(m, nd)
3935 self.assertEqual(m.tobytes(), nd.tobytes())
3936
3937 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3938 m = memoryview(nd)
3939 self.assertEqual(m, nd)
3940 self.assertEqual(m.tobytes(), nd.tobytes())
3941
3942 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3943 format='<hQiLl')
3944 m = memoryview(nd)
3945 self.assertEqual(m, nd)
3946 self.assertEqual(m.tobytes(), nd.tobytes())
3947
3948 # Unknown formats are handled: tobytes() purely depends on itemsize.
3949 if ctypes:
3950 # format: "T{>l:x:>l:y:}"
3951 class BEPoint(ctypes.BigEndianStructure):
3952 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3953 point = BEPoint(100, 200)
3954 a = memoryview(point)
3955 self.assertEqual(a.tobytes(), bytes(point))
3956
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003957 def test_memoryview_get_contiguous(self):
3958 # Many implicit tests are already in self.verify().
3959
3960 # no buffer interface
3961 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3962
3963 # writable request to read-only object
3964 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3965
3966 # writable request to non-contiguous object
3967 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3968 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3969
3970 # scalar, read-only request from read-only exporter
3971 nd = ndarray(9, shape=(), format="L")
3972 for order in ['C', 'F', 'A']:
3973 m = get_contiguous(nd, PyBUF_READ, order)
3974 self.assertEqual(m, nd)
3975 self.assertEqual(m[()], 9)
3976
3977 # scalar, read-only request from writable exporter
3978 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3979 for order in ['C', 'F', 'A']:
3980 m = get_contiguous(nd, PyBUF_READ, order)
3981 self.assertEqual(m, nd)
3982 self.assertEqual(m[()], 9)
3983
3984 # scalar, writable request
3985 for order in ['C', 'F', 'A']:
3986 nd[()] = 9
3987 m = get_contiguous(nd, PyBUF_WRITE, order)
3988 self.assertEqual(m, nd)
3989 self.assertEqual(m[()], 9)
3990
3991 m[()] = 10
3992 self.assertEqual(m[()], 10)
3993 self.assertEqual(nd[()], 10)
3994
3995 # zeros in shape
3996 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3997 for order in ['C', 'F', 'A']:
3998 m = get_contiguous(nd, PyBUF_READ, order)
3999 self.assertRaises(IndexError, m.__getitem__, 0)
4000 self.assertEqual(m, nd)
4001 self.assertEqual(m.tolist(), [])
4002
4003 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
4004 flags=ND_WRITABLE)
4005 for order in ['C', 'F', 'A']:
4006 m = get_contiguous(nd, PyBUF_READ, order)
4007 self.assertEqual(ndarray(m).tolist(), [[], []])
4008
4009 # one-dimensional
4010 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
4011 for order in ['C', 'F', 'A']:
4012 m = get_contiguous(nd, PyBUF_WRITE, order)
4013 self.assertEqual(m, nd)
4014 self.assertEqual(m.tolist(), nd.tolist())
4015
4016 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
4017 for order in ['C', 'F', 'A']:
4018 m = get_contiguous(nd, PyBUF_WRITE, order)
4019 self.assertEqual(m, nd)
4020 self.assertEqual(m.tolist(), nd.tolist())
4021
4022 # one-dimensional, non-contiguous
4023 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
4024 for order in ['C', 'F', 'A']:
4025 m = get_contiguous(nd, PyBUF_READ, order)
4026 self.assertEqual(m, nd)
4027 self.assertEqual(m.tolist(), nd.tolist())
4028 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4029 self.assertEqual(m[1], 3)
4030 self.assertEqual(nd[1], 3)
4031
4032 nd = nd[::-1]
4033 for order in ['C', 'F', 'A']:
4034 m = get_contiguous(nd, PyBUF_READ, order)
4035 self.assertEqual(m, nd)
4036 self.assertEqual(m.tolist(), nd.tolist())
4037 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4038 self.assertEqual(m[1], 1)
4039 self.assertEqual(nd[1], 1)
4040
4041 # multi-dimensional, contiguous input
4042 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
4043 for order in ['C', 'A']:
4044 m = get_contiguous(nd, PyBUF_WRITE, order)
4045 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4046
4047 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
4048 m = get_contiguous(nd, PyBUF_READ, order)
4049 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4050
4051 nd = ndarray(list(range(12)), shape=[3, 4],
4052 flags=ND_WRITABLE|ND_FORTRAN)
4053 for order in ['F', 'A']:
4054 m = get_contiguous(nd, PyBUF_WRITE, order)
4055 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4056
4057 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
4058 m = get_contiguous(nd, PyBUF_READ, order)
4059 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4060
4061 # multi-dimensional, non-contiguous input
4062 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
4063 for order in ['C', 'F', 'A']:
4064 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
4065 order)
4066 m = get_contiguous(nd, PyBUF_READ, order)
4067 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4068
4069 # flags
4070 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
4071 m = get_contiguous(nd, PyBUF_READ, 'C')
4072 self.assertTrue(m.c_contiguous)
4073
4074 def test_memoryview_serializing(self):
4075
4076 # C-contiguous
4077 size = struct.calcsize('i')
4078 a = array.array('i', [1,2,3,4,5])
4079 m = memoryview(a)
4080 buf = io.BytesIO(m)
4081 b = bytearray(5*size)
4082 buf.readinto(b)
4083 self.assertEqual(m.tobytes(), b)
4084
4085 # C-contiguous, multi-dimensional
4086 size = struct.calcsize('L')
4087 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
4088 m = memoryview(nd)
4089 buf = io.BytesIO(m)
4090 b = bytearray(2*3*2*size)
4091 buf.readinto(b)
4092 self.assertEqual(m.tobytes(), b)
4093
4094 # Fortran contiguous, multi-dimensional
4095 #size = struct.calcsize('L')
4096 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
4097 # flags=ND_FORTRAN)
4098 #m = memoryview(nd)
4099 #buf = io.BytesIO(m)
4100 #b = bytearray(2*3*2*size)
4101 #buf.readinto(b)
4102 #self.assertEqual(m.tobytes(), b)
4103
4104 def test_memoryview_hash(self):
4105
4106 # bytes exporter
4107 b = bytes(list(range(12)))
4108 m = memoryview(b)
4109 self.assertEqual(hash(b), hash(m))
4110
4111 # C-contiguous
4112 mc = m.cast('c', shape=[3,4])
4113 self.assertEqual(hash(mc), hash(b))
4114
4115 # non-contiguous
4116 mx = m[::-2]
4117 b = bytes(list(range(12))[::-2])
4118 self.assertEqual(hash(mx), hash(b))
4119
4120 # Fortran contiguous
4121 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
4122 m = memoryview(nd)
4123 self.assertEqual(hash(m), hash(nd))
4124
4125 # multi-dimensional slice
4126 nd = ndarray(list(range(30)), shape=[3,2,5])
4127 x = nd[::2, ::, ::-1]
4128 m = memoryview(x)
4129 self.assertEqual(hash(m), hash(x))
4130
4131 # multi-dimensional slice with suboffsets
4132 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
4133 x = nd[::2, ::, ::-1]
4134 m = memoryview(x)
4135 self.assertEqual(hash(m), hash(x))
4136
Stefan Krah4af77a02012-11-02 17:49:22 +01004137 # equality-hash invariant
4138 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004139 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004140
4141 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004142 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004143
Stefan Krahb716f842012-11-04 20:53:50 +01004144 self.assertEqual(a, b)
4145 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004146
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004147 # non-byte formats
4148 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4149 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004150 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004151
4152 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4153 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004154 self.assertRaises(ValueError, m.__hash__)
4155
4156 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4157 m = memoryview(nd)
4158 self.assertRaises(ValueError, m.__hash__)
4159
4160 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4161 m = memoryview(nd)
4162 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004163
4164 def test_memoryview_release(self):
4165
4166 # Create re-exporter from getbuffer(memoryview), then release the view.
4167 a = bytearray([1,2,3])
4168 m = memoryview(a)
4169 nd = ndarray(m) # re-exporter
4170 self.assertRaises(BufferError, m.release)
4171 del nd
4172 m.release()
4173
Stefan Krah4e99a312012-03-05 09:30:47 +01004174 a = bytearray([1,2,3])
4175 m = memoryview(a)
4176 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4177 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4178 self.assertIs(nd2.obj, m)
4179 self.assertRaises(BufferError, m.release)
4180 del nd1, nd2
4181 m.release()
4182
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004183 # chained views
4184 a = bytearray([1,2,3])
4185 m1 = memoryview(a)
4186 m2 = memoryview(m1)
4187 nd = ndarray(m2) # re-exporter
4188 m1.release()
4189 self.assertRaises(BufferError, m2.release)
4190 del nd
4191 m2.release()
4192
Stefan Krah4e99a312012-03-05 09:30:47 +01004193 a = bytearray([1,2,3])
4194 m1 = memoryview(a)
4195 m2 = memoryview(m1)
4196 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4197 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4198 self.assertIs(nd2.obj, m2)
4199 m1.release()
4200 self.assertRaises(BufferError, m2.release)
4201 del nd1, nd2
4202 m2.release()
4203
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004204 # Allow changing layout while buffers are exported.
4205 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4206 m1 = memoryview(nd)
4207
4208 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4209 m2 = memoryview(nd)
4210
4211 x = memoryview(m1)
4212 self.assertEqual(x.tolist(), m1.tolist())
4213
4214 y = memoryview(m2)
4215 self.assertEqual(y.tolist(), m2.tolist())
4216 self.assertEqual(y.tolist(), nd.tolist())
4217 m2.release()
4218 y.release()
4219
4220 nd.pop() # pop the current view
4221 self.assertEqual(x.tolist(), nd.tolist())
4222
4223 del nd
4224 m1.release()
4225 x.release()
4226
4227 # If multiple memoryviews share the same managed buffer, implicit
4228 # release() in the context manager's __exit__() method should still
4229 # work.
4230 def catch22(b):
4231 with memoryview(b) as m2:
4232 pass
4233
4234 x = bytearray(b'123')
4235 with memoryview(x) as m1:
4236 catch22(m1)
4237 self.assertEqual(m1[0], ord(b'1'))
4238
Stefan Krah4e99a312012-03-05 09:30:47 +01004239 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4240 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4241 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4242 self.assertIs(z.obj, x)
4243 with memoryview(z) as m:
4244 catch22(m)
4245 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4246
4247 # Test garbage collection.
4248 for flags in (0, ND_REDIRECT):
4249 x = bytearray(b'123')
4250 with memoryview(x) as m1:
4251 del x
4252 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4253 with memoryview(y) as m2:
4254 del y
4255 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4256 with memoryview(z) as m3:
4257 del z
4258 catch22(m3)
4259 catch22(m2)
4260 catch22(m1)
4261 self.assertEqual(m1[0], ord(b'1'))
4262 self.assertEqual(m2[1], ord(b'2'))
4263 self.assertEqual(m3[2], ord(b'3'))
4264 del m3
4265 del m2
4266 del m1
4267
4268 x = bytearray(b'123')
4269 with memoryview(x) as m1:
4270 del x
4271 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4272 with memoryview(y) as m2:
4273 del y
4274 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4275 with memoryview(z) as m3:
4276 del z
4277 catch22(m1)
4278 catch22(m2)
4279 catch22(m3)
4280 self.assertEqual(m1[0], ord(b'1'))
4281 self.assertEqual(m2[1], ord(b'2'))
4282 self.assertEqual(m3[2], ord(b'3'))
4283 del m1, m2, m3
4284
Stefan Krahfcbb4162012-03-05 10:45:31 +01004285 # memoryview.release() fails if the view has exported buffers.
4286 x = bytearray(b'123')
4287 with self.assertRaises(BufferError):
4288 with memoryview(x) as m:
4289 ex = ndarray(m)
4290 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004291
Stefan Krah4e99a312012-03-05 09:30:47 +01004292 def test_memoryview_redirect(self):
4293
4294 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4295 a = array.array('d', [1.0 * x for x in range(12)])
4296
4297 for x in (nd, a):
4298 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4299 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4300 m = memoryview(z)
4301
4302 self.assertIs(y.obj, x)
4303 self.assertIs(z.obj, x)
4304 self.assertIs(m.obj, x)
4305
4306 self.assertEqual(m, x)
4307 self.assertEqual(m, y)
4308 self.assertEqual(m, z)
4309
4310 self.assertEqual(m[1:3], x[1:3])
4311 self.assertEqual(m[1:3], y[1:3])
4312 self.assertEqual(m[1:3], z[1:3])
4313 del y, z
4314 self.assertEqual(m[1:3], x[1:3])
4315
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004316 def test_memoryview_from_static_exporter(self):
4317
4318 fmt = 'B'
4319 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4320
4321 # exceptions
4322 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4323
4324 # view.obj==x
4325 x = staticarray()
4326 y = memoryview(x)
4327 self.verify(y, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004328 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004329 ndim=1, shape=[12], strides=[1],
4330 lst=lst)
4331 for i in range(12):
4332 self.assertEqual(y[i], i)
4333 del x
4334 del y
4335
4336 x = staticarray()
4337 y = memoryview(x)
4338 del y
4339 del x
4340
4341 x = staticarray()
4342 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4343 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4344 m = memoryview(z)
4345 self.assertIs(y.obj, x)
4346 self.assertIs(m.obj, z)
4347 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004348 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004349 ndim=1, shape=[12], strides=[1],
4350 lst=lst)
4351 del x, y, z, m
4352
4353 x = staticarray()
4354 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4355 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4356 m = memoryview(z)
4357 self.assertIs(y.obj, x)
4358 self.assertIs(z.obj, x)
4359 self.assertIs(m.obj, x)
4360 self.verify(m, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004361 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004362 ndim=1, shape=[12], strides=[1],
4363 lst=lst)
4364 del x, y, z, m
4365
4366 # view.obj==NULL
4367 x = staticarray(legacy_mode=True)
4368 y = memoryview(x)
4369 self.verify(y, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004370 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004371 ndim=1, shape=[12], strides=[1],
4372 lst=lst)
4373 for i in range(12):
4374 self.assertEqual(y[i], i)
4375 del x
4376 del y
4377
4378 x = staticarray(legacy_mode=True)
4379 y = memoryview(x)
4380 del y
4381 del x
4382
4383 x = staticarray(legacy_mode=True)
4384 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4385 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4386 m = memoryview(z)
4387 self.assertIs(y.obj, None)
4388 self.assertIs(m.obj, z)
4389 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004390 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004391 ndim=1, shape=[12], strides=[1],
4392 lst=lst)
4393 del x, y, z, m
4394
4395 x = staticarray(legacy_mode=True)
4396 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4397 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4398 m = memoryview(z)
4399 # Clearly setting view.obj==NULL is inferior, since it
4400 # messes up the redirection chain:
4401 self.assertIs(y.obj, None)
4402 self.assertIs(z.obj, y)
4403 self.assertIs(m.obj, y)
4404 self.verify(m, obj=y,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004405 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004406 ndim=1, shape=[12], strides=[1],
4407 lst=lst)
4408 del x, y, z, m
4409
Stefan Krah1649c1b2012-03-05 17:45:17 +01004410 def test_memoryview_getbuffer_undefined(self):
4411
4412 # getbufferproc does not adhere to the new documentation
4413 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4414 self.assertRaises(BufferError, memoryview, nd)
4415
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004416 def test_issue_7385(self):
4417 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4418 self.assertRaises(BufferError, memoryview, x)
4419
Joannah Nanjekye9e66aba2019-08-20 11:46:36 -03004420 @support.cpython_only
4421 def test_pybuffer_size_from_format(self):
4422 # basic tests
4423 for format in ('', 'ii', '3s'):
4424 self.assertEqual(_testcapi.PyBuffer_SizeFromFormat(format),
4425 struct.calcsize(format))
4426
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004427
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004428if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004429 unittest.main()