blob: e0006f23ebacc598f3eb012d00d176789841c5bf [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#
13
14import unittest
15from test import support
16from itertools import permutations, product
17from random import randrange, sample, choice
18from sysconfig import get_config_var
19from platform import architecture
20import warnings
21import sys, array, io
22from decimal import Decimal
23from fractions import Fraction
24
25try:
26 from _testbuffer import *
27except ImportError:
28 ndarray = None
29
30try:
31 import struct
32except ImportError:
33 struct = None
34
35try:
36 with warnings.catch_warnings():
37 from numpy import ndarray as numpy_array
38except ImportError:
39 numpy_array = None
40
41
42SHORT_TEST = True
43
44
45# ======================================================================
46# Random lists by format specifier
47# ======================================================================
48
49# Native format chars and their ranges.
50NATIVE = {
51 '?':0, 'c':0, 'b':0, 'B':0,
52 'h':0, 'H':0, 'i':0, 'I':0,
53 'l':0, 'L':0, 'n':0, 'N':0,
54 'f':0, 'd':0, 'P':0
55}
56
57if struct:
58 try:
59 # Add "qQ" if present in native mode.
60 struct.pack('Q', 2**64-1)
61 NATIVE['q'] = 0
62 NATIVE['Q'] = 0
63 except struct.error:
64 pass
65
66# Standard format chars and their ranges.
67STANDARD = {
68 '?':(0, 2), 'c':(0, 1<<8),
69 'b':(-(1<<7), 1<<7), 'B':(0, 1<<8),
70 'h':(-(1<<15), 1<<15), 'H':(0, 1<<16),
71 'i':(-(1<<31), 1<<31), 'I':(0, 1<<32),
72 'l':(-(1<<31), 1<<31), 'L':(0, 1<<32),
73 'q':(-(1<<63), 1<<63), 'Q':(0, 1<<64),
74 'f':(-(1<<63), 1<<63), 'd':(-(1<<1023), 1<<1023)
75}
76
77def native_type_range(fmt):
78 """Return range of a native type."""
79 if fmt == 'c':
80 lh = (0, 256)
81 elif fmt == '?':
82 lh = (0, 2)
83 elif fmt == 'f':
84 lh = (-(1<<63), 1<<63)
85 elif fmt == 'd':
86 lh = (-(1<<1023), 1<<1023)
87 else:
88 for exp in (128, 127, 64, 63, 32, 31, 16, 15, 8, 7):
89 try:
90 struct.pack(fmt, (1<<exp)-1)
91 break
92 except struct.error:
93 pass
94 lh = (-(1<<exp), 1<<exp) if exp & 1 else (0, 1<<exp)
95 return lh
96
97fmtdict = {
98 '':NATIVE,
99 '@':NATIVE,
100 '<':STANDARD,
101 '>':STANDARD,
102 '=':STANDARD,
103 '!':STANDARD
104}
105
106if struct:
107 for fmt in fmtdict['@']:
108 fmtdict['@'][fmt] = native_type_range(fmt)
109
110MEMORYVIEW = NATIVE.copy()
111ARRAY = NATIVE.copy()
112for k in NATIVE:
113 if not k in "bBhHiIlLfd":
114 del ARRAY[k]
115
116BYTEFMT = NATIVE.copy()
117for k in NATIVE:
118 if not k in "Bbc":
119 del BYTEFMT[k]
120
121fmtdict['m'] = MEMORYVIEW
122fmtdict['@m'] = MEMORYVIEW
123fmtdict['a'] = ARRAY
124fmtdict['b'] = BYTEFMT
125fmtdict['@b'] = BYTEFMT
126
127# Capabilities of the test objects:
128MODE = 0
129MULT = 1
130cap = { # format chars # multiplier
131 'ndarray': (['', '@', '<', '>', '=', '!'], ['', '1', '2', '3']),
132 'array': (['a'], ['']),
133 'numpy': ([''], ['']),
134 'memoryview': (['@m', 'm'], ['']),
135 'bytefmt': (['@b', 'b'], ['']),
136}
137
138def randrange_fmt(mode, char, obj):
139 """Return random item for a type specified by a mode and a single
140 format character."""
141 x = randrange(*fmtdict[mode][char])
142 if char == 'c':
143 x = bytes(chr(x), 'latin1')
144 if char == '?':
145 x = bool(x)
146 if char == 'f' or char == 'd':
147 x = struct.pack(char, x)
148 x = struct.unpack(char, x)[0]
149 if obj == 'numpy' and x == b'\x00':
150 # http://projects.scipy.org/numpy/ticket/1925
151 x = b'\x01'
152 return x
153
154def gen_item(fmt, obj):
155 """Return single random item."""
156 mode, chars = fmt.split('#')
157 x = []
158 for c in chars:
159 x.append(randrange_fmt(mode, c, obj))
160 return x[0] if len(x) == 1 else tuple(x)
161
162def gen_items(n, fmt, obj):
163 """Return a list of random items (or a scalar)."""
164 if n == 0:
165 return gen_item(fmt, obj)
166 lst = [0] * n
167 for i in range(n):
168 lst[i] = gen_item(fmt, obj)
169 return lst
170
171def struct_items(n, obj):
172 mode = choice(cap[obj][MODE])
173 xfmt = mode + '#'
174 fmt = mode.strip('amb')
175 nmemb = randrange(2, 10) # number of struct members
176 for _ in range(nmemb):
177 char = choice(tuple(fmtdict[mode]))
178 multiplier = choice(cap[obj][MULT])
179 xfmt += (char * int(multiplier if multiplier else 1))
180 fmt += (multiplier + char)
181 items = gen_items(n, xfmt, obj)
182 item = gen_item(xfmt, obj)
183 return fmt, items, item
184
185def randitems(n, obj='ndarray', mode=None, char=None):
186 """Return random format, items, item."""
187 if mode is None:
188 mode = choice(cap[obj][MODE])
189 if char is None:
190 char = choice(tuple(fmtdict[mode]))
191 multiplier = choice(cap[obj][MULT])
192 fmt = mode + '#' + char * int(multiplier if multiplier else 1)
193 items = gen_items(n, fmt, obj)
194 item = gen_item(fmt, obj)
195 fmt = mode.strip('amb') + multiplier + char
196 return fmt, items, item
197
198def iter_mode(n, obj='ndarray'):
199 """Iterate through supported mode/char combinations."""
200 for mode in cap[obj][MODE]:
201 for char in fmtdict[mode]:
202 yield randitems(n, obj, mode, char)
203
204def iter_format(nitems, testobj='ndarray'):
205 """Yield (format, items, item) for all possible modes and format
206 characters plus one random compound format string."""
207 for t in iter_mode(nitems, testobj):
208 yield t
209 if testobj != 'ndarray':
210 raise StopIteration
211 yield struct_items(nitems, testobj)
212
213
214def is_byte_format(fmt):
215 return 'c' in fmt or 'b' in fmt or 'B' in fmt
216
217def is_memoryview_format(fmt):
218 """format suitable for memoryview"""
219 x = len(fmt)
220 return ((x == 1 or (x == 2 and fmt[0] == '@')) and
221 fmt[x-1] in MEMORYVIEW)
222
223NON_BYTE_FORMAT = [c for c in fmtdict['@'] if not is_byte_format(c)]
224
225
226# ======================================================================
227# Multi-dimensional tolist(), slicing and slice assignments
228# ======================================================================
229
230def atomp(lst):
231 """Tuple items (representing structs) are regarded as atoms."""
232 return not isinstance(lst, list)
233
234def listp(lst):
235 return isinstance(lst, list)
236
237def prod(lst):
238 """Product of list elements."""
239 if len(lst) == 0:
240 return 0
241 x = lst[0]
242 for v in lst[1:]:
243 x *= v
244 return x
245
246def strides_from_shape(ndim, shape, itemsize, layout):
247 """Calculate strides of a contiguous array. Layout is 'C' or
248 'F' (Fortran)."""
249 if ndim == 0:
250 return ()
251 if layout == 'C':
252 strides = list(shape[1:]) + [itemsize]
253 for i in range(ndim-2, -1, -1):
254 strides[i] *= strides[i+1]
255 else:
256 strides = [itemsize] + list(shape[:-1])
257 for i in range(1, ndim):
258 strides[i] *= strides[i-1]
259 return strides
260
261def _ca(items, s):
262 """Convert flat item list to the nested list representation of a
263 multidimensional C array with shape 's'."""
264 if atomp(items):
265 return items
266 if len(s) == 0:
267 return items[0]
268 lst = [0] * s[0]
269 stride = len(items) // s[0] if s[0] else 0
270 for i in range(s[0]):
271 start = i*stride
272 lst[i] = _ca(items[start:start+stride], s[1:])
273 return lst
274
275def _fa(items, s):
276 """Convert flat item list to the nested list representation of a
277 multidimensional Fortran array with shape 's'."""
278 if atomp(items):
279 return items
280 if len(s) == 0:
281 return items[0]
282 lst = [0] * s[0]
283 stride = s[0]
284 for i in range(s[0]):
285 lst[i] = _fa(items[i::stride], s[1:])
286 return lst
287
288def carray(items, shape):
289 if listp(items) and not 0 in shape and prod(shape) != len(items):
290 raise ValueError("prod(shape) != len(items)")
291 return _ca(items, shape)
292
293def farray(items, shape):
294 if listp(items) and not 0 in shape and prod(shape) != len(items):
295 raise ValueError("prod(shape) != len(items)")
296 return _fa(items, shape)
297
298def indices(shape):
299 """Generate all possible tuples of indices."""
300 iterables = [range(v) for v in shape]
301 return product(*iterables)
302
303def getindex(ndim, ind, strides):
304 """Convert multi-dimensional index to the position in the flat list."""
305 ret = 0
306 for i in range(ndim):
307 ret += strides[i] * ind[i]
308 return ret
309
310def transpose(src, shape):
311 """Transpose flat item list that is regarded as a multi-dimensional
312 matrix defined by shape: dest...[k][j][i] = src[i][j][k]... """
313 if not shape:
314 return src
315 ndim = len(shape)
316 sstrides = strides_from_shape(ndim, shape, 1, 'C')
317 dstrides = strides_from_shape(ndim, shape[::-1], 1, 'C')
318 dest = [0] * len(src)
319 for ind in indices(shape):
320 fr = getindex(ndim, ind, sstrides)
321 to = getindex(ndim, ind[::-1], dstrides)
322 dest[to] = src[fr]
323 return dest
324
325def _flatten(lst):
326 """flatten list"""
327 if lst == []:
328 return lst
329 if atomp(lst):
330 return [lst]
331 return _flatten(lst[0]) + _flatten(lst[1:])
332
333def flatten(lst):
334 """flatten list or return scalar"""
335 if atomp(lst): # scalar
336 return lst
337 return _flatten(lst)
338
339def slice_shape(lst, slices):
340 """Get the shape of lst after slicing: slices is a list of slice
341 objects."""
342 if atomp(lst):
343 return []
344 return [len(lst[slices[0]])] + slice_shape(lst[0], slices[1:])
345
346def multislice(lst, slices):
347 """Multi-dimensional slicing: slices is a list of slice objects."""
348 if atomp(lst):
349 return lst
350 return [multislice(sublst, slices[1:]) for sublst in lst[slices[0]]]
351
352def m_assign(llst, rlst, lslices, rslices):
353 """Multi-dimensional slice assignment: llst and rlst are the operands,
354 lslices and rslices are lists of slice objects. llst and rlst must
355 have the same structure.
356
357 For a two-dimensional example, this is not implemented in Python:
358
359 llst[0:3:2, 0:3:2] = rlst[1:3:1, 1:3:1]
360
361 Instead we write:
362
363 lslices = [slice(0,3,2), slice(0,3,2)]
364 rslices = [slice(1,3,1), slice(1,3,1)]
365 multislice_assign(llst, rlst, lslices, rslices)
366 """
367 if atomp(rlst):
368 return rlst
369 rlst = [m_assign(l, r, lslices[1:], rslices[1:])
370 for l, r in zip(llst[lslices[0]], rlst[rslices[0]])]
371 llst[lslices[0]] = rlst
372 return llst
373
374def cmp_structure(llst, rlst, lslices, rslices):
375 """Compare the structure of llst[lslices] and rlst[rslices]."""
376 lshape = slice_shape(llst, lslices)
377 rshape = slice_shape(rlst, rslices)
378 if (len(lshape) != len(rshape)):
379 return -1
380 for i in range(len(lshape)):
381 if lshape[i] != rshape[i]:
382 return -1
383 if lshape[i] == 0:
384 return 0
385 return 0
386
387def multislice_assign(llst, rlst, lslices, rslices):
388 """Return llst after assigning: llst[lslices] = rlst[rslices]"""
389 if cmp_structure(llst, rlst, lslices, rslices) < 0:
390 raise ValueError("lvalue and rvalue have different structures")
391 return m_assign(llst, rlst, lslices, rslices)
392
393
394# ======================================================================
395# Random structures
396# ======================================================================
397
398#
399# PEP-3118 is very permissive with respect to the contents of a
400# Py_buffer. In particular:
401#
402# - shape can be zero
403# - strides can be any integer, including zero
404# - offset can point to any location in the underlying
405# memory block, provided that it is a multiple of
406# itemsize.
407#
408# The functions in this section test and verify random structures
409# in full generality. A structure is valid iff it fits in the
410# underlying memory block.
411#
412# The structure 't' (short for 'tuple') is fully defined by:
413#
414# t = (memlen, itemsize, ndim, shape, strides, offset)
415#
416
417def verify_structure(memlen, itemsize, ndim, shape, strides, offset):
418 """Verify that the parameters represent a valid array within
419 the bounds of the allocated memory:
420 char *mem: start of the physical memory block
421 memlen: length of the physical memory block
422 offset: (char *)buf - mem
423 """
424 if offset % itemsize:
425 return False
426 if offset < 0 or offset+itemsize > memlen:
427 return False
428 if any(v % itemsize for v in strides):
429 return False
430
431 if ndim <= 0:
432 return ndim == 0 and not shape and not strides
433 if 0 in shape:
434 return True
435
436 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
437 if strides[j] <= 0)
438 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
439 if strides[j] > 0)
440
441 return 0 <= offset+imin and offset+imax+itemsize <= memlen
442
443def get_item(lst, indices):
444 for i in indices:
445 lst = lst[i]
446 return lst
447
448def memory_index(indices, t):
449 """Location of an item in the underlying memory."""
450 memlen, itemsize, ndim, shape, strides, offset = t
451 p = offset
452 for i in range(ndim):
453 p += strides[i]*indices[i]
454 return p
455
456def is_overlapping(t):
457 """The structure 't' is overlapping if at least one memory location
458 is visited twice while iterating through all possible tuples of
459 indices."""
460 memlen, itemsize, ndim, shape, strides, offset = t
461 visited = 1<<memlen
462 for ind in indices(shape):
463 i = memory_index(ind, t)
464 bit = 1<<i
465 if visited & bit:
466 return True
467 visited |= bit
468 return False
469
470def rand_structure(itemsize, valid, maxdim=5, maxshape=16, shape=()):
471 """Return random structure:
472 (memlen, itemsize, ndim, shape, strides, offset)
473 If 'valid' is true, the returned structure is valid, otherwise invalid.
474 If 'shape' is given, use that instead of creating a random shape.
475 """
476 if not shape:
477 ndim = randrange(maxdim+1)
478 if (ndim == 0):
479 if valid:
480 return itemsize, itemsize, ndim, (), (), 0
481 else:
482 nitems = randrange(1, 16+1)
483 memlen = nitems * itemsize
484 offset = -itemsize if randrange(2) == 0 else memlen
485 return memlen, itemsize, ndim, (), (), offset
486
487 minshape = 2
488 n = randrange(100)
489 if n >= 95 and valid:
490 minshape = 0
491 elif n >= 90:
492 minshape = 1
493 shape = [0] * ndim
494
495 for i in range(ndim):
496 shape[i] = randrange(minshape, maxshape+1)
497 else:
498 ndim = len(shape)
499
500 maxstride = 5
501 n = randrange(100)
502 zero_stride = True if n >= 95 and n & 1 else False
503
504 strides = [0] * ndim
505 strides[ndim-1] = itemsize * randrange(-maxstride, maxstride+1)
506 if not zero_stride and strides[ndim-1] == 0:
507 strides[ndim-1] = itemsize
508
509 for i in range(ndim-2, -1, -1):
510 maxstride *= shape[i+1] if shape[i+1] else 1
511 if zero_stride:
512 strides[i] = itemsize * randrange(-maxstride, maxstride+1)
513 else:
514 strides[i] = ((1,-1)[randrange(2)] *
515 itemsize * randrange(1, maxstride+1))
516
517 imin = imax = 0
518 if not 0 in shape:
519 imin = sum(strides[j]*(shape[j]-1) for j in range(ndim)
520 if strides[j] <= 0)
521 imax = sum(strides[j]*(shape[j]-1) for j in range(ndim)
522 if strides[j] > 0)
523
524 nitems = imax - imin
525 if valid:
526 offset = -imin * itemsize
527 memlen = offset + (imax+1) * itemsize
528 else:
529 memlen = (-imin + imax) * itemsize
530 offset = -imin-itemsize if randrange(2) == 0 else memlen
531 return memlen, itemsize, ndim, shape, strides, offset
532
533def randslice_from_slicelen(slicelen, listlen):
534 """Create a random slice of len slicelen that fits into listlen."""
535 maxstart = listlen - slicelen
536 start = randrange(maxstart+1)
537 maxstep = (listlen - start) // slicelen if slicelen else 1
538 step = randrange(1, maxstep+1)
539 stop = start + slicelen * step
540 s = slice(start, stop, step)
541 _, _, _, control = slice_indices(s, listlen)
542 if control != slicelen:
543 raise RuntimeError
544 return s
545
546def randslice_from_shape(ndim, shape):
547 """Create two sets of slices for an array x with shape 'shape'
548 such that shapeof(x[lslices]) == shapeof(x[rslices])."""
549 lslices = [0] * ndim
550 rslices = [0] * ndim
551 for n in range(ndim):
552 l = shape[n]
553 slicelen = randrange(1, l+1) if l > 0 else 0
554 lslices[n] = randslice_from_slicelen(slicelen, l)
555 rslices[n] = randslice_from_slicelen(slicelen, l)
556 return tuple(lslices), tuple(rslices)
557
558def rand_aligned_slices(maxdim=5, maxshape=16):
559 """Create (lshape, rshape, tuple(lslices), tuple(rslices)) such that
560 shapeof(x[lslices]) == shapeof(y[rslices]), where x is an array
561 with shape 'lshape' and y is an array with shape 'rshape'."""
562 ndim = randrange(1, maxdim+1)
563 minshape = 2
564 n = randrange(100)
565 if n >= 95:
566 minshape = 0
567 elif n >= 90:
568 minshape = 1
569 all_random = True if randrange(100) >= 80 else False
570 lshape = [0]*ndim; rshape = [0]*ndim
571 lslices = [0]*ndim; rslices = [0]*ndim
572
573 for n in range(ndim):
574 small = randrange(minshape, maxshape+1)
575 big = randrange(minshape, maxshape+1)
576 if big < small:
577 big, small = small, big
578
579 # Create a slice that fits the smaller value.
580 if all_random:
581 start = randrange(-small, small+1)
582 stop = randrange(-small, small+1)
583 step = (1,-1)[randrange(2)] * randrange(1, small+2)
584 s_small = slice(start, stop, step)
585 _, _, _, slicelen = slice_indices(s_small, small)
586 else:
587 slicelen = randrange(1, small+1) if small > 0 else 0
588 s_small = randslice_from_slicelen(slicelen, small)
589
590 # Create a slice of the same length for the bigger value.
591 s_big = randslice_from_slicelen(slicelen, big)
592 if randrange(2) == 0:
593 rshape[n], lshape[n] = big, small
594 rslices[n], lslices[n] = s_big, s_small
595 else:
596 rshape[n], lshape[n] = small, big
597 rslices[n], lslices[n] = s_small, s_big
598
599 return lshape, rshape, tuple(lslices), tuple(rslices)
600
601def randitems_from_structure(fmt, t):
602 """Return a list of random items for structure 't' with format
603 'fmtchar'."""
604 memlen, itemsize, _, _, _, _ = t
605 return gen_items(memlen//itemsize, '#'+fmt, 'numpy')
606
607def ndarray_from_structure(items, fmt, t, flags=0):
608 """Return ndarray from the tuple returned by rand_structure()"""
609 memlen, itemsize, ndim, shape, strides, offset = t
610 return ndarray(items, shape=shape, strides=strides, format=fmt,
611 offset=offset, flags=ND_WRITABLE|flags)
612
613def numpy_array_from_structure(items, fmt, t):
614 """Return numpy_array from the tuple returned by rand_structure()"""
615 memlen, itemsize, ndim, shape, strides, offset = t
616 buf = bytearray(memlen)
617 for j, v in enumerate(items):
618 struct.pack_into(fmt, buf, j*itemsize, v)
619 return numpy_array(buffer=buf, shape=shape, strides=strides,
620 dtype=fmt, offset=offset)
621
622
623# ======================================================================
624# memoryview casts
625# ======================================================================
626
627def cast_items(exporter, fmt, itemsize, shape=None):
628 """Interpret the raw memory of 'exporter' as a list of items with
629 size 'itemsize'. If shape=None, the new structure is assumed to
630 be 1-D with n * itemsize = bytelen. If shape is given, the usual
631 constraint for contiguous arrays prod(shape) * itemsize = bytelen
632 applies. On success, return (items, shape). If the constraints
633 cannot be met, return (None, None). If a chunk of bytes is interpreted
634 as NaN as a result of float conversion, return ('nan', None)."""
635 bytelen = exporter.nbytes
636 if shape:
637 if prod(shape) * itemsize != bytelen:
638 return None, shape
639 elif shape == []:
640 if exporter.ndim == 0 or itemsize != bytelen:
641 return None, shape
642 else:
643 n, r = divmod(bytelen, itemsize)
644 shape = [n]
645 if r != 0:
646 return None, shape
647
648 mem = exporter.tobytes()
649 byteitems = [mem[i:i+itemsize] for i in range(0, len(mem), itemsize)]
650
651 items = []
652 for v in byteitems:
653 item = struct.unpack(fmt, v)[0]
654 if item != item:
655 return 'nan', shape
656 items.append(item)
657
658 return (items, shape) if shape != [] else (items[0], shape)
659
660def gencastshapes():
661 """Generate shapes to test casting."""
662 for n in range(32):
663 yield [n]
664 ndim = randrange(4, 6)
665 minshape = 1 if randrange(100) > 80 else 2
666 yield [randrange(minshape, 5) for _ in range(ndim)]
667 ndim = randrange(2, 4)
668 minshape = 1 if randrange(100) > 80 else 2
669 yield [randrange(minshape, 5) for _ in range(ndim)]
670
671
672# ======================================================================
673# Actual tests
674# ======================================================================
675
676def genslices(n):
677 """Generate all possible slices for a single dimension."""
678 return product(range(-n, n+1), range(-n, n+1), range(-n, n+1))
679
680def genslices_ndim(ndim, shape):
681 """Generate all possible slice tuples for 'shape'."""
682 iterables = [genslices(shape[n]) for n in range(ndim)]
683 return product(*iterables)
684
685def rslice(n, allow_empty=False):
686 """Generate random slice for a single dimension of length n.
687 If zero=True, the slices may be empty, otherwise they will
688 be non-empty."""
689 minlen = 0 if allow_empty or n == 0 else 1
690 slicelen = randrange(minlen, n+1)
691 return randslice_from_slicelen(slicelen, n)
692
693def rslices(n, allow_empty=False):
694 """Generate random slices for a single dimension."""
695 for _ in range(5):
696 yield rslice(n, allow_empty)
697
698def rslices_ndim(ndim, shape, iterations=5):
699 """Generate random slice tuples for 'shape'."""
700 # non-empty slices
701 for _ in range(iterations):
702 yield tuple(rslice(shape[n]) for n in range(ndim))
703 # possibly empty slices
704 for _ in range(iterations):
705 yield tuple(rslice(shape[n], allow_empty=True) for n in range(ndim))
706 # invalid slices
707 yield tuple(slice(0,1,0) for _ in range(ndim))
708
709def rpermutation(iterable, r=None):
710 pool = tuple(iterable)
711 r = len(pool) if r is None else r
712 yield tuple(sample(pool, r))
713
714def ndarray_print(nd):
715 """Print ndarray for debugging."""
716 try:
717 x = nd.tolist()
718 except (TypeError, NotImplementedError):
719 x = nd.tobytes()
720 if isinstance(nd, ndarray):
721 offset = nd.offset
722 flags = nd.flags
723 else:
724 offset = 'unknown'
725 flags = 'unknown'
726 print("ndarray(%s, shape=%s, strides=%s, suboffsets=%s, offset=%s, "
727 "format='%s', itemsize=%s, flags=%s)" %
728 (x, nd.shape, nd.strides, nd.suboffsets, offset,
729 nd.format, nd.itemsize, flags))
730 sys.stdout.flush()
731
732
733ITERATIONS = 100
734MAXDIM = 5
735MAXSHAPE = 10
736
737if SHORT_TEST:
738 ITERATIONS = 10
739 MAXDIM = 3
740 MAXSHAPE = 4
741 genslices = rslices
742 genslices_ndim = rslices_ndim
743 permutations = rpermutation
744
745
746@unittest.skipUnless(struct, 'struct module required for this test.')
747@unittest.skipUnless(ndarray, 'ndarray object required for this test')
748class TestBufferProtocol(unittest.TestCase):
749
750 def setUp(self):
751 self.sizeof_void_p = get_config_var('SIZEOF_VOID_P')
752 if not self.sizeof_void_p:
753 self.sizeof_void_p = 8 if architecture()[0] == '64bit' else 4
754
755 def verify(self, result, obj=-1,
756 itemsize={1}, fmt=-1, readonly={1},
757 ndim={1}, shape=-1, strides=-1,
758 lst=-1, sliced=False, cast=False):
759 # Verify buffer contents against expected values. Default values
760 # are deliberately initialized to invalid types.
761 if shape:
762 expected_len = prod(shape)*itemsize
763 else:
764 if not fmt: # array has been implicitly cast to unsigned bytes
765 expected_len = len(lst)
766 else: # ndim = 0
767 expected_len = itemsize
768
769 # Reconstruct suboffsets from strides. Support for slicing
770 # could be added, but is currently only needed for test_getbuf().
771 suboffsets = ()
772 if result.suboffsets:
773 self.assertGreater(ndim, 0)
774
775 suboffset0 = 0
776 for n in range(1, ndim):
777 if shape[n] == 0:
778 break
779 if strides[n] <= 0:
780 suboffset0 += -strides[n] * (shape[n]-1)
781
782 suboffsets = [suboffset0] + [-1 for v in range(ndim-1)]
783
784 # Not correct if slicing has occurred in the first dimension.
785 stride0 = self.sizeof_void_p
786 if strides[0] < 0:
787 stride0 = -stride0
788 strides = [stride0] + list(strides[1:])
789
790 self.assertIs(result.obj, obj)
791 self.assertEqual(result.nbytes, expected_len)
792 self.assertEqual(result.itemsize, itemsize)
793 self.assertEqual(result.format, fmt)
794 self.assertEqual(result.readonly, readonly)
795 self.assertEqual(result.ndim, ndim)
796 self.assertEqual(result.shape, tuple(shape))
797 if not (sliced and suboffsets):
798 self.assertEqual(result.strides, tuple(strides))
799 self.assertEqual(result.suboffsets, tuple(suboffsets))
800
801 if isinstance(result, ndarray) or is_memoryview_format(fmt):
802 rep = result.tolist() if fmt else result.tobytes()
803 self.assertEqual(rep, lst)
804
805 if not fmt: # array has been cast to unsigned bytes,
806 return # the remaining tests won't work.
807
808 # PyBuffer_GetPointer() is the definition how to access an item.
809 # If PyBuffer_GetPointer(indices) is correct for all possible
810 # combinations of indices, the buffer is correct.
811 #
812 # Also test tobytes() against the flattened 'lst', with all items
813 # packed to bytes.
814 if not cast: # casts chop up 'lst' in different ways
815 b = bytearray()
816 buf_err = None
817 for ind in indices(shape):
818 try:
819 item1 = get_pointer(result, ind)
820 item2 = get_item(lst, ind)
821 if isinstance(item2, tuple):
822 x = struct.pack(fmt, *item2)
823 else:
824 x = struct.pack(fmt, item2)
825 b.extend(x)
826 except BufferError:
827 buf_err = True # re-exporter does not provide full buffer
828 break
829 self.assertEqual(item1, item2)
830
831 if not buf_err:
832 # test tobytes()
833 self.assertEqual(result.tobytes(), b)
834
835 if not buf_err and is_memoryview_format(fmt):
836
837 # lst := expected multi-dimensional logical representation
838 # flatten(lst) := elements in C-order
839 ff = fmt if fmt else 'B'
840 flattened = flatten(lst)
841
842 # Rules for 'A': if the array is already contiguous, return
843 # the array unaltered. Otherwise, return a contiguous 'C'
844 # representation.
845 for order in ['C', 'F', 'A']:
846 expected = result
847 if order == 'F':
848 if not is_contiguous(result, 'A') or \
849 is_contiguous(result, 'C'):
850 # For constructing the ndarray, convert the
851 # flattened logical representation to Fortran order.
852 trans = transpose(flattened, shape)
853 expected = ndarray(trans, shape=shape, format=ff,
854 flags=ND_FORTRAN)
855 else: # 'C', 'A'
856 if not is_contiguous(result, 'A') or \
857 is_contiguous(result, 'F') and order == 'C':
858 # The flattened list is already in C-order.
859 expected = ndarray(flattened, shape=shape, format=ff)
860 contig = get_contiguous(result, PyBUF_READ, order)
861 contig = get_contiguous(result, PyBUF_READ, order)
862 self.assertEqual(contig.tobytes(), b)
863 self.assertTrue(cmp_contig(contig, expected))
864
865 if is_memoryview_format(fmt):
866 try:
867 m = memoryview(result)
868 except BufferError: # re-exporter does not provide full information
869 return
870 ex = result.obj if isinstance(result, memoryview) else result
871 self.assertIs(m.obj, ex)
872 self.assertEqual(m.nbytes, expected_len)
873 self.assertEqual(m.itemsize, itemsize)
874 self.assertEqual(m.format, fmt)
875 self.assertEqual(m.readonly, readonly)
876 self.assertEqual(m.ndim, ndim)
877 self.assertEqual(m.shape, tuple(shape))
878 if not (sliced and suboffsets):
879 self.assertEqual(m.strides, tuple(strides))
880 self.assertEqual(m.suboffsets, tuple(suboffsets))
881
882 n = 1 if ndim == 0 else len(lst)
883 self.assertEqual(len(m), n)
884
885 rep = result.tolist() if fmt else result.tobytes()
886 self.assertEqual(rep, lst)
887 self.assertEqual(m, result)
888
889 def verify_getbuf(self, orig_ex, ex, req, sliced=False):
890 def simple_fmt(ex):
891 return ex.format == '' or ex.format == 'B'
892 def match(req, flag):
893 return ((req&flag) == flag)
894
895 if (# writable request to read-only exporter
896 (ex.readonly and match(req, PyBUF_WRITABLE)) or
897 # cannot match explicit contiguity request
898 (match(req, PyBUF_C_CONTIGUOUS) and not ex.c_contiguous) or
899 (match(req, PyBUF_F_CONTIGUOUS) and not ex.f_contiguous) or
900 (match(req, PyBUF_ANY_CONTIGUOUS) and not ex.contiguous) or
901 # buffer needs suboffsets
902 (not match(req, PyBUF_INDIRECT) and ex.suboffsets) or
903 # buffer without strides must be C-contiguous
904 (not match(req, PyBUF_STRIDES) and not ex.c_contiguous) or
905 # PyBUF_SIMPLE|PyBUF_FORMAT and PyBUF_WRITABLE|PyBUF_FORMAT
906 (not match(req, PyBUF_ND) and match(req, PyBUF_FORMAT))):
907
908 self.assertRaises(BufferError, ndarray, ex, getbuf=req)
909 return
910
911 if isinstance(ex, ndarray) or is_memoryview_format(ex.format):
912 lst = ex.tolist()
913 else:
914 nd = ndarray(ex, getbuf=PyBUF_FULL_RO)
915 lst = nd.tolist()
916
917 # The consumer may have requested default values or a NULL format.
918 ro = 0 if match(req, PyBUF_WRITABLE) else ex.readonly
919 fmt = ex.format
920 itemsize = ex.itemsize
921 ndim = ex.ndim
922 if not match(req, PyBUF_FORMAT):
923 # itemsize refers to the original itemsize before the cast.
924 # The equality product(shape) * itemsize = len still holds.
925 # The equality calcsize(format) = itemsize does _not_ hold.
926 fmt = ''
927 lst = orig_ex.tobytes() # Issue 12834
928 if not match(req, PyBUF_ND):
929 ndim = 1
930 shape = orig_ex.shape if match(req, PyBUF_ND) else ()
931 strides = orig_ex.strides if match(req, PyBUF_STRIDES) else ()
932
933 nd = ndarray(ex, getbuf=req)
934 self.verify(nd, obj=ex,
935 itemsize=itemsize, fmt=fmt, readonly=ro,
936 ndim=ndim, shape=shape, strides=strides,
937 lst=lst, sliced=sliced)
938
939 def test_ndarray_getbuf(self):
940 requests = (
941 # distinct flags
942 PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE,
943 PyBUF_C_CONTIGUOUS, PyBUF_F_CONTIGUOUS, PyBUF_ANY_CONTIGUOUS,
944 # compound requests
945 PyBUF_FULL, PyBUF_FULL_RO,
946 PyBUF_RECORDS, PyBUF_RECORDS_RO,
947 PyBUF_STRIDED, PyBUF_STRIDED_RO,
948 PyBUF_CONTIG, PyBUF_CONTIG_RO,
949 )
950 # items and format
951 items_fmt = (
952 ([True if x % 2 else False for x in range(12)], '?'),
953 ([1,2,3,4,5,6,7,8,9,10,11,12], 'b'),
954 ([1,2,3,4,5,6,7,8,9,10,11,12], 'B'),
955 ([(2**31-x) if x % 2 else (-2**31+x) for x in range(12)], 'l')
956 )
957 # shape, strides, offset
958 structure = (
959 ([], [], 0),
960 ([12], [], 0),
961 ([12], [-1], 11),
962 ([6], [2], 0),
963 ([6], [-2], 11),
964 ([3, 4], [], 0),
965 ([3, 4], [-4, -1], 11),
966 ([2, 2], [4, 1], 4),
967 ([2, 2], [-4, -1], 8)
968 )
969 # ndarray creation flags
970 ndflags = (
971 0, ND_WRITABLE, ND_FORTRAN, ND_FORTRAN|ND_WRITABLE,
972 ND_PIL, ND_PIL|ND_WRITABLE
973 )
974 # flags that can actually be used as flags
975 real_flags = (0, PyBUF_WRITABLE, PyBUF_FORMAT,
976 PyBUF_WRITABLE|PyBUF_FORMAT)
977
978 for items, fmt in items_fmt:
979 itemsize = struct.calcsize(fmt)
980 for shape, strides, offset in structure:
981 strides = [v * itemsize for v in strides]
982 offset *= itemsize
983 for flags in ndflags:
984
985 if strides and (flags&ND_FORTRAN):
986 continue
987 if not shape and (flags&ND_PIL):
988 continue
989
990 _items = items if shape else items[0]
991 ex1 = ndarray(_items, format=fmt, flags=flags,
992 shape=shape, strides=strides, offset=offset)
993 ex2 = ex1[::-2] if shape else None
994
995 m1 = memoryview(ex1)
996 if ex2:
997 m2 = memoryview(ex2)
998 if ex1.ndim == 0 or (ex1.ndim == 1 and shape and strides):
999 self.assertEqual(m1, ex1)
1000 if ex2 and ex2.ndim == 1 and shape and strides:
1001 self.assertEqual(m2, ex2)
1002
1003 for req in requests:
1004 for bits in real_flags:
1005 self.verify_getbuf(ex1, ex1, req|bits)
1006 self.verify_getbuf(ex1, m1, req|bits)
1007 if ex2:
1008 self.verify_getbuf(ex2, ex2, req|bits,
1009 sliced=True)
1010 self.verify_getbuf(ex2, m2, req|bits,
1011 sliced=True)
1012
1013 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1014
1015 # ND_GETBUF_FAIL
1016 ex = ndarray(items, shape=[12], flags=ND_GETBUF_FAIL)
1017 self.assertRaises(BufferError, ndarray, ex)
1018
1019 # Request complex structure from a simple exporter. In this
1020 # particular case the test object is not PEP-3118 compliant.
1021 base = ndarray([9], [1])
1022 ex = ndarray(base, getbuf=PyBUF_SIMPLE)
1023 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_WRITABLE)
1024 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ND)
1025 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_STRIDES)
1026 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_C_CONTIGUOUS)
1027 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_F_CONTIGUOUS)
1028 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ANY_CONTIGUOUS)
1029 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1030
1031 def test_ndarray_exceptions(self):
1032 nd = ndarray([9], [1])
1033 ndm = ndarray([9], [1], flags=ND_VAREXPORT)
1034
1035 # Initialization of a new ndarray or mutation of an existing array.
1036 for c in (ndarray, nd.push, ndm.push):
1037 # Invalid types.
1038 self.assertRaises(TypeError, c, {1,2,3})
1039 self.assertRaises(TypeError, c, [1,2,'3'])
1040 self.assertRaises(TypeError, c, [1,2,(3,4)])
1041 self.assertRaises(TypeError, c, [1,2,3], shape={3})
1042 self.assertRaises(TypeError, c, [1,2,3], shape=[3], strides={1})
1043 self.assertRaises(TypeError, c, [1,2,3], shape=[3], offset=[])
1044 self.assertRaises(TypeError, c, [1], shape=[1], format={})
1045 self.assertRaises(TypeError, c, [1], shape=[1], flags={})
1046 self.assertRaises(TypeError, c, [1], shape=[1], getbuf={})
1047
1048 # ND_FORTRAN flag is only valid without strides.
1049 self.assertRaises(TypeError, c, [1], shape=[1], strides=[1],
1050 flags=ND_FORTRAN)
1051
1052 # ND_PIL flag is only valid with ndim > 0.
1053 self.assertRaises(TypeError, c, [1], shape=[], flags=ND_PIL)
1054
1055 # Invalid items.
1056 self.assertRaises(ValueError, c, [], shape=[1])
1057 self.assertRaises(ValueError, c, ['XXX'], shape=[1], format="L")
1058 # Invalid combination of items and format.
1059 self.assertRaises(struct.error, c, [1000], shape=[1], format="B")
1060 self.assertRaises(ValueError, c, [1,(2,3)], shape=[2], format="B")
1061 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="QL")
1062
1063 # Invalid ndim.
1064 n = ND_MAX_NDIM+1
1065 self.assertRaises(ValueError, c, [1]*n, shape=[1]*n)
1066
1067 # Invalid shape.
1068 self.assertRaises(ValueError, c, [1], shape=[-1])
1069 self.assertRaises(ValueError, c, [1,2,3], shape=['3'])
1070 self.assertRaises(OverflowError, c, [1], shape=[2**128])
1071 # prod(shape) * itemsize != len(items)
1072 self.assertRaises(ValueError, c, [1,2,3,4,5], shape=[2,2], offset=3)
1073
1074 # Invalid strides.
1075 self.assertRaises(ValueError, c, [1,2,3], shape=[3], strides=['1'])
1076 self.assertRaises(OverflowError, c, [1], shape=[1],
1077 strides=[2**128])
1078
1079 # Invalid combination of strides and shape.
1080 self.assertRaises(ValueError, c, [1,2], shape=[2,1], strides=[1])
1081 # Invalid combination of strides and format.
1082 self.assertRaises(ValueError, c, [1,2,3,4], shape=[2], strides=[3],
1083 format="L")
1084
1085 # Invalid offset.
1086 self.assertRaises(ValueError, c, [1,2,3], shape=[3], offset=4)
1087 self.assertRaises(ValueError, c, [1,2,3], shape=[1], offset=3,
1088 format="L")
1089
1090 # Invalid format.
1091 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="")
1092 self.assertRaises(struct.error, c, [(1,2,3)], shape=[1],
1093 format="@#$")
1094
1095 # Striding out of the memory bounds.
1096 items = [1,2,3,4,5,6,7,8,9,10]
1097 self.assertRaises(ValueError, c, items, shape=[2,3],
1098 strides=[-3, -2], offset=5)
1099
1100 # Constructing consumer: format argument invalid.
1101 self.assertRaises(TypeError, c, bytearray(), format="Q")
1102
1103 # Constructing original base object: getbuf argument invalid.
1104 self.assertRaises(TypeError, c, [1], shape=[1], getbuf=PyBUF_FULL)
1105
1106 # Shape argument is mandatory for original base objects.
1107 self.assertRaises(TypeError, c, [1])
1108
1109
1110 # PyBUF_WRITABLE request to read-only provider.
1111 self.assertRaises(BufferError, ndarray, b'123', getbuf=PyBUF_WRITABLE)
1112
1113 # ND_VAREXPORT can only be specified during construction.
1114 nd = ndarray([9], [1], flags=ND_VAREXPORT)
1115 self.assertRaises(ValueError, nd.push, [1], [1], flags=ND_VAREXPORT)
1116
1117 # Invalid operation for consumers: push/pop
1118 nd = ndarray(b'123')
1119 self.assertRaises(BufferError, nd.push, [1], [1])
1120 self.assertRaises(BufferError, nd.pop)
1121
1122 # ND_VAREXPORT not set: push/pop fail with exported buffers
1123 nd = ndarray([9], [1])
1124 nd.push([1], [1])
1125 m = memoryview(nd)
1126 self.assertRaises(BufferError, nd.push, [1], [1])
1127 self.assertRaises(BufferError, nd.pop)
1128 m.release()
1129 nd.pop()
1130
1131 # Single remaining buffer: pop fails
1132 self.assertRaises(BufferError, nd.pop)
1133 del nd
1134
1135 # get_pointer()
1136 self.assertRaises(TypeError, get_pointer, {}, [1,2,3])
1137 self.assertRaises(TypeError, get_pointer, b'123', {})
1138
1139 nd = ndarray(list(range(100)), shape=[1]*100)
1140 self.assertRaises(ValueError, get_pointer, nd, [5])
1141
1142 nd = ndarray(list(range(12)), shape=[3,4])
1143 self.assertRaises(ValueError, get_pointer, nd, [2,3,4])
1144 self.assertRaises(ValueError, get_pointer, nd, [3,3])
1145 self.assertRaises(ValueError, get_pointer, nd, [-3,3])
1146 self.assertRaises(OverflowError, get_pointer, nd, [1<<64,3])
1147
1148 # tolist() needs format
1149 ex = ndarray([1,2,3], shape=[3], format='L')
1150 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1151 self.assertRaises(ValueError, nd.tolist)
1152
1153 # memoryview_from_buffer()
1154 ex1 = ndarray([1,2,3], shape=[3], format='L')
1155 ex2 = ndarray(ex1)
1156 nd = ndarray(ex2)
1157 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1158
1159 nd = ndarray([(1,)*200], shape=[1], format='L'*200)
1160 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1161
1162 n = ND_MAX_NDIM
1163 nd = ndarray(list(range(n)), shape=[1]*n)
1164 self.assertRaises(ValueError, nd.memoryview_from_buffer)
1165
1166 # get_contiguous()
1167 nd = ndarray([1], shape=[1])
1168 self.assertRaises(TypeError, get_contiguous, 1, 2, 3, 4, 5)
1169 self.assertRaises(TypeError, get_contiguous, nd, "xyz", 'C')
1170 self.assertRaises(OverflowError, get_contiguous, nd, 2**64, 'C')
1171 self.assertRaises(TypeError, get_contiguous, nd, PyBUF_READ, 961)
1172 self.assertRaises(UnicodeEncodeError, get_contiguous, nd, PyBUF_READ,
1173 '\u2007')
1174
1175 # cmp_contig()
1176 nd = ndarray([1], shape=[1])
1177 self.assertRaises(TypeError, cmp_contig, 1, 2, 3, 4, 5)
1178 self.assertRaises(TypeError, cmp_contig, {}, nd)
1179 self.assertRaises(TypeError, cmp_contig, nd, {})
1180
1181 # is_contiguous()
1182 nd = ndarray([1], shape=[1])
1183 self.assertRaises(TypeError, is_contiguous, 1, 2, 3, 4, 5)
1184 self.assertRaises(TypeError, is_contiguous, {}, 'A')
1185 self.assertRaises(TypeError, is_contiguous, nd, 201)
1186
1187 def test_ndarray_linked_list(self):
1188 for perm in permutations(range(5)):
1189 m = [0]*5
1190 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
1191 m[0] = memoryview(nd)
1192
1193 for i in range(1, 5):
1194 nd.push([1,2,3], shape=[3])
1195 m[i] = memoryview(nd)
1196
1197 for i in range(5):
1198 m[perm[i]].release()
1199
1200 self.assertRaises(BufferError, nd.pop)
1201 del nd
1202
1203 def test_ndarray_format_scalar(self):
1204 # ndim = 0: scalar
1205 for fmt, scalar, _ in iter_format(0):
1206 itemsize = struct.calcsize(fmt)
1207 nd = ndarray(scalar, shape=(), format=fmt)
1208 self.verify(nd, obj=None,
1209 itemsize=itemsize, fmt=fmt, readonly=1,
1210 ndim=0, shape=(), strides=(),
1211 lst=scalar)
1212
1213 def test_ndarray_format_shape(self):
1214 # ndim = 1, shape = [n]
1215 nitems = randrange(1, 10)
1216 for fmt, items, _ in iter_format(nitems):
1217 itemsize = struct.calcsize(fmt)
1218 for flags in (0, ND_PIL):
1219 nd = ndarray(items, shape=[nitems], format=fmt, flags=flags)
1220 self.verify(nd, obj=None,
1221 itemsize=itemsize, fmt=fmt, readonly=1,
1222 ndim=1, shape=(nitems,), strides=(itemsize,),
1223 lst=items)
1224
1225 def test_ndarray_format_strides(self):
1226 # ndim = 1, strides
1227 nitems = randrange(1, 30)
1228 for fmt, items, _ in iter_format(nitems):
1229 itemsize = struct.calcsize(fmt)
1230 for step in range(-5, 5):
1231 if step == 0:
1232 continue
1233
1234 shape = [len(items[::step])]
1235 strides = [step*itemsize]
1236 offset = itemsize*(nitems-1) if step < 0 else 0
1237
1238 for flags in (0, ND_PIL):
1239 nd = ndarray(items, shape=shape, strides=strides,
1240 format=fmt, offset=offset, flags=flags)
1241 self.verify(nd, obj=None,
1242 itemsize=itemsize, fmt=fmt, readonly=1,
1243 ndim=1, shape=shape, strides=strides,
1244 lst=items[::step])
1245
1246 def test_ndarray_fortran(self):
1247 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1248 ex = ndarray(items, shape=(3, 4), strides=(1, 3))
1249 nd = ndarray(ex, getbuf=PyBUF_F_CONTIGUOUS|PyBUF_FORMAT)
1250 self.assertEqual(nd.tolist(), farray(items, (3, 4)))
1251
1252 def test_ndarray_multidim(self):
1253 for ndim in range(5):
1254 shape_t = [randrange(2, 10) for _ in range(ndim)]
1255 nitems = prod(shape_t)
1256 for shape in permutations(shape_t):
1257
1258 fmt, items, _ = randitems(nitems)
1259 itemsize = struct.calcsize(fmt)
1260
1261 for flags in (0, ND_PIL):
1262 if ndim == 0 and flags == ND_PIL:
1263 continue
1264
1265 # C array
1266 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1267
1268 strides = strides_from_shape(ndim, shape, itemsize, 'C')
1269 lst = carray(items, shape)
1270 self.verify(nd, obj=None,
1271 itemsize=itemsize, fmt=fmt, readonly=1,
1272 ndim=ndim, shape=shape, strides=strides,
1273 lst=lst)
1274
1275 if is_memoryview_format(fmt):
1276 # memoryview: reconstruct strides
1277 ex = ndarray(items, shape=shape, format=fmt)
1278 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
1279 self.assertTrue(nd.strides == ())
1280 mv = nd.memoryview_from_buffer()
1281 self.verify(mv, obj=None,
1282 itemsize=itemsize, fmt=fmt, readonly=1,
1283 ndim=ndim, shape=shape, strides=strides,
1284 lst=lst)
1285
1286 # Fortran array
1287 nd = ndarray(items, shape=shape, format=fmt,
1288 flags=flags|ND_FORTRAN)
1289
1290 strides = strides_from_shape(ndim, shape, itemsize, 'F')
1291 lst = farray(items, shape)
1292 self.verify(nd, obj=None,
1293 itemsize=itemsize, fmt=fmt, readonly=1,
1294 ndim=ndim, shape=shape, strides=strides,
1295 lst=lst)
1296
1297 def test_ndarray_index_invalid(self):
1298 # not writable
1299 nd = ndarray([1], shape=[1])
1300 self.assertRaises(TypeError, nd.__setitem__, 1, 8)
1301 mv = memoryview(nd)
1302 self.assertEqual(mv, nd)
1303 self.assertRaises(TypeError, mv.__setitem__, 1, 8)
1304
1305 # cannot be deleted
1306 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1307 self.assertRaises(TypeError, nd.__delitem__, 1)
1308 mv = memoryview(nd)
1309 self.assertEqual(mv, nd)
1310 self.assertRaises(TypeError, mv.__delitem__, 1)
1311
1312 # overflow
1313 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1314 self.assertRaises(OverflowError, nd.__getitem__, 1<<64)
1315 self.assertRaises(OverflowError, nd.__setitem__, 1<<64, 8)
1316 mv = memoryview(nd)
1317 self.assertEqual(mv, nd)
1318 self.assertRaises(IndexError, mv.__getitem__, 1<<64)
1319 self.assertRaises(IndexError, mv.__setitem__, 1<<64, 8)
1320
1321 # format
1322 items = [1,2,3,4,5,6,7,8]
1323 nd = ndarray(items, shape=[len(items)], format="B", flags=ND_WRITABLE)
1324 self.assertRaises(struct.error, nd.__setitem__, 2, 300)
1325 self.assertRaises(ValueError, nd.__setitem__, 1, (100, 200))
1326 mv = memoryview(nd)
1327 self.assertEqual(mv, nd)
1328 self.assertRaises(ValueError, mv.__setitem__, 2, 300)
1329 self.assertRaises(TypeError, mv.__setitem__, 1, (100, 200))
1330
1331 items = [(1,2), (3,4), (5,6)]
1332 nd = ndarray(items, shape=[len(items)], format="LQ", flags=ND_WRITABLE)
1333 self.assertRaises(ValueError, nd.__setitem__, 2, 300)
1334 self.assertRaises(struct.error, nd.__setitem__, 1, (b'\x001', 200))
1335
1336 def test_ndarray_index_scalar(self):
1337 # scalar
1338 nd = ndarray(1, shape=(), flags=ND_WRITABLE)
1339 mv = memoryview(nd)
1340 self.assertEqual(mv, nd)
1341
1342 x = nd[()]; self.assertEqual(x, 1)
1343 x = nd[...]; self.assertEqual(x.tolist(), nd.tolist())
1344
1345 x = mv[()]; self.assertEqual(x, 1)
1346 x = mv[...]; self.assertEqual(x.tolist(), nd.tolist())
1347
1348 self.assertRaises(TypeError, nd.__getitem__, 0)
1349 self.assertRaises(TypeError, mv.__getitem__, 0)
1350 self.assertRaises(TypeError, nd.__setitem__, 0, 8)
1351 self.assertRaises(TypeError, mv.__setitem__, 0, 8)
1352
1353 self.assertEqual(nd.tolist(), 1)
1354 self.assertEqual(mv.tolist(), 1)
1355
1356 nd[()] = 9; self.assertEqual(nd.tolist(), 9)
1357 mv[()] = 9; self.assertEqual(mv.tolist(), 9)
1358
1359 nd[...] = 5; self.assertEqual(nd.tolist(), 5)
1360 mv[...] = 5; self.assertEqual(mv.tolist(), 5)
1361
1362 def test_ndarray_index_null_strides(self):
1363 ex = ndarray(list(range(2*4)), shape=[2, 4], flags=ND_WRITABLE)
1364 nd = ndarray(ex, getbuf=PyBUF_CONTIG)
1365
1366 # Sub-views are only possible for full exporters.
1367 self.assertRaises(BufferError, nd.__getitem__, 1)
1368 # Same for slices.
1369 self.assertRaises(BufferError, nd.__getitem__, slice(3,5,1))
1370
1371 def test_ndarray_index_getitem_single(self):
1372 # getitem
1373 for fmt, items, _ in iter_format(5):
1374 nd = ndarray(items, shape=[5], format=fmt)
1375 for i in range(-5, 5):
1376 self.assertEqual(nd[i], items[i])
1377
1378 self.assertRaises(IndexError, nd.__getitem__, -6)
1379 self.assertRaises(IndexError, nd.__getitem__, 5)
1380
1381 if is_memoryview_format(fmt):
1382 mv = memoryview(nd)
1383 self.assertEqual(mv, nd)
1384 for i in range(-5, 5):
1385 self.assertEqual(mv[i], items[i])
1386
1387 self.assertRaises(IndexError, mv.__getitem__, -6)
1388 self.assertRaises(IndexError, mv.__getitem__, 5)
1389
1390 # getitem with null strides
1391 for fmt, items, _ in iter_format(5):
1392 ex = ndarray(items, shape=[5], flags=ND_WRITABLE, format=fmt)
1393 nd = ndarray(ex, getbuf=PyBUF_CONTIG|PyBUF_FORMAT)
1394
1395 for i in range(-5, 5):
1396 self.assertEqual(nd[i], items[i])
1397
1398 if is_memoryview_format(fmt):
1399 mv = nd.memoryview_from_buffer()
1400 self.assertIs(mv.__eq__(nd), NotImplemented)
1401 for i in range(-5, 5):
1402 self.assertEqual(mv[i], items[i])
1403
1404 # getitem with null format
1405 items = [1,2,3,4,5]
1406 ex = ndarray(items, shape=[5])
1407 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO)
1408 for i in range(-5, 5):
1409 self.assertEqual(nd[i], items[i])
1410
1411 # getitem with null shape/strides/format
1412 items = [1,2,3,4,5]
1413 ex = ndarray(items, shape=[5])
1414 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1415
1416 for i in range(-5, 5):
1417 self.assertEqual(nd[i], items[i])
1418
1419 def test_ndarray_index_setitem_single(self):
1420 # assign single value
1421 for fmt, items, single_item in iter_format(5):
1422 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1423 for i in range(5):
1424 items[i] = single_item
1425 nd[i] = single_item
1426 self.assertEqual(nd.tolist(), items)
1427
1428 self.assertRaises(IndexError, nd.__setitem__, -6, single_item)
1429 self.assertRaises(IndexError, nd.__setitem__, 5, single_item)
1430
1431 if not is_memoryview_format(fmt):
1432 continue
1433
1434 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1435 mv = memoryview(nd)
1436 self.assertEqual(mv, nd)
1437 for i in range(5):
1438 items[i] = single_item
1439 mv[i] = single_item
1440 self.assertEqual(mv.tolist(), items)
1441
1442 self.assertRaises(IndexError, mv.__setitem__, -6, single_item)
1443 self.assertRaises(IndexError, mv.__setitem__, 5, single_item)
1444
1445
1446 # assign single value: lobject = robject
1447 for fmt, items, single_item in iter_format(5):
1448 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1449 for i in range(-5, 4):
1450 items[i] = items[i+1]
1451 nd[i] = nd[i+1]
1452 self.assertEqual(nd.tolist(), items)
1453
1454 if not is_memoryview_format(fmt):
1455 continue
1456
1457 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1458 mv = memoryview(nd)
1459 self.assertEqual(mv, nd)
1460 for i in range(-5, 4):
1461 items[i] = items[i+1]
1462 mv[i] = mv[i+1]
1463 self.assertEqual(mv.tolist(), items)
1464
1465 def test_ndarray_index_getitem_multidim(self):
1466 shape_t = (2, 3, 5)
1467 nitems = prod(shape_t)
1468 for shape in permutations(shape_t):
1469
1470 fmt, items, _ = randitems(nitems)
1471
1472 for flags in (0, ND_PIL):
1473 # C array
1474 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1475 lst = carray(items, shape)
1476
1477 for i in range(-shape[0], shape[0]):
1478 self.assertEqual(lst[i], nd[i].tolist())
1479 for j in range(-shape[1], shape[1]):
1480 self.assertEqual(lst[i][j], nd[i][j].tolist())
1481 for k in range(-shape[2], shape[2]):
1482 self.assertEqual(lst[i][j][k], nd[i][j][k])
1483
1484 # Fortran array
1485 nd = ndarray(items, shape=shape, format=fmt,
1486 flags=flags|ND_FORTRAN)
1487 lst = farray(items, shape)
1488
1489 for i in range(-shape[0], shape[0]):
1490 self.assertEqual(lst[i], nd[i].tolist())
1491 for j in range(-shape[1], shape[1]):
1492 self.assertEqual(lst[i][j], nd[i][j].tolist())
1493 for k in range(shape[2], shape[2]):
1494 self.assertEqual(lst[i][j][k], nd[i][j][k])
1495
1496 def test_ndarray_sequence(self):
1497 nd = ndarray(1, shape=())
1498 self.assertRaises(TypeError, eval, "1 in nd", locals())
1499 mv = memoryview(nd)
1500 self.assertEqual(mv, nd)
1501 self.assertRaises(TypeError, eval, "1 in mv", locals())
1502
1503 for fmt, items, _ in iter_format(5):
1504 nd = ndarray(items, shape=[5], format=fmt)
1505 for i, v in enumerate(nd):
1506 self.assertEqual(v, items[i])
1507 self.assertTrue(v in nd)
1508
1509 if is_memoryview_format(fmt):
1510 mv = memoryview(nd)
1511 for i, v in enumerate(mv):
1512 self.assertEqual(v, items[i])
1513 self.assertTrue(v in mv)
1514
1515 def test_ndarray_slice_invalid(self):
1516 items = [1,2,3,4,5,6,7,8]
1517
1518 # rvalue is not an exporter
1519 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1520 ml = memoryview(xl)
1521 self.assertRaises(TypeError, xl.__setitem__, slice(0,8,1), items)
1522 self.assertRaises(TypeError, ml.__setitem__, slice(0,8,1), items)
1523
1524 # rvalue is not a full exporter
1525 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1526 ex = ndarray(items, shape=[8], flags=ND_WRITABLE)
1527 xr = ndarray(ex, getbuf=PyBUF_ND)
1528 self.assertRaises(BufferError, xl.__setitem__, slice(0,8,1), xr)
1529
1530 # zero step
1531 nd = ndarray(items, shape=[8], format="L", flags=ND_WRITABLE)
1532 mv = memoryview(nd)
1533 self.assertRaises(ValueError, nd.__getitem__, slice(0,1,0))
1534 self.assertRaises(ValueError, mv.__getitem__, slice(0,1,0))
1535
1536 nd = ndarray(items, shape=[2,4], format="L", flags=ND_WRITABLE)
1537 mv = memoryview(nd)
1538
1539 self.assertRaises(ValueError, nd.__getitem__,
1540 (slice(0,1,1), slice(0,1,0)))
1541 self.assertRaises(ValueError, nd.__getitem__,
1542 (slice(0,1,0), slice(0,1,1)))
1543 self.assertRaises(TypeError, nd.__getitem__, "@%$")
1544 self.assertRaises(TypeError, nd.__getitem__, ("@%$", slice(0,1,1)))
1545 self.assertRaises(TypeError, nd.__getitem__, (slice(0,1,1), {}))
1546
1547 # memoryview: not implemented
1548 self.assertRaises(NotImplementedError, mv.__getitem__,
1549 (slice(0,1,1), slice(0,1,0)))
1550 self.assertRaises(TypeError, mv.__getitem__, "@%$")
1551
1552 # differing format
1553 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1554 xr = ndarray(items, shape=[8], format="b")
1555 ml = memoryview(xl)
1556 mr = memoryview(xr)
1557 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1558 self.assertEqual(xl.tolist(), items)
1559 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1560 self.assertEqual(ml.tolist(), items)
1561
1562 # differing itemsize
1563 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1564 yr = ndarray(items, shape=[8], format="L")
1565 ml = memoryview(xl)
1566 mr = memoryview(xr)
1567 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1568 self.assertEqual(xl.tolist(), items)
1569 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1570 self.assertEqual(ml.tolist(), items)
1571
1572 # differing ndim
1573 xl = ndarray(items, shape=[2, 4], format="b", flags=ND_WRITABLE)
1574 xr = ndarray(items, shape=[8], format="b")
1575 ml = memoryview(xl)
1576 mr = memoryview(xr)
1577 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1578 self.assertEqual(xl.tolist(), [[1,2,3,4], [5,6,7,8]])
1579 self.assertRaises(NotImplementedError, ml.__setitem__, slice(0,1,1),
1580 mr[7:8])
1581
1582 # differing shape
1583 xl = ndarray(items, shape=[8], format="b", flags=ND_WRITABLE)
1584 xr = ndarray(items, shape=[8], format="b")
1585 ml = memoryview(xl)
1586 mr = memoryview(xr)
1587 self.assertRaises(ValueError, xl.__setitem__, slice(0,2,1), xr[7:8])
1588 self.assertEqual(xl.tolist(), items)
1589 self.assertRaises(ValueError, ml.__setitem__, slice(0,2,1), mr[7:8])
1590 self.assertEqual(ml.tolist(), items)
1591
1592 # _testbuffer.c module functions
1593 self.assertRaises(TypeError, slice_indices, slice(0,1,2), {})
1594 self.assertRaises(TypeError, slice_indices, "###########", 1)
1595 self.assertRaises(ValueError, slice_indices, slice(0,1,0), 4)
1596
1597 x = ndarray(items, shape=[8], format="b", flags=ND_PIL)
1598 self.assertRaises(TypeError, x.add_suboffsets)
1599
1600 ex = ndarray(items, shape=[8], format="B")
1601 x = ndarray(ex, getbuf=PyBUF_SIMPLE)
1602 self.assertRaises(TypeError, x.add_suboffsets)
1603
1604 def test_ndarray_slice_zero_shape(self):
1605 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1606
1607 x = ndarray(items, shape=[12], format="L", flags=ND_WRITABLE)
1608 y = ndarray(items, shape=[12], format="L")
1609 x[4:4] = y[9:9]
1610 self.assertEqual(x.tolist(), items)
1611
1612 ml = memoryview(x)
1613 mr = memoryview(y)
1614 self.assertEqual(ml, x)
1615 self.assertEqual(ml, y)
1616 ml[4:4] = mr[9:9]
1617 self.assertEqual(ml.tolist(), items)
1618
1619 x = ndarray(items, shape=[3, 4], format="L", flags=ND_WRITABLE)
1620 y = ndarray(items, shape=[4, 3], format="L")
1621 x[1:2, 2:2] = y[1:2, 3:3]
1622 self.assertEqual(x.tolist(), carray(items, [3, 4]))
1623
1624 def test_ndarray_slice_multidim(self):
1625 shape_t = (2, 3, 5)
1626 ndim = len(shape_t)
1627 nitems = prod(shape_t)
1628 for shape in permutations(shape_t):
1629
1630 fmt, items, _ = randitems(nitems)
1631 itemsize = struct.calcsize(fmt)
1632
1633 for flags in (0, ND_PIL):
1634 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1635 lst = carray(items, shape)
1636
1637 for slices in rslices_ndim(ndim, shape):
1638
1639 listerr = None
1640 try:
1641 sliced = multislice(lst, slices)
1642 except Exception as e:
1643 listerr = e.__class__
1644
1645 nderr = None
1646 try:
1647 ndsliced = nd[slices]
1648 except Exception as e:
1649 nderr = e.__class__
1650
1651 if nderr or listerr:
1652 self.assertIs(nderr, listerr)
1653 else:
1654 self.assertEqual(ndsliced.tolist(), sliced)
1655
1656 def test_ndarray_slice_redundant_suboffsets(self):
1657 shape_t = (2, 3, 5, 2)
1658 ndim = len(shape_t)
1659 nitems = prod(shape_t)
1660 for shape in permutations(shape_t):
1661
1662 fmt, items, _ = randitems(nitems)
1663 itemsize = struct.calcsize(fmt)
1664
1665 nd = ndarray(items, shape=shape, format=fmt)
1666 nd.add_suboffsets()
1667 ex = ndarray(items, shape=shape, format=fmt)
1668 ex.add_suboffsets()
1669 mv = memoryview(ex)
1670 lst = carray(items, shape)
1671
1672 for slices in rslices_ndim(ndim, shape):
1673
1674 listerr = None
1675 try:
1676 sliced = multislice(lst, slices)
1677 except Exception as e:
1678 listerr = e.__class__
1679
1680 nderr = None
1681 try:
1682 ndsliced = nd[slices]
1683 except Exception as e:
1684 nderr = e.__class__
1685
1686 if nderr or listerr:
1687 self.assertIs(nderr, listerr)
1688 else:
1689 self.assertEqual(ndsliced.tolist(), sliced)
1690
1691 def test_ndarray_slice_assign_single(self):
1692 for fmt, items, _ in iter_format(5):
1693 for lslice in genslices(5):
1694 for rslice in genslices(5):
1695 for flags in (0, ND_PIL):
1696
1697 f = flags|ND_WRITABLE
1698 nd = ndarray(items, shape=[5], format=fmt, flags=f)
1699 ex = ndarray(items, shape=[5], format=fmt, flags=f)
1700 mv = memoryview(ex)
1701
1702 lsterr = None
1703 diff_structure = None
1704 lst = items[:]
1705 try:
1706 lval = lst[lslice]
1707 rval = lst[rslice]
1708 lst[lslice] = lst[rslice]
1709 diff_structure = len(lval) != len(rval)
1710 except Exception as e:
1711 lsterr = e.__class__
1712
1713 nderr = None
1714 try:
1715 nd[lslice] = nd[rslice]
1716 except Exception as e:
1717 nderr = e.__class__
1718
1719 if diff_structure: # ndarray cannot change shape
1720 self.assertIs(nderr, ValueError)
1721 else:
1722 self.assertEqual(nd.tolist(), lst)
1723 self.assertIs(nderr, lsterr)
1724
1725 if not is_memoryview_format(fmt):
1726 continue
1727
1728 mverr = None
1729 try:
1730 mv[lslice] = mv[rslice]
1731 except Exception as e:
1732 mverr = e.__class__
1733
1734 if diff_structure: # memoryview cannot change shape
1735 self.assertIs(mverr, ValueError)
1736 else:
1737 self.assertEqual(mv.tolist(), lst)
1738 self.assertEqual(mv, nd)
1739 self.assertIs(mverr, lsterr)
1740 self.verify(mv, obj=ex,
1741 itemsize=nd.itemsize, fmt=fmt, readonly=0,
1742 ndim=nd.ndim, shape=nd.shape, strides=nd.strides,
1743 lst=nd.tolist())
1744
1745 def test_ndarray_slice_assign_multidim(self):
1746 shape_t = (2, 3, 5)
1747 ndim = len(shape_t)
1748 nitems = prod(shape_t)
1749 for shape in permutations(shape_t):
1750
1751 fmt, items, _ = randitems(nitems)
1752
1753 for flags in (0, ND_PIL):
1754 for _ in range(ITERATIONS):
1755 lslices, rslices = randslice_from_shape(ndim, shape)
1756
1757 nd = ndarray(items, shape=shape, format=fmt,
1758 flags=flags|ND_WRITABLE)
1759 lst = carray(items, shape)
1760
1761 listerr = None
1762 try:
1763 result = multislice_assign(lst, lst, lslices, rslices)
1764 except Exception as e:
1765 listerr = e.__class__
1766
1767 nderr = None
1768 try:
1769 nd[lslices] = nd[rslices]
1770 except Exception as e:
1771 nderr = e.__class__
1772
1773 if nderr or listerr:
1774 self.assertIs(nderr, listerr)
1775 else:
1776 self.assertEqual(nd.tolist(), result)
1777
1778 def test_ndarray_random(self):
1779 # construction of valid arrays
1780 for _ in range(ITERATIONS):
1781 for fmt in fmtdict['@']:
1782 itemsize = struct.calcsize(fmt)
1783
1784 t = rand_structure(itemsize, True, maxdim=MAXDIM,
1785 maxshape=MAXSHAPE)
1786 self.assertTrue(verify_structure(*t))
1787 items = randitems_from_structure(fmt, t)
1788
1789 x = ndarray_from_structure(items, fmt, t)
1790 xlist = x.tolist()
1791
1792 mv = memoryview(x)
1793 if is_memoryview_format(fmt):
1794 mvlist = mv.tolist()
1795 self.assertEqual(mvlist, xlist)
1796
1797 if t[2] > 0:
1798 # ndim > 0: test against suboffsets representation.
1799 y = ndarray_from_structure(items, fmt, t, flags=ND_PIL)
1800 ylist = y.tolist()
1801 self.assertEqual(xlist, ylist)
1802
1803 mv = memoryview(y)
1804 if is_memoryview_format(fmt):
1805 self.assertEqual(mv, y)
1806 mvlist = mv.tolist()
1807 self.assertEqual(mvlist, ylist)
1808
1809 if numpy_array:
1810 shape = t[3]
1811 if 0 in shape:
1812 continue # http://projects.scipy.org/numpy/ticket/1910
1813 z = numpy_array_from_structure(items, fmt, t)
1814 self.verify(x, obj=None,
1815 itemsize=z.itemsize, fmt=fmt, readonly=0,
1816 ndim=z.ndim, shape=z.shape, strides=z.strides,
1817 lst=z.tolist())
1818
1819 def test_ndarray_random_invalid(self):
1820 # exceptions during construction of invalid arrays
1821 for _ in range(ITERATIONS):
1822 for fmt in fmtdict['@']:
1823 itemsize = struct.calcsize(fmt)
1824
1825 t = rand_structure(itemsize, False, maxdim=MAXDIM,
1826 maxshape=MAXSHAPE)
1827 self.assertFalse(verify_structure(*t))
1828 items = randitems_from_structure(fmt, t)
1829
1830 nderr = False
1831 try:
1832 x = ndarray_from_structure(items, fmt, t)
1833 except Exception as e:
1834 nderr = e.__class__
1835 self.assertTrue(nderr)
1836
1837 if numpy_array:
1838 numpy_err = False
1839 try:
1840 y = numpy_array_from_structure(items, fmt, t)
1841 except Exception as e:
1842 numpy_err = e.__class__
1843
1844 if 0: # http://projects.scipy.org/numpy/ticket/1910
1845 self.assertTrue(numpy_err)
1846
1847 def test_ndarray_random_slice_assign(self):
1848 # valid slice assignments
1849 for _ in range(ITERATIONS):
1850 for fmt in fmtdict['@']:
1851 itemsize = struct.calcsize(fmt)
1852
1853 lshape, rshape, lslices, rslices = \
1854 rand_aligned_slices(maxdim=MAXDIM, maxshape=MAXSHAPE)
1855 tl = rand_structure(itemsize, True, shape=lshape)
1856 tr = rand_structure(itemsize, True, shape=rshape)
1857 self.assertTrue(verify_structure(*tl))
1858 self.assertTrue(verify_structure(*tr))
1859 litems = randitems_from_structure(fmt, tl)
1860 ritems = randitems_from_structure(fmt, tr)
1861
1862 xl = ndarray_from_structure(litems, fmt, tl)
1863 xr = ndarray_from_structure(ritems, fmt, tr)
1864 xl[lslices] = xr[rslices]
1865 xllist = xl.tolist()
1866 xrlist = xr.tolist()
1867
1868 ml = memoryview(xl)
1869 mr = memoryview(xr)
1870 self.assertEqual(ml.tolist(), xllist)
1871 self.assertEqual(mr.tolist(), xrlist)
1872
1873 if tl[2] > 0 and tr[2] > 0:
1874 # ndim > 0: test against suboffsets representation.
1875 yl = ndarray_from_structure(litems, fmt, tl, flags=ND_PIL)
1876 yr = ndarray_from_structure(ritems, fmt, tr, flags=ND_PIL)
1877 yl[lslices] = yr[rslices]
1878 yllist = yl.tolist()
1879 yrlist = yr.tolist()
1880 self.assertEqual(xllist, yllist)
1881 self.assertEqual(xrlist, yrlist)
1882
1883 ml = memoryview(yl)
1884 mr = memoryview(yr)
1885 self.assertEqual(ml.tolist(), yllist)
1886 self.assertEqual(mr.tolist(), yrlist)
1887
1888 if numpy_array:
1889 if 0 in lshape or 0 in rshape:
1890 continue # http://projects.scipy.org/numpy/ticket/1910
1891
1892 zl = numpy_array_from_structure(litems, fmt, tl)
1893 zr = numpy_array_from_structure(ritems, fmt, tr)
1894 zl[lslices] = zr[rslices]
1895
1896 if not is_overlapping(tl) and not is_overlapping(tr):
1897 # Slice assignment of overlapping structures
1898 # is undefined in NumPy.
1899 self.verify(xl, obj=None,
1900 itemsize=zl.itemsize, fmt=fmt, readonly=0,
1901 ndim=zl.ndim, shape=zl.shape,
1902 strides=zl.strides, lst=zl.tolist())
1903
1904 self.verify(xr, obj=None,
1905 itemsize=zr.itemsize, fmt=fmt, readonly=0,
1906 ndim=zr.ndim, shape=zr.shape,
1907 strides=zr.strides, lst=zr.tolist())
1908
1909 def test_ndarray_re_export(self):
1910 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1911
1912 nd = ndarray(items, shape=[3,4], flags=ND_PIL)
1913 ex = ndarray(nd)
1914
1915 self.assertTrue(ex.flags & ND_PIL)
1916 self.assertIs(ex.obj, nd)
1917 self.assertEqual(ex.suboffsets, (0, -1))
1918 self.assertFalse(ex.c_contiguous)
1919 self.assertFalse(ex.f_contiguous)
1920 self.assertFalse(ex.contiguous)
1921
1922 def test_ndarray_zero_shape(self):
1923 # zeros in shape
1924 for flags in (0, ND_PIL):
1925 nd = ndarray([1,2,3], shape=[0], flags=flags)
1926 mv = memoryview(nd)
1927 self.assertEqual(mv, nd)
1928 self.assertEqual(nd.tolist(), [])
1929 self.assertEqual(mv.tolist(), [])
1930
1931 nd = ndarray([1,2,3], shape=[0,3,3], flags=flags)
1932 self.assertEqual(nd.tolist(), [])
1933
1934 nd = ndarray([1,2,3], shape=[3,0,3], flags=flags)
1935 self.assertEqual(nd.tolist(), [[], [], []])
1936
1937 nd = ndarray([1,2,3], shape=[3,3,0], flags=flags)
1938 self.assertEqual(nd.tolist(),
1939 [[[], [], []], [[], [], []], [[], [], []]])
1940
1941 def test_ndarray_zero_strides(self):
1942 # zero strides
1943 for flags in (0, ND_PIL):
1944 nd = ndarray([1], shape=[5], strides=[0], flags=flags)
1945 mv = memoryview(nd)
1946 self.assertEqual(mv, nd)
1947 self.assertEqual(nd.tolist(), [1, 1, 1, 1, 1])
1948 self.assertEqual(mv.tolist(), [1, 1, 1, 1, 1])
1949
1950 def test_ndarray_offset(self):
1951 nd = ndarray(list(range(20)), shape=[3], offset=7)
1952 self.assertEqual(nd.offset, 7)
1953 self.assertEqual(nd.tolist(), [7,8,9])
1954
1955 def test_ndarray_memoryview_from_buffer(self):
1956 for flags in (0, ND_PIL):
1957 nd = ndarray(list(range(3)), shape=[3], flags=flags)
1958 m = nd.memoryview_from_buffer()
1959 self.assertEqual(m, nd)
1960
1961 def test_ndarray_get_pointer(self):
1962 for flags in (0, ND_PIL):
1963 nd = ndarray(list(range(3)), shape=[3], flags=flags)
1964 for i in range(3):
1965 self.assertEqual(nd[i], get_pointer(nd, [i]))
1966
1967 def test_ndarray_tolist_null_strides(self):
1968 ex = ndarray(list(range(20)), shape=[2,2,5])
1969
1970 nd = ndarray(ex, getbuf=PyBUF_ND|PyBUF_FORMAT)
1971 self.assertEqual(nd.tolist(), ex.tolist())
1972
1973 m = memoryview(ex)
1974 self.assertEqual(m.tolist(), ex.tolist())
1975
1976 def test_ndarray_cmp_contig(self):
1977
1978 self.assertFalse(cmp_contig(b"123", b"456"))
1979
1980 x = ndarray(list(range(12)), shape=[3,4])
1981 y = ndarray(list(range(12)), shape=[4,3])
1982 self.assertFalse(cmp_contig(x, y))
1983
1984 x = ndarray([1], shape=[1], format="B")
1985 self.assertTrue(cmp_contig(x, b'\x01'))
1986 self.assertTrue(cmp_contig(b'\x01', x))
1987
1988 def test_ndarray_hash(self):
1989
1990 a = array.array('L', [1,2,3])
1991 nd = ndarray(a)
1992 self.assertRaises(ValueError, hash, nd)
1993
1994 # one-dimensional
1995 b = bytes(list(range(12)))
1996
1997 nd = ndarray(list(range(12)), shape=[12])
1998 self.assertEqual(hash(nd), hash(b))
1999
2000 # C-contiguous
2001 nd = ndarray(list(range(12)), shape=[3,4])
2002 self.assertEqual(hash(nd), hash(b))
2003
2004 nd = ndarray(list(range(12)), shape=[3,2,2])
2005 self.assertEqual(hash(nd), hash(b))
2006
2007 # Fortran contiguous
2008 b = bytes(transpose(list(range(12)), shape=[4,3]))
2009 nd = ndarray(list(range(12)), shape=[3,4], flags=ND_FORTRAN)
2010 self.assertEqual(hash(nd), hash(b))
2011
2012 b = bytes(transpose(list(range(12)), shape=[2,3,2]))
2013 nd = ndarray(list(range(12)), shape=[2,3,2], flags=ND_FORTRAN)
2014 self.assertEqual(hash(nd), hash(b))
2015
2016 # suboffsets
2017 b = bytes(list(range(12)))
2018 nd = ndarray(list(range(12)), shape=[2,2,3], flags=ND_PIL)
2019 self.assertEqual(hash(nd), hash(b))
2020
2021 # non-byte formats
2022 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
2023 self.assertEqual(hash(nd), hash(nd.tobytes()))
2024
2025 def test_memoryview_construction(self):
2026
2027 items_shape = [(9, []), ([1,2,3], [3]), (list(range(2*3*5)), [2,3,5])]
2028
2029 # NumPy style, C-contiguous:
2030 for items, shape in items_shape:
2031
2032 # From PEP-3118 compliant exporter:
2033 ex = ndarray(items, shape=shape)
2034 m = memoryview(ex)
2035 self.assertTrue(m.c_contiguous)
2036 self.assertTrue(m.contiguous)
2037
2038 ndim = len(shape)
2039 strides = strides_from_shape(ndim, shape, 1, 'C')
2040 lst = carray(items, shape)
2041
2042 self.verify(m, obj=ex,
2043 itemsize=1, fmt='B', readonly=1,
2044 ndim=ndim, shape=shape, strides=strides,
2045 lst=lst)
2046
2047 # From memoryview:
2048 m2 = memoryview(m)
2049 self.verify(m2, obj=ex,
2050 itemsize=1, fmt='B', readonly=1,
2051 ndim=ndim, shape=shape, strides=strides,
2052 lst=lst)
2053
2054 # PyMemoryView_FromBuffer(): no strides
2055 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2056 self.assertEqual(nd.strides, ())
2057 m = nd.memoryview_from_buffer()
2058 self.verify(m, obj=None,
2059 itemsize=1, fmt='B', readonly=1,
2060 ndim=ndim, shape=shape, strides=strides,
2061 lst=lst)
2062
2063 # PyMemoryView_FromBuffer(): no format, shape, strides
2064 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2065 self.assertEqual(nd.format, '')
2066 self.assertEqual(nd.shape, ())
2067 self.assertEqual(nd.strides, ())
2068 m = nd.memoryview_from_buffer()
2069
2070 lst = [items] if ndim == 0 else items
2071 self.verify(m, obj=None,
2072 itemsize=1, fmt='B', readonly=1,
2073 ndim=1, shape=[ex.nbytes], strides=(1,),
2074 lst=lst)
2075
2076 # NumPy style, Fortran contiguous:
2077 for items, shape in items_shape:
2078
2079 # From PEP-3118 compliant exporter:
2080 ex = ndarray(items, shape=shape, flags=ND_FORTRAN)
2081 m = memoryview(ex)
2082 self.assertTrue(m.f_contiguous)
2083 self.assertTrue(m.contiguous)
2084
2085 ndim = len(shape)
2086 strides = strides_from_shape(ndim, shape, 1, 'F')
2087 lst = farray(items, shape)
2088
2089 self.verify(m, obj=ex,
2090 itemsize=1, fmt='B', readonly=1,
2091 ndim=ndim, shape=shape, strides=strides,
2092 lst=lst)
2093
2094 # From memoryview:
2095 m2 = memoryview(m)
2096 self.verify(m2, obj=ex,
2097 itemsize=1, fmt='B', readonly=1,
2098 ndim=ndim, shape=shape, strides=strides,
2099 lst=lst)
2100
2101 # PIL style:
2102 for items, shape in items_shape[1:]:
2103
2104 # From PEP-3118 compliant exporter:
2105 ex = ndarray(items, shape=shape, flags=ND_PIL)
2106 m = memoryview(ex)
2107
2108 ndim = len(shape)
2109 lst = carray(items, shape)
2110
2111 self.verify(m, obj=ex,
2112 itemsize=1, fmt='B', readonly=1,
2113 ndim=ndim, shape=shape, strides=ex.strides,
2114 lst=lst)
2115
2116 # From memoryview:
2117 m2 = memoryview(m)
2118 self.verify(m2, obj=ex,
2119 itemsize=1, fmt='B', readonly=1,
2120 ndim=ndim, shape=shape, strides=ex.strides,
2121 lst=lst)
2122
2123 # Invalid number of arguments:
2124 self.assertRaises(TypeError, memoryview, b'9', 'x')
2125 # Not a buffer provider:
2126 self.assertRaises(TypeError, memoryview, {})
2127 # Non-compliant buffer provider:
2128 ex = ndarray([1,2,3], shape=[3])
2129 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2130 self.assertRaises(BufferError, memoryview, nd)
2131 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2132 self.assertRaises(BufferError, memoryview, nd)
2133
2134 # ndim > 64
2135 nd = ndarray([1]*128, shape=[1]*128, format='L')
2136 self.assertRaises(ValueError, memoryview, nd)
2137 self.assertRaises(ValueError, nd.memoryview_from_buffer)
2138 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'C')
2139 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'F')
2140 self.assertRaises(ValueError, get_contiguous, nd[::-1], PyBUF_READ, 'C')
2141
2142 def test_memoryview_cast_zero_shape(self):
2143 # Casts are undefined if shape contains zeros. These arrays are
2144 # regarded as C-contiguous by Numpy and PyBuffer_GetContiguous(),
2145 # so they are not caught by the test for C-contiguity in memory_cast().
2146 items = [1,2,3]
2147 for shape in ([0,3,3], [3,0,3], [0,3,3]):
2148 ex = ndarray(items, shape=shape)
2149 self.assertTrue(ex.c_contiguous)
2150 msrc = memoryview(ex)
2151 self.assertRaises(TypeError, msrc.cast, 'c')
2152
2153 def test_memoryview_struct_module(self):
2154
2155 class INT(object):
2156 def __init__(self, val):
2157 self.val = val
2158 def __int__(self):
2159 return self.val
2160
2161 class IDX(object):
2162 def __init__(self, val):
2163 self.val = val
2164 def __index__(self):
2165 return self.val
2166
2167 def f(): return 7
2168
2169 values = [INT(9), IDX(9),
2170 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2),
2171 [1,2,3], {4,5,6}, {7:8}, (), (9,),
2172 True, False, None, NotImplemented,
2173 b'a', b'abc', bytearray(b'a'), bytearray(b'abc'),
2174 'a', 'abc', r'a', r'abc',
2175 f, lambda x: x]
2176
2177 for fmt, items, item in iter_format(10, 'memoryview'):
2178 ex = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2179 nd = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2180 m = memoryview(ex)
2181
2182 struct.pack_into(fmt, nd, 0, item)
2183 m[0] = item
2184 self.assertEqual(m[0], nd[0])
2185
2186 itemsize = struct.calcsize(fmt)
2187 if 'P' in fmt:
2188 continue
2189
2190 for v in values:
2191 struct_err = None
2192 try:
2193 struct.pack_into(fmt, nd, itemsize, v)
2194 except struct.error:
2195 struct_err = struct.error
2196
2197 mv_err = None
2198 try:
2199 m[1] = v
2200 except (TypeError, ValueError) as e:
2201 mv_err = e.__class__
2202
2203 if struct_err or mv_err:
2204 self.assertIsNot(struct_err, None)
2205 self.assertIsNot(mv_err, None)
2206 else:
2207 self.assertEqual(m[1], nd[1])
2208
2209 def test_memoryview_cast_zero_strides(self):
2210 # Casts are undefined if strides contains zeros. These arrays are
2211 # (sometimes!) regarded as C-contiguous by Numpy, but not by
2212 # PyBuffer_GetContiguous().
2213 ex = ndarray([1,2,3], shape=[3], strides=[0])
2214 self.assertFalse(ex.c_contiguous)
2215 msrc = memoryview(ex)
2216 self.assertRaises(TypeError, msrc.cast, 'c')
2217
2218 def test_memoryview_cast_invalid(self):
2219 # invalid format
2220 for sfmt in NON_BYTE_FORMAT:
2221 sformat = '@' + sfmt if randrange(2) else sfmt
2222 ssize = struct.calcsize(sformat)
2223 for dfmt in NON_BYTE_FORMAT:
2224 dformat = '@' + dfmt if randrange(2) else dfmt
2225 dsize = struct.calcsize(dformat)
2226 ex = ndarray(list(range(32)), shape=[32//ssize], format=sformat)
2227 msrc = memoryview(ex)
2228 self.assertRaises(TypeError, msrc.cast, dfmt, [32//dsize])
2229
2230 for sfmt, sitems, _ in iter_format(1):
2231 ex = ndarray(sitems, shape=[1], format=sfmt)
2232 msrc = memoryview(ex)
2233 for dfmt, _, _ in iter_format(1):
2234 if (not is_memoryview_format(sfmt) or
2235 not is_memoryview_format(dfmt)):
2236 self.assertRaises(ValueError, msrc.cast, dfmt,
2237 [32//dsize])
2238 else:
2239 if not is_byte_format(sfmt) and not is_byte_format(dfmt):
2240 self.assertRaises(TypeError, msrc.cast, dfmt,
2241 [32//dsize])
2242
2243 # invalid shape
2244 size_h = struct.calcsize('h')
2245 size_d = struct.calcsize('d')
2246 ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h')
2247 msrc = memoryview(ex)
2248 self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d')
2249
2250 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2251 m = memoryview(ex)
2252
2253 # incorrect number of args
2254 self.assertRaises(TypeError, m.cast)
2255 self.assertRaises(TypeError, m.cast, 1, 2, 3)
2256
2257 # incorrect dest format type
2258 self.assertRaises(TypeError, m.cast, {})
2259
2260 # incorrect dest format
2261 self.assertRaises(ValueError, m.cast, "X")
2262 self.assertRaises(ValueError, m.cast, "@X")
2263 self.assertRaises(ValueError, m.cast, "@XY")
2264
2265 # dest format not implemented
2266 self.assertRaises(ValueError, m.cast, "=B")
2267 self.assertRaises(ValueError, m.cast, "!L")
2268 self.assertRaises(ValueError, m.cast, "<P")
2269 self.assertRaises(ValueError, m.cast, ">l")
2270 self.assertRaises(ValueError, m.cast, "BI")
2271 self.assertRaises(ValueError, m.cast, "xBI")
2272
2273 # src format not implemented
2274 ex = ndarray([(1,2), (3,4)], shape=[2], format="II")
2275 m = memoryview(ex)
2276 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2277 self.assertRaises(NotImplementedError, m.__setitem__, 0, 8)
2278 self.assertRaises(NotImplementedError, m.tolist)
2279
2280 # incorrect shape type
2281 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2282 m = memoryview(ex)
2283 self.assertRaises(TypeError, m.cast, "B", shape={})
2284
2285 # incorrect shape elements
2286 ex = ndarray(list(range(120)), shape=[2*3*4*5])
2287 m = memoryview(ex)
2288 self.assertRaises(OverflowError, m.cast, "B", shape=[2**64])
2289 self.assertRaises(ValueError, m.cast, "B", shape=[-1])
2290 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1])
2291 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0])
2292 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x'])
2293
2294 # N-D -> N-D cast
2295 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11])
2296 m = memoryview(ex)
2297 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2298
2299 # cast with ndim > 64
2300 nd = ndarray(list(range(128)), shape=[128], format='I')
2301 m = memoryview(nd)
2302 self.assertRaises(ValueError, m.cast, 'I', [1]*128)
2303
2304 # view->len not a multiple of itemsize
2305 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2306 m = memoryview(ex)
2307 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2308
2309 # product(shape) * itemsize != buffer size
2310 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2311 m = memoryview(ex)
2312 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5])
2313
2314 # product(shape) * itemsize overflow
2315 nd = ndarray(list(range(128)), shape=[128], format='I')
2316 m1 = memoryview(nd)
2317 nd = ndarray(list(range(128)), shape=[128], format='B')
2318 m2 = memoryview(nd)
2319 if sys.maxsize == 2**63-1:
2320 self.assertRaises(TypeError, m1.cast, 'B',
2321 [7, 7, 73, 127, 337, 92737, 649657])
2322 self.assertRaises(ValueError, m1.cast, 'B',
2323 [2**20, 2**20, 2**10, 2**10, 2**3])
2324 self.assertRaises(ValueError, m2.cast, 'I',
2325 [2**20, 2**20, 2**10, 2**10, 2**1])
2326 else:
2327 self.assertRaises(TypeError, m1.cast, 'B',
2328 [1, 2147483647])
2329 self.assertRaises(ValueError, m1.cast, 'B',
2330 [2**10, 2**10, 2**5, 2**5, 2**1])
2331 self.assertRaises(ValueError, m2.cast, 'I',
2332 [2**10, 2**10, 2**5, 2**3, 2**1])
2333
2334 def test_memoryview_cast(self):
2335 bytespec = (
2336 ('B', lambda ex: list(ex.tobytes())),
2337 ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]),
2338 ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]),
2339 )
2340
2341 def iter_roundtrip(ex, m, items, fmt):
2342 srcsize = struct.calcsize(fmt)
2343 for bytefmt, to_bytelist in bytespec:
2344
2345 m2 = m.cast(bytefmt)
2346 lst = to_bytelist(ex)
2347 self.verify(m2, obj=ex,
2348 itemsize=1, fmt=bytefmt, readonly=0,
2349 ndim=1, shape=[31*srcsize], strides=(1,),
2350 lst=lst, cast=True)
2351
2352 m3 = m2.cast(fmt)
2353 self.assertEqual(m3, ex)
2354 lst = ex.tolist()
2355 self.verify(m3, obj=ex,
2356 itemsize=srcsize, fmt=fmt, readonly=0,
2357 ndim=1, shape=[31], strides=(srcsize,),
2358 lst=lst, cast=True)
2359
2360 # cast from ndim = 0 to ndim = 1
2361 srcsize = struct.calcsize('I')
2362 ex = ndarray(9, shape=[], format='I')
2363 destitems, destshape = cast_items(ex, 'B', 1)
2364 m = memoryview(ex)
2365 m2 = m.cast('B')
2366 self.verify(m2, obj=ex,
2367 itemsize=1, fmt='B', readonly=1,
2368 ndim=1, shape=destshape, strides=(1,),
2369 lst=destitems, cast=True)
2370
2371 # cast from ndim = 1 to ndim = 0
2372 destsize = struct.calcsize('I')
2373 ex = ndarray([9]*destsize, shape=[destsize], format='B')
2374 destitems, destshape = cast_items(ex, 'I', destsize, shape=[])
2375 m = memoryview(ex)
2376 m2 = m.cast('I', shape=[])
2377 self.verify(m2, obj=ex,
2378 itemsize=destsize, fmt='I', readonly=1,
2379 ndim=0, shape=(), strides=(),
2380 lst=destitems, cast=True)
2381
2382 # array.array: roundtrip to/from bytes
2383 for fmt, items, _ in iter_format(31, 'array'):
2384 ex = array.array(fmt, items)
2385 m = memoryview(ex)
2386 iter_roundtrip(ex, m, items, fmt)
2387
2388 # ndarray: roundtrip to/from bytes
2389 for fmt, items, _ in iter_format(31, 'memoryview'):
2390 ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE)
2391 m = memoryview(ex)
2392 iter_roundtrip(ex, m, items, fmt)
2393
2394 def test_memoryview_cast_1D_ND(self):
2395 # Cast between C-contiguous buffers. At least one buffer must
2396 # be 1D, at least one format must be 'c', 'b' or 'B'.
2397 for _tshape in gencastshapes():
2398 for char in fmtdict['@']:
2399 tfmt = ('', '@')[randrange(2)] + char
2400 tsize = struct.calcsize(tfmt)
2401 n = prod(_tshape) * tsize
2402 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2403 for fmt, items, _ in iter_format(n, obj):
2404 size = struct.calcsize(fmt)
2405 shape = [n] if n > 0 else []
2406 tshape = _tshape + [size]
2407
2408 ex = ndarray(items, shape=shape, format=fmt)
2409 m = memoryview(ex)
2410
2411 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2412
2413 if titems is None:
2414 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2415 continue
2416 if titems == 'nan':
2417 continue # NaNs in lists are a recipe for trouble.
2418
2419 # 1D -> ND
2420 nd = ndarray(titems, shape=tshape, format=tfmt)
2421
2422 m2 = m.cast(tfmt, shape=tshape)
2423 ndim = len(tshape)
2424 strides = nd.strides
2425 lst = nd.tolist()
2426 self.verify(m2, obj=ex,
2427 itemsize=tsize, fmt=tfmt, readonly=1,
2428 ndim=ndim, shape=tshape, strides=strides,
2429 lst=lst, cast=True)
2430
2431 # ND -> 1D
2432 m3 = m2.cast(fmt)
2433 m4 = m2.cast(fmt, shape=shape)
2434 ndim = len(shape)
2435 strides = ex.strides
2436 lst = ex.tolist()
2437
2438 self.verify(m3, obj=ex,
2439 itemsize=size, fmt=fmt, readonly=1,
2440 ndim=ndim, shape=shape, strides=strides,
2441 lst=lst, cast=True)
2442
2443 self.verify(m4, obj=ex,
2444 itemsize=size, fmt=fmt, readonly=1,
2445 ndim=ndim, shape=shape, strides=strides,
2446 lst=lst, cast=True)
2447
2448 def test_memoryview_tolist(self):
2449
2450 # Most tolist() tests are in self.verify() etc.
2451
2452 a = array.array('h', list(range(-6, 6)))
2453 m = memoryview(a)
2454 self.assertEqual(m, a)
2455 self.assertEqual(m.tolist(), a.tolist())
2456
2457 a = a[2::3]
2458 m = m[2::3]
2459 self.assertEqual(m, a)
2460 self.assertEqual(m.tolist(), a.tolist())
2461
2462 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2463 m = memoryview(ex)
2464 self.assertEqual(m.tolist(), ex.tolist())
2465
2466 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2467 m = memoryview(ex)
2468 self.assertRaises(NotImplementedError, m.tolist)
2469
2470 ex = ndarray([b'12345'], shape=[1], format="s")
2471 m = memoryview(ex)
2472 self.assertRaises(NotImplementedError, m.tolist)
2473
2474 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2475 m = memoryview(ex)
2476 self.assertRaises(NotImplementedError, m.tolist)
2477
2478 def test_memoryview_repr(self):
2479 m = memoryview(bytearray(9))
2480 r = m.__repr__()
2481 self.assertTrue(r.startswith("<memory"))
2482
2483 m.release()
2484 r = m.__repr__()
2485 self.assertTrue(r.startswith("<released"))
2486
2487 def test_memoryview_sequence(self):
2488
2489 for fmt in ('d', 'f'):
2490 inf = float(3e400)
2491 ex = array.array(fmt, [1.0, inf, 3.0])
2492 m = memoryview(ex)
2493 self.assertIn(1.0, m)
2494 self.assertIn(5e700, m)
2495 self.assertIn(3.0, m)
2496
2497 ex = ndarray(9.0, [], format='f')
2498 m = memoryview(ex)
2499 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2500
2501 def test_memoryview_index(self):
2502
2503 # ndim = 0
2504 ex = ndarray(12.5, shape=[], format='d')
2505 m = memoryview(ex)
2506 self.assertEqual(m[()], 12.5)
2507 self.assertEqual(m[...], m)
2508 self.assertEqual(m[...], ex)
2509 self.assertRaises(TypeError, m.__getitem__, 0)
2510
2511 ex = ndarray((1,2,3), shape=[], format='iii')
2512 m = memoryview(ex)
2513 self.assertRaises(NotImplementedError, m.__getitem__, ())
2514
2515 # range
2516 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2517 m = memoryview(ex)
2518
2519 self.assertRaises(IndexError, m.__getitem__, 2**64)
2520 self.assertRaises(TypeError, m.__getitem__, 2.0)
2521 self.assertRaises(TypeError, m.__getitem__, 0.0)
2522
2523 # out of bounds
2524 self.assertRaises(IndexError, m.__getitem__, -8)
2525 self.assertRaises(IndexError, m.__getitem__, 8)
2526
2527 # Not implemented: multidimensional sub-views
2528 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2529 m = memoryview(ex)
2530
2531 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2532 self.assertRaises(NotImplementedError, m.__setitem__, 0, 9)
2533 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2534
2535 def test_memoryview_assign(self):
2536
2537 # ndim = 0
2538 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2539 m = memoryview(ex)
2540 m[()] = 22.5
2541 self.assertEqual(m[()], 22.5)
2542 m[...] = 23.5
2543 self.assertEqual(m[()], 23.5)
2544 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2545
2546 # read-only
2547 ex = ndarray(list(range(7)), shape=[7])
2548 m = memoryview(ex)
2549 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2550
2551 # range
2552 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2553 m = memoryview(ex)
2554
2555 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2556 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2557 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2558
2559 # out of bounds
2560 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2561 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2562
2563 # pack_single() success:
2564 for fmt in fmtdict['@']:
2565 if fmt == 'c' or fmt == '?':
2566 continue
2567 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2568 m = memoryview(ex)
2569 i = randrange(-3, 3)
2570 m[i] = 8
2571 self.assertEqual(m[i], 8)
2572 self.assertEqual(m[i], ex[i])
2573
2574 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2575 flags=ND_WRITABLE)
2576 m = memoryview(ex)
2577 m[2] = b'9'
2578 self.assertEqual(m[2], b'9')
2579
2580 ex = ndarray([True, False, True], shape=[3], format='?',
2581 flags=ND_WRITABLE)
2582 m = memoryview(ex)
2583 m[1] = True
2584 self.assertEqual(m[1], True)
2585
2586 # pack_single() exceptions:
2587 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2588 m = memoryview(nd)
2589 self.assertRaises(TypeError, m.__setitem__, 0, 100)
2590
2591 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
2592 m1 = memoryview(ex)
2593
2594 for fmt, _range in fmtdict['@'].items():
2595 if (fmt == '?'): # PyObject_IsTrue() accepts anything
2596 continue
2597 if fmt == 'c': # special case tested above
2598 continue
2599 m2 = m1.cast(fmt)
2600 lo, hi = _range
2601 if fmt == 'd' or fmt == 'f':
2602 lo, hi = -2**1024, 2**1024
2603 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
2604 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
2605 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
2606 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
2607
2608 # invalid item
2609 m2 = m1.cast('c')
2610 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
2611
2612 # format not implemented
2613 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
2614 m = memoryview(ex)
2615 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2616
2617 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
2618 m = memoryview(ex)
2619 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2620
2621 # Not implemented: multidimensional sub-views
2622 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2623 m = memoryview(ex)
2624
2625 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
2626
2627 def test_memoryview_slice(self):
2628
2629 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2630 m = memoryview(ex)
2631
2632 # zero step
2633 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
2634 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
2635 bytearray([1,2]))
2636
2637 # invalid slice key
2638 self.assertRaises(TypeError, m.__getitem__, ())
2639
2640 # multidimensional slices
2641 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2642 m = memoryview(ex)
2643
2644 self.assertRaises(NotImplementedError, m.__getitem__,
2645 (slice(0,2,1), slice(0,2,1)))
2646 self.assertRaises(NotImplementedError, m.__setitem__,
2647 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
2648
2649 # invalid slice tuple
2650 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
2651 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
2652 bytearray([1,2]))
2653
2654 # rvalue is not an exporter
2655 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
2656
2657 # non-contiguous slice assignment
2658 for flags in (0, ND_PIL):
2659 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
2660 flags=ND_WRITABLE|flags)
2661 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
2662 m1 = memoryview(ex1)
2663 m2 = memoryview(ex2)
2664
2665 ex1[2:5] = ex1[2:5]
2666 m1[2:5] = m2[2:5]
2667
2668 self.assertEqual(m1, ex1)
2669 self.assertEqual(m2, ex2)
2670
2671 ex1[1:3][::-1] = ex2[0:2][::1]
2672 m1[1:3][::-1] = m2[0:2][::1]
2673
2674 self.assertEqual(m1, ex1)
2675 self.assertEqual(m2, ex2)
2676
2677 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
2678 m1[4:1:-2][::-1] = m1[1:4:2][::1]
2679
2680 self.assertEqual(m1, ex1)
2681 self.assertEqual(m2, ex2)
2682
2683 def test_memoryview_array(self):
2684
2685 def cmptest(testcase, a, b, m, singleitem):
2686 for i, _ in enumerate(a):
2687 ai = a[i]
2688 mi = m[i]
2689 testcase.assertEqual(ai, mi)
2690 a[i] = singleitem
2691 if singleitem != ai:
2692 testcase.assertNotEqual(a, m)
2693 testcase.assertNotEqual(a, b)
2694 else:
2695 testcase.assertEqual(a, m)
2696 testcase.assertEqual(a, b)
2697 m[i] = singleitem
2698 testcase.assertEqual(a, m)
2699 testcase.assertEqual(b, m)
2700 a[i] = ai
2701 m[i] = mi
2702
2703 for n in range(1, 5):
2704 for fmt, items, singleitem in iter_format(n, 'array'):
2705 for lslice in genslices(n):
2706 for rslice in genslices(n):
2707
2708 a = array.array(fmt, items)
2709 b = array.array(fmt, items)
2710 m = memoryview(b)
2711
2712 self.assertEqual(m, a)
2713 self.assertEqual(m.tolist(), a.tolist())
2714 self.assertEqual(m.tobytes(), a.tobytes())
2715 self.assertEqual(len(m), len(a))
2716
2717 cmptest(self, a, b, m, singleitem)
2718
2719 array_err = None
2720 have_resize = None
2721 try:
2722 al = a[lslice]
2723 ar = a[rslice]
2724 a[lslice] = a[rslice]
2725 have_resize = len(al) != len(ar)
2726 except Exception as e:
2727 array_err = e.__class__
2728
2729 m_err = None
2730 try:
2731 m[lslice] = m[rslice]
2732 except Exception as e:
2733 m_err = e.__class__
2734
2735 if have_resize: # memoryview cannot change shape
2736 self.assertIs(m_err, ValueError)
2737 elif m_err or array_err:
2738 self.assertIs(m_err, array_err)
2739 else:
2740 self.assertEqual(m, a)
2741 self.assertEqual(m.tolist(), a.tolist())
2742 self.assertEqual(m.tobytes(), a.tobytes())
2743 cmptest(self, a, b, m, singleitem)
2744
2745 def test_memoryview_compare(self):
2746
2747 a = array.array('L', [1, 2, 3])
2748 b = array.array('L', [1, 2, 7])
2749
2750 # Ordering comparisons raise:
2751 v = memoryview(a)
2752 w = memoryview(b)
2753 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
2754 self.assertIs(getattr(v, attr)(w), NotImplemented)
2755 self.assertIs(getattr(a, attr)(v), NotImplemented)
2756
2757 # Released views compare equal to themselves:
2758 v = memoryview(a)
2759 v.release()
2760 self.assertEqual(v, v)
2761 self.assertNotEqual(v, a)
2762 self.assertNotEqual(a, v)
2763
2764 v = memoryview(a)
2765 w = memoryview(a)
2766 w.release()
2767 self.assertNotEqual(v, w)
2768 self.assertNotEqual(w, v)
2769
2770 # Operand does not implement the buffer protocol:
2771 v = memoryview(a)
2772 self.assertNotEqual(v, [1, 2, 3])
2773
2774 # Different formats:
2775 c = array.array('l', [1, 2, 3])
2776 v = memoryview(a)
2777 self.assertNotEqual(v, c)
2778 self.assertNotEqual(c, v)
2779
2780 # Not implemented formats. Ugly, but inevitable. This is the same as
2781 # issue #2531: equality is also used for membership testing and must
2782 # return a result.
2783 a = ndarray([(1, 1.5), (2, 2.7)], shape=[2], format='ld')
2784 v = memoryview(a)
2785 self.assertNotEqual(v, a)
2786 self.assertNotEqual(a, v)
2787
2788 a = ndarray([b'12345'], shape=[1], format="s")
2789 v = memoryview(a)
2790 self.assertNotEqual(v, a)
2791 self.assertNotEqual(a, v)
2792
2793 nd = ndarray([(1,1,1), (2,2,2), (3,3,3)], shape=[3], format='iii')
2794 v = memoryview(nd)
2795 self.assertNotEqual(v, nd)
2796 self.assertNotEqual(nd, v)
2797
2798 # '@' prefix can be dropped:
2799 nd1 = ndarray([1,2,3], shape=[3], format='@i')
2800 nd2 = ndarray([1,2,3], shape=[3], format='i')
2801 v = memoryview(nd1)
2802 w = memoryview(nd2)
2803 self.assertEqual(v, w)
2804 self.assertEqual(w, v)
2805 self.assertEqual(v, nd2)
2806 self.assertEqual(nd2, v)
2807 self.assertEqual(w, nd1)
2808 self.assertEqual(nd1, w)
2809
2810 # ndim = 0
2811 nd1 = ndarray(1729, shape=[], format='@L')
2812 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
2813 v = memoryview(nd1)
2814 w = memoryview(nd2)
2815 self.assertEqual(v, w)
2816 self.assertEqual(w, v)
2817 self.assertEqual(v, nd2)
2818 self.assertEqual(nd2, v)
2819 self.assertEqual(w, nd1)
2820 self.assertEqual(nd1, w)
2821
2822 self.assertFalse(v.__ne__(w))
2823 self.assertFalse(w.__ne__(v))
2824
2825 w[()] = 1728
2826 self.assertNotEqual(v, w)
2827 self.assertNotEqual(w, v)
2828 self.assertNotEqual(v, nd2)
2829 self.assertNotEqual(nd2, v)
2830 self.assertNotEqual(w, nd1)
2831 self.assertNotEqual(nd1, w)
2832
2833 self.assertFalse(v.__eq__(w))
2834 self.assertFalse(w.__eq__(v))
2835
2836 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
2837 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
2838 m = memoryview(ex)
2839
2840 self.assertEqual(m, nd)
2841 m[9] = 100
2842 self.assertNotEqual(m, nd)
2843
2844 # ndim = 1: contiguous
2845 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
2846 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
2847 v = memoryview(nd1)
2848 w = memoryview(nd2)
2849
2850 self.assertEqual(v, nd1)
2851 self.assertEqual(w, nd2)
2852 self.assertNotEqual(v, nd2)
2853 self.assertNotEqual(w, nd1)
2854 self.assertNotEqual(v, w)
2855
2856 # ndim = 1: non-contiguous
2857 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
2858 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
2859 v = memoryview(nd1)
2860 w = memoryview(nd2)
2861
2862 self.assertEqual(v, nd2[::2])
2863 self.assertEqual(w[::2], nd1)
2864 self.assertEqual(v, w[::2])
2865 self.assertEqual(v[::-1], w[::-2])
2866
2867 # ndim = 1: non-contiguous, suboffsets
2868 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
2869 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
2870 flags=ND_PIL)
2871 v = memoryview(nd1)
2872 w = memoryview(nd2)
2873
2874 self.assertEqual(v, nd2[::2])
2875 self.assertEqual(w[::2], nd1)
2876 self.assertEqual(v, w[::2])
2877 self.assertEqual(v[::-1], w[::-2])
2878
2879 # ndim = 1: zeros in shape
2880 nd1 = ndarray([900, 961], shape=[0], format='@h')
2881 nd2 = ndarray([-900, -961], shape=[0], format='@h')
2882 v = memoryview(nd1)
2883 w = memoryview(nd2)
2884
2885 self.assertEqual(v, nd1)
2886 self.assertEqual(w, nd2)
2887 self.assertEqual(v, nd2)
2888 self.assertEqual(w, nd1)
2889 self.assertEqual(v, w)
2890
2891 # ndim = 1: zero strides
2892 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
2893 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
2894 v = memoryview(nd1)
2895 w = memoryview(nd2)
2896
2897 self.assertEqual(v, nd1)
2898 self.assertEqual(w, nd2)
2899 self.assertEqual(v, nd2)
2900 self.assertEqual(w, nd1)
2901 self.assertEqual(v, w)
2902
2903 n = 10
2904 for char in fmtdict['@m']:
2905 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
2906 for flags in (0, ND_PIL):
2907 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
2908 m = memoryview(nd)
2909 self.assertEqual(m, nd)
2910
2911 nd = nd[::-3]
2912 m = memoryview(nd)
2913 self.assertEqual(m, nd)
2914
2915 ##### ndim > 1: C-contiguous
2916 # different values
2917 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
2918 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
2919 v = memoryview(nd1)
2920 w = memoryview(nd2)
2921
2922 self.assertEqual(v, nd1)
2923 self.assertEqual(w, nd2)
2924 self.assertNotEqual(v, nd2)
2925 self.assertNotEqual(w, nd1)
2926 self.assertNotEqual(v, w)
2927
2928 # different shape
2929 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
2930 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
2931 v = memoryview(nd1)
2932 w = memoryview(nd2)
2933
2934 self.assertEqual(v, nd1)
2935 self.assertEqual(w, nd2)
2936 self.assertNotEqual(v, nd2)
2937 self.assertNotEqual(w, nd1)
2938 self.assertNotEqual(v, w)
2939
2940 # different format
2941 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
2942 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
2943 v = memoryview(nd1)
2944 w = memoryview(nd2)
2945
2946 self.assertEqual(v, nd1)
2947 self.assertEqual(w, nd2)
2948 self.assertNotEqual(v, nd2)
2949 self.assertNotEqual(w, nd1)
2950 self.assertNotEqual(v, w)
2951
2952 ##### ndim > 1: Fortran contiguous
2953 # different values
2954 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
2955 flags=ND_FORTRAN)
2956 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
2957 flags=ND_FORTRAN)
2958 v = memoryview(nd1)
2959 w = memoryview(nd2)
2960
2961 self.assertEqual(v, nd1)
2962 self.assertEqual(w, nd2)
2963 self.assertNotEqual(v, nd2)
2964 self.assertNotEqual(w, nd1)
2965 self.assertNotEqual(v, w)
2966
2967 # different shape
2968 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
2969 flags=ND_FORTRAN)
2970 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
2971 flags=ND_FORTRAN)
2972 v = memoryview(nd1)
2973 w = memoryview(nd2)
2974
2975 self.assertEqual(v, nd1)
2976 self.assertEqual(w, nd2)
2977 self.assertNotEqual(v, nd2)
2978 self.assertNotEqual(w, nd1)
2979 self.assertNotEqual(v, w)
2980
2981 # different format
2982 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
2983 flags=ND_FORTRAN)
2984 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
2985 flags=ND_FORTRAN)
2986 v = memoryview(nd1)
2987 w = memoryview(nd2)
2988
2989 self.assertEqual(v, nd1)
2990 self.assertEqual(w, nd2)
2991 self.assertNotEqual(v, nd2)
2992 self.assertNotEqual(w, nd1)
2993 self.assertNotEqual(v, w)
2994
2995 ##### ndim > 1: mixed C/Fortran contiguous
2996 lst1 = list(range(-15, 15))
2997 lst2 = transpose(lst1, [3, 2, 5])
2998 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
2999 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3000 v = memoryview(nd1)
3001 w = memoryview(nd2)
3002
3003 self.assertEqual(v, nd1)
3004 self.assertEqual(w, nd2)
3005 self.assertEqual(v, w)
3006
3007 ##### ndim > 1: non-contiguous
3008 # different values
3009 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3010 nd1 = ex1[3:1:-1, ::-2]
3011 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3012 nd2 = ex2[1:3:1, ::-2]
3013 v = memoryview(nd1)
3014 w = memoryview(nd2)
3015
3016 self.assertEqual(v, nd1)
3017 self.assertEqual(w, nd2)
3018 self.assertNotEqual(v, nd2)
3019 self.assertNotEqual(w, nd1)
3020 self.assertNotEqual(v, w)
3021
3022 # different shape
3023 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3024 nd1 = ex1[1:3:, ::-2]
3025 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3026 nd2 = ex2[1:3:, ::-2]
3027 v = memoryview(nd1)
3028 w = memoryview(nd2)
3029
3030 self.assertEqual(v, nd1)
3031 self.assertEqual(w, nd2)
3032 self.assertNotEqual(v, nd2)
3033 self.assertNotEqual(w, nd1)
3034 self.assertNotEqual(v, w)
3035
3036 # different format
3037 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i')
3038 nd1 = ex1[1:3:, ::-2]
3039 nd2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I')
3040 nd2 = ex2[1:3:, ::-2]
3041 v = memoryview(nd1)
3042 w = memoryview(nd2)
3043
3044 self.assertEqual(v, nd1)
3045 self.assertEqual(w, nd2)
3046 self.assertNotEqual(v, nd2)
3047 self.assertNotEqual(w, nd1)
3048 self.assertNotEqual(v, w)
3049
3050 ##### ndim > 1: zeros in shape
3051 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3052 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3053 v = memoryview(nd1)
3054 w = memoryview(nd2)
3055
3056 self.assertEqual(v, nd1)
3057 self.assertEqual(w, nd2)
3058 self.assertNotEqual(v, nd2)
3059 self.assertNotEqual(w, nd1)
3060 self.assertNotEqual(v, w)
3061
3062 # ndim > 1: zero strides
3063 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3064 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3065 v = memoryview(nd1)
3066 w = memoryview(nd2)
3067
3068 self.assertEqual(v, nd1)
3069 self.assertEqual(w, nd2)
3070 self.assertEqual(v, nd2)
3071 self.assertEqual(w, nd1)
3072 self.assertEqual(v, w)
3073 self.assertEqual(v.tolist(), w.tolist())
3074
3075 ##### ndim > 1: suboffsets
3076 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3077 nd1 = ex1[3:1:-1, ::-2]
3078 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3079 nd2 = ex2[1:3:1, ::-2]
3080 v = memoryview(nd1)
3081 w = memoryview(nd2)
3082
3083 self.assertEqual(v, nd1)
3084 self.assertEqual(w, nd2)
3085 self.assertNotEqual(v, nd2)
3086 self.assertNotEqual(w, nd1)
3087 self.assertNotEqual(v, w)
3088
3089 # different shape
3090 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b', flags=ND_PIL)
3091 nd1 = ex1[1:3:, ::-2]
3092 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3093 nd2 = ex2[1:3:, ::-2]
3094 v = memoryview(nd1)
3095 w = memoryview(nd2)
3096
3097 self.assertEqual(v, nd1)
3098 self.assertEqual(w, nd2)
3099 self.assertNotEqual(v, nd2)
3100 self.assertNotEqual(w, nd1)
3101 self.assertNotEqual(v, w)
3102
3103 # different format
3104 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3105 nd1 = ex1[1:3:, ::-2]
3106 nd2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
3107 nd2 = ex2[1:3:, ::-2]
3108 v = memoryview(nd1)
3109 w = memoryview(nd2)
3110
3111 self.assertEqual(v, nd1)
3112 self.assertEqual(w, nd2)
3113 self.assertNotEqual(v, nd2)
3114 self.assertNotEqual(w, nd1)
3115 self.assertNotEqual(v, w)
3116
3117 # initialize mixed C/Fortran + suboffsets
3118 lst1 = list(range(-15, 15))
3119 lst2 = transpose(lst1, [3, 2, 5])
3120 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3121 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3122 v = memoryview(nd1)
3123 w = memoryview(nd2)
3124
3125 self.assertEqual(v, nd1)
3126 self.assertEqual(w, nd2)
3127 self.assertEqual(v, w)
3128
3129 def test_memoryview_check_released(self):
3130
3131 a = array.array('d', [1.1, 2.2, 3.3])
3132
3133 m = memoryview(a)
3134 m.release()
3135
3136 # PyMemoryView_FromObject()
3137 self.assertRaises(ValueError, memoryview, m)
3138 # memoryview.cast()
3139 self.assertRaises(ValueError, m.cast, 'c')
3140 # getbuffer()
3141 self.assertRaises(ValueError, ndarray, m)
3142 # memoryview.tolist()
3143 self.assertRaises(ValueError, m.tolist)
3144 # memoryview.tobytes()
3145 self.assertRaises(ValueError, m.tobytes)
3146 # sequence
3147 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3148 # subscript
3149 self.assertRaises(ValueError, m.__getitem__, 0)
3150 # assignment
3151 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3152
3153 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3154 'shape', 'strides', 'suboffsets', 'c_contiguous',
3155 'f_contiguous', 'contiguous'):
3156 self.assertRaises(ValueError, m.__getattribute__, attr)
3157
3158 # richcompare
3159 b = array.array('d', [1.1, 2.2, 3.3])
3160 m1 = memoryview(a)
3161 m2 = memoryview(b)
3162
3163 self.assertEqual(m1, m2)
3164 m1.release()
3165 self.assertNotEqual(m1, m2)
3166 self.assertNotEqual(m1, a)
3167 self.assertEqual(m1, m1)
3168
3169 def test_memoryview_tobytes(self):
3170 # Many implicit tests are already in self.verify().
3171
3172 nd = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3173
3174 m = memoryview(nd)
3175 self.assertEqual(m.tobytes(), nd.tobytes())
3176
3177 def test_memoryview_get_contiguous(self):
3178 # Many implicit tests are already in self.verify().
3179
3180 # no buffer interface
3181 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3182
3183 # writable request to read-only object
3184 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3185
3186 # writable request to non-contiguous object
3187 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3188 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3189
3190 # scalar, read-only request from read-only exporter
3191 nd = ndarray(9, shape=(), format="L")
3192 for order in ['C', 'F', 'A']:
3193 m = get_contiguous(nd, PyBUF_READ, order)
3194 self.assertEqual(m, nd)
3195 self.assertEqual(m[()], 9)
3196
3197 # scalar, read-only request from writable exporter
3198 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3199 for order in ['C', 'F', 'A']:
3200 m = get_contiguous(nd, PyBUF_READ, order)
3201 self.assertEqual(m, nd)
3202 self.assertEqual(m[()], 9)
3203
3204 # scalar, writable request
3205 for order in ['C', 'F', 'A']:
3206 nd[()] = 9
3207 m = get_contiguous(nd, PyBUF_WRITE, order)
3208 self.assertEqual(m, nd)
3209 self.assertEqual(m[()], 9)
3210
3211 m[()] = 10
3212 self.assertEqual(m[()], 10)
3213 self.assertEqual(nd[()], 10)
3214
3215 # zeros in shape
3216 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3217 for order in ['C', 'F', 'A']:
3218 m = get_contiguous(nd, PyBUF_READ, order)
3219 self.assertRaises(IndexError, m.__getitem__, 0)
3220 self.assertEqual(m, nd)
3221 self.assertEqual(m.tolist(), [])
3222
3223 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
3224 flags=ND_WRITABLE)
3225 for order in ['C', 'F', 'A']:
3226 m = get_contiguous(nd, PyBUF_READ, order)
3227 self.assertEqual(ndarray(m).tolist(), [[], []])
3228
3229 # one-dimensional
3230 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
3231 for order in ['C', 'F', 'A']:
3232 m = get_contiguous(nd, PyBUF_WRITE, order)
3233 self.assertEqual(m, nd)
3234 self.assertEqual(m.tolist(), nd.tolist())
3235
3236 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
3237 for order in ['C', 'F', 'A']:
3238 m = get_contiguous(nd, PyBUF_WRITE, order)
3239 self.assertEqual(m, nd)
3240 self.assertEqual(m.tolist(), nd.tolist())
3241
3242 # one-dimensional, non-contiguous
3243 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
3244 for order in ['C', 'F', 'A']:
3245 m = get_contiguous(nd, PyBUF_READ, order)
3246 self.assertEqual(m, nd)
3247 self.assertEqual(m.tolist(), nd.tolist())
3248 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3249 self.assertEqual(m[1], 3)
3250 self.assertEqual(nd[1], 3)
3251
3252 nd = nd[::-1]
3253 for order in ['C', 'F', 'A']:
3254 m = get_contiguous(nd, PyBUF_READ, order)
3255 self.assertEqual(m, nd)
3256 self.assertEqual(m.tolist(), nd.tolist())
3257 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3258 self.assertEqual(m[1], 1)
3259 self.assertEqual(nd[1], 1)
3260
3261 # multi-dimensional, contiguous input
3262 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
3263 for order in ['C', 'A']:
3264 m = get_contiguous(nd, PyBUF_WRITE, order)
3265 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3266
3267 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
3268 m = get_contiguous(nd, PyBUF_READ, order)
3269 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3270
3271 nd = ndarray(list(range(12)), shape=[3, 4],
3272 flags=ND_WRITABLE|ND_FORTRAN)
3273 for order in ['F', 'A']:
3274 m = get_contiguous(nd, PyBUF_WRITE, order)
3275 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3276
3277 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
3278 m = get_contiguous(nd, PyBUF_READ, order)
3279 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3280
3281 # multi-dimensional, non-contiguous input
3282 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
3283 for order in ['C', 'F', 'A']:
3284 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
3285 order)
3286 m = get_contiguous(nd, PyBUF_READ, order)
3287 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3288
3289 # flags
3290 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
3291 m = get_contiguous(nd, PyBUF_READ, 'C')
3292 self.assertTrue(m.c_contiguous)
3293
3294 def test_memoryview_serializing(self):
3295
3296 # C-contiguous
3297 size = struct.calcsize('i')
3298 a = array.array('i', [1,2,3,4,5])
3299 m = memoryview(a)
3300 buf = io.BytesIO(m)
3301 b = bytearray(5*size)
3302 buf.readinto(b)
3303 self.assertEqual(m.tobytes(), b)
3304
3305 # C-contiguous, multi-dimensional
3306 size = struct.calcsize('L')
3307 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
3308 m = memoryview(nd)
3309 buf = io.BytesIO(m)
3310 b = bytearray(2*3*2*size)
3311 buf.readinto(b)
3312 self.assertEqual(m.tobytes(), b)
3313
3314 # Fortran contiguous, multi-dimensional
3315 #size = struct.calcsize('L')
3316 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
3317 # flags=ND_FORTRAN)
3318 #m = memoryview(nd)
3319 #buf = io.BytesIO(m)
3320 #b = bytearray(2*3*2*size)
3321 #buf.readinto(b)
3322 #self.assertEqual(m.tobytes(), b)
3323
3324 def test_memoryview_hash(self):
3325
3326 # bytes exporter
3327 b = bytes(list(range(12)))
3328 m = memoryview(b)
3329 self.assertEqual(hash(b), hash(m))
3330
3331 # C-contiguous
3332 mc = m.cast('c', shape=[3,4])
3333 self.assertEqual(hash(mc), hash(b))
3334
3335 # non-contiguous
3336 mx = m[::-2]
3337 b = bytes(list(range(12))[::-2])
3338 self.assertEqual(hash(mx), hash(b))
3339
3340 # Fortran contiguous
3341 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
3342 m = memoryview(nd)
3343 self.assertEqual(hash(m), hash(nd))
3344
3345 # multi-dimensional slice
3346 nd = ndarray(list(range(30)), shape=[3,2,5])
3347 x = nd[::2, ::, ::-1]
3348 m = memoryview(x)
3349 self.assertEqual(hash(m), hash(x))
3350
3351 # multi-dimensional slice with suboffsets
3352 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
3353 x = nd[::2, ::, ::-1]
3354 m = memoryview(x)
3355 self.assertEqual(hash(m), hash(x))
3356
3357 # non-byte formats
3358 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
3359 m = memoryview(nd)
3360 self.assertEqual(hash(m), hash(nd.tobytes()))
3361
3362 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
3363 m = memoryview(nd)
3364 self.assertEqual(hash(m), hash(nd.tobytes()))
3365
3366 def test_memoryview_release(self):
3367
3368 # Create re-exporter from getbuffer(memoryview), then release the view.
3369 a = bytearray([1,2,3])
3370 m = memoryview(a)
3371 nd = ndarray(m) # re-exporter
3372 self.assertRaises(BufferError, m.release)
3373 del nd
3374 m.release()
3375
Stefan Krah4e99a312012-03-05 09:30:47 +01003376 a = bytearray([1,2,3])
3377 m = memoryview(a)
3378 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3379 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3380 self.assertIs(nd2.obj, m)
3381 self.assertRaises(BufferError, m.release)
3382 del nd1, nd2
3383 m.release()
3384
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003385 # chained views
3386 a = bytearray([1,2,3])
3387 m1 = memoryview(a)
3388 m2 = memoryview(m1)
3389 nd = ndarray(m2) # re-exporter
3390 m1.release()
3391 self.assertRaises(BufferError, m2.release)
3392 del nd
3393 m2.release()
3394
Stefan Krah4e99a312012-03-05 09:30:47 +01003395 a = bytearray([1,2,3])
3396 m1 = memoryview(a)
3397 m2 = memoryview(m1)
3398 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3399 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3400 self.assertIs(nd2.obj, m2)
3401 m1.release()
3402 self.assertRaises(BufferError, m2.release)
3403 del nd1, nd2
3404 m2.release()
3405
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003406 # Allow changing layout while buffers are exported.
3407 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
3408 m1 = memoryview(nd)
3409
3410 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
3411 m2 = memoryview(nd)
3412
3413 x = memoryview(m1)
3414 self.assertEqual(x.tolist(), m1.tolist())
3415
3416 y = memoryview(m2)
3417 self.assertEqual(y.tolist(), m2.tolist())
3418 self.assertEqual(y.tolist(), nd.tolist())
3419 m2.release()
3420 y.release()
3421
3422 nd.pop() # pop the current view
3423 self.assertEqual(x.tolist(), nd.tolist())
3424
3425 del nd
3426 m1.release()
3427 x.release()
3428
3429 # If multiple memoryviews share the same managed buffer, implicit
3430 # release() in the context manager's __exit__() method should still
3431 # work.
3432 def catch22(b):
3433 with memoryview(b) as m2:
3434 pass
3435
3436 x = bytearray(b'123')
3437 with memoryview(x) as m1:
3438 catch22(m1)
3439 self.assertEqual(m1[0], ord(b'1'))
3440
Stefan Krah4e99a312012-03-05 09:30:47 +01003441 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
3442 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3443 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3444 self.assertIs(z.obj, x)
3445 with memoryview(z) as m:
3446 catch22(m)
3447 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
3448
3449 # Test garbage collection.
3450 for flags in (0, ND_REDIRECT):
3451 x = bytearray(b'123')
3452 with memoryview(x) as m1:
3453 del x
3454 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
3455 with memoryview(y) as m2:
3456 del y
3457 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
3458 with memoryview(z) as m3:
3459 del z
3460 catch22(m3)
3461 catch22(m2)
3462 catch22(m1)
3463 self.assertEqual(m1[0], ord(b'1'))
3464 self.assertEqual(m2[1], ord(b'2'))
3465 self.assertEqual(m3[2], ord(b'3'))
3466 del m3
3467 del m2
3468 del m1
3469
3470 x = bytearray(b'123')
3471 with memoryview(x) as m1:
3472 del x
3473 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
3474 with memoryview(y) as m2:
3475 del y
3476 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
3477 with memoryview(z) as m3:
3478 del z
3479 catch22(m1)
3480 catch22(m2)
3481 catch22(m3)
3482 self.assertEqual(m1[0], ord(b'1'))
3483 self.assertEqual(m2[1], ord(b'2'))
3484 self.assertEqual(m3[2], ord(b'3'))
3485 del m1, m2, m3
3486
Stefan Krahfcbb4162012-03-05 10:45:31 +01003487 # memoryview.release() fails if the view has exported buffers.
3488 x = bytearray(b'123')
3489 with self.assertRaises(BufferError):
3490 with memoryview(x) as m:
3491 ex = ndarray(m)
3492 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003493
Stefan Krah4e99a312012-03-05 09:30:47 +01003494 def test_memoryview_redirect(self):
3495
3496 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
3497 a = array.array('d', [1.0 * x for x in range(12)])
3498
3499 for x in (nd, a):
3500 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3501 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3502 m = memoryview(z)
3503
3504 self.assertIs(y.obj, x)
3505 self.assertIs(z.obj, x)
3506 self.assertIs(m.obj, x)
3507
3508 self.assertEqual(m, x)
3509 self.assertEqual(m, y)
3510 self.assertEqual(m, z)
3511
3512 self.assertEqual(m[1:3], x[1:3])
3513 self.assertEqual(m[1:3], y[1:3])
3514 self.assertEqual(m[1:3], z[1:3])
3515 del y, z
3516 self.assertEqual(m[1:3], x[1:3])
3517
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01003518 def test_memoryview_from_static_exporter(self):
3519
3520 fmt = 'B'
3521 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
3522
3523 # exceptions
3524 self.assertRaises(TypeError, staticarray, 1, 2, 3)
3525
3526 # view.obj==x
3527 x = staticarray()
3528 y = memoryview(x)
3529 self.verify(y, obj=x,
3530 itemsize=1, fmt=fmt, readonly=1,
3531 ndim=1, shape=[12], strides=[1],
3532 lst=lst)
3533 for i in range(12):
3534 self.assertEqual(y[i], i)
3535 del x
3536 del y
3537
3538 x = staticarray()
3539 y = memoryview(x)
3540 del y
3541 del x
3542
3543 x = staticarray()
3544 y = ndarray(x, getbuf=PyBUF_FULL_RO)
3545 z = ndarray(y, getbuf=PyBUF_FULL_RO)
3546 m = memoryview(z)
3547 self.assertIs(y.obj, x)
3548 self.assertIs(m.obj, z)
3549 self.verify(m, obj=z,
3550 itemsize=1, fmt=fmt, readonly=1,
3551 ndim=1, shape=[12], strides=[1],
3552 lst=lst)
3553 del x, y, z, m
3554
3555 x = staticarray()
3556 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3557 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3558 m = memoryview(z)
3559 self.assertIs(y.obj, x)
3560 self.assertIs(z.obj, x)
3561 self.assertIs(m.obj, x)
3562 self.verify(m, obj=x,
3563 itemsize=1, fmt=fmt, readonly=1,
3564 ndim=1, shape=[12], strides=[1],
3565 lst=lst)
3566 del x, y, z, m
3567
3568 # view.obj==NULL
3569 x = staticarray(legacy_mode=True)
3570 y = memoryview(x)
3571 self.verify(y, obj=None,
3572 itemsize=1, fmt=fmt, readonly=1,
3573 ndim=1, shape=[12], strides=[1],
3574 lst=lst)
3575 for i in range(12):
3576 self.assertEqual(y[i], i)
3577 del x
3578 del y
3579
3580 x = staticarray(legacy_mode=True)
3581 y = memoryview(x)
3582 del y
3583 del x
3584
3585 x = staticarray(legacy_mode=True)
3586 y = ndarray(x, getbuf=PyBUF_FULL_RO)
3587 z = ndarray(y, getbuf=PyBUF_FULL_RO)
3588 m = memoryview(z)
3589 self.assertIs(y.obj, None)
3590 self.assertIs(m.obj, z)
3591 self.verify(m, obj=z,
3592 itemsize=1, fmt=fmt, readonly=1,
3593 ndim=1, shape=[12], strides=[1],
3594 lst=lst)
3595 del x, y, z, m
3596
3597 x = staticarray(legacy_mode=True)
3598 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3599 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
3600 m = memoryview(z)
3601 # Clearly setting view.obj==NULL is inferior, since it
3602 # messes up the redirection chain:
3603 self.assertIs(y.obj, None)
3604 self.assertIs(z.obj, y)
3605 self.assertIs(m.obj, y)
3606 self.verify(m, obj=y,
3607 itemsize=1, fmt=fmt, readonly=1,
3608 ndim=1, shape=[12], strides=[1],
3609 lst=lst)
3610 del x, y, z, m
3611
Stefan Krah1649c1b2012-03-05 17:45:17 +01003612 def test_memoryview_getbuffer_undefined(self):
3613
3614 # getbufferproc does not adhere to the new documentation
3615 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
3616 self.assertRaises(BufferError, memoryview, nd)
3617
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003618 def test_issue_7385(self):
3619 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
3620 self.assertRaises(BufferError, memoryview, x)
3621
3622
3623def test_main():
3624 support.run_unittest(TestBufferProtocol)
3625
3626
3627if __name__ == "__main__":
3628 test_main()