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