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