blob: a4fb7704ef8b71e57dbcf450413a4940f128aa15 [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):
2435 # Casts are undefined if shape contains zeros. These arrays are
2436 # regarded as C-contiguous by Numpy and PyBuffer_GetContiguous(),
2437 # so they are not caught by the test for C-contiguity in memory_cast().
2438 items = [1,2,3]
2439 for shape in ([0,3,3], [3,0,3], [0,3,3]):
2440 ex = ndarray(items, shape=shape)
2441 self.assertTrue(ex.c_contiguous)
2442 msrc = memoryview(ex)
2443 self.assertRaises(TypeError, msrc.cast, 'c')
2444
2445 def test_memoryview_struct_module(self):
2446
2447 class INT(object):
2448 def __init__(self, val):
2449 self.val = val
2450 def __int__(self):
2451 return self.val
2452
2453 class IDX(object):
2454 def __init__(self, val):
2455 self.val = val
2456 def __index__(self):
2457 return self.val
2458
2459 def f(): return 7
2460
2461 values = [INT(9), IDX(9),
2462 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2),
2463 [1,2,3], {4,5,6}, {7:8}, (), (9,),
2464 True, False, None, NotImplemented,
2465 b'a', b'abc', bytearray(b'a'), bytearray(b'abc'),
2466 'a', 'abc', r'a', r'abc',
2467 f, lambda x: x]
2468
2469 for fmt, items, item in iter_format(10, 'memoryview'):
2470 ex = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2471 nd = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2472 m = memoryview(ex)
2473
2474 struct.pack_into(fmt, nd, 0, item)
2475 m[0] = item
2476 self.assertEqual(m[0], nd[0])
2477
2478 itemsize = struct.calcsize(fmt)
2479 if 'P' in fmt:
2480 continue
2481
2482 for v in values:
2483 struct_err = None
2484 try:
2485 struct.pack_into(fmt, nd, itemsize, v)
2486 except struct.error:
2487 struct_err = struct.error
2488
2489 mv_err = None
2490 try:
2491 m[1] = v
2492 except (TypeError, ValueError) as e:
2493 mv_err = e.__class__
2494
2495 if struct_err or mv_err:
2496 self.assertIsNot(struct_err, None)
2497 self.assertIsNot(mv_err, None)
2498 else:
2499 self.assertEqual(m[1], nd[1])
2500
2501 def test_memoryview_cast_zero_strides(self):
2502 # Casts are undefined if strides contains zeros. These arrays are
2503 # (sometimes!) regarded as C-contiguous by Numpy, but not by
2504 # PyBuffer_GetContiguous().
2505 ex = ndarray([1,2,3], shape=[3], strides=[0])
2506 self.assertFalse(ex.c_contiguous)
2507 msrc = memoryview(ex)
2508 self.assertRaises(TypeError, msrc.cast, 'c')
2509
2510 def test_memoryview_cast_invalid(self):
2511 # invalid format
2512 for sfmt in NON_BYTE_FORMAT:
2513 sformat = '@' + sfmt if randrange(2) else sfmt
2514 ssize = struct.calcsize(sformat)
2515 for dfmt in NON_BYTE_FORMAT:
2516 dformat = '@' + dfmt if randrange(2) else dfmt
2517 dsize = struct.calcsize(dformat)
2518 ex = ndarray(list(range(32)), shape=[32//ssize], format=sformat)
2519 msrc = memoryview(ex)
2520 self.assertRaises(TypeError, msrc.cast, dfmt, [32//dsize])
2521
2522 for sfmt, sitems, _ in iter_format(1):
2523 ex = ndarray(sitems, shape=[1], format=sfmt)
2524 msrc = memoryview(ex)
2525 for dfmt, _, _ in iter_format(1):
2526 if (not is_memoryview_format(sfmt) or
2527 not is_memoryview_format(dfmt)):
2528 self.assertRaises(ValueError, msrc.cast, dfmt,
2529 [32//dsize])
2530 else:
2531 if not is_byte_format(sfmt) and not is_byte_format(dfmt):
2532 self.assertRaises(TypeError, msrc.cast, dfmt,
2533 [32//dsize])
2534
2535 # invalid shape
2536 size_h = struct.calcsize('h')
2537 size_d = struct.calcsize('d')
2538 ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h')
2539 msrc = memoryview(ex)
2540 self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d')
2541
2542 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2543 m = memoryview(ex)
2544
2545 # incorrect number of args
2546 self.assertRaises(TypeError, m.cast)
2547 self.assertRaises(TypeError, m.cast, 1, 2, 3)
2548
2549 # incorrect dest format type
2550 self.assertRaises(TypeError, m.cast, {})
2551
2552 # incorrect dest format
2553 self.assertRaises(ValueError, m.cast, "X")
2554 self.assertRaises(ValueError, m.cast, "@X")
2555 self.assertRaises(ValueError, m.cast, "@XY")
2556
2557 # dest format not implemented
2558 self.assertRaises(ValueError, m.cast, "=B")
2559 self.assertRaises(ValueError, m.cast, "!L")
2560 self.assertRaises(ValueError, m.cast, "<P")
2561 self.assertRaises(ValueError, m.cast, ">l")
2562 self.assertRaises(ValueError, m.cast, "BI")
2563 self.assertRaises(ValueError, m.cast, "xBI")
2564
2565 # src format not implemented
2566 ex = ndarray([(1,2), (3,4)], shape=[2], format="II")
2567 m = memoryview(ex)
2568 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2569 self.assertRaises(NotImplementedError, m.__setitem__, 0, 8)
2570 self.assertRaises(NotImplementedError, m.tolist)
2571
2572 # incorrect shape type
2573 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2574 m = memoryview(ex)
2575 self.assertRaises(TypeError, m.cast, "B", shape={})
2576
2577 # incorrect shape elements
2578 ex = ndarray(list(range(120)), shape=[2*3*4*5])
2579 m = memoryview(ex)
2580 self.assertRaises(OverflowError, m.cast, "B", shape=[2**64])
2581 self.assertRaises(ValueError, m.cast, "B", shape=[-1])
2582 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1])
2583 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0])
2584 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x'])
2585
2586 # N-D -> N-D cast
2587 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11])
2588 m = memoryview(ex)
2589 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2590
2591 # cast with ndim > 64
2592 nd = ndarray(list(range(128)), shape=[128], format='I')
2593 m = memoryview(nd)
2594 self.assertRaises(ValueError, m.cast, 'I', [1]*128)
2595
2596 # view->len not a multiple of itemsize
2597 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2598 m = memoryview(ex)
2599 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2600
2601 # product(shape) * itemsize != buffer size
2602 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2603 m = memoryview(ex)
2604 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5])
2605
2606 # product(shape) * itemsize overflow
2607 nd = ndarray(list(range(128)), shape=[128], format='I')
2608 m1 = memoryview(nd)
2609 nd = ndarray(list(range(128)), shape=[128], format='B')
2610 m2 = memoryview(nd)
2611 if sys.maxsize == 2**63-1:
2612 self.assertRaises(TypeError, m1.cast, 'B',
2613 [7, 7, 73, 127, 337, 92737, 649657])
2614 self.assertRaises(ValueError, m1.cast, 'B',
2615 [2**20, 2**20, 2**10, 2**10, 2**3])
2616 self.assertRaises(ValueError, m2.cast, 'I',
2617 [2**20, 2**20, 2**10, 2**10, 2**1])
2618 else:
2619 self.assertRaises(TypeError, m1.cast, 'B',
2620 [1, 2147483647])
2621 self.assertRaises(ValueError, m1.cast, 'B',
2622 [2**10, 2**10, 2**5, 2**5, 2**1])
2623 self.assertRaises(ValueError, m2.cast, 'I',
2624 [2**10, 2**10, 2**5, 2**3, 2**1])
2625
2626 def test_memoryview_cast(self):
2627 bytespec = (
2628 ('B', lambda ex: list(ex.tobytes())),
2629 ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]),
2630 ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]),
2631 )
2632
2633 def iter_roundtrip(ex, m, items, fmt):
2634 srcsize = struct.calcsize(fmt)
2635 for bytefmt, to_bytelist in bytespec:
2636
2637 m2 = m.cast(bytefmt)
2638 lst = to_bytelist(ex)
2639 self.verify(m2, obj=ex,
2640 itemsize=1, fmt=bytefmt, readonly=0,
2641 ndim=1, shape=[31*srcsize], strides=(1,),
2642 lst=lst, cast=True)
2643
2644 m3 = m2.cast(fmt)
2645 self.assertEqual(m3, ex)
2646 lst = ex.tolist()
2647 self.verify(m3, obj=ex,
2648 itemsize=srcsize, fmt=fmt, readonly=0,
2649 ndim=1, shape=[31], strides=(srcsize,),
2650 lst=lst, cast=True)
2651
2652 # cast from ndim = 0 to ndim = 1
2653 srcsize = struct.calcsize('I')
2654 ex = ndarray(9, shape=[], format='I')
2655 destitems, destshape = cast_items(ex, 'B', 1)
2656 m = memoryview(ex)
2657 m2 = m.cast('B')
2658 self.verify(m2, obj=ex,
2659 itemsize=1, fmt='B', readonly=1,
2660 ndim=1, shape=destshape, strides=(1,),
2661 lst=destitems, cast=True)
2662
2663 # cast from ndim = 1 to ndim = 0
2664 destsize = struct.calcsize('I')
2665 ex = ndarray([9]*destsize, shape=[destsize], format='B')
2666 destitems, destshape = cast_items(ex, 'I', destsize, shape=[])
2667 m = memoryview(ex)
2668 m2 = m.cast('I', shape=[])
2669 self.verify(m2, obj=ex,
2670 itemsize=destsize, fmt='I', readonly=1,
2671 ndim=0, shape=(), strides=(),
2672 lst=destitems, cast=True)
2673
2674 # array.array: roundtrip to/from bytes
2675 for fmt, items, _ in iter_format(31, 'array'):
2676 ex = array.array(fmt, items)
2677 m = memoryview(ex)
2678 iter_roundtrip(ex, m, items, fmt)
2679
2680 # ndarray: roundtrip to/from bytes
2681 for fmt, items, _ in iter_format(31, 'memoryview'):
2682 ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE)
2683 m = memoryview(ex)
2684 iter_roundtrip(ex, m, items, fmt)
2685
2686 def test_memoryview_cast_1D_ND(self):
2687 # Cast between C-contiguous buffers. At least one buffer must
2688 # be 1D, at least one format must be 'c', 'b' or 'B'.
2689 for _tshape in gencastshapes():
2690 for char in fmtdict['@']:
2691 tfmt = ('', '@')[randrange(2)] + char
2692 tsize = struct.calcsize(tfmt)
2693 n = prod(_tshape) * tsize
2694 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2695 for fmt, items, _ in iter_format(n, obj):
2696 size = struct.calcsize(fmt)
2697 shape = [n] if n > 0 else []
2698 tshape = _tshape + [size]
2699
2700 ex = ndarray(items, shape=shape, format=fmt)
2701 m = memoryview(ex)
2702
2703 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2704
2705 if titems is None:
2706 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2707 continue
2708 if titems == 'nan':
2709 continue # NaNs in lists are a recipe for trouble.
2710
2711 # 1D -> ND
2712 nd = ndarray(titems, shape=tshape, format=tfmt)
2713
2714 m2 = m.cast(tfmt, shape=tshape)
2715 ndim = len(tshape)
2716 strides = nd.strides
2717 lst = nd.tolist()
2718 self.verify(m2, obj=ex,
2719 itemsize=tsize, fmt=tfmt, readonly=1,
2720 ndim=ndim, shape=tshape, strides=strides,
2721 lst=lst, cast=True)
2722
2723 # ND -> 1D
2724 m3 = m2.cast(fmt)
2725 m4 = m2.cast(fmt, shape=shape)
2726 ndim = len(shape)
2727 strides = ex.strides
2728 lst = ex.tolist()
2729
2730 self.verify(m3, obj=ex,
2731 itemsize=size, fmt=fmt, readonly=1,
2732 ndim=ndim, shape=shape, strides=strides,
2733 lst=lst, cast=True)
2734
2735 self.verify(m4, obj=ex,
2736 itemsize=size, fmt=fmt, readonly=1,
2737 ndim=ndim, shape=shape, strides=strides,
2738 lst=lst, cast=True)
2739
2740 def test_memoryview_tolist(self):
2741
2742 # Most tolist() tests are in self.verify() etc.
2743
2744 a = array.array('h', list(range(-6, 6)))
2745 m = memoryview(a)
2746 self.assertEqual(m, a)
2747 self.assertEqual(m.tolist(), a.tolist())
2748
2749 a = a[2::3]
2750 m = m[2::3]
2751 self.assertEqual(m, a)
2752 self.assertEqual(m.tolist(), a.tolist())
2753
2754 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2755 m = memoryview(ex)
2756 self.assertEqual(m.tolist(), ex.tolist())
2757
2758 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2759 m = memoryview(ex)
2760 self.assertRaises(NotImplementedError, m.tolist)
2761
2762 ex = ndarray([b'12345'], shape=[1], format="s")
2763 m = memoryview(ex)
2764 self.assertRaises(NotImplementedError, m.tolist)
2765
2766 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2767 m = memoryview(ex)
2768 self.assertRaises(NotImplementedError, m.tolist)
2769
2770 def test_memoryview_repr(self):
2771 m = memoryview(bytearray(9))
2772 r = m.__repr__()
2773 self.assertTrue(r.startswith("<memory"))
2774
2775 m.release()
2776 r = m.__repr__()
2777 self.assertTrue(r.startswith("<released"))
2778
2779 def test_memoryview_sequence(self):
2780
2781 for fmt in ('d', 'f'):
2782 inf = float(3e400)
2783 ex = array.array(fmt, [1.0, inf, 3.0])
2784 m = memoryview(ex)
2785 self.assertIn(1.0, m)
2786 self.assertIn(5e700, m)
2787 self.assertIn(3.0, m)
2788
2789 ex = ndarray(9.0, [], format='f')
2790 m = memoryview(ex)
2791 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2792
2793 def test_memoryview_index(self):
2794
2795 # ndim = 0
2796 ex = ndarray(12.5, shape=[], format='d')
2797 m = memoryview(ex)
2798 self.assertEqual(m[()], 12.5)
2799 self.assertEqual(m[...], m)
2800 self.assertEqual(m[...], ex)
2801 self.assertRaises(TypeError, m.__getitem__, 0)
2802
2803 ex = ndarray((1,2,3), shape=[], format='iii')
2804 m = memoryview(ex)
2805 self.assertRaises(NotImplementedError, m.__getitem__, ())
2806
2807 # range
2808 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2809 m = memoryview(ex)
2810
2811 self.assertRaises(IndexError, m.__getitem__, 2**64)
2812 self.assertRaises(TypeError, m.__getitem__, 2.0)
2813 self.assertRaises(TypeError, m.__getitem__, 0.0)
2814
2815 # out of bounds
2816 self.assertRaises(IndexError, m.__getitem__, -8)
2817 self.assertRaises(IndexError, m.__getitem__, 8)
2818
2819 # Not implemented: multidimensional sub-views
2820 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2821 m = memoryview(ex)
2822
2823 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2824 self.assertRaises(NotImplementedError, m.__setitem__, 0, 9)
2825 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2826
2827 def test_memoryview_assign(self):
2828
2829 # ndim = 0
2830 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2831 m = memoryview(ex)
2832 m[()] = 22.5
2833 self.assertEqual(m[()], 22.5)
2834 m[...] = 23.5
2835 self.assertEqual(m[()], 23.5)
2836 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2837
2838 # read-only
2839 ex = ndarray(list(range(7)), shape=[7])
2840 m = memoryview(ex)
2841 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2842
2843 # range
2844 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2845 m = memoryview(ex)
2846
2847 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2848 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2849 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2850
2851 # out of bounds
2852 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2853 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2854
2855 # pack_single() success:
2856 for fmt in fmtdict['@']:
2857 if fmt == 'c' or fmt == '?':
2858 continue
2859 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2860 m = memoryview(ex)
2861 i = randrange(-3, 3)
2862 m[i] = 8
2863 self.assertEqual(m[i], 8)
2864 self.assertEqual(m[i], ex[i])
2865
2866 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2867 flags=ND_WRITABLE)
2868 m = memoryview(ex)
2869 m[2] = b'9'
2870 self.assertEqual(m[2], b'9')
2871
2872 ex = ndarray([True, False, True], shape=[3], format='?',
2873 flags=ND_WRITABLE)
2874 m = memoryview(ex)
2875 m[1] = True
2876 self.assertEqual(m[1], True)
2877
2878 # pack_single() exceptions:
2879 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2880 m = memoryview(nd)
2881 self.assertRaises(TypeError, m.__setitem__, 0, 100)
2882
2883 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
2884 m1 = memoryview(ex)
2885
2886 for fmt, _range in fmtdict['@'].items():
2887 if (fmt == '?'): # PyObject_IsTrue() accepts anything
2888 continue
2889 if fmt == 'c': # special case tested above
2890 continue
2891 m2 = m1.cast(fmt)
2892 lo, hi = _range
2893 if fmt == 'd' or fmt == 'f':
2894 lo, hi = -2**1024, 2**1024
2895 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
2896 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
2897 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
2898 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
2899
2900 # invalid item
2901 m2 = m1.cast('c')
2902 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
2903
2904 # format not implemented
2905 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
2906 m = memoryview(ex)
2907 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2908
2909 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
2910 m = memoryview(ex)
2911 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2912
2913 # Not implemented: multidimensional sub-views
2914 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2915 m = memoryview(ex)
2916
2917 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
2918
2919 def test_memoryview_slice(self):
2920
2921 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2922 m = memoryview(ex)
2923
2924 # zero step
2925 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
2926 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
2927 bytearray([1,2]))
2928
2929 # invalid slice key
2930 self.assertRaises(TypeError, m.__getitem__, ())
2931
2932 # multidimensional slices
2933 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2934 m = memoryview(ex)
2935
2936 self.assertRaises(NotImplementedError, m.__getitem__,
2937 (slice(0,2,1), slice(0,2,1)))
2938 self.assertRaises(NotImplementedError, m.__setitem__,
2939 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
2940
2941 # invalid slice tuple
2942 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
2943 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
2944 bytearray([1,2]))
2945
2946 # rvalue is not an exporter
2947 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
2948
2949 # non-contiguous slice assignment
2950 for flags in (0, ND_PIL):
2951 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
2952 flags=ND_WRITABLE|flags)
2953 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
2954 m1 = memoryview(ex1)
2955 m2 = memoryview(ex2)
2956
2957 ex1[2:5] = ex1[2:5]
2958 m1[2:5] = m2[2:5]
2959
2960 self.assertEqual(m1, ex1)
2961 self.assertEqual(m2, ex2)
2962
2963 ex1[1:3][::-1] = ex2[0:2][::1]
2964 m1[1:3][::-1] = m2[0:2][::1]
2965
2966 self.assertEqual(m1, ex1)
2967 self.assertEqual(m2, ex2)
2968
2969 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
2970 m1[4:1:-2][::-1] = m1[1:4:2][::1]
2971
2972 self.assertEqual(m1, ex1)
2973 self.assertEqual(m2, ex2)
2974
2975 def test_memoryview_array(self):
2976
2977 def cmptest(testcase, a, b, m, singleitem):
2978 for i, _ in enumerate(a):
2979 ai = a[i]
2980 mi = m[i]
2981 testcase.assertEqual(ai, mi)
2982 a[i] = singleitem
2983 if singleitem != ai:
2984 testcase.assertNotEqual(a, m)
2985 testcase.assertNotEqual(a, b)
2986 else:
2987 testcase.assertEqual(a, m)
2988 testcase.assertEqual(a, b)
2989 m[i] = singleitem
2990 testcase.assertEqual(a, m)
2991 testcase.assertEqual(b, m)
2992 a[i] = ai
2993 m[i] = mi
2994
2995 for n in range(1, 5):
2996 for fmt, items, singleitem in iter_format(n, 'array'):
2997 for lslice in genslices(n):
2998 for rslice in genslices(n):
2999
3000 a = array.array(fmt, items)
3001 b = array.array(fmt, items)
3002 m = memoryview(b)
3003
3004 self.assertEqual(m, a)
3005 self.assertEqual(m.tolist(), a.tolist())
3006 self.assertEqual(m.tobytes(), a.tobytes())
3007 self.assertEqual(len(m), len(a))
3008
3009 cmptest(self, a, b, m, singleitem)
3010
3011 array_err = None
3012 have_resize = None
3013 try:
3014 al = a[lslice]
3015 ar = a[rslice]
3016 a[lslice] = a[rslice]
3017 have_resize = len(al) != len(ar)
3018 except Exception as e:
3019 array_err = e.__class__
3020
3021 m_err = None
3022 try:
3023 m[lslice] = m[rslice]
3024 except Exception as e:
3025 m_err = e.__class__
3026
3027 if have_resize: # memoryview cannot change shape
3028 self.assertIs(m_err, ValueError)
3029 elif m_err or array_err:
3030 self.assertIs(m_err, array_err)
3031 else:
3032 self.assertEqual(m, a)
3033 self.assertEqual(m.tolist(), a.tolist())
3034 self.assertEqual(m.tobytes(), a.tobytes())
3035 cmptest(self, a, b, m, singleitem)
3036
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003037 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003038
3039 a = array.array('L', [1, 2, 3])
3040 b = array.array('L', [1, 2, 7])
3041
3042 # Ordering comparisons raise:
3043 v = memoryview(a)
3044 w = memoryview(b)
3045 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3046 self.assertIs(getattr(v, attr)(w), NotImplemented)
3047 self.assertIs(getattr(a, attr)(v), NotImplemented)
3048
3049 # Released views compare equal to themselves:
3050 v = memoryview(a)
3051 v.release()
3052 self.assertEqual(v, v)
3053 self.assertNotEqual(v, a)
3054 self.assertNotEqual(a, v)
3055
3056 v = memoryview(a)
3057 w = memoryview(a)
3058 w.release()
3059 self.assertNotEqual(v, w)
3060 self.assertNotEqual(w, v)
3061
3062 # Operand does not implement the buffer protocol:
3063 v = memoryview(a)
3064 self.assertNotEqual(v, [1, 2, 3])
3065
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003066 # NaNs
3067 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3068 nd[0] = (-1, float('nan'))
3069 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003070
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003071 # Depends on issue #15625: the struct module does not understand 'u'.
3072 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003073 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003074 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003075 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003076
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003077 # Some ctypes format strings are unknown to the struct module.
3078 if ctypes:
3079 # format: "T{>l:x:>l:y:}"
3080 class BEPoint(ctypes.BigEndianStructure):
3081 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3082 point = BEPoint(100, 200)
3083 a = memoryview(point)
3084 b = memoryview(point)
3085 self.assertNotEqual(a, b)
3086 self.assertNotEqual(a, point)
3087 self.assertNotEqual(point, a)
3088 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003089
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003090 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003091
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003092 nd1 = ndarray(1729, shape=[], format='@L')
3093 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
3094 v = memoryview(nd1)
3095 w = memoryview(nd2)
3096 self.assertEqual(v, w)
3097 self.assertEqual(w, v)
3098 self.assertEqual(v, nd2)
3099 self.assertEqual(nd2, v)
3100 self.assertEqual(w, nd1)
3101 self.assertEqual(nd1, w)
3102
3103 self.assertFalse(v.__ne__(w))
3104 self.assertFalse(w.__ne__(v))
3105
3106 w[()] = 1728
3107 self.assertNotEqual(v, w)
3108 self.assertNotEqual(w, v)
3109 self.assertNotEqual(v, nd2)
3110 self.assertNotEqual(nd2, v)
3111 self.assertNotEqual(w, nd1)
3112 self.assertNotEqual(nd1, w)
3113
3114 self.assertFalse(v.__eq__(w))
3115 self.assertFalse(w.__eq__(v))
3116
3117 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3118 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3119 m = memoryview(ex)
3120
3121 self.assertEqual(m, nd)
3122 m[9] = 100
3123 self.assertNotEqual(m, nd)
3124
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003125 # struct module: equal
3126 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3127 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3128 flags=ND_WRITABLE)
3129 v = memoryview(nd1)
3130 w = memoryview(nd2)
3131 self.assertEqual(v, w)
3132 self.assertEqual(w, v)
3133 self.assertEqual(v, nd2)
3134 self.assertEqual(nd2, v)
3135 self.assertEqual(w, nd1)
3136 self.assertEqual(nd1, w)
3137
3138 # struct module: not equal
3139 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3140 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3141 flags=ND_WRITABLE)
3142 v = memoryview(nd1)
3143 w = memoryview(nd2)
3144 self.assertNotEqual(v, w)
3145 self.assertNotEqual(w, v)
3146 self.assertNotEqual(v, nd2)
3147 self.assertNotEqual(nd2, v)
3148 self.assertNotEqual(w, nd1)
3149 self.assertNotEqual(nd1, w)
3150 self.assertEqual(v, nd1)
3151 self.assertEqual(w, nd2)
3152
3153 def test_memoryview_compare_ndim_one(self):
3154
3155 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003156 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3157 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3158 v = memoryview(nd1)
3159 w = memoryview(nd2)
3160
3161 self.assertEqual(v, nd1)
3162 self.assertEqual(w, nd2)
3163 self.assertNotEqual(v, nd2)
3164 self.assertNotEqual(w, nd1)
3165 self.assertNotEqual(v, w)
3166
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003167 # contiguous, struct module
3168 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3169 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3170 v = memoryview(nd1)
3171 w = memoryview(nd2)
3172
3173 self.assertEqual(v, nd1)
3174 self.assertEqual(w, nd2)
3175 self.assertNotEqual(v, nd2)
3176 self.assertNotEqual(w, nd1)
3177 self.assertNotEqual(v, w)
3178
3179 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003180 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3181 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3182 v = memoryview(nd1)
3183 w = memoryview(nd2)
3184
3185 self.assertEqual(v, nd2[::2])
3186 self.assertEqual(w[::2], nd1)
3187 self.assertEqual(v, w[::2])
3188 self.assertEqual(v[::-1], w[::-2])
3189
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003190 # non-contiguous, struct module
3191 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3192 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3193 v = memoryview(nd1)
3194 w = memoryview(nd2)
3195
3196 self.assertEqual(v, nd2[::2])
3197 self.assertEqual(w[::2], nd1)
3198 self.assertEqual(v, w[::2])
3199 self.assertEqual(v[::-1], w[::-2])
3200
3201 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003202 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3203 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3204 flags=ND_PIL)
3205 v = memoryview(nd1)
3206 w = memoryview(nd2)
3207
3208 self.assertEqual(v, nd2[::2])
3209 self.assertEqual(w[::2], nd1)
3210 self.assertEqual(v, w[::2])
3211 self.assertEqual(v[::-1], w[::-2])
3212
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003213 # non-contiguous, suboffsets, struct module
3214 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3215 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3216 flags=ND_PIL)
3217 v = memoryview(nd1)
3218 w = memoryview(nd2)
3219
3220 self.assertEqual(v, nd2[::2])
3221 self.assertEqual(w[::2], nd1)
3222 self.assertEqual(v, w[::2])
3223 self.assertEqual(v[::-1], w[::-2])
3224
3225 def test_memoryview_compare_zero_shape(self):
3226
3227 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003228 nd1 = ndarray([900, 961], shape=[0], format='@h')
3229 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3230 v = memoryview(nd1)
3231 w = memoryview(nd2)
3232
3233 self.assertEqual(v, nd1)
3234 self.assertEqual(w, nd2)
3235 self.assertEqual(v, nd2)
3236 self.assertEqual(w, nd1)
3237 self.assertEqual(v, w)
3238
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003239 # zeros in shape, struct module
3240 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3241 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3242 v = memoryview(nd1)
3243 w = memoryview(nd2)
3244
3245 self.assertEqual(v, nd1)
3246 self.assertEqual(w, nd2)
3247 self.assertEqual(v, nd2)
3248 self.assertEqual(w, nd1)
3249 self.assertEqual(v, w)
3250
3251 def test_memoryview_compare_zero_strides(self):
3252
3253 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003254 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3255 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3256 v = memoryview(nd1)
3257 w = memoryview(nd2)
3258
3259 self.assertEqual(v, nd1)
3260 self.assertEqual(w, nd2)
3261 self.assertEqual(v, nd2)
3262 self.assertEqual(w, nd1)
3263 self.assertEqual(v, w)
3264
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003265 # zero strides, struct module
3266 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3267 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3268 v = memoryview(nd1)
3269 w = memoryview(nd2)
3270
3271 self.assertEqual(v, nd1)
3272 self.assertEqual(w, nd2)
3273 self.assertEqual(v, nd2)
3274 self.assertEqual(w, nd1)
3275 self.assertEqual(v, w)
3276
3277 def test_memoryview_compare_random_formats(self):
3278
3279 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003280 n = 10
3281 for char in fmtdict['@m']:
3282 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3283 for flags in (0, ND_PIL):
3284 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3285 m = memoryview(nd)
3286 self.assertEqual(m, nd)
3287
3288 nd = nd[::-3]
3289 m = memoryview(nd)
3290 self.assertEqual(m, nd)
3291
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003292 # random formats
3293 n = 10
3294 for _ in range(100):
3295 fmt, items, singleitem = randitems(n)
3296 for flags in (0, ND_PIL):
3297 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3298 m = memoryview(nd)
3299 self.assertEqual(m, nd)
3300
3301 nd = nd[::-3]
3302 m = memoryview(nd)
3303 self.assertEqual(m, nd)
3304
3305 def test_memoryview_compare_multidim_c(self):
3306
3307 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003308 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3309 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3310 v = memoryview(nd1)
3311 w = memoryview(nd2)
3312
3313 self.assertEqual(v, nd1)
3314 self.assertEqual(w, nd2)
3315 self.assertNotEqual(v, nd2)
3316 self.assertNotEqual(w, nd1)
3317 self.assertNotEqual(v, w)
3318
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003319 # C-contiguous, different values, struct module
3320 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3321 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3322 v = memoryview(nd1)
3323 w = memoryview(nd2)
3324
3325 self.assertEqual(v, nd1)
3326 self.assertEqual(w, nd2)
3327 self.assertNotEqual(v, nd2)
3328 self.assertNotEqual(w, nd1)
3329 self.assertNotEqual(v, w)
3330
3331 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003332 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3333 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3334 v = memoryview(nd1)
3335 w = memoryview(nd2)
3336
3337 self.assertEqual(v, nd1)
3338 self.assertEqual(w, nd2)
3339 self.assertNotEqual(v, nd2)
3340 self.assertNotEqual(w, nd1)
3341 self.assertNotEqual(v, w)
3342
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003343 # C-contiguous, different shape, struct module
3344 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3345 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003346 v = memoryview(nd1)
3347 w = memoryview(nd2)
3348
3349 self.assertEqual(v, nd1)
3350 self.assertEqual(w, nd2)
3351 self.assertNotEqual(v, nd2)
3352 self.assertNotEqual(w, nd1)
3353 self.assertNotEqual(v, w)
3354
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003355 # C-contiguous, different format, struct module
3356 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3357 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3358 v = memoryview(nd1)
3359 w = memoryview(nd2)
3360
3361 self.assertEqual(v, nd1)
3362 self.assertEqual(w, nd2)
3363 self.assertEqual(v, nd2)
3364 self.assertEqual(w, nd1)
3365 self.assertEqual(v, w)
3366
3367 def test_memoryview_compare_multidim_fortran(self):
3368
3369 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003370 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3371 flags=ND_FORTRAN)
3372 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3373 flags=ND_FORTRAN)
3374 v = memoryview(nd1)
3375 w = memoryview(nd2)
3376
3377 self.assertEqual(v, nd1)
3378 self.assertEqual(w, nd2)
3379 self.assertNotEqual(v, nd2)
3380 self.assertNotEqual(w, nd1)
3381 self.assertNotEqual(v, w)
3382
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003383 # Fortran-contiguous, different values, struct module
3384 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3385 flags=ND_FORTRAN)
3386 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3387 flags=ND_FORTRAN)
3388 v = memoryview(nd1)
3389 w = memoryview(nd2)
3390
3391 self.assertEqual(v, nd1)
3392 self.assertEqual(w, nd2)
3393 self.assertNotEqual(v, nd2)
3394 self.assertNotEqual(w, nd1)
3395 self.assertNotEqual(v, w)
3396
3397 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003398 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3399 flags=ND_FORTRAN)
3400 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3401 flags=ND_FORTRAN)
3402 v = memoryview(nd1)
3403 w = memoryview(nd2)
3404
3405 self.assertEqual(v, nd1)
3406 self.assertEqual(w, nd2)
3407 self.assertNotEqual(v, nd2)
3408 self.assertNotEqual(w, nd1)
3409 self.assertNotEqual(v, w)
3410
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003411 # Fortran-contiguous, different shape, struct module
3412 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003413 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003414 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003415 flags=ND_FORTRAN)
3416 v = memoryview(nd1)
3417 w = memoryview(nd2)
3418
3419 self.assertEqual(v, nd1)
3420 self.assertEqual(w, nd2)
3421 self.assertNotEqual(v, nd2)
3422 self.assertNotEqual(w, nd1)
3423 self.assertNotEqual(v, w)
3424
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003425 # Fortran-contiguous, different format, struct module
3426 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3427 flags=ND_FORTRAN)
3428 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3429 flags=ND_FORTRAN)
3430 v = memoryview(nd1)
3431 w = memoryview(nd2)
3432
3433 self.assertEqual(v, nd1)
3434 self.assertEqual(w, nd2)
3435 self.assertEqual(v, nd2)
3436 self.assertEqual(w, nd1)
3437 self.assertEqual(v, w)
3438
3439 def test_memoryview_compare_multidim_mixed(self):
3440
3441 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003442 lst1 = list(range(-15, 15))
3443 lst2 = transpose(lst1, [3, 2, 5])
3444 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3445 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3446 v = memoryview(nd1)
3447 w = memoryview(nd2)
3448
3449 self.assertEqual(v, nd1)
3450 self.assertEqual(w, nd2)
3451 self.assertEqual(v, w)
3452
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003453 # mixed C/Fortran contiguous, struct module
3454 lst1 = [(-3.3, -22, b'x')]*30
3455 lst1[5] = (-2.2, -22, b'x')
3456 lst2 = transpose(lst1, [3, 2, 5])
3457 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3458 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3459 v = memoryview(nd1)
3460 w = memoryview(nd2)
3461
3462 self.assertEqual(v, nd1)
3463 self.assertEqual(w, nd2)
3464 self.assertEqual(v, w)
3465
3466 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003467 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3468 nd1 = ex1[3:1:-1, ::-2]
3469 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3470 nd2 = ex2[1:3:1, ::-2]
3471 v = memoryview(nd1)
3472 w = memoryview(nd2)
3473
3474 self.assertEqual(v, nd1)
3475 self.assertEqual(w, nd2)
3476 self.assertNotEqual(v, nd2)
3477 self.assertNotEqual(w, nd1)
3478 self.assertNotEqual(v, w)
3479
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003480 # same values, non-contiguous, struct module
3481 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3482 nd1 = ex1[3:1:-1, ::-2]
3483 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3484 nd2 = ex2[1:3:1, ::-2]
3485 v = memoryview(nd1)
3486 w = memoryview(nd2)
3487
3488 self.assertEqual(v, nd1)
3489 self.assertEqual(w, nd2)
3490 self.assertEqual(v, nd2)
3491 self.assertEqual(w, nd1)
3492 self.assertEqual(v, w)
3493
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003494 # different shape
3495 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3496 nd1 = ex1[1:3:, ::-2]
3497 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3498 nd2 = ex2[1:3:, ::-2]
3499 v = memoryview(nd1)
3500 w = memoryview(nd2)
3501
3502 self.assertEqual(v, nd1)
3503 self.assertEqual(w, nd2)
3504 self.assertNotEqual(v, nd2)
3505 self.assertNotEqual(w, nd1)
3506 self.assertNotEqual(v, w)
3507
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003508 # different shape, struct module
3509 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003510 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003511 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003512 nd2 = ex2[1:3:, ::-2]
3513 v = memoryview(nd1)
3514 w = memoryview(nd2)
3515
3516 self.assertEqual(v, nd1)
3517 self.assertEqual(w, nd2)
3518 self.assertNotEqual(v, nd2)
3519 self.assertNotEqual(w, nd1)
3520 self.assertNotEqual(v, w)
3521
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003522 # different format, struct module
3523 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3524 nd1 = ex1[1:3:, ::-2]
3525 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3526 nd2 = ex2[1:3:, ::-2]
3527 v = memoryview(nd1)
3528 w = memoryview(nd2)
3529
3530 self.assertEqual(v, nd1)
3531 self.assertEqual(w, nd2)
3532 self.assertNotEqual(v, nd2)
3533 self.assertNotEqual(w, nd1)
3534 self.assertNotEqual(v, w)
3535
3536 def test_memoryview_compare_multidim_zero_shape(self):
3537
3538 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003539 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3540 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3541 v = memoryview(nd1)
3542 w = memoryview(nd2)
3543
3544 self.assertEqual(v, nd1)
3545 self.assertEqual(w, nd2)
3546 self.assertNotEqual(v, nd2)
3547 self.assertNotEqual(w, nd1)
3548 self.assertNotEqual(v, w)
3549
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003550 # zeros in shape, struct module
3551 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3552 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3553 v = memoryview(nd1)
3554 w = memoryview(nd2)
3555
3556 self.assertEqual(v, nd1)
3557 self.assertEqual(w, nd2)
3558 self.assertNotEqual(v, nd2)
3559 self.assertNotEqual(w, nd1)
3560 self.assertNotEqual(v, w)
3561
3562 def test_memoryview_compare_multidim_zero_strides(self):
3563
3564 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003565 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3566 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3567 v = memoryview(nd1)
3568 w = memoryview(nd2)
3569
3570 self.assertEqual(v, nd1)
3571 self.assertEqual(w, nd2)
3572 self.assertEqual(v, nd2)
3573 self.assertEqual(w, nd1)
3574 self.assertEqual(v, w)
3575 self.assertEqual(v.tolist(), w.tolist())
3576
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003577 # zero strides, struct module
3578 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3579 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3580 v = memoryview(nd1)
3581 w = memoryview(nd2)
3582
3583 self.assertEqual(v, nd1)
3584 self.assertEqual(w, nd2)
3585 self.assertEqual(v, nd2)
3586 self.assertEqual(w, nd1)
3587 self.assertEqual(v, w)
3588
3589 def test_memoryview_compare_multidim_suboffsets(self):
3590
3591 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003592 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3593 nd1 = ex1[3:1:-1, ::-2]
3594 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3595 nd2 = ex2[1:3:1, ::-2]
3596 v = memoryview(nd1)
3597 w = memoryview(nd2)
3598
3599 self.assertEqual(v, nd1)
3600 self.assertEqual(w, nd2)
3601 self.assertNotEqual(v, nd2)
3602 self.assertNotEqual(w, nd1)
3603 self.assertNotEqual(v, w)
3604
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003605 # suboffsets, struct module
3606 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3607 flags=ND_WRITABLE)
3608 ex1[2][7] = (1, -2)
3609 nd1 = ex1[3:1:-1, ::-2]
3610
3611 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3612 flags=ND_PIL|ND_WRITABLE)
3613 ex2[2][7] = (1, -2)
3614 nd2 = ex2[1:3:1, ::-2]
3615
3616 v = memoryview(nd1)
3617 w = memoryview(nd2)
3618
3619 self.assertEqual(v, nd1)
3620 self.assertEqual(w, nd2)
3621 self.assertEqual(v, nd2)
3622 self.assertEqual(w, nd1)
3623 self.assertEqual(v, w)
3624
3625 # suboffsets, different shape
3626 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3627 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003628 nd1 = ex1[1:3:, ::-2]
3629 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3630 nd2 = ex2[1:3:, ::-2]
3631 v = memoryview(nd1)
3632 w = memoryview(nd2)
3633
3634 self.assertEqual(v, nd1)
3635 self.assertEqual(w, nd2)
3636 self.assertNotEqual(v, nd2)
3637 self.assertNotEqual(w, nd1)
3638 self.assertNotEqual(v, w)
3639
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003640 # suboffsets, different shape, struct module
3641 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3642 flags=ND_PIL|ND_WRITABLE)
3643 nd1 = ex1[1:2:, ::-2]
3644
3645 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3646 nd2 = ex2[1:2:, ::-2]
3647
3648 v = memoryview(nd1)
3649 w = memoryview(nd2)
3650
3651 self.assertEqual(v, nd1)
3652 self.assertEqual(w, nd2)
3653 self.assertNotEqual(v, nd2)
3654 self.assertNotEqual(w, nd1)
3655 self.assertNotEqual(v, w)
3656
3657 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003658 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3659 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003660 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003661 nd2 = ex2[1:3:, ::-2]
3662 v = memoryview(nd1)
3663 w = memoryview(nd2)
3664
3665 self.assertEqual(v, nd1)
3666 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003667 self.assertEqual(v, nd2)
3668 self.assertEqual(w, nd1)
3669 self.assertEqual(v, w)
3670
3671 # suboffsets, different format, struct module
3672 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3673 flags=ND_PIL|ND_WRITABLE)
3674 ex1[1][2][2] = (b'sushi', b'', 1)
3675 nd1 = ex1[1:3:, ::-2]
3676
3677 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3678 flags=ND_PIL|ND_WRITABLE)
3679 ex1[1][2][2] = (b'sushi', b'', 1)
3680 nd2 = ex2[1:3:, ::-2]
3681
3682 v = memoryview(nd1)
3683 w = memoryview(nd2)
3684
3685 self.assertEqual(v, nd1)
3686 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003687 self.assertNotEqual(v, nd2)
3688 self.assertNotEqual(w, nd1)
3689 self.assertNotEqual(v, w)
3690
3691 # initialize mixed C/Fortran + suboffsets
3692 lst1 = list(range(-15, 15))
3693 lst2 = transpose(lst1, [3, 2, 5])
3694 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3695 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3696 v = memoryview(nd1)
3697 w = memoryview(nd2)
3698
3699 self.assertEqual(v, nd1)
3700 self.assertEqual(w, nd2)
3701 self.assertEqual(v, w)
3702
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003703 # initialize mixed C/Fortran + suboffsets, struct module
3704 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3705 lst1[11] = (b'ramen', b'spicy', 9.45)
3706 lst2 = transpose(lst1, [3, 2, 5])
3707
3708 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3709 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3710 flags=ND_FORTRAN|ND_PIL)
3711 v = memoryview(nd1)
3712 w = memoryview(nd2)
3713
3714 self.assertEqual(v, nd1)
3715 self.assertEqual(w, nd2)
3716 self.assertEqual(v, w)
3717
3718 def test_memoryview_compare_not_equal(self):
3719
3720 # items not equal
3721 for byteorder in ['=', '<', '>', '!']:
3722 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3723 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3724 flags=ND_WRITABLE|ND_FORTRAN)
3725 y[2][3][1][1][1] = 1
3726 a = memoryview(x)
3727 b = memoryview(y)
3728 self.assertEqual(a, x)
3729 self.assertEqual(b, y)
3730 self.assertNotEqual(a, b)
3731 self.assertNotEqual(a, y)
3732 self.assertNotEqual(b, x)
3733
3734 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3735 format=byteorder+'QLH')
3736 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3737 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3738 y[2][3][1][1][1] = (1, 1, 1)
3739 a = memoryview(x)
3740 b = memoryview(y)
3741 self.assertEqual(a, x)
3742 self.assertEqual(b, y)
3743 self.assertNotEqual(a, b)
3744 self.assertNotEqual(a, y)
3745 self.assertNotEqual(b, x)
3746
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003747 def test_memoryview_check_released(self):
3748
3749 a = array.array('d', [1.1, 2.2, 3.3])
3750
3751 m = memoryview(a)
3752 m.release()
3753
3754 # PyMemoryView_FromObject()
3755 self.assertRaises(ValueError, memoryview, m)
3756 # memoryview.cast()
3757 self.assertRaises(ValueError, m.cast, 'c')
3758 # getbuffer()
3759 self.assertRaises(ValueError, ndarray, m)
3760 # memoryview.tolist()
3761 self.assertRaises(ValueError, m.tolist)
3762 # memoryview.tobytes()
3763 self.assertRaises(ValueError, m.tobytes)
3764 # sequence
3765 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3766 # subscript
3767 self.assertRaises(ValueError, m.__getitem__, 0)
3768 # assignment
3769 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3770
3771 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3772 'shape', 'strides', 'suboffsets', 'c_contiguous',
3773 'f_contiguous', 'contiguous'):
3774 self.assertRaises(ValueError, m.__getattribute__, attr)
3775
3776 # richcompare
3777 b = array.array('d', [1.1, 2.2, 3.3])
3778 m1 = memoryview(a)
3779 m2 = memoryview(b)
3780
3781 self.assertEqual(m1, m2)
3782 m1.release()
3783 self.assertNotEqual(m1, m2)
3784 self.assertNotEqual(m1, a)
3785 self.assertEqual(m1, m1)
3786
3787 def test_memoryview_tobytes(self):
3788 # Many implicit tests are already in self.verify().
3789
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003790 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003791
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003792 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003793 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003794 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003795 self.assertEqual(m.tobytes(), nd.tobytes())
3796
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003797 nd = ndarray([t], shape=[1], format='>hQiLl')
3798 m = memoryview(nd)
3799 self.assertEqual(m, nd)
3800 self.assertEqual(m.tobytes(), nd.tobytes())
3801
3802 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3803 m = memoryview(nd)
3804 self.assertEqual(m, nd)
3805 self.assertEqual(m.tobytes(), nd.tobytes())
3806
3807 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3808 format='<hQiLl')
3809 m = memoryview(nd)
3810 self.assertEqual(m, nd)
3811 self.assertEqual(m.tobytes(), nd.tobytes())
3812
3813 # Unknown formats are handled: tobytes() purely depends on itemsize.
3814 if ctypes:
3815 # format: "T{>l:x:>l:y:}"
3816 class BEPoint(ctypes.BigEndianStructure):
3817 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3818 point = BEPoint(100, 200)
3819 a = memoryview(point)
3820 self.assertEqual(a.tobytes(), bytes(point))
3821
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003822 def test_memoryview_get_contiguous(self):
3823 # Many implicit tests are already in self.verify().
3824
3825 # no buffer interface
3826 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3827
3828 # writable request to read-only object
3829 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3830
3831 # writable request to non-contiguous object
3832 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3833 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3834
3835 # scalar, read-only request from read-only exporter
3836 nd = ndarray(9, shape=(), format="L")
3837 for order in ['C', 'F', 'A']:
3838 m = get_contiguous(nd, PyBUF_READ, order)
3839 self.assertEqual(m, nd)
3840 self.assertEqual(m[()], 9)
3841
3842 # scalar, read-only request from writable exporter
3843 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
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, writable request
3850 for order in ['C', 'F', 'A']:
3851 nd[()] = 9
3852 m = get_contiguous(nd, PyBUF_WRITE, order)
3853 self.assertEqual(m, nd)
3854 self.assertEqual(m[()], 9)
3855
3856 m[()] = 10
3857 self.assertEqual(m[()], 10)
3858 self.assertEqual(nd[()], 10)
3859
3860 # zeros in shape
3861 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3862 for order in ['C', 'F', 'A']:
3863 m = get_contiguous(nd, PyBUF_READ, order)
3864 self.assertRaises(IndexError, m.__getitem__, 0)
3865 self.assertEqual(m, nd)
3866 self.assertEqual(m.tolist(), [])
3867
3868 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
3869 flags=ND_WRITABLE)
3870 for order in ['C', 'F', 'A']:
3871 m = get_contiguous(nd, PyBUF_READ, order)
3872 self.assertEqual(ndarray(m).tolist(), [[], []])
3873
3874 # one-dimensional
3875 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
3876 for order in ['C', 'F', 'A']:
3877 m = get_contiguous(nd, PyBUF_WRITE, order)
3878 self.assertEqual(m, nd)
3879 self.assertEqual(m.tolist(), nd.tolist())
3880
3881 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
3882 for order in ['C', 'F', 'A']:
3883 m = get_contiguous(nd, PyBUF_WRITE, order)
3884 self.assertEqual(m, nd)
3885 self.assertEqual(m.tolist(), nd.tolist())
3886
3887 # one-dimensional, non-contiguous
3888 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
3889 for order in ['C', 'F', 'A']:
3890 m = get_contiguous(nd, PyBUF_READ, order)
3891 self.assertEqual(m, nd)
3892 self.assertEqual(m.tolist(), nd.tolist())
3893 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3894 self.assertEqual(m[1], 3)
3895 self.assertEqual(nd[1], 3)
3896
3897 nd = nd[::-1]
3898 for order in ['C', 'F', 'A']:
3899 m = get_contiguous(nd, PyBUF_READ, order)
3900 self.assertEqual(m, nd)
3901 self.assertEqual(m.tolist(), nd.tolist())
3902 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3903 self.assertEqual(m[1], 1)
3904 self.assertEqual(nd[1], 1)
3905
3906 # multi-dimensional, contiguous input
3907 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
3908 for order in ['C', 'A']:
3909 m = get_contiguous(nd, PyBUF_WRITE, order)
3910 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3911
3912 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
3913 m = get_contiguous(nd, PyBUF_READ, order)
3914 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3915
3916 nd = ndarray(list(range(12)), shape=[3, 4],
3917 flags=ND_WRITABLE|ND_FORTRAN)
3918 for order in ['F', 'A']:
3919 m = get_contiguous(nd, PyBUF_WRITE, order)
3920 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3921
3922 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
3923 m = get_contiguous(nd, PyBUF_READ, order)
3924 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3925
3926 # multi-dimensional, non-contiguous input
3927 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
3928 for order in ['C', 'F', 'A']:
3929 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
3930 order)
3931 m = get_contiguous(nd, PyBUF_READ, order)
3932 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3933
3934 # flags
3935 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
3936 m = get_contiguous(nd, PyBUF_READ, 'C')
3937 self.assertTrue(m.c_contiguous)
3938
3939 def test_memoryview_serializing(self):
3940
3941 # C-contiguous
3942 size = struct.calcsize('i')
3943 a = array.array('i', [1,2,3,4,5])
3944 m = memoryview(a)
3945 buf = io.BytesIO(m)
3946 b = bytearray(5*size)
3947 buf.readinto(b)
3948 self.assertEqual(m.tobytes(), b)
3949
3950 # C-contiguous, multi-dimensional
3951 size = struct.calcsize('L')
3952 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
3953 m = memoryview(nd)
3954 buf = io.BytesIO(m)
3955 b = bytearray(2*3*2*size)
3956 buf.readinto(b)
3957 self.assertEqual(m.tobytes(), b)
3958
3959 # Fortran contiguous, multi-dimensional
3960 #size = struct.calcsize('L')
3961 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
3962 # flags=ND_FORTRAN)
3963 #m = memoryview(nd)
3964 #buf = io.BytesIO(m)
3965 #b = bytearray(2*3*2*size)
3966 #buf.readinto(b)
3967 #self.assertEqual(m.tobytes(), b)
3968
3969 def test_memoryview_hash(self):
3970
3971 # bytes exporter
3972 b = bytes(list(range(12)))
3973 m = memoryview(b)
3974 self.assertEqual(hash(b), hash(m))
3975
3976 # C-contiguous
3977 mc = m.cast('c', shape=[3,4])
3978 self.assertEqual(hash(mc), hash(b))
3979
3980 # non-contiguous
3981 mx = m[::-2]
3982 b = bytes(list(range(12))[::-2])
3983 self.assertEqual(hash(mx), hash(b))
3984
3985 # Fortran contiguous
3986 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
3987 m = memoryview(nd)
3988 self.assertEqual(hash(m), hash(nd))
3989
3990 # multi-dimensional slice
3991 nd = ndarray(list(range(30)), shape=[3,2,5])
3992 x = nd[::2, ::, ::-1]
3993 m = memoryview(x)
3994 self.assertEqual(hash(m), hash(x))
3995
3996 # multi-dimensional slice with suboffsets
3997 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
3998 x = nd[::2, ::, ::-1]
3999 m = memoryview(x)
4000 self.assertEqual(hash(m), hash(x))
4001
Stefan Krah4af77a02012-11-02 17:49:22 +01004002 # equality-hash invariant
4003 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004004 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004005
4006 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004007 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004008
Stefan Krahb716f842012-11-04 20:53:50 +01004009 self.assertEqual(a, b)
4010 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004011
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004012 # non-byte formats
4013 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4014 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004015 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004016
4017 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4018 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004019 self.assertRaises(ValueError, m.__hash__)
4020
4021 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4022 m = memoryview(nd)
4023 self.assertRaises(ValueError, m.__hash__)
4024
4025 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4026 m = memoryview(nd)
4027 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004028
4029 def test_memoryview_release(self):
4030
4031 # Create re-exporter from getbuffer(memoryview), then release the view.
4032 a = bytearray([1,2,3])
4033 m = memoryview(a)
4034 nd = ndarray(m) # re-exporter
4035 self.assertRaises(BufferError, m.release)
4036 del nd
4037 m.release()
4038
Stefan Krah4e99a312012-03-05 09:30:47 +01004039 a = bytearray([1,2,3])
4040 m = memoryview(a)
4041 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4042 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4043 self.assertIs(nd2.obj, m)
4044 self.assertRaises(BufferError, m.release)
4045 del nd1, nd2
4046 m.release()
4047
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004048 # chained views
4049 a = bytearray([1,2,3])
4050 m1 = memoryview(a)
4051 m2 = memoryview(m1)
4052 nd = ndarray(m2) # re-exporter
4053 m1.release()
4054 self.assertRaises(BufferError, m2.release)
4055 del nd
4056 m2.release()
4057
Stefan Krah4e99a312012-03-05 09:30:47 +01004058 a = bytearray([1,2,3])
4059 m1 = memoryview(a)
4060 m2 = memoryview(m1)
4061 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4062 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4063 self.assertIs(nd2.obj, m2)
4064 m1.release()
4065 self.assertRaises(BufferError, m2.release)
4066 del nd1, nd2
4067 m2.release()
4068
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004069 # Allow changing layout while buffers are exported.
4070 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4071 m1 = memoryview(nd)
4072
4073 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4074 m2 = memoryview(nd)
4075
4076 x = memoryview(m1)
4077 self.assertEqual(x.tolist(), m1.tolist())
4078
4079 y = memoryview(m2)
4080 self.assertEqual(y.tolist(), m2.tolist())
4081 self.assertEqual(y.tolist(), nd.tolist())
4082 m2.release()
4083 y.release()
4084
4085 nd.pop() # pop the current view
4086 self.assertEqual(x.tolist(), nd.tolist())
4087
4088 del nd
4089 m1.release()
4090 x.release()
4091
4092 # If multiple memoryviews share the same managed buffer, implicit
4093 # release() in the context manager's __exit__() method should still
4094 # work.
4095 def catch22(b):
4096 with memoryview(b) as m2:
4097 pass
4098
4099 x = bytearray(b'123')
4100 with memoryview(x) as m1:
4101 catch22(m1)
4102 self.assertEqual(m1[0], ord(b'1'))
4103
Stefan Krah4e99a312012-03-05 09:30:47 +01004104 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4105 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4106 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4107 self.assertIs(z.obj, x)
4108 with memoryview(z) as m:
4109 catch22(m)
4110 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4111
4112 # Test garbage collection.
4113 for flags in (0, ND_REDIRECT):
4114 x = bytearray(b'123')
4115 with memoryview(x) as m1:
4116 del x
4117 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4118 with memoryview(y) as m2:
4119 del y
4120 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4121 with memoryview(z) as m3:
4122 del z
4123 catch22(m3)
4124 catch22(m2)
4125 catch22(m1)
4126 self.assertEqual(m1[0], ord(b'1'))
4127 self.assertEqual(m2[1], ord(b'2'))
4128 self.assertEqual(m3[2], ord(b'3'))
4129 del m3
4130 del m2
4131 del m1
4132
4133 x = bytearray(b'123')
4134 with memoryview(x) as m1:
4135 del x
4136 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4137 with memoryview(y) as m2:
4138 del y
4139 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4140 with memoryview(z) as m3:
4141 del z
4142 catch22(m1)
4143 catch22(m2)
4144 catch22(m3)
4145 self.assertEqual(m1[0], ord(b'1'))
4146 self.assertEqual(m2[1], ord(b'2'))
4147 self.assertEqual(m3[2], ord(b'3'))
4148 del m1, m2, m3
4149
Stefan Krahfcbb4162012-03-05 10:45:31 +01004150 # memoryview.release() fails if the view has exported buffers.
4151 x = bytearray(b'123')
4152 with self.assertRaises(BufferError):
4153 with memoryview(x) as m:
4154 ex = ndarray(m)
4155 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004156
Stefan Krah4e99a312012-03-05 09:30:47 +01004157 def test_memoryview_redirect(self):
4158
4159 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4160 a = array.array('d', [1.0 * x for x in range(12)])
4161
4162 for x in (nd, a):
4163 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4164 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4165 m = memoryview(z)
4166
4167 self.assertIs(y.obj, x)
4168 self.assertIs(z.obj, x)
4169 self.assertIs(m.obj, x)
4170
4171 self.assertEqual(m, x)
4172 self.assertEqual(m, y)
4173 self.assertEqual(m, z)
4174
4175 self.assertEqual(m[1:3], x[1:3])
4176 self.assertEqual(m[1:3], y[1:3])
4177 self.assertEqual(m[1:3], z[1:3])
4178 del y, z
4179 self.assertEqual(m[1:3], x[1:3])
4180
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004181 def test_memoryview_from_static_exporter(self):
4182
4183 fmt = 'B'
4184 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4185
4186 # exceptions
4187 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4188
4189 # view.obj==x
4190 x = staticarray()
4191 y = memoryview(x)
4192 self.verify(y, obj=x,
4193 itemsize=1, fmt=fmt, readonly=1,
4194 ndim=1, shape=[12], strides=[1],
4195 lst=lst)
4196 for i in range(12):
4197 self.assertEqual(y[i], i)
4198 del x
4199 del y
4200
4201 x = staticarray()
4202 y = memoryview(x)
4203 del y
4204 del x
4205
4206 x = staticarray()
4207 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4208 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4209 m = memoryview(z)
4210 self.assertIs(y.obj, x)
4211 self.assertIs(m.obj, z)
4212 self.verify(m, obj=z,
4213 itemsize=1, fmt=fmt, readonly=1,
4214 ndim=1, shape=[12], strides=[1],
4215 lst=lst)
4216 del x, y, z, m
4217
4218 x = staticarray()
4219 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4220 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4221 m = memoryview(z)
4222 self.assertIs(y.obj, x)
4223 self.assertIs(z.obj, x)
4224 self.assertIs(m.obj, x)
4225 self.verify(m, obj=x,
4226 itemsize=1, fmt=fmt, readonly=1,
4227 ndim=1, shape=[12], strides=[1],
4228 lst=lst)
4229 del x, y, z, m
4230
4231 # view.obj==NULL
4232 x = staticarray(legacy_mode=True)
4233 y = memoryview(x)
4234 self.verify(y, obj=None,
4235 itemsize=1, fmt=fmt, readonly=1,
4236 ndim=1, shape=[12], strides=[1],
4237 lst=lst)
4238 for i in range(12):
4239 self.assertEqual(y[i], i)
4240 del x
4241 del y
4242
4243 x = staticarray(legacy_mode=True)
4244 y = memoryview(x)
4245 del y
4246 del x
4247
4248 x = staticarray(legacy_mode=True)
4249 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4250 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4251 m = memoryview(z)
4252 self.assertIs(y.obj, None)
4253 self.assertIs(m.obj, z)
4254 self.verify(m, obj=z,
4255 itemsize=1, fmt=fmt, readonly=1,
4256 ndim=1, shape=[12], strides=[1],
4257 lst=lst)
4258 del x, y, z, m
4259
4260 x = staticarray(legacy_mode=True)
4261 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4262 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4263 m = memoryview(z)
4264 # Clearly setting view.obj==NULL is inferior, since it
4265 # messes up the redirection chain:
4266 self.assertIs(y.obj, None)
4267 self.assertIs(z.obj, y)
4268 self.assertIs(m.obj, y)
4269 self.verify(m, obj=y,
4270 itemsize=1, fmt=fmt, readonly=1,
4271 ndim=1, shape=[12], strides=[1],
4272 lst=lst)
4273 del x, y, z, m
4274
Stefan Krah1649c1b2012-03-05 17:45:17 +01004275 def test_memoryview_getbuffer_undefined(self):
4276
4277 # getbufferproc does not adhere to the new documentation
4278 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4279 self.assertRaises(BufferError, memoryview, nd)
4280
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004281 def test_issue_7385(self):
4282 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4283 self.assertRaises(BufferError, memoryview, x)
4284
4285
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004286if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004287 unittest.main()