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