blob: d921a5aacc93bb20c11a36f4dc56959e3e342c1b [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':
Raymond Hettingerbb6c0aa2014-11-22 22:14:41 -0800219 return
Stefan Krah9a2d99e2012-02-25 12:24:21 +0100220 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),
Stefan Krah363af442015-02-01 14:53:54 +01001010 ([1,3,1], [], 0),
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001011 ([12], [], 0),
1012 ([12], [-1], 11),
1013 ([6], [2], 0),
1014 ([6], [-2], 11),
1015 ([3, 4], [], 0),
1016 ([3, 4], [-4, -1], 11),
1017 ([2, 2], [4, 1], 4),
1018 ([2, 2], [-4, -1], 8)
1019 )
1020 # ndarray creation flags
1021 ndflags = (
1022 0, ND_WRITABLE, ND_FORTRAN, ND_FORTRAN|ND_WRITABLE,
1023 ND_PIL, ND_PIL|ND_WRITABLE
1024 )
1025 # flags that can actually be used as flags
1026 real_flags = (0, PyBUF_WRITABLE, PyBUF_FORMAT,
1027 PyBUF_WRITABLE|PyBUF_FORMAT)
1028
1029 for items, fmt in items_fmt:
1030 itemsize = struct.calcsize(fmt)
1031 for shape, strides, offset in structure:
1032 strides = [v * itemsize for v in strides]
1033 offset *= itemsize
1034 for flags in ndflags:
1035
1036 if strides and (flags&ND_FORTRAN):
1037 continue
1038 if not shape and (flags&ND_PIL):
1039 continue
1040
1041 _items = items if shape else items[0]
1042 ex1 = ndarray(_items, format=fmt, flags=flags,
1043 shape=shape, strides=strides, offset=offset)
1044 ex2 = ex1[::-2] if shape else None
1045
1046 m1 = memoryview(ex1)
1047 if ex2:
1048 m2 = memoryview(ex2)
1049 if ex1.ndim == 0 or (ex1.ndim == 1 and shape and strides):
1050 self.assertEqual(m1, ex1)
1051 if ex2 and ex2.ndim == 1 and shape and strides:
1052 self.assertEqual(m2, ex2)
1053
1054 for req in requests:
1055 for bits in real_flags:
1056 self.verify_getbuf(ex1, ex1, req|bits)
1057 self.verify_getbuf(ex1, m1, req|bits)
1058 if ex2:
1059 self.verify_getbuf(ex2, ex2, req|bits,
1060 sliced=True)
1061 self.verify_getbuf(ex2, m2, req|bits,
1062 sliced=True)
1063
1064 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1065
1066 # ND_GETBUF_FAIL
1067 ex = ndarray(items, shape=[12], flags=ND_GETBUF_FAIL)
1068 self.assertRaises(BufferError, ndarray, ex)
1069
1070 # Request complex structure from a simple exporter. In this
1071 # particular case the test object is not PEP-3118 compliant.
1072 base = ndarray([9], [1])
1073 ex = ndarray(base, getbuf=PyBUF_SIMPLE)
1074 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_WRITABLE)
1075 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ND)
1076 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_STRIDES)
1077 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_C_CONTIGUOUS)
1078 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_F_CONTIGUOUS)
1079 self.assertRaises(BufferError, ndarray, ex, getbuf=PyBUF_ANY_CONTIGUOUS)
1080 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1081
Stefan Krah363af442015-02-01 14:53:54 +01001082 # Issue #22445: New precise contiguity definition.
1083 for shape in [1,12,1], [7,0,7]:
1084 for order in 0, ND_FORTRAN:
1085 ex = ndarray(items, shape=shape, flags=order|ND_WRITABLE)
1086 self.assertTrue(is_contiguous(ex, 'F'))
1087 self.assertTrue(is_contiguous(ex, 'C'))
1088
1089 for flags in requests:
1090 nd = ndarray(ex, getbuf=flags)
1091 self.assertTrue(is_contiguous(nd, 'F'))
1092 self.assertTrue(is_contiguous(nd, 'C'))
1093
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001094 def test_ndarray_exceptions(self):
1095 nd = ndarray([9], [1])
1096 ndm = ndarray([9], [1], flags=ND_VAREXPORT)
1097
1098 # Initialization of a new ndarray or mutation of an existing array.
1099 for c in (ndarray, nd.push, ndm.push):
1100 # Invalid types.
1101 self.assertRaises(TypeError, c, {1,2,3})
1102 self.assertRaises(TypeError, c, [1,2,'3'])
1103 self.assertRaises(TypeError, c, [1,2,(3,4)])
1104 self.assertRaises(TypeError, c, [1,2,3], shape={3})
1105 self.assertRaises(TypeError, c, [1,2,3], shape=[3], strides={1})
1106 self.assertRaises(TypeError, c, [1,2,3], shape=[3], offset=[])
1107 self.assertRaises(TypeError, c, [1], shape=[1], format={})
1108 self.assertRaises(TypeError, c, [1], shape=[1], flags={})
1109 self.assertRaises(TypeError, c, [1], shape=[1], getbuf={})
1110
1111 # ND_FORTRAN flag is only valid without strides.
1112 self.assertRaises(TypeError, c, [1], shape=[1], strides=[1],
1113 flags=ND_FORTRAN)
1114
1115 # ND_PIL flag is only valid with ndim > 0.
1116 self.assertRaises(TypeError, c, [1], shape=[], flags=ND_PIL)
1117
1118 # Invalid items.
1119 self.assertRaises(ValueError, c, [], shape=[1])
1120 self.assertRaises(ValueError, c, ['XXX'], shape=[1], format="L")
1121 # Invalid combination of items and format.
1122 self.assertRaises(struct.error, c, [1000], shape=[1], format="B")
1123 self.assertRaises(ValueError, c, [1,(2,3)], shape=[2], format="B")
1124 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="QL")
1125
1126 # Invalid ndim.
1127 n = ND_MAX_NDIM+1
1128 self.assertRaises(ValueError, c, [1]*n, shape=[1]*n)
1129
1130 # Invalid shape.
1131 self.assertRaises(ValueError, c, [1], shape=[-1])
1132 self.assertRaises(ValueError, c, [1,2,3], shape=['3'])
1133 self.assertRaises(OverflowError, c, [1], shape=[2**128])
1134 # prod(shape) * itemsize != len(items)
1135 self.assertRaises(ValueError, c, [1,2,3,4,5], shape=[2,2], offset=3)
1136
1137 # Invalid strides.
1138 self.assertRaises(ValueError, c, [1,2,3], shape=[3], strides=['1'])
1139 self.assertRaises(OverflowError, c, [1], shape=[1],
1140 strides=[2**128])
1141
1142 # Invalid combination of strides and shape.
1143 self.assertRaises(ValueError, c, [1,2], shape=[2,1], strides=[1])
1144 # Invalid combination of strides and format.
1145 self.assertRaises(ValueError, c, [1,2,3,4], shape=[2], strides=[3],
1146 format="L")
1147
1148 # Invalid offset.
1149 self.assertRaises(ValueError, c, [1,2,3], shape=[3], offset=4)
1150 self.assertRaises(ValueError, c, [1,2,3], shape=[1], offset=3,
1151 format="L")
1152
1153 # Invalid format.
1154 self.assertRaises(ValueError, c, [1,2,3], shape=[3], format="")
1155 self.assertRaises(struct.error, c, [(1,2,3)], shape=[1],
1156 format="@#$")
1157
1158 # Striding out of the memory bounds.
1159 items = [1,2,3,4,5,6,7,8,9,10]
1160 self.assertRaises(ValueError, c, items, shape=[2,3],
1161 strides=[-3, -2], offset=5)
1162
1163 # Constructing consumer: format argument invalid.
1164 self.assertRaises(TypeError, c, bytearray(), format="Q")
1165
1166 # Constructing original base object: getbuf argument invalid.
1167 self.assertRaises(TypeError, c, [1], shape=[1], getbuf=PyBUF_FULL)
1168
1169 # Shape argument is mandatory for original base objects.
1170 self.assertRaises(TypeError, c, [1])
1171
1172
1173 # PyBUF_WRITABLE request to read-only provider.
1174 self.assertRaises(BufferError, ndarray, b'123', getbuf=PyBUF_WRITABLE)
1175
1176 # ND_VAREXPORT can only be specified during construction.
1177 nd = ndarray([9], [1], flags=ND_VAREXPORT)
1178 self.assertRaises(ValueError, nd.push, [1], [1], flags=ND_VAREXPORT)
1179
1180 # Invalid operation for consumers: push/pop
1181 nd = ndarray(b'123')
1182 self.assertRaises(BufferError, nd.push, [1], [1])
1183 self.assertRaises(BufferError, nd.pop)
1184
1185 # ND_VAREXPORT not set: push/pop fail with exported buffers
1186 nd = ndarray([9], [1])
1187 nd.push([1], [1])
1188 m = memoryview(nd)
1189 self.assertRaises(BufferError, nd.push, [1], [1])
1190 self.assertRaises(BufferError, nd.pop)
1191 m.release()
1192 nd.pop()
1193
1194 # Single remaining buffer: pop fails
1195 self.assertRaises(BufferError, nd.pop)
1196 del nd
1197
1198 # get_pointer()
1199 self.assertRaises(TypeError, get_pointer, {}, [1,2,3])
1200 self.assertRaises(TypeError, get_pointer, b'123', {})
1201
1202 nd = ndarray(list(range(100)), shape=[1]*100)
1203 self.assertRaises(ValueError, get_pointer, nd, [5])
1204
1205 nd = ndarray(list(range(12)), shape=[3,4])
1206 self.assertRaises(ValueError, get_pointer, nd, [2,3,4])
1207 self.assertRaises(ValueError, get_pointer, nd, [3,3])
1208 self.assertRaises(ValueError, get_pointer, nd, [-3,3])
1209 self.assertRaises(OverflowError, get_pointer, nd, [1<<64,3])
1210
1211 # tolist() needs format
1212 ex = ndarray([1,2,3], shape=[3], format='L')
1213 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1214 self.assertRaises(ValueError, nd.tolist)
1215
1216 # memoryview_from_buffer()
1217 ex1 = ndarray([1,2,3], shape=[3], format='L')
1218 ex2 = ndarray(ex1)
1219 nd = ndarray(ex2)
1220 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1221
1222 nd = ndarray([(1,)*200], shape=[1], format='L'*200)
1223 self.assertRaises(TypeError, nd.memoryview_from_buffer)
1224
1225 n = ND_MAX_NDIM
1226 nd = ndarray(list(range(n)), shape=[1]*n)
1227 self.assertRaises(ValueError, nd.memoryview_from_buffer)
1228
1229 # get_contiguous()
1230 nd = ndarray([1], shape=[1])
1231 self.assertRaises(TypeError, get_contiguous, 1, 2, 3, 4, 5)
1232 self.assertRaises(TypeError, get_contiguous, nd, "xyz", 'C')
1233 self.assertRaises(OverflowError, get_contiguous, nd, 2**64, 'C')
1234 self.assertRaises(TypeError, get_contiguous, nd, PyBUF_READ, 961)
1235 self.assertRaises(UnicodeEncodeError, get_contiguous, nd, PyBUF_READ,
1236 '\u2007')
Stefan Krah66e63172012-08-23 15:53:45 +02001237 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'Z')
1238 self.assertRaises(ValueError, get_contiguous, nd, 255, 'A')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01001239
1240 # cmp_contig()
1241 nd = ndarray([1], shape=[1])
1242 self.assertRaises(TypeError, cmp_contig, 1, 2, 3, 4, 5)
1243 self.assertRaises(TypeError, cmp_contig, {}, nd)
1244 self.assertRaises(TypeError, cmp_contig, nd, {})
1245
1246 # is_contiguous()
1247 nd = ndarray([1], shape=[1])
1248 self.assertRaises(TypeError, is_contiguous, 1, 2, 3, 4, 5)
1249 self.assertRaises(TypeError, is_contiguous, {}, 'A')
1250 self.assertRaises(TypeError, is_contiguous, nd, 201)
1251
1252 def test_ndarray_linked_list(self):
1253 for perm in permutations(range(5)):
1254 m = [0]*5
1255 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
1256 m[0] = memoryview(nd)
1257
1258 for i in range(1, 5):
1259 nd.push([1,2,3], shape=[3])
1260 m[i] = memoryview(nd)
1261
1262 for i in range(5):
1263 m[perm[i]].release()
1264
1265 self.assertRaises(BufferError, nd.pop)
1266 del nd
1267
1268 def test_ndarray_format_scalar(self):
1269 # ndim = 0: scalar
1270 for fmt, scalar, _ in iter_format(0):
1271 itemsize = struct.calcsize(fmt)
1272 nd = ndarray(scalar, shape=(), format=fmt)
1273 self.verify(nd, obj=None,
1274 itemsize=itemsize, fmt=fmt, readonly=1,
1275 ndim=0, shape=(), strides=(),
1276 lst=scalar)
1277
1278 def test_ndarray_format_shape(self):
1279 # ndim = 1, shape = [n]
1280 nitems = randrange(1, 10)
1281 for fmt, items, _ in iter_format(nitems):
1282 itemsize = struct.calcsize(fmt)
1283 for flags in (0, ND_PIL):
1284 nd = ndarray(items, shape=[nitems], format=fmt, flags=flags)
1285 self.verify(nd, obj=None,
1286 itemsize=itemsize, fmt=fmt, readonly=1,
1287 ndim=1, shape=(nitems,), strides=(itemsize,),
1288 lst=items)
1289
1290 def test_ndarray_format_strides(self):
1291 # ndim = 1, strides
1292 nitems = randrange(1, 30)
1293 for fmt, items, _ in iter_format(nitems):
1294 itemsize = struct.calcsize(fmt)
1295 for step in range(-5, 5):
1296 if step == 0:
1297 continue
1298
1299 shape = [len(items[::step])]
1300 strides = [step*itemsize]
1301 offset = itemsize*(nitems-1) if step < 0 else 0
1302
1303 for flags in (0, ND_PIL):
1304 nd = ndarray(items, shape=shape, strides=strides,
1305 format=fmt, offset=offset, flags=flags)
1306 self.verify(nd, obj=None,
1307 itemsize=itemsize, fmt=fmt, readonly=1,
1308 ndim=1, shape=shape, strides=strides,
1309 lst=items[::step])
1310
1311 def test_ndarray_fortran(self):
1312 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1313 ex = ndarray(items, shape=(3, 4), strides=(1, 3))
1314 nd = ndarray(ex, getbuf=PyBUF_F_CONTIGUOUS|PyBUF_FORMAT)
1315 self.assertEqual(nd.tolist(), farray(items, (3, 4)))
1316
1317 def test_ndarray_multidim(self):
1318 for ndim in range(5):
1319 shape_t = [randrange(2, 10) for _ in range(ndim)]
1320 nitems = prod(shape_t)
1321 for shape in permutations(shape_t):
1322
1323 fmt, items, _ = randitems(nitems)
1324 itemsize = struct.calcsize(fmt)
1325
1326 for flags in (0, ND_PIL):
1327 if ndim == 0 and flags == ND_PIL:
1328 continue
1329
1330 # C array
1331 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1332
1333 strides = strides_from_shape(ndim, shape, itemsize, 'C')
1334 lst = carray(items, shape)
1335 self.verify(nd, obj=None,
1336 itemsize=itemsize, fmt=fmt, readonly=1,
1337 ndim=ndim, shape=shape, strides=strides,
1338 lst=lst)
1339
1340 if is_memoryview_format(fmt):
1341 # memoryview: reconstruct strides
1342 ex = ndarray(items, shape=shape, format=fmt)
1343 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
1344 self.assertTrue(nd.strides == ())
1345 mv = nd.memoryview_from_buffer()
1346 self.verify(mv, obj=None,
1347 itemsize=itemsize, fmt=fmt, readonly=1,
1348 ndim=ndim, shape=shape, strides=strides,
1349 lst=lst)
1350
1351 # Fortran array
1352 nd = ndarray(items, shape=shape, format=fmt,
1353 flags=flags|ND_FORTRAN)
1354
1355 strides = strides_from_shape(ndim, shape, itemsize, 'F')
1356 lst = farray(items, shape)
1357 self.verify(nd, obj=None,
1358 itemsize=itemsize, fmt=fmt, readonly=1,
1359 ndim=ndim, shape=shape, strides=strides,
1360 lst=lst)
1361
1362 def test_ndarray_index_invalid(self):
1363 # not writable
1364 nd = ndarray([1], shape=[1])
1365 self.assertRaises(TypeError, nd.__setitem__, 1, 8)
1366 mv = memoryview(nd)
1367 self.assertEqual(mv, nd)
1368 self.assertRaises(TypeError, mv.__setitem__, 1, 8)
1369
1370 # cannot be deleted
1371 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1372 self.assertRaises(TypeError, nd.__delitem__, 1)
1373 mv = memoryview(nd)
1374 self.assertEqual(mv, nd)
1375 self.assertRaises(TypeError, mv.__delitem__, 1)
1376
1377 # overflow
1378 nd = ndarray([1], shape=[1], flags=ND_WRITABLE)
1379 self.assertRaises(OverflowError, nd.__getitem__, 1<<64)
1380 self.assertRaises(OverflowError, nd.__setitem__, 1<<64, 8)
1381 mv = memoryview(nd)
1382 self.assertEqual(mv, nd)
1383 self.assertRaises(IndexError, mv.__getitem__, 1<<64)
1384 self.assertRaises(IndexError, mv.__setitem__, 1<<64, 8)
1385
1386 # format
1387 items = [1,2,3,4,5,6,7,8]
1388 nd = ndarray(items, shape=[len(items)], format="B", flags=ND_WRITABLE)
1389 self.assertRaises(struct.error, nd.__setitem__, 2, 300)
1390 self.assertRaises(ValueError, nd.__setitem__, 1, (100, 200))
1391 mv = memoryview(nd)
1392 self.assertEqual(mv, nd)
1393 self.assertRaises(ValueError, mv.__setitem__, 2, 300)
1394 self.assertRaises(TypeError, mv.__setitem__, 1, (100, 200))
1395
1396 items = [(1,2), (3,4), (5,6)]
1397 nd = ndarray(items, shape=[len(items)], format="LQ", flags=ND_WRITABLE)
1398 self.assertRaises(ValueError, nd.__setitem__, 2, 300)
1399 self.assertRaises(struct.error, nd.__setitem__, 1, (b'\x001', 200))
1400
1401 def test_ndarray_index_scalar(self):
1402 # scalar
1403 nd = ndarray(1, shape=(), flags=ND_WRITABLE)
1404 mv = memoryview(nd)
1405 self.assertEqual(mv, nd)
1406
1407 x = nd[()]; self.assertEqual(x, 1)
1408 x = nd[...]; self.assertEqual(x.tolist(), nd.tolist())
1409
1410 x = mv[()]; self.assertEqual(x, 1)
1411 x = mv[...]; self.assertEqual(x.tolist(), nd.tolist())
1412
1413 self.assertRaises(TypeError, nd.__getitem__, 0)
1414 self.assertRaises(TypeError, mv.__getitem__, 0)
1415 self.assertRaises(TypeError, nd.__setitem__, 0, 8)
1416 self.assertRaises(TypeError, mv.__setitem__, 0, 8)
1417
1418 self.assertEqual(nd.tolist(), 1)
1419 self.assertEqual(mv.tolist(), 1)
1420
1421 nd[()] = 9; self.assertEqual(nd.tolist(), 9)
1422 mv[()] = 9; self.assertEqual(mv.tolist(), 9)
1423
1424 nd[...] = 5; self.assertEqual(nd.tolist(), 5)
1425 mv[...] = 5; self.assertEqual(mv.tolist(), 5)
1426
1427 def test_ndarray_index_null_strides(self):
1428 ex = ndarray(list(range(2*4)), shape=[2, 4], flags=ND_WRITABLE)
1429 nd = ndarray(ex, getbuf=PyBUF_CONTIG)
1430
1431 # Sub-views are only possible for full exporters.
1432 self.assertRaises(BufferError, nd.__getitem__, 1)
1433 # Same for slices.
1434 self.assertRaises(BufferError, nd.__getitem__, slice(3,5,1))
1435
1436 def test_ndarray_index_getitem_single(self):
1437 # getitem
1438 for fmt, items, _ in iter_format(5):
1439 nd = ndarray(items, shape=[5], format=fmt)
1440 for i in range(-5, 5):
1441 self.assertEqual(nd[i], items[i])
1442
1443 self.assertRaises(IndexError, nd.__getitem__, -6)
1444 self.assertRaises(IndexError, nd.__getitem__, 5)
1445
1446 if is_memoryview_format(fmt):
1447 mv = memoryview(nd)
1448 self.assertEqual(mv, nd)
1449 for i in range(-5, 5):
1450 self.assertEqual(mv[i], items[i])
1451
1452 self.assertRaises(IndexError, mv.__getitem__, -6)
1453 self.assertRaises(IndexError, mv.__getitem__, 5)
1454
1455 # getitem with null strides
1456 for fmt, items, _ in iter_format(5):
1457 ex = ndarray(items, shape=[5], flags=ND_WRITABLE, format=fmt)
1458 nd = ndarray(ex, getbuf=PyBUF_CONTIG|PyBUF_FORMAT)
1459
1460 for i in range(-5, 5):
1461 self.assertEqual(nd[i], items[i])
1462
1463 if is_memoryview_format(fmt):
1464 mv = nd.memoryview_from_buffer()
1465 self.assertIs(mv.__eq__(nd), NotImplemented)
1466 for i in range(-5, 5):
1467 self.assertEqual(mv[i], items[i])
1468
1469 # getitem with null format
1470 items = [1,2,3,4,5]
1471 ex = ndarray(items, shape=[5])
1472 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO)
1473 for i in range(-5, 5):
1474 self.assertEqual(nd[i], items[i])
1475
1476 # getitem with null shape/strides/format
1477 items = [1,2,3,4,5]
1478 ex = ndarray(items, shape=[5])
1479 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
1480
1481 for i in range(-5, 5):
1482 self.assertEqual(nd[i], items[i])
1483
1484 def test_ndarray_index_setitem_single(self):
1485 # assign single value
1486 for fmt, items, single_item in iter_format(5):
1487 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1488 for i in range(5):
1489 items[i] = single_item
1490 nd[i] = single_item
1491 self.assertEqual(nd.tolist(), items)
1492
1493 self.assertRaises(IndexError, nd.__setitem__, -6, single_item)
1494 self.assertRaises(IndexError, nd.__setitem__, 5, single_item)
1495
1496 if not is_memoryview_format(fmt):
1497 continue
1498
1499 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1500 mv = memoryview(nd)
1501 self.assertEqual(mv, nd)
1502 for i in range(5):
1503 items[i] = single_item
1504 mv[i] = single_item
1505 self.assertEqual(mv.tolist(), items)
1506
1507 self.assertRaises(IndexError, mv.__setitem__, -6, single_item)
1508 self.assertRaises(IndexError, mv.__setitem__, 5, single_item)
1509
1510
1511 # assign single value: lobject = robject
1512 for fmt, items, single_item in iter_format(5):
1513 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1514 for i in range(-5, 4):
1515 items[i] = items[i+1]
1516 nd[i] = nd[i+1]
1517 self.assertEqual(nd.tolist(), items)
1518
1519 if not is_memoryview_format(fmt):
1520 continue
1521
1522 nd = ndarray(items, shape=[5], format=fmt, flags=ND_WRITABLE)
1523 mv = memoryview(nd)
1524 self.assertEqual(mv, nd)
1525 for i in range(-5, 4):
1526 items[i] = items[i+1]
1527 mv[i] = mv[i+1]
1528 self.assertEqual(mv.tolist(), items)
1529
1530 def test_ndarray_index_getitem_multidim(self):
1531 shape_t = (2, 3, 5)
1532 nitems = prod(shape_t)
1533 for shape in permutations(shape_t):
1534
1535 fmt, items, _ = randitems(nitems)
1536
1537 for flags in (0, ND_PIL):
1538 # C array
1539 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1540 lst = carray(items, shape)
1541
1542 for i in range(-shape[0], shape[0]):
1543 self.assertEqual(lst[i], nd[i].tolist())
1544 for j in range(-shape[1], shape[1]):
1545 self.assertEqual(lst[i][j], nd[i][j].tolist())
1546 for k in range(-shape[2], shape[2]):
1547 self.assertEqual(lst[i][j][k], nd[i][j][k])
1548
1549 # Fortran array
1550 nd = ndarray(items, shape=shape, format=fmt,
1551 flags=flags|ND_FORTRAN)
1552 lst = farray(items, shape)
1553
1554 for i in range(-shape[0], shape[0]):
1555 self.assertEqual(lst[i], nd[i].tolist())
1556 for j in range(-shape[1], shape[1]):
1557 self.assertEqual(lst[i][j], nd[i][j].tolist())
1558 for k in range(shape[2], shape[2]):
1559 self.assertEqual(lst[i][j][k], nd[i][j][k])
1560
1561 def test_ndarray_sequence(self):
1562 nd = ndarray(1, shape=())
1563 self.assertRaises(TypeError, eval, "1 in nd", locals())
1564 mv = memoryview(nd)
1565 self.assertEqual(mv, nd)
1566 self.assertRaises(TypeError, eval, "1 in mv", locals())
1567
1568 for fmt, items, _ in iter_format(5):
1569 nd = ndarray(items, shape=[5], format=fmt)
1570 for i, v in enumerate(nd):
1571 self.assertEqual(v, items[i])
1572 self.assertTrue(v in nd)
1573
1574 if is_memoryview_format(fmt):
1575 mv = memoryview(nd)
1576 for i, v in enumerate(mv):
1577 self.assertEqual(v, items[i])
1578 self.assertTrue(v in mv)
1579
1580 def test_ndarray_slice_invalid(self):
1581 items = [1,2,3,4,5,6,7,8]
1582
1583 # rvalue is not an exporter
1584 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1585 ml = memoryview(xl)
1586 self.assertRaises(TypeError, xl.__setitem__, slice(0,8,1), items)
1587 self.assertRaises(TypeError, ml.__setitem__, slice(0,8,1), items)
1588
1589 # rvalue is not a full exporter
1590 xl = ndarray(items, shape=[8], flags=ND_WRITABLE)
1591 ex = ndarray(items, shape=[8], flags=ND_WRITABLE)
1592 xr = ndarray(ex, getbuf=PyBUF_ND)
1593 self.assertRaises(BufferError, xl.__setitem__, slice(0,8,1), xr)
1594
1595 # zero step
1596 nd = ndarray(items, shape=[8], format="L", flags=ND_WRITABLE)
1597 mv = memoryview(nd)
1598 self.assertRaises(ValueError, nd.__getitem__, slice(0,1,0))
1599 self.assertRaises(ValueError, mv.__getitem__, slice(0,1,0))
1600
1601 nd = ndarray(items, shape=[2,4], format="L", flags=ND_WRITABLE)
1602 mv = memoryview(nd)
1603
1604 self.assertRaises(ValueError, nd.__getitem__,
1605 (slice(0,1,1), slice(0,1,0)))
1606 self.assertRaises(ValueError, nd.__getitem__,
1607 (slice(0,1,0), slice(0,1,1)))
1608 self.assertRaises(TypeError, nd.__getitem__, "@%$")
1609 self.assertRaises(TypeError, nd.__getitem__, ("@%$", slice(0,1,1)))
1610 self.assertRaises(TypeError, nd.__getitem__, (slice(0,1,1), {}))
1611
1612 # memoryview: not implemented
1613 self.assertRaises(NotImplementedError, mv.__getitem__,
1614 (slice(0,1,1), slice(0,1,0)))
1615 self.assertRaises(TypeError, mv.__getitem__, "@%$")
1616
1617 # differing format
1618 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1619 xr = ndarray(items, shape=[8], format="b")
1620 ml = memoryview(xl)
1621 mr = memoryview(xr)
1622 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1623 self.assertEqual(xl.tolist(), items)
1624 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1625 self.assertEqual(ml.tolist(), items)
1626
1627 # differing itemsize
1628 xl = ndarray(items, shape=[8], format="B", flags=ND_WRITABLE)
1629 yr = ndarray(items, shape=[8], format="L")
1630 ml = memoryview(xl)
1631 mr = memoryview(xr)
1632 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1633 self.assertEqual(xl.tolist(), items)
1634 self.assertRaises(ValueError, ml.__setitem__, slice(0,1,1), mr[7:8])
1635 self.assertEqual(ml.tolist(), items)
1636
1637 # differing ndim
1638 xl = ndarray(items, shape=[2, 4], format="b", flags=ND_WRITABLE)
1639 xr = ndarray(items, shape=[8], format="b")
1640 ml = memoryview(xl)
1641 mr = memoryview(xr)
1642 self.assertRaises(ValueError, xl.__setitem__, slice(0,1,1), xr[7:8])
1643 self.assertEqual(xl.tolist(), [[1,2,3,4], [5,6,7,8]])
1644 self.assertRaises(NotImplementedError, ml.__setitem__, slice(0,1,1),
1645 mr[7:8])
1646
1647 # differing shape
1648 xl = ndarray(items, shape=[8], format="b", flags=ND_WRITABLE)
1649 xr = ndarray(items, shape=[8], format="b")
1650 ml = memoryview(xl)
1651 mr = memoryview(xr)
1652 self.assertRaises(ValueError, xl.__setitem__, slice(0,2,1), xr[7:8])
1653 self.assertEqual(xl.tolist(), items)
1654 self.assertRaises(ValueError, ml.__setitem__, slice(0,2,1), mr[7:8])
1655 self.assertEqual(ml.tolist(), items)
1656
1657 # _testbuffer.c module functions
1658 self.assertRaises(TypeError, slice_indices, slice(0,1,2), {})
1659 self.assertRaises(TypeError, slice_indices, "###########", 1)
1660 self.assertRaises(ValueError, slice_indices, slice(0,1,0), 4)
1661
1662 x = ndarray(items, shape=[8], format="b", flags=ND_PIL)
1663 self.assertRaises(TypeError, x.add_suboffsets)
1664
1665 ex = ndarray(items, shape=[8], format="B")
1666 x = ndarray(ex, getbuf=PyBUF_SIMPLE)
1667 self.assertRaises(TypeError, x.add_suboffsets)
1668
1669 def test_ndarray_slice_zero_shape(self):
1670 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1671
1672 x = ndarray(items, shape=[12], format="L", flags=ND_WRITABLE)
1673 y = ndarray(items, shape=[12], format="L")
1674 x[4:4] = y[9:9]
1675 self.assertEqual(x.tolist(), items)
1676
1677 ml = memoryview(x)
1678 mr = memoryview(y)
1679 self.assertEqual(ml, x)
1680 self.assertEqual(ml, y)
1681 ml[4:4] = mr[9:9]
1682 self.assertEqual(ml.tolist(), items)
1683
1684 x = ndarray(items, shape=[3, 4], format="L", flags=ND_WRITABLE)
1685 y = ndarray(items, shape=[4, 3], format="L")
1686 x[1:2, 2:2] = y[1:2, 3:3]
1687 self.assertEqual(x.tolist(), carray(items, [3, 4]))
1688
1689 def test_ndarray_slice_multidim(self):
1690 shape_t = (2, 3, 5)
1691 ndim = len(shape_t)
1692 nitems = prod(shape_t)
1693 for shape in permutations(shape_t):
1694
1695 fmt, items, _ = randitems(nitems)
1696 itemsize = struct.calcsize(fmt)
1697
1698 for flags in (0, ND_PIL):
1699 nd = ndarray(items, shape=shape, format=fmt, flags=flags)
1700 lst = carray(items, shape)
1701
1702 for slices in rslices_ndim(ndim, shape):
1703
1704 listerr = None
1705 try:
1706 sliced = multislice(lst, slices)
1707 except Exception as e:
1708 listerr = e.__class__
1709
1710 nderr = None
1711 try:
1712 ndsliced = nd[slices]
1713 except Exception as e:
1714 nderr = e.__class__
1715
1716 if nderr or listerr:
1717 self.assertIs(nderr, listerr)
1718 else:
1719 self.assertEqual(ndsliced.tolist(), sliced)
1720
1721 def test_ndarray_slice_redundant_suboffsets(self):
1722 shape_t = (2, 3, 5, 2)
1723 ndim = len(shape_t)
1724 nitems = prod(shape_t)
1725 for shape in permutations(shape_t):
1726
1727 fmt, items, _ = randitems(nitems)
1728 itemsize = struct.calcsize(fmt)
1729
1730 nd = ndarray(items, shape=shape, format=fmt)
1731 nd.add_suboffsets()
1732 ex = ndarray(items, shape=shape, format=fmt)
1733 ex.add_suboffsets()
1734 mv = memoryview(ex)
1735 lst = carray(items, shape)
1736
1737 for slices in rslices_ndim(ndim, shape):
1738
1739 listerr = None
1740 try:
1741 sliced = multislice(lst, slices)
1742 except Exception as e:
1743 listerr = e.__class__
1744
1745 nderr = None
1746 try:
1747 ndsliced = nd[slices]
1748 except Exception as e:
1749 nderr = e.__class__
1750
1751 if nderr or listerr:
1752 self.assertIs(nderr, listerr)
1753 else:
1754 self.assertEqual(ndsliced.tolist(), sliced)
1755
1756 def test_ndarray_slice_assign_single(self):
1757 for fmt, items, _ in iter_format(5):
1758 for lslice in genslices(5):
1759 for rslice in genslices(5):
1760 for flags in (0, ND_PIL):
1761
1762 f = flags|ND_WRITABLE
1763 nd = ndarray(items, shape=[5], format=fmt, flags=f)
1764 ex = ndarray(items, shape=[5], format=fmt, flags=f)
1765 mv = memoryview(ex)
1766
1767 lsterr = None
1768 diff_structure = None
1769 lst = items[:]
1770 try:
1771 lval = lst[lslice]
1772 rval = lst[rslice]
1773 lst[lslice] = lst[rslice]
1774 diff_structure = len(lval) != len(rval)
1775 except Exception as e:
1776 lsterr = e.__class__
1777
1778 nderr = None
1779 try:
1780 nd[lslice] = nd[rslice]
1781 except Exception as e:
1782 nderr = e.__class__
1783
1784 if diff_structure: # ndarray cannot change shape
1785 self.assertIs(nderr, ValueError)
1786 else:
1787 self.assertEqual(nd.tolist(), lst)
1788 self.assertIs(nderr, lsterr)
1789
1790 if not is_memoryview_format(fmt):
1791 continue
1792
1793 mverr = None
1794 try:
1795 mv[lslice] = mv[rslice]
1796 except Exception as e:
1797 mverr = e.__class__
1798
1799 if diff_structure: # memoryview cannot change shape
1800 self.assertIs(mverr, ValueError)
1801 else:
1802 self.assertEqual(mv.tolist(), lst)
1803 self.assertEqual(mv, nd)
1804 self.assertIs(mverr, lsterr)
1805 self.verify(mv, obj=ex,
1806 itemsize=nd.itemsize, fmt=fmt, readonly=0,
1807 ndim=nd.ndim, shape=nd.shape, strides=nd.strides,
1808 lst=nd.tolist())
1809
1810 def test_ndarray_slice_assign_multidim(self):
1811 shape_t = (2, 3, 5)
1812 ndim = len(shape_t)
1813 nitems = prod(shape_t)
1814 for shape in permutations(shape_t):
1815
1816 fmt, items, _ = randitems(nitems)
1817
1818 for flags in (0, ND_PIL):
1819 for _ in range(ITERATIONS):
1820 lslices, rslices = randslice_from_shape(ndim, shape)
1821
1822 nd = ndarray(items, shape=shape, format=fmt,
1823 flags=flags|ND_WRITABLE)
1824 lst = carray(items, shape)
1825
1826 listerr = None
1827 try:
1828 result = multislice_assign(lst, lst, lslices, rslices)
1829 except Exception as e:
1830 listerr = e.__class__
1831
1832 nderr = None
1833 try:
1834 nd[lslices] = nd[rslices]
1835 except Exception as e:
1836 nderr = e.__class__
1837
1838 if nderr or listerr:
1839 self.assertIs(nderr, listerr)
1840 else:
1841 self.assertEqual(nd.tolist(), result)
1842
1843 def test_ndarray_random(self):
1844 # construction of valid arrays
1845 for _ in range(ITERATIONS):
1846 for fmt in fmtdict['@']:
1847 itemsize = struct.calcsize(fmt)
1848
1849 t = rand_structure(itemsize, True, maxdim=MAXDIM,
1850 maxshape=MAXSHAPE)
1851 self.assertTrue(verify_structure(*t))
1852 items = randitems_from_structure(fmt, t)
1853
1854 x = ndarray_from_structure(items, fmt, t)
1855 xlist = x.tolist()
1856
1857 mv = memoryview(x)
1858 if is_memoryview_format(fmt):
1859 mvlist = mv.tolist()
1860 self.assertEqual(mvlist, xlist)
1861
1862 if t[2] > 0:
1863 # ndim > 0: test against suboffsets representation.
1864 y = ndarray_from_structure(items, fmt, t, flags=ND_PIL)
1865 ylist = y.tolist()
1866 self.assertEqual(xlist, ylist)
1867
1868 mv = memoryview(y)
1869 if is_memoryview_format(fmt):
1870 self.assertEqual(mv, y)
1871 mvlist = mv.tolist()
1872 self.assertEqual(mvlist, ylist)
1873
1874 if numpy_array:
1875 shape = t[3]
1876 if 0 in shape:
1877 continue # http://projects.scipy.org/numpy/ticket/1910
1878 z = numpy_array_from_structure(items, fmt, t)
1879 self.verify(x, obj=None,
1880 itemsize=z.itemsize, fmt=fmt, readonly=0,
1881 ndim=z.ndim, shape=z.shape, strides=z.strides,
1882 lst=z.tolist())
1883
1884 def test_ndarray_random_invalid(self):
1885 # exceptions during construction of invalid arrays
1886 for _ in range(ITERATIONS):
1887 for fmt in fmtdict['@']:
1888 itemsize = struct.calcsize(fmt)
1889
1890 t = rand_structure(itemsize, False, maxdim=MAXDIM,
1891 maxshape=MAXSHAPE)
1892 self.assertFalse(verify_structure(*t))
1893 items = randitems_from_structure(fmt, t)
1894
1895 nderr = False
1896 try:
1897 x = ndarray_from_structure(items, fmt, t)
1898 except Exception as e:
1899 nderr = e.__class__
1900 self.assertTrue(nderr)
1901
1902 if numpy_array:
1903 numpy_err = False
1904 try:
1905 y = numpy_array_from_structure(items, fmt, t)
1906 except Exception as e:
1907 numpy_err = e.__class__
1908
1909 if 0: # http://projects.scipy.org/numpy/ticket/1910
1910 self.assertTrue(numpy_err)
1911
1912 def test_ndarray_random_slice_assign(self):
1913 # valid slice assignments
1914 for _ in range(ITERATIONS):
1915 for fmt in fmtdict['@']:
1916 itemsize = struct.calcsize(fmt)
1917
1918 lshape, rshape, lslices, rslices = \
1919 rand_aligned_slices(maxdim=MAXDIM, maxshape=MAXSHAPE)
1920 tl = rand_structure(itemsize, True, shape=lshape)
1921 tr = rand_structure(itemsize, True, shape=rshape)
1922 self.assertTrue(verify_structure(*tl))
1923 self.assertTrue(verify_structure(*tr))
1924 litems = randitems_from_structure(fmt, tl)
1925 ritems = randitems_from_structure(fmt, tr)
1926
1927 xl = ndarray_from_structure(litems, fmt, tl)
1928 xr = ndarray_from_structure(ritems, fmt, tr)
1929 xl[lslices] = xr[rslices]
1930 xllist = xl.tolist()
1931 xrlist = xr.tolist()
1932
1933 ml = memoryview(xl)
1934 mr = memoryview(xr)
1935 self.assertEqual(ml.tolist(), xllist)
1936 self.assertEqual(mr.tolist(), xrlist)
1937
1938 if tl[2] > 0 and tr[2] > 0:
1939 # ndim > 0: test against suboffsets representation.
1940 yl = ndarray_from_structure(litems, fmt, tl, flags=ND_PIL)
1941 yr = ndarray_from_structure(ritems, fmt, tr, flags=ND_PIL)
1942 yl[lslices] = yr[rslices]
1943 yllist = yl.tolist()
1944 yrlist = yr.tolist()
1945 self.assertEqual(xllist, yllist)
1946 self.assertEqual(xrlist, yrlist)
1947
1948 ml = memoryview(yl)
1949 mr = memoryview(yr)
1950 self.assertEqual(ml.tolist(), yllist)
1951 self.assertEqual(mr.tolist(), yrlist)
1952
1953 if numpy_array:
1954 if 0 in lshape or 0 in rshape:
1955 continue # http://projects.scipy.org/numpy/ticket/1910
1956
1957 zl = numpy_array_from_structure(litems, fmt, tl)
1958 zr = numpy_array_from_structure(ritems, fmt, tr)
1959 zl[lslices] = zr[rslices]
1960
1961 if not is_overlapping(tl) and not is_overlapping(tr):
1962 # Slice assignment of overlapping structures
1963 # is undefined in NumPy.
1964 self.verify(xl, obj=None,
1965 itemsize=zl.itemsize, fmt=fmt, readonly=0,
1966 ndim=zl.ndim, shape=zl.shape,
1967 strides=zl.strides, lst=zl.tolist())
1968
1969 self.verify(xr, obj=None,
1970 itemsize=zr.itemsize, fmt=fmt, readonly=0,
1971 ndim=zr.ndim, shape=zr.shape,
1972 strides=zr.strides, lst=zr.tolist())
1973
1974 def test_ndarray_re_export(self):
1975 items = [1,2,3,4,5,6,7,8,9,10,11,12]
1976
1977 nd = ndarray(items, shape=[3,4], flags=ND_PIL)
1978 ex = ndarray(nd)
1979
1980 self.assertTrue(ex.flags & ND_PIL)
1981 self.assertIs(ex.obj, nd)
1982 self.assertEqual(ex.suboffsets, (0, -1))
1983 self.assertFalse(ex.c_contiguous)
1984 self.assertFalse(ex.f_contiguous)
1985 self.assertFalse(ex.contiguous)
1986
1987 def test_ndarray_zero_shape(self):
1988 # zeros in shape
1989 for flags in (0, ND_PIL):
1990 nd = ndarray([1,2,3], shape=[0], flags=flags)
1991 mv = memoryview(nd)
1992 self.assertEqual(mv, nd)
1993 self.assertEqual(nd.tolist(), [])
1994 self.assertEqual(mv.tolist(), [])
1995
1996 nd = ndarray([1,2,3], shape=[0,3,3], flags=flags)
1997 self.assertEqual(nd.tolist(), [])
1998
1999 nd = ndarray([1,2,3], shape=[3,0,3], flags=flags)
2000 self.assertEqual(nd.tolist(), [[], [], []])
2001
2002 nd = ndarray([1,2,3], shape=[3,3,0], flags=flags)
2003 self.assertEqual(nd.tolist(),
2004 [[[], [], []], [[], [], []], [[], [], []]])
2005
2006 def test_ndarray_zero_strides(self):
2007 # zero strides
2008 for flags in (0, ND_PIL):
2009 nd = ndarray([1], shape=[5], strides=[0], flags=flags)
2010 mv = memoryview(nd)
2011 self.assertEqual(mv, nd)
2012 self.assertEqual(nd.tolist(), [1, 1, 1, 1, 1])
2013 self.assertEqual(mv.tolist(), [1, 1, 1, 1, 1])
2014
2015 def test_ndarray_offset(self):
2016 nd = ndarray(list(range(20)), shape=[3], offset=7)
2017 self.assertEqual(nd.offset, 7)
2018 self.assertEqual(nd.tolist(), [7,8,9])
2019
2020 def test_ndarray_memoryview_from_buffer(self):
2021 for flags in (0, ND_PIL):
2022 nd = ndarray(list(range(3)), shape=[3], flags=flags)
2023 m = nd.memoryview_from_buffer()
2024 self.assertEqual(m, nd)
2025
2026 def test_ndarray_get_pointer(self):
2027 for flags in (0, ND_PIL):
2028 nd = ndarray(list(range(3)), shape=[3], flags=flags)
2029 for i in range(3):
2030 self.assertEqual(nd[i], get_pointer(nd, [i]))
2031
2032 def test_ndarray_tolist_null_strides(self):
2033 ex = ndarray(list(range(20)), shape=[2,2,5])
2034
2035 nd = ndarray(ex, getbuf=PyBUF_ND|PyBUF_FORMAT)
2036 self.assertEqual(nd.tolist(), ex.tolist())
2037
2038 m = memoryview(ex)
2039 self.assertEqual(m.tolist(), ex.tolist())
2040
2041 def test_ndarray_cmp_contig(self):
2042
2043 self.assertFalse(cmp_contig(b"123", b"456"))
2044
2045 x = ndarray(list(range(12)), shape=[3,4])
2046 y = ndarray(list(range(12)), shape=[4,3])
2047 self.assertFalse(cmp_contig(x, y))
2048
2049 x = ndarray([1], shape=[1], format="B")
2050 self.assertTrue(cmp_contig(x, b'\x01'))
2051 self.assertTrue(cmp_contig(b'\x01', x))
2052
2053 def test_ndarray_hash(self):
2054
2055 a = array.array('L', [1,2,3])
2056 nd = ndarray(a)
2057 self.assertRaises(ValueError, hash, nd)
2058
2059 # one-dimensional
2060 b = bytes(list(range(12)))
2061
2062 nd = ndarray(list(range(12)), shape=[12])
2063 self.assertEqual(hash(nd), hash(b))
2064
2065 # C-contiguous
2066 nd = ndarray(list(range(12)), shape=[3,4])
2067 self.assertEqual(hash(nd), hash(b))
2068
2069 nd = ndarray(list(range(12)), shape=[3,2,2])
2070 self.assertEqual(hash(nd), hash(b))
2071
2072 # Fortran contiguous
2073 b = bytes(transpose(list(range(12)), shape=[4,3]))
2074 nd = ndarray(list(range(12)), shape=[3,4], flags=ND_FORTRAN)
2075 self.assertEqual(hash(nd), hash(b))
2076
2077 b = bytes(transpose(list(range(12)), shape=[2,3,2]))
2078 nd = ndarray(list(range(12)), shape=[2,3,2], flags=ND_FORTRAN)
2079 self.assertEqual(hash(nd), hash(b))
2080
2081 # suboffsets
2082 b = bytes(list(range(12)))
2083 nd = ndarray(list(range(12)), shape=[2,2,3], flags=ND_PIL)
2084 self.assertEqual(hash(nd), hash(b))
2085
2086 # non-byte formats
2087 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
2088 self.assertEqual(hash(nd), hash(nd.tobytes()))
2089
Stefan Krah7d12d9d2012-07-28 12:25:55 +02002090 def test_py_buffer_to_contiguous(self):
2091
2092 # The requests are used in _testbuffer.c:py_buffer_to_contiguous
2093 # to generate buffers without full information for testing.
2094 requests = (
2095 # distinct flags
2096 PyBUF_INDIRECT, PyBUF_STRIDES, PyBUF_ND, PyBUF_SIMPLE,
2097 # compound requests
2098 PyBUF_FULL, PyBUF_FULL_RO,
2099 PyBUF_RECORDS, PyBUF_RECORDS_RO,
2100 PyBUF_STRIDED, PyBUF_STRIDED_RO,
2101 PyBUF_CONTIG, PyBUF_CONTIG_RO,
2102 )
2103
2104 # no buffer interface
2105 self.assertRaises(TypeError, py_buffer_to_contiguous, {}, 'F',
2106 PyBUF_FULL_RO)
2107
2108 # scalar, read-only request
2109 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
2110 for order in ['C', 'F', 'A']:
2111 for request in requests:
2112 b = py_buffer_to_contiguous(nd, order, request)
2113 self.assertEqual(b, nd.tobytes())
2114
2115 # zeros in shape
2116 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
2117 for order in ['C', 'F', 'A']:
2118 for request in requests:
2119 b = py_buffer_to_contiguous(nd, order, request)
2120 self.assertEqual(b, b'')
2121
2122 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
2123 flags=ND_WRITABLE)
2124 for order in ['C', 'F', 'A']:
2125 for request in requests:
2126 b = py_buffer_to_contiguous(nd, order, request)
2127 self.assertEqual(b, b'')
2128
2129 ### One-dimensional arrays are trivial, since Fortran and C order
2130 ### are the same.
2131
2132 # one-dimensional
2133 for f in [0, ND_FORTRAN]:
2134 nd = ndarray([1], shape=[1], format="h", flags=f|ND_WRITABLE)
2135 ndbytes = nd.tobytes()
2136 for order in ['C', 'F', 'A']:
2137 for request in requests:
2138 b = py_buffer_to_contiguous(nd, order, request)
2139 self.assertEqual(b, ndbytes)
2140
2141 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=f|ND_WRITABLE)
2142 ndbytes = nd.tobytes()
2143 for order in ['C', 'F', 'A']:
2144 for request in requests:
2145 b = py_buffer_to_contiguous(nd, order, request)
2146 self.assertEqual(b, ndbytes)
2147
2148 # one-dimensional, non-contiguous input
2149 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
2150 ndbytes = nd.tobytes()
2151 for order in ['C', 'F', 'A']:
2152 for request in [PyBUF_STRIDES, PyBUF_FULL]:
2153 b = py_buffer_to_contiguous(nd, order, request)
2154 self.assertEqual(b, ndbytes)
2155
2156 nd = nd[::-1]
2157 ndbytes = nd.tobytes()
2158 for order in ['C', 'F', 'A']:
2159 for request in requests:
2160 try:
2161 b = py_buffer_to_contiguous(nd, order, request)
2162 except BufferError:
2163 continue
2164 self.assertEqual(b, ndbytes)
2165
2166 ###
2167 ### Multi-dimensional arrays:
2168 ###
2169 ### The goal here is to preserve the logical representation of the
2170 ### input array but change the physical representation if necessary.
2171 ###
2172 ### _testbuffer example:
2173 ### ====================
2174 ###
2175 ### C input array:
2176 ### --------------
2177 ### >>> nd = ndarray(list(range(12)), shape=[3, 4])
2178 ### >>> nd.tolist()
2179 ### [[0, 1, 2, 3],
2180 ### [4, 5, 6, 7],
2181 ### [8, 9, 10, 11]]
2182 ###
2183 ### Fortran output:
2184 ### ---------------
2185 ### >>> py_buffer_to_contiguous(nd, 'F', PyBUF_FULL_RO)
2186 ### >>> b'\x00\x04\x08\x01\x05\t\x02\x06\n\x03\x07\x0b'
2187 ###
2188 ### The return value corresponds to this input list for
2189 ### _testbuffer's ndarray:
2190 ### >>> nd = ndarray([0,4,8,1,5,9,2,6,10,3,7,11], shape=[3,4],
2191 ### flags=ND_FORTRAN)
2192 ### >>> nd.tolist()
2193 ### [[0, 1, 2, 3],
2194 ### [4, 5, 6, 7],
2195 ### [8, 9, 10, 11]]
2196 ###
2197 ### The logical array is the same, but the values in memory are now
2198 ### in Fortran order.
2199 ###
2200 ### NumPy example:
2201 ### ==============
2202 ### _testbuffer's ndarray takes lists to initialize the memory.
2203 ### Here's the same sequence in NumPy:
2204 ###
2205 ### C input:
2206 ### --------
2207 ### >>> nd = ndarray(buffer=bytearray(list(range(12))),
2208 ### shape=[3, 4], dtype='B')
2209 ### >>> nd
2210 ### array([[ 0, 1, 2, 3],
2211 ### [ 4, 5, 6, 7],
2212 ### [ 8, 9, 10, 11]], dtype=uint8)
2213 ###
2214 ### Fortran output:
2215 ### ---------------
2216 ### >>> fortran_buf = nd.tostring(order='F')
2217 ### >>> fortran_buf
2218 ### b'\x00\x04\x08\x01\x05\t\x02\x06\n\x03\x07\x0b'
2219 ###
2220 ### >>> nd = ndarray(buffer=fortran_buf, shape=[3, 4],
2221 ### dtype='B', order='F')
2222 ###
2223 ### >>> nd
2224 ### array([[ 0, 1, 2, 3],
2225 ### [ 4, 5, 6, 7],
2226 ### [ 8, 9, 10, 11]], dtype=uint8)
2227 ###
2228
2229 # multi-dimensional, contiguous input
2230 lst = list(range(12))
2231 for f in [0, ND_FORTRAN]:
2232 nd = ndarray(lst, shape=[3, 4], flags=f|ND_WRITABLE)
2233 if numpy_array:
2234 na = numpy_array(buffer=bytearray(lst),
2235 shape=[3, 4], dtype='B',
2236 order='C' if f == 0 else 'F')
2237
2238 # 'C' request
2239 if f == ND_FORTRAN: # 'F' to 'C'
2240 x = ndarray(transpose(lst, [4, 3]), shape=[3, 4],
2241 flags=ND_WRITABLE)
2242 expected = x.tobytes()
2243 else:
2244 expected = nd.tobytes()
2245 for request in requests:
2246 try:
2247 b = py_buffer_to_contiguous(nd, 'C', request)
2248 except BufferError:
2249 continue
2250
2251 self.assertEqual(b, expected)
2252
2253 # Check that output can be used as the basis for constructing
2254 # a C array that is logically identical to the input array.
2255 y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE)
2256 self.assertEqual(memoryview(y), memoryview(nd))
2257
2258 if numpy_array:
2259 self.assertEqual(b, na.tostring(order='C'))
2260
2261 # 'F' request
2262 if f == 0: # 'C' to 'F'
2263 x = ndarray(transpose(lst, [3, 4]), shape=[4, 3],
2264 flags=ND_WRITABLE)
2265 else:
2266 x = ndarray(lst, shape=[3, 4], flags=ND_WRITABLE)
2267 expected = x.tobytes()
2268 for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT,
2269 PyBUF_STRIDES, PyBUF_ND]:
2270 try:
2271 b = py_buffer_to_contiguous(nd, 'F', request)
2272 except BufferError:
2273 continue
2274 self.assertEqual(b, expected)
2275
2276 # Check that output can be used as the basis for constructing
2277 # a Fortran array that is logically identical to the input array.
2278 y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE)
2279 self.assertEqual(memoryview(y), memoryview(nd))
2280
2281 if numpy_array:
2282 self.assertEqual(b, na.tostring(order='F'))
2283
2284 # 'A' request
2285 if f == ND_FORTRAN:
2286 x = ndarray(lst, shape=[3, 4], flags=ND_WRITABLE)
2287 expected = x.tobytes()
2288 else:
2289 expected = nd.tobytes()
2290 for request in [PyBUF_FULL, PyBUF_FULL_RO, PyBUF_INDIRECT,
2291 PyBUF_STRIDES, PyBUF_ND]:
2292 try:
2293 b = py_buffer_to_contiguous(nd, 'A', request)
2294 except BufferError:
2295 continue
2296
2297 self.assertEqual(b, expected)
2298
2299 # Check that output can be used as the basis for constructing
2300 # an array with order=f that is logically identical to the input
2301 # array.
2302 y = ndarray([v for v in b], shape=[3, 4], flags=f|ND_WRITABLE)
2303 self.assertEqual(memoryview(y), memoryview(nd))
2304
2305 if numpy_array:
2306 self.assertEqual(b, na.tostring(order='A'))
2307
2308 # multi-dimensional, non-contiguous input
2309 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
2310
2311 # 'C'
2312 b = py_buffer_to_contiguous(nd, 'C', 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
2317 # 'F'
2318 b = py_buffer_to_contiguous(nd, 'F', PyBUF_FULL_RO)
2319 x = ndarray(transpose(lst, [3, 4]), shape=[4, 3], flags=ND_WRITABLE)
2320 self.assertEqual(b, x.tobytes())
2321 y = ndarray([v for v in b], shape=[3, 4], flags=ND_FORTRAN|ND_WRITABLE)
2322 self.assertEqual(memoryview(y), memoryview(nd))
2323
2324 # 'A'
2325 b = py_buffer_to_contiguous(nd, 'A', PyBUF_FULL_RO)
2326 self.assertEqual(b, nd.tobytes())
2327 y = ndarray([v for v in b], shape=[3, 4], flags=ND_WRITABLE)
2328 self.assertEqual(memoryview(y), memoryview(nd))
2329
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002330 def test_memoryview_construction(self):
2331
2332 items_shape = [(9, []), ([1,2,3], [3]), (list(range(2*3*5)), [2,3,5])]
2333
2334 # NumPy style, C-contiguous:
2335 for items, shape in items_shape:
2336
2337 # From PEP-3118 compliant exporter:
2338 ex = ndarray(items, shape=shape)
2339 m = memoryview(ex)
2340 self.assertTrue(m.c_contiguous)
2341 self.assertTrue(m.contiguous)
2342
2343 ndim = len(shape)
2344 strides = strides_from_shape(ndim, shape, 1, 'C')
2345 lst = carray(items, shape)
2346
2347 self.verify(m, obj=ex,
2348 itemsize=1, fmt='B', readonly=1,
2349 ndim=ndim, shape=shape, strides=strides,
2350 lst=lst)
2351
2352 # From memoryview:
2353 m2 = memoryview(m)
2354 self.verify(m2, obj=ex,
2355 itemsize=1, fmt='B', readonly=1,
2356 ndim=ndim, shape=shape, strides=strides,
2357 lst=lst)
2358
2359 # PyMemoryView_FromBuffer(): no strides
2360 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2361 self.assertEqual(nd.strides, ())
2362 m = nd.memoryview_from_buffer()
2363 self.verify(m, obj=None,
2364 itemsize=1, fmt='B', readonly=1,
2365 ndim=ndim, shape=shape, strides=strides,
2366 lst=lst)
2367
2368 # PyMemoryView_FromBuffer(): no format, shape, strides
2369 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2370 self.assertEqual(nd.format, '')
2371 self.assertEqual(nd.shape, ())
2372 self.assertEqual(nd.strides, ())
2373 m = nd.memoryview_from_buffer()
2374
2375 lst = [items] if ndim == 0 else items
2376 self.verify(m, obj=None,
2377 itemsize=1, fmt='B', readonly=1,
2378 ndim=1, shape=[ex.nbytes], strides=(1,),
2379 lst=lst)
2380
2381 # NumPy style, Fortran contiguous:
2382 for items, shape in items_shape:
2383
2384 # From PEP-3118 compliant exporter:
2385 ex = ndarray(items, shape=shape, flags=ND_FORTRAN)
2386 m = memoryview(ex)
2387 self.assertTrue(m.f_contiguous)
2388 self.assertTrue(m.contiguous)
2389
2390 ndim = len(shape)
2391 strides = strides_from_shape(ndim, shape, 1, 'F')
2392 lst = farray(items, shape)
2393
2394 self.verify(m, obj=ex,
2395 itemsize=1, fmt='B', readonly=1,
2396 ndim=ndim, shape=shape, strides=strides,
2397 lst=lst)
2398
2399 # From memoryview:
2400 m2 = memoryview(m)
2401 self.verify(m2, obj=ex,
2402 itemsize=1, fmt='B', readonly=1,
2403 ndim=ndim, shape=shape, strides=strides,
2404 lst=lst)
2405
2406 # PIL style:
2407 for items, shape in items_shape[1:]:
2408
2409 # From PEP-3118 compliant exporter:
2410 ex = ndarray(items, shape=shape, flags=ND_PIL)
2411 m = memoryview(ex)
2412
2413 ndim = len(shape)
2414 lst = carray(items, shape)
2415
2416 self.verify(m, obj=ex,
2417 itemsize=1, fmt='B', readonly=1,
2418 ndim=ndim, shape=shape, strides=ex.strides,
2419 lst=lst)
2420
2421 # From memoryview:
2422 m2 = memoryview(m)
2423 self.verify(m2, obj=ex,
2424 itemsize=1, fmt='B', readonly=1,
2425 ndim=ndim, shape=shape, strides=ex.strides,
2426 lst=lst)
2427
2428 # Invalid number of arguments:
2429 self.assertRaises(TypeError, memoryview, b'9', 'x')
2430 # Not a buffer provider:
2431 self.assertRaises(TypeError, memoryview, {})
2432 # Non-compliant buffer provider:
2433 ex = ndarray([1,2,3], shape=[3])
2434 nd = ndarray(ex, getbuf=PyBUF_SIMPLE)
2435 self.assertRaises(BufferError, memoryview, nd)
2436 nd = ndarray(ex, getbuf=PyBUF_CONTIG_RO|PyBUF_FORMAT)
2437 self.assertRaises(BufferError, memoryview, nd)
2438
2439 # ndim > 64
2440 nd = ndarray([1]*128, shape=[1]*128, format='L')
2441 self.assertRaises(ValueError, memoryview, nd)
2442 self.assertRaises(ValueError, nd.memoryview_from_buffer)
2443 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'C')
2444 self.assertRaises(ValueError, get_contiguous, nd, PyBUF_READ, 'F')
2445 self.assertRaises(ValueError, get_contiguous, nd[::-1], PyBUF_READ, 'C')
2446
2447 def test_memoryview_cast_zero_shape(self):
Antoine Pitrou60b18342013-10-03 19:55:41 +02002448 # Casts are undefined if buffer is multidimensional and shape
2449 # contains zeros. These arrays are regarded as C-contiguous by
2450 # Numpy and PyBuffer_GetContiguous(), so they are not caught by
2451 # the test for C-contiguity in memory_cast().
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002452 items = [1,2,3]
2453 for shape in ([0,3,3], [3,0,3], [0,3,3]):
2454 ex = ndarray(items, shape=shape)
2455 self.assertTrue(ex.c_contiguous)
2456 msrc = memoryview(ex)
2457 self.assertRaises(TypeError, msrc.cast, 'c')
Antoine Pitrou60b18342013-10-03 19:55:41 +02002458 # Monodimensional empty view can be cast (issue #19014).
2459 for fmt, _, _ in iter_format(1, 'memoryview'):
2460 msrc = memoryview(b'')
2461 m = msrc.cast(fmt)
2462 self.assertEqual(m.tobytes(), b'')
2463 self.assertEqual(m.tolist(), [])
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002464
Antoine Pitroua6545102015-03-10 22:32:00 +01002465 check_sizeof = support.check_sizeof
2466
2467 def test_memoryview_sizeof(self):
2468 check = self.check_sizeof
2469 vsize = support.calcvobjsize
Antoine Pitrou63afdaa2015-03-10 22:35:24 +01002470 base_struct = 'Pnin 2P2n2i5P P'
Antoine Pitroua6545102015-03-10 22:32:00 +01002471 per_dim = '3n'
2472
2473 items = list(range(8))
2474 check(memoryview(b''), vsize(base_struct + 1 * per_dim))
2475 a = ndarray(items, shape=[2, 4], format="b")
2476 check(memoryview(a), vsize(base_struct + 2 * per_dim))
2477 a = ndarray(items, shape=[2, 2, 2], format="b")
2478 check(memoryview(a), vsize(base_struct + 3 * per_dim))
2479
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002480 def test_memoryview_struct_module(self):
2481
2482 class INT(object):
2483 def __init__(self, val):
2484 self.val = val
2485 def __int__(self):
2486 return self.val
2487
2488 class IDX(object):
2489 def __init__(self, val):
2490 self.val = val
2491 def __index__(self):
2492 return self.val
2493
2494 def f(): return 7
2495
2496 values = [INT(9), IDX(9),
2497 2.2+3j, Decimal("-21.1"), 12.2, Fraction(5, 2),
2498 [1,2,3], {4,5,6}, {7:8}, (), (9,),
2499 True, False, None, NotImplemented,
2500 b'a', b'abc', bytearray(b'a'), bytearray(b'abc'),
2501 'a', 'abc', r'a', r'abc',
2502 f, lambda x: x]
2503
2504 for fmt, items, item in iter_format(10, 'memoryview'):
2505 ex = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2506 nd = ndarray(items, shape=[10], format=fmt, flags=ND_WRITABLE)
2507 m = memoryview(ex)
2508
2509 struct.pack_into(fmt, nd, 0, item)
2510 m[0] = item
2511 self.assertEqual(m[0], nd[0])
2512
2513 itemsize = struct.calcsize(fmt)
2514 if 'P' in fmt:
2515 continue
2516
2517 for v in values:
2518 struct_err = None
2519 try:
2520 struct.pack_into(fmt, nd, itemsize, v)
2521 except struct.error:
2522 struct_err = struct.error
2523
2524 mv_err = None
2525 try:
2526 m[1] = v
2527 except (TypeError, ValueError) as e:
2528 mv_err = e.__class__
2529
2530 if struct_err or mv_err:
2531 self.assertIsNot(struct_err, None)
2532 self.assertIsNot(mv_err, None)
2533 else:
2534 self.assertEqual(m[1], nd[1])
2535
2536 def test_memoryview_cast_zero_strides(self):
2537 # Casts are undefined if strides contains zeros. These arrays are
2538 # (sometimes!) regarded as C-contiguous by Numpy, but not by
2539 # PyBuffer_GetContiguous().
2540 ex = ndarray([1,2,3], shape=[3], strides=[0])
2541 self.assertFalse(ex.c_contiguous)
2542 msrc = memoryview(ex)
2543 self.assertRaises(TypeError, msrc.cast, 'c')
2544
2545 def test_memoryview_cast_invalid(self):
2546 # invalid format
2547 for sfmt in NON_BYTE_FORMAT:
2548 sformat = '@' + sfmt if randrange(2) else sfmt
2549 ssize = struct.calcsize(sformat)
2550 for dfmt in NON_BYTE_FORMAT:
2551 dformat = '@' + dfmt if randrange(2) else dfmt
2552 dsize = struct.calcsize(dformat)
2553 ex = ndarray(list(range(32)), shape=[32//ssize], format=sformat)
2554 msrc = memoryview(ex)
2555 self.assertRaises(TypeError, msrc.cast, dfmt, [32//dsize])
2556
2557 for sfmt, sitems, _ in iter_format(1):
2558 ex = ndarray(sitems, shape=[1], format=sfmt)
2559 msrc = memoryview(ex)
2560 for dfmt, _, _ in iter_format(1):
2561 if (not is_memoryview_format(sfmt) or
2562 not is_memoryview_format(dfmt)):
2563 self.assertRaises(ValueError, msrc.cast, dfmt,
2564 [32//dsize])
2565 else:
2566 if not is_byte_format(sfmt) and not is_byte_format(dfmt):
2567 self.assertRaises(TypeError, msrc.cast, dfmt,
2568 [32//dsize])
2569
2570 # invalid shape
2571 size_h = struct.calcsize('h')
2572 size_d = struct.calcsize('d')
2573 ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h')
2574 msrc = memoryview(ex)
2575 self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d')
2576
2577 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2578 m = memoryview(ex)
2579
2580 # incorrect number of args
2581 self.assertRaises(TypeError, m.cast)
2582 self.assertRaises(TypeError, m.cast, 1, 2, 3)
2583
2584 # incorrect dest format type
2585 self.assertRaises(TypeError, m.cast, {})
2586
2587 # incorrect dest format
2588 self.assertRaises(ValueError, m.cast, "X")
2589 self.assertRaises(ValueError, m.cast, "@X")
2590 self.assertRaises(ValueError, m.cast, "@XY")
2591
2592 # dest format not implemented
2593 self.assertRaises(ValueError, m.cast, "=B")
2594 self.assertRaises(ValueError, m.cast, "!L")
2595 self.assertRaises(ValueError, m.cast, "<P")
2596 self.assertRaises(ValueError, m.cast, ">l")
2597 self.assertRaises(ValueError, m.cast, "BI")
2598 self.assertRaises(ValueError, m.cast, "xBI")
2599
2600 # src format not implemented
2601 ex = ndarray([(1,2), (3,4)], shape=[2], format="II")
2602 m = memoryview(ex)
2603 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2604 self.assertRaises(NotImplementedError, m.__setitem__, 0, 8)
2605 self.assertRaises(NotImplementedError, m.tolist)
2606
2607 # incorrect shape type
2608 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2609 m = memoryview(ex)
2610 self.assertRaises(TypeError, m.cast, "B", shape={})
2611
2612 # incorrect shape elements
2613 ex = ndarray(list(range(120)), shape=[2*3*4*5])
2614 m = memoryview(ex)
2615 self.assertRaises(OverflowError, m.cast, "B", shape=[2**64])
2616 self.assertRaises(ValueError, m.cast, "B", shape=[-1])
2617 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1])
2618 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0])
2619 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x'])
2620
2621 # N-D -> N-D cast
2622 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11])
2623 m = memoryview(ex)
2624 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2625
2626 # cast with ndim > 64
2627 nd = ndarray(list(range(128)), shape=[128], format='I')
2628 m = memoryview(nd)
2629 self.assertRaises(ValueError, m.cast, 'I', [1]*128)
2630
2631 # view->len not a multiple of itemsize
2632 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2633 m = memoryview(ex)
2634 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2635
2636 # product(shape) * itemsize != buffer size
2637 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2638 m = memoryview(ex)
2639 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5])
2640
2641 # product(shape) * itemsize overflow
2642 nd = ndarray(list(range(128)), shape=[128], format='I')
2643 m1 = memoryview(nd)
2644 nd = ndarray(list(range(128)), shape=[128], format='B')
2645 m2 = memoryview(nd)
2646 if sys.maxsize == 2**63-1:
2647 self.assertRaises(TypeError, m1.cast, 'B',
2648 [7, 7, 73, 127, 337, 92737, 649657])
2649 self.assertRaises(ValueError, m1.cast, 'B',
2650 [2**20, 2**20, 2**10, 2**10, 2**3])
2651 self.assertRaises(ValueError, m2.cast, 'I',
2652 [2**20, 2**20, 2**10, 2**10, 2**1])
2653 else:
2654 self.assertRaises(TypeError, m1.cast, 'B',
2655 [1, 2147483647])
2656 self.assertRaises(ValueError, m1.cast, 'B',
2657 [2**10, 2**10, 2**5, 2**5, 2**1])
2658 self.assertRaises(ValueError, m2.cast, 'I',
2659 [2**10, 2**10, 2**5, 2**3, 2**1])
2660
2661 def test_memoryview_cast(self):
2662 bytespec = (
2663 ('B', lambda ex: list(ex.tobytes())),
2664 ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]),
2665 ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]),
2666 )
2667
2668 def iter_roundtrip(ex, m, items, fmt):
2669 srcsize = struct.calcsize(fmt)
2670 for bytefmt, to_bytelist in bytespec:
2671
2672 m2 = m.cast(bytefmt)
2673 lst = to_bytelist(ex)
2674 self.verify(m2, obj=ex,
2675 itemsize=1, fmt=bytefmt, readonly=0,
2676 ndim=1, shape=[31*srcsize], strides=(1,),
2677 lst=lst, cast=True)
2678
2679 m3 = m2.cast(fmt)
2680 self.assertEqual(m3, ex)
2681 lst = ex.tolist()
2682 self.verify(m3, obj=ex,
2683 itemsize=srcsize, fmt=fmt, readonly=0,
2684 ndim=1, shape=[31], strides=(srcsize,),
2685 lst=lst, cast=True)
2686
2687 # cast from ndim = 0 to ndim = 1
2688 srcsize = struct.calcsize('I')
2689 ex = ndarray(9, shape=[], format='I')
2690 destitems, destshape = cast_items(ex, 'B', 1)
2691 m = memoryview(ex)
2692 m2 = m.cast('B')
2693 self.verify(m2, obj=ex,
2694 itemsize=1, fmt='B', readonly=1,
2695 ndim=1, shape=destshape, strides=(1,),
2696 lst=destitems, cast=True)
2697
2698 # cast from ndim = 1 to ndim = 0
2699 destsize = struct.calcsize('I')
2700 ex = ndarray([9]*destsize, shape=[destsize], format='B')
2701 destitems, destshape = cast_items(ex, 'I', destsize, shape=[])
2702 m = memoryview(ex)
2703 m2 = m.cast('I', shape=[])
2704 self.verify(m2, obj=ex,
2705 itemsize=destsize, fmt='I', readonly=1,
2706 ndim=0, shape=(), strides=(),
2707 lst=destitems, cast=True)
2708
2709 # array.array: roundtrip to/from bytes
2710 for fmt, items, _ in iter_format(31, 'array'):
2711 ex = array.array(fmt, items)
2712 m = memoryview(ex)
2713 iter_roundtrip(ex, m, items, fmt)
2714
2715 # ndarray: roundtrip to/from bytes
2716 for fmt, items, _ in iter_format(31, 'memoryview'):
2717 ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE)
2718 m = memoryview(ex)
2719 iter_roundtrip(ex, m, items, fmt)
2720
2721 def test_memoryview_cast_1D_ND(self):
2722 # Cast between C-contiguous buffers. At least one buffer must
2723 # be 1D, at least one format must be 'c', 'b' or 'B'.
2724 for _tshape in gencastshapes():
2725 for char in fmtdict['@']:
2726 tfmt = ('', '@')[randrange(2)] + char
2727 tsize = struct.calcsize(tfmt)
2728 n = prod(_tshape) * tsize
2729 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2730 for fmt, items, _ in iter_format(n, obj):
2731 size = struct.calcsize(fmt)
2732 shape = [n] if n > 0 else []
2733 tshape = _tshape + [size]
2734
2735 ex = ndarray(items, shape=shape, format=fmt)
2736 m = memoryview(ex)
2737
2738 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2739
2740 if titems is None:
2741 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2742 continue
2743 if titems == 'nan':
2744 continue # NaNs in lists are a recipe for trouble.
2745
2746 # 1D -> ND
2747 nd = ndarray(titems, shape=tshape, format=tfmt)
2748
2749 m2 = m.cast(tfmt, shape=tshape)
2750 ndim = len(tshape)
2751 strides = nd.strides
2752 lst = nd.tolist()
2753 self.verify(m2, obj=ex,
2754 itemsize=tsize, fmt=tfmt, readonly=1,
2755 ndim=ndim, shape=tshape, strides=strides,
2756 lst=lst, cast=True)
2757
2758 # ND -> 1D
2759 m3 = m2.cast(fmt)
2760 m4 = m2.cast(fmt, shape=shape)
2761 ndim = len(shape)
2762 strides = ex.strides
2763 lst = ex.tolist()
2764
2765 self.verify(m3, obj=ex,
2766 itemsize=size, fmt=fmt, readonly=1,
2767 ndim=ndim, shape=shape, strides=strides,
2768 lst=lst, cast=True)
2769
2770 self.verify(m4, obj=ex,
2771 itemsize=size, fmt=fmt, readonly=1,
2772 ndim=ndim, shape=shape, strides=strides,
2773 lst=lst, cast=True)
2774
2775 def test_memoryview_tolist(self):
2776
2777 # Most tolist() tests are in self.verify() etc.
2778
2779 a = array.array('h', list(range(-6, 6)))
2780 m = memoryview(a)
2781 self.assertEqual(m, a)
2782 self.assertEqual(m.tolist(), a.tolist())
2783
2784 a = a[2::3]
2785 m = m[2::3]
2786 self.assertEqual(m, a)
2787 self.assertEqual(m.tolist(), a.tolist())
2788
2789 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2790 m = memoryview(ex)
2791 self.assertEqual(m.tolist(), ex.tolist())
2792
2793 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2794 m = memoryview(ex)
2795 self.assertRaises(NotImplementedError, m.tolist)
2796
2797 ex = ndarray([b'12345'], shape=[1], format="s")
2798 m = memoryview(ex)
2799 self.assertRaises(NotImplementedError, m.tolist)
2800
2801 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2802 m = memoryview(ex)
2803 self.assertRaises(NotImplementedError, m.tolist)
2804
2805 def test_memoryview_repr(self):
2806 m = memoryview(bytearray(9))
2807 r = m.__repr__()
2808 self.assertTrue(r.startswith("<memory"))
2809
2810 m.release()
2811 r = m.__repr__()
2812 self.assertTrue(r.startswith("<released"))
2813
2814 def test_memoryview_sequence(self):
2815
2816 for fmt in ('d', 'f'):
2817 inf = float(3e400)
2818 ex = array.array(fmt, [1.0, inf, 3.0])
2819 m = memoryview(ex)
2820 self.assertIn(1.0, m)
2821 self.assertIn(5e700, m)
2822 self.assertIn(3.0, m)
2823
2824 ex = ndarray(9.0, [], format='f')
2825 m = memoryview(ex)
2826 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2827
2828 def test_memoryview_index(self):
2829
2830 # ndim = 0
2831 ex = ndarray(12.5, shape=[], format='d')
2832 m = memoryview(ex)
2833 self.assertEqual(m[()], 12.5)
2834 self.assertEqual(m[...], m)
2835 self.assertEqual(m[...], ex)
2836 self.assertRaises(TypeError, m.__getitem__, 0)
2837
2838 ex = ndarray((1,2,3), shape=[], format='iii')
2839 m = memoryview(ex)
2840 self.assertRaises(NotImplementedError, m.__getitem__, ())
2841
2842 # range
2843 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2844 m = memoryview(ex)
2845
2846 self.assertRaises(IndexError, m.__getitem__, 2**64)
2847 self.assertRaises(TypeError, m.__getitem__, 2.0)
2848 self.assertRaises(TypeError, m.__getitem__, 0.0)
2849
2850 # out of bounds
2851 self.assertRaises(IndexError, m.__getitem__, -8)
2852 self.assertRaises(IndexError, m.__getitem__, 8)
2853
2854 # Not implemented: multidimensional sub-views
2855 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2856 m = memoryview(ex)
2857
2858 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2859 self.assertRaises(NotImplementedError, m.__setitem__, 0, 9)
2860 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2861
2862 def test_memoryview_assign(self):
2863
2864 # ndim = 0
2865 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2866 m = memoryview(ex)
2867 m[()] = 22.5
2868 self.assertEqual(m[()], 22.5)
2869 m[...] = 23.5
2870 self.assertEqual(m[()], 23.5)
2871 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2872
2873 # read-only
2874 ex = ndarray(list(range(7)), shape=[7])
2875 m = memoryview(ex)
2876 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2877
2878 # range
2879 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2880 m = memoryview(ex)
2881
2882 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2883 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2884 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2885
2886 # out of bounds
2887 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2888 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2889
2890 # pack_single() success:
2891 for fmt in fmtdict['@']:
2892 if fmt == 'c' or fmt == '?':
2893 continue
2894 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2895 m = memoryview(ex)
2896 i = randrange(-3, 3)
2897 m[i] = 8
2898 self.assertEqual(m[i], 8)
2899 self.assertEqual(m[i], ex[i])
2900
2901 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2902 flags=ND_WRITABLE)
2903 m = memoryview(ex)
2904 m[2] = b'9'
2905 self.assertEqual(m[2], b'9')
2906
2907 ex = ndarray([True, False, True], shape=[3], format='?',
2908 flags=ND_WRITABLE)
2909 m = memoryview(ex)
2910 m[1] = True
2911 self.assertEqual(m[1], True)
2912
2913 # pack_single() exceptions:
2914 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2915 m = memoryview(nd)
2916 self.assertRaises(TypeError, m.__setitem__, 0, 100)
2917
2918 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
2919 m1 = memoryview(ex)
2920
2921 for fmt, _range in fmtdict['@'].items():
2922 if (fmt == '?'): # PyObject_IsTrue() accepts anything
2923 continue
2924 if fmt == 'c': # special case tested above
2925 continue
2926 m2 = m1.cast(fmt)
2927 lo, hi = _range
2928 if fmt == 'd' or fmt == 'f':
2929 lo, hi = -2**1024, 2**1024
2930 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
2931 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
2932 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
2933 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
2934
2935 # invalid item
2936 m2 = m1.cast('c')
2937 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
2938
2939 # format not implemented
2940 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
2941 m = memoryview(ex)
2942 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2943
2944 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
2945 m = memoryview(ex)
2946 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2947
2948 # Not implemented: multidimensional sub-views
2949 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2950 m = memoryview(ex)
2951
2952 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
2953
2954 def test_memoryview_slice(self):
2955
2956 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2957 m = memoryview(ex)
2958
2959 # zero step
2960 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
2961 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
2962 bytearray([1,2]))
2963
2964 # invalid slice key
2965 self.assertRaises(TypeError, m.__getitem__, ())
2966
2967 # multidimensional slices
2968 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
2969 m = memoryview(ex)
2970
2971 self.assertRaises(NotImplementedError, m.__getitem__,
2972 (slice(0,2,1), slice(0,2,1)))
2973 self.assertRaises(NotImplementedError, m.__setitem__,
2974 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
2975
2976 # invalid slice tuple
2977 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
2978 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
2979 bytearray([1,2]))
2980
2981 # rvalue is not an exporter
2982 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
2983
2984 # non-contiguous slice assignment
2985 for flags in (0, ND_PIL):
2986 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
2987 flags=ND_WRITABLE|flags)
2988 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
2989 m1 = memoryview(ex1)
2990 m2 = memoryview(ex2)
2991
2992 ex1[2:5] = ex1[2:5]
2993 m1[2:5] = m2[2:5]
2994
2995 self.assertEqual(m1, ex1)
2996 self.assertEqual(m2, ex2)
2997
2998 ex1[1:3][::-1] = ex2[0:2][::1]
2999 m1[1:3][::-1] = m2[0:2][::1]
3000
3001 self.assertEqual(m1, ex1)
3002 self.assertEqual(m2, ex2)
3003
3004 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
3005 m1[4:1:-2][::-1] = m1[1:4:2][::1]
3006
3007 self.assertEqual(m1, ex1)
3008 self.assertEqual(m2, ex2)
3009
3010 def test_memoryview_array(self):
3011
3012 def cmptest(testcase, a, b, m, singleitem):
3013 for i, _ in enumerate(a):
3014 ai = a[i]
3015 mi = m[i]
3016 testcase.assertEqual(ai, mi)
3017 a[i] = singleitem
3018 if singleitem != ai:
3019 testcase.assertNotEqual(a, m)
3020 testcase.assertNotEqual(a, b)
3021 else:
3022 testcase.assertEqual(a, m)
3023 testcase.assertEqual(a, b)
3024 m[i] = singleitem
3025 testcase.assertEqual(a, m)
3026 testcase.assertEqual(b, m)
3027 a[i] = ai
3028 m[i] = mi
3029
3030 for n in range(1, 5):
3031 for fmt, items, singleitem in iter_format(n, 'array'):
3032 for lslice in genslices(n):
3033 for rslice in genslices(n):
3034
3035 a = array.array(fmt, items)
3036 b = array.array(fmt, items)
3037 m = memoryview(b)
3038
3039 self.assertEqual(m, a)
3040 self.assertEqual(m.tolist(), a.tolist())
3041 self.assertEqual(m.tobytes(), a.tobytes())
3042 self.assertEqual(len(m), len(a))
3043
3044 cmptest(self, a, b, m, singleitem)
3045
3046 array_err = None
3047 have_resize = None
3048 try:
3049 al = a[lslice]
3050 ar = a[rslice]
3051 a[lslice] = a[rslice]
3052 have_resize = len(al) != len(ar)
3053 except Exception as e:
3054 array_err = e.__class__
3055
3056 m_err = None
3057 try:
3058 m[lslice] = m[rslice]
3059 except Exception as e:
3060 m_err = e.__class__
3061
3062 if have_resize: # memoryview cannot change shape
3063 self.assertIs(m_err, ValueError)
3064 elif m_err or array_err:
3065 self.assertIs(m_err, array_err)
3066 else:
3067 self.assertEqual(m, a)
3068 self.assertEqual(m.tolist(), a.tolist())
3069 self.assertEqual(m.tobytes(), a.tobytes())
3070 cmptest(self, a, b, m, singleitem)
3071
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003072 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003073
3074 a = array.array('L', [1, 2, 3])
3075 b = array.array('L', [1, 2, 7])
3076
3077 # Ordering comparisons raise:
3078 v = memoryview(a)
3079 w = memoryview(b)
3080 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3081 self.assertIs(getattr(v, attr)(w), NotImplemented)
3082 self.assertIs(getattr(a, attr)(v), NotImplemented)
3083
3084 # Released views compare equal to themselves:
3085 v = memoryview(a)
3086 v.release()
3087 self.assertEqual(v, v)
3088 self.assertNotEqual(v, a)
3089 self.assertNotEqual(a, v)
3090
3091 v = memoryview(a)
3092 w = memoryview(a)
3093 w.release()
3094 self.assertNotEqual(v, w)
3095 self.assertNotEqual(w, v)
3096
3097 # Operand does not implement the buffer protocol:
3098 v = memoryview(a)
3099 self.assertNotEqual(v, [1, 2, 3])
3100
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003101 # NaNs
3102 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3103 nd[0] = (-1, float('nan'))
3104 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003105
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003106 # Depends on issue #15625: the struct module does not understand 'u'.
3107 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003108 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003109 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003110 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003111
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003112 # Some ctypes format strings are unknown to the struct module.
3113 if ctypes:
3114 # format: "T{>l:x:>l:y:}"
3115 class BEPoint(ctypes.BigEndianStructure):
3116 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3117 point = BEPoint(100, 200)
3118 a = memoryview(point)
3119 b = memoryview(point)
3120 self.assertNotEqual(a, b)
3121 self.assertNotEqual(a, point)
3122 self.assertNotEqual(point, a)
3123 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003124
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003125 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003126
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003127 nd1 = ndarray(1729, shape=[], format='@L')
3128 nd2 = ndarray(1729, shape=[], format='L', 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 self.assertFalse(v.__ne__(w))
3139 self.assertFalse(w.__ne__(v))
3140
3141 w[()] = 1728
3142 self.assertNotEqual(v, w)
3143 self.assertNotEqual(w, v)
3144 self.assertNotEqual(v, nd2)
3145 self.assertNotEqual(nd2, v)
3146 self.assertNotEqual(w, nd1)
3147 self.assertNotEqual(nd1, w)
3148
3149 self.assertFalse(v.__eq__(w))
3150 self.assertFalse(w.__eq__(v))
3151
3152 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3153 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3154 m = memoryview(ex)
3155
3156 self.assertEqual(m, nd)
3157 m[9] = 100
3158 self.assertNotEqual(m, nd)
3159
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003160 # struct module: equal
3161 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3162 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3163 flags=ND_WRITABLE)
3164 v = memoryview(nd1)
3165 w = memoryview(nd2)
3166 self.assertEqual(v, w)
3167 self.assertEqual(w, v)
3168 self.assertEqual(v, nd2)
3169 self.assertEqual(nd2, v)
3170 self.assertEqual(w, nd1)
3171 self.assertEqual(nd1, w)
3172
3173 # struct module: not equal
3174 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3175 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3176 flags=ND_WRITABLE)
3177 v = memoryview(nd1)
3178 w = memoryview(nd2)
3179 self.assertNotEqual(v, w)
3180 self.assertNotEqual(w, v)
3181 self.assertNotEqual(v, nd2)
3182 self.assertNotEqual(nd2, v)
3183 self.assertNotEqual(w, nd1)
3184 self.assertNotEqual(nd1, w)
3185 self.assertEqual(v, nd1)
3186 self.assertEqual(w, nd2)
3187
3188 def test_memoryview_compare_ndim_one(self):
3189
3190 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003191 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3192 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3193 v = memoryview(nd1)
3194 w = memoryview(nd2)
3195
3196 self.assertEqual(v, nd1)
3197 self.assertEqual(w, nd2)
3198 self.assertNotEqual(v, nd2)
3199 self.assertNotEqual(w, nd1)
3200 self.assertNotEqual(v, w)
3201
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003202 # contiguous, struct module
3203 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3204 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3205 v = memoryview(nd1)
3206 w = memoryview(nd2)
3207
3208 self.assertEqual(v, nd1)
3209 self.assertEqual(w, nd2)
3210 self.assertNotEqual(v, nd2)
3211 self.assertNotEqual(w, nd1)
3212 self.assertNotEqual(v, w)
3213
3214 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003215 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3216 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
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
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003225 # non-contiguous, struct module
3226 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3227 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3228 v = memoryview(nd1)
3229 w = memoryview(nd2)
3230
3231 self.assertEqual(v, nd2[::2])
3232 self.assertEqual(w[::2], nd1)
3233 self.assertEqual(v, w[::2])
3234 self.assertEqual(v[::-1], w[::-2])
3235
3236 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003237 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3238 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3239 flags=ND_PIL)
3240 v = memoryview(nd1)
3241 w = memoryview(nd2)
3242
3243 self.assertEqual(v, nd2[::2])
3244 self.assertEqual(w[::2], nd1)
3245 self.assertEqual(v, w[::2])
3246 self.assertEqual(v[::-1], w[::-2])
3247
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003248 # non-contiguous, suboffsets, struct module
3249 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3250 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3251 flags=ND_PIL)
3252 v = memoryview(nd1)
3253 w = memoryview(nd2)
3254
3255 self.assertEqual(v, nd2[::2])
3256 self.assertEqual(w[::2], nd1)
3257 self.assertEqual(v, w[::2])
3258 self.assertEqual(v[::-1], w[::-2])
3259
3260 def test_memoryview_compare_zero_shape(self):
3261
3262 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003263 nd1 = ndarray([900, 961], shape=[0], format='@h')
3264 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3265 v = memoryview(nd1)
3266 w = memoryview(nd2)
3267
3268 self.assertEqual(v, nd1)
3269 self.assertEqual(w, nd2)
3270 self.assertEqual(v, nd2)
3271 self.assertEqual(w, nd1)
3272 self.assertEqual(v, w)
3273
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003274 # zeros in shape, struct module
3275 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3276 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3277 v = memoryview(nd1)
3278 w = memoryview(nd2)
3279
3280 self.assertEqual(v, nd1)
3281 self.assertEqual(w, nd2)
3282 self.assertEqual(v, nd2)
3283 self.assertEqual(w, nd1)
3284 self.assertEqual(v, w)
3285
3286 def test_memoryview_compare_zero_strides(self):
3287
3288 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003289 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3290 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3291 v = memoryview(nd1)
3292 w = memoryview(nd2)
3293
3294 self.assertEqual(v, nd1)
3295 self.assertEqual(w, nd2)
3296 self.assertEqual(v, nd2)
3297 self.assertEqual(w, nd1)
3298 self.assertEqual(v, w)
3299
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003300 # zero strides, struct module
3301 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3302 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3303 v = memoryview(nd1)
3304 w = memoryview(nd2)
3305
3306 self.assertEqual(v, nd1)
3307 self.assertEqual(w, nd2)
3308 self.assertEqual(v, nd2)
3309 self.assertEqual(w, nd1)
3310 self.assertEqual(v, w)
3311
3312 def test_memoryview_compare_random_formats(self):
3313
3314 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003315 n = 10
3316 for char in fmtdict['@m']:
3317 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3318 for flags in (0, ND_PIL):
3319 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3320 m = memoryview(nd)
3321 self.assertEqual(m, nd)
3322
3323 nd = nd[::-3]
3324 m = memoryview(nd)
3325 self.assertEqual(m, nd)
3326
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003327 # random formats
3328 n = 10
3329 for _ in range(100):
3330 fmt, items, singleitem = randitems(n)
3331 for flags in (0, ND_PIL):
3332 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3333 m = memoryview(nd)
3334 self.assertEqual(m, nd)
3335
3336 nd = nd[::-3]
3337 m = memoryview(nd)
3338 self.assertEqual(m, nd)
3339
3340 def test_memoryview_compare_multidim_c(self):
3341
3342 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003343 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3344 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3345 v = memoryview(nd1)
3346 w = memoryview(nd2)
3347
3348 self.assertEqual(v, nd1)
3349 self.assertEqual(w, nd2)
3350 self.assertNotEqual(v, nd2)
3351 self.assertNotEqual(w, nd1)
3352 self.assertNotEqual(v, w)
3353
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003354 # C-contiguous, different values, struct module
3355 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3356 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3357 v = memoryview(nd1)
3358 w = memoryview(nd2)
3359
3360 self.assertEqual(v, nd1)
3361 self.assertEqual(w, nd2)
3362 self.assertNotEqual(v, nd2)
3363 self.assertNotEqual(w, nd1)
3364 self.assertNotEqual(v, w)
3365
3366 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003367 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3368 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3369 v = memoryview(nd1)
3370 w = memoryview(nd2)
3371
3372 self.assertEqual(v, nd1)
3373 self.assertEqual(w, nd2)
3374 self.assertNotEqual(v, nd2)
3375 self.assertNotEqual(w, nd1)
3376 self.assertNotEqual(v, w)
3377
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003378 # C-contiguous, different shape, struct module
3379 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3380 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003381 v = memoryview(nd1)
3382 w = memoryview(nd2)
3383
3384 self.assertEqual(v, nd1)
3385 self.assertEqual(w, nd2)
3386 self.assertNotEqual(v, nd2)
3387 self.assertNotEqual(w, nd1)
3388 self.assertNotEqual(v, w)
3389
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003390 # C-contiguous, different format, struct module
3391 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3392 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3393 v = memoryview(nd1)
3394 w = memoryview(nd2)
3395
3396 self.assertEqual(v, nd1)
3397 self.assertEqual(w, nd2)
3398 self.assertEqual(v, nd2)
3399 self.assertEqual(w, nd1)
3400 self.assertEqual(v, w)
3401
3402 def test_memoryview_compare_multidim_fortran(self):
3403
3404 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003405 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3406 flags=ND_FORTRAN)
3407 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3408 flags=ND_FORTRAN)
3409 v = memoryview(nd1)
3410 w = memoryview(nd2)
3411
3412 self.assertEqual(v, nd1)
3413 self.assertEqual(w, nd2)
3414 self.assertNotEqual(v, nd2)
3415 self.assertNotEqual(w, nd1)
3416 self.assertNotEqual(v, w)
3417
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003418 # Fortran-contiguous, different values, struct module
3419 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3420 flags=ND_FORTRAN)
3421 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3422 flags=ND_FORTRAN)
3423 v = memoryview(nd1)
3424 w = memoryview(nd2)
3425
3426 self.assertEqual(v, nd1)
3427 self.assertEqual(w, nd2)
3428 self.assertNotEqual(v, nd2)
3429 self.assertNotEqual(w, nd1)
3430 self.assertNotEqual(v, w)
3431
3432 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003433 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3434 flags=ND_FORTRAN)
3435 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3436 flags=ND_FORTRAN)
3437 v = memoryview(nd1)
3438 w = memoryview(nd2)
3439
3440 self.assertEqual(v, nd1)
3441 self.assertEqual(w, nd2)
3442 self.assertNotEqual(v, nd2)
3443 self.assertNotEqual(w, nd1)
3444 self.assertNotEqual(v, w)
3445
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003446 # Fortran-contiguous, different shape, struct module
3447 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003448 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003449 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003450 flags=ND_FORTRAN)
3451 v = memoryview(nd1)
3452 w = memoryview(nd2)
3453
3454 self.assertEqual(v, nd1)
3455 self.assertEqual(w, nd2)
3456 self.assertNotEqual(v, nd2)
3457 self.assertNotEqual(w, nd1)
3458 self.assertNotEqual(v, w)
3459
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003460 # Fortran-contiguous, different format, struct module
3461 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3462 flags=ND_FORTRAN)
3463 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3464 flags=ND_FORTRAN)
3465 v = memoryview(nd1)
3466 w = memoryview(nd2)
3467
3468 self.assertEqual(v, nd1)
3469 self.assertEqual(w, nd2)
3470 self.assertEqual(v, nd2)
3471 self.assertEqual(w, nd1)
3472 self.assertEqual(v, w)
3473
3474 def test_memoryview_compare_multidim_mixed(self):
3475
3476 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003477 lst1 = list(range(-15, 15))
3478 lst2 = transpose(lst1, [3, 2, 5])
3479 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3480 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3481 v = memoryview(nd1)
3482 w = memoryview(nd2)
3483
3484 self.assertEqual(v, nd1)
3485 self.assertEqual(w, nd2)
3486 self.assertEqual(v, w)
3487
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003488 # mixed C/Fortran contiguous, struct module
3489 lst1 = [(-3.3, -22, b'x')]*30
3490 lst1[5] = (-2.2, -22, b'x')
3491 lst2 = transpose(lst1, [3, 2, 5])
3492 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3493 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3494 v = memoryview(nd1)
3495 w = memoryview(nd2)
3496
3497 self.assertEqual(v, nd1)
3498 self.assertEqual(w, nd2)
3499 self.assertEqual(v, w)
3500
3501 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003502 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3503 nd1 = ex1[3:1:-1, ::-2]
3504 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3505 nd2 = ex2[1:3:1, ::-2]
3506 v = memoryview(nd1)
3507 w = memoryview(nd2)
3508
3509 self.assertEqual(v, nd1)
3510 self.assertEqual(w, nd2)
3511 self.assertNotEqual(v, nd2)
3512 self.assertNotEqual(w, nd1)
3513 self.assertNotEqual(v, w)
3514
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003515 # same values, non-contiguous, struct module
3516 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3517 nd1 = ex1[3:1:-1, ::-2]
3518 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3519 nd2 = ex2[1:3:1, ::-2]
3520 v = memoryview(nd1)
3521 w = memoryview(nd2)
3522
3523 self.assertEqual(v, nd1)
3524 self.assertEqual(w, nd2)
3525 self.assertEqual(v, nd2)
3526 self.assertEqual(w, nd1)
3527 self.assertEqual(v, w)
3528
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003529 # different shape
3530 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3531 nd1 = ex1[1:3:, ::-2]
3532 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3533 nd2 = ex2[1:3:, ::-2]
3534 v = memoryview(nd1)
3535 w = memoryview(nd2)
3536
3537 self.assertEqual(v, nd1)
3538 self.assertEqual(w, nd2)
3539 self.assertNotEqual(v, nd2)
3540 self.assertNotEqual(w, nd1)
3541 self.assertNotEqual(v, w)
3542
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003543 # different shape, struct module
3544 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003545 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003546 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003547 nd2 = ex2[1:3:, ::-2]
3548 v = memoryview(nd1)
3549 w = memoryview(nd2)
3550
3551 self.assertEqual(v, nd1)
3552 self.assertEqual(w, nd2)
3553 self.assertNotEqual(v, nd2)
3554 self.assertNotEqual(w, nd1)
3555 self.assertNotEqual(v, w)
3556
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003557 # different format, struct module
3558 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3559 nd1 = ex1[1:3:, ::-2]
3560 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3561 nd2 = ex2[1:3:, ::-2]
3562 v = memoryview(nd1)
3563 w = memoryview(nd2)
3564
3565 self.assertEqual(v, nd1)
3566 self.assertEqual(w, nd2)
3567 self.assertNotEqual(v, nd2)
3568 self.assertNotEqual(w, nd1)
3569 self.assertNotEqual(v, w)
3570
3571 def test_memoryview_compare_multidim_zero_shape(self):
3572
3573 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003574 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3575 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3576 v = memoryview(nd1)
3577 w = memoryview(nd2)
3578
3579 self.assertEqual(v, nd1)
3580 self.assertEqual(w, nd2)
3581 self.assertNotEqual(v, nd2)
3582 self.assertNotEqual(w, nd1)
3583 self.assertNotEqual(v, w)
3584
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003585 # zeros in shape, struct module
3586 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3587 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3588 v = memoryview(nd1)
3589 w = memoryview(nd2)
3590
3591 self.assertEqual(v, nd1)
3592 self.assertEqual(w, nd2)
3593 self.assertNotEqual(v, nd2)
3594 self.assertNotEqual(w, nd1)
3595 self.assertNotEqual(v, w)
3596
3597 def test_memoryview_compare_multidim_zero_strides(self):
3598
3599 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003600 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3601 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3602 v = memoryview(nd1)
3603 w = memoryview(nd2)
3604
3605 self.assertEqual(v, nd1)
3606 self.assertEqual(w, nd2)
3607 self.assertEqual(v, nd2)
3608 self.assertEqual(w, nd1)
3609 self.assertEqual(v, w)
3610 self.assertEqual(v.tolist(), w.tolist())
3611
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003612 # zero strides, struct module
3613 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3614 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3615 v = memoryview(nd1)
3616 w = memoryview(nd2)
3617
3618 self.assertEqual(v, nd1)
3619 self.assertEqual(w, nd2)
3620 self.assertEqual(v, nd2)
3621 self.assertEqual(w, nd1)
3622 self.assertEqual(v, w)
3623
3624 def test_memoryview_compare_multidim_suboffsets(self):
3625
3626 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003627 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3628 nd1 = ex1[3:1:-1, ::-2]
3629 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3630 nd2 = ex2[1:3:1, ::-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, struct module
3641 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3642 flags=ND_WRITABLE)
3643 ex1[2][7] = (1, -2)
3644 nd1 = ex1[3:1:-1, ::-2]
3645
3646 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3647 flags=ND_PIL|ND_WRITABLE)
3648 ex2[2][7] = (1, -2)
3649 nd2 = ex2[1:3:1, ::-2]
3650
3651 v = memoryview(nd1)
3652 w = memoryview(nd2)
3653
3654 self.assertEqual(v, nd1)
3655 self.assertEqual(w, nd2)
3656 self.assertEqual(v, nd2)
3657 self.assertEqual(w, nd1)
3658 self.assertEqual(v, w)
3659
3660 # suboffsets, different shape
3661 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3662 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003663 nd1 = ex1[1:3:, ::-2]
3664 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3665 nd2 = ex2[1:3:, ::-2]
3666 v = memoryview(nd1)
3667 w = memoryview(nd2)
3668
3669 self.assertEqual(v, nd1)
3670 self.assertEqual(w, nd2)
3671 self.assertNotEqual(v, nd2)
3672 self.assertNotEqual(w, nd1)
3673 self.assertNotEqual(v, w)
3674
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003675 # suboffsets, different shape, struct module
3676 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3677 flags=ND_PIL|ND_WRITABLE)
3678 nd1 = ex1[1:2:, ::-2]
3679
3680 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3681 nd2 = ex2[1:2:, ::-2]
3682
3683 v = memoryview(nd1)
3684 w = memoryview(nd2)
3685
3686 self.assertEqual(v, nd1)
3687 self.assertEqual(w, nd2)
3688 self.assertNotEqual(v, nd2)
3689 self.assertNotEqual(w, nd1)
3690 self.assertNotEqual(v, w)
3691
3692 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003693 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3694 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003695 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003696 nd2 = ex2[1:3:, ::-2]
3697 v = memoryview(nd1)
3698 w = memoryview(nd2)
3699
3700 self.assertEqual(v, nd1)
3701 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003702 self.assertEqual(v, nd2)
3703 self.assertEqual(w, nd1)
3704 self.assertEqual(v, w)
3705
3706 # suboffsets, different format, struct module
3707 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3708 flags=ND_PIL|ND_WRITABLE)
3709 ex1[1][2][2] = (b'sushi', b'', 1)
3710 nd1 = ex1[1:3:, ::-2]
3711
3712 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3713 flags=ND_PIL|ND_WRITABLE)
3714 ex1[1][2][2] = (b'sushi', b'', 1)
3715 nd2 = ex2[1:3:, ::-2]
3716
3717 v = memoryview(nd1)
3718 w = memoryview(nd2)
3719
3720 self.assertEqual(v, nd1)
3721 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003722 self.assertNotEqual(v, nd2)
3723 self.assertNotEqual(w, nd1)
3724 self.assertNotEqual(v, w)
3725
3726 # initialize mixed C/Fortran + suboffsets
3727 lst1 = list(range(-15, 15))
3728 lst2 = transpose(lst1, [3, 2, 5])
3729 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3730 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3731 v = memoryview(nd1)
3732 w = memoryview(nd2)
3733
3734 self.assertEqual(v, nd1)
3735 self.assertEqual(w, nd2)
3736 self.assertEqual(v, w)
3737
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003738 # initialize mixed C/Fortran + suboffsets, struct module
3739 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3740 lst1[11] = (b'ramen', b'spicy', 9.45)
3741 lst2 = transpose(lst1, [3, 2, 5])
3742
3743 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3744 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3745 flags=ND_FORTRAN|ND_PIL)
3746 v = memoryview(nd1)
3747 w = memoryview(nd2)
3748
3749 self.assertEqual(v, nd1)
3750 self.assertEqual(w, nd2)
3751 self.assertEqual(v, w)
3752
3753 def test_memoryview_compare_not_equal(self):
3754
3755 # items not equal
3756 for byteorder in ['=', '<', '>', '!']:
3757 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3758 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3759 flags=ND_WRITABLE|ND_FORTRAN)
3760 y[2][3][1][1][1] = 1
3761 a = memoryview(x)
3762 b = memoryview(y)
3763 self.assertEqual(a, x)
3764 self.assertEqual(b, y)
3765 self.assertNotEqual(a, b)
3766 self.assertNotEqual(a, y)
3767 self.assertNotEqual(b, x)
3768
3769 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3770 format=byteorder+'QLH')
3771 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3772 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3773 y[2][3][1][1][1] = (1, 1, 1)
3774 a = memoryview(x)
3775 b = memoryview(y)
3776 self.assertEqual(a, x)
3777 self.assertEqual(b, y)
3778 self.assertNotEqual(a, b)
3779 self.assertNotEqual(a, y)
3780 self.assertNotEqual(b, x)
3781
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003782 def test_memoryview_check_released(self):
3783
3784 a = array.array('d', [1.1, 2.2, 3.3])
3785
3786 m = memoryview(a)
3787 m.release()
3788
3789 # PyMemoryView_FromObject()
3790 self.assertRaises(ValueError, memoryview, m)
3791 # memoryview.cast()
3792 self.assertRaises(ValueError, m.cast, 'c')
3793 # getbuffer()
3794 self.assertRaises(ValueError, ndarray, m)
3795 # memoryview.tolist()
3796 self.assertRaises(ValueError, m.tolist)
3797 # memoryview.tobytes()
3798 self.assertRaises(ValueError, m.tobytes)
3799 # sequence
3800 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3801 # subscript
3802 self.assertRaises(ValueError, m.__getitem__, 0)
3803 # assignment
3804 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3805
3806 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3807 'shape', 'strides', 'suboffsets', 'c_contiguous',
3808 'f_contiguous', 'contiguous'):
3809 self.assertRaises(ValueError, m.__getattribute__, attr)
3810
3811 # richcompare
3812 b = array.array('d', [1.1, 2.2, 3.3])
3813 m1 = memoryview(a)
3814 m2 = memoryview(b)
3815
3816 self.assertEqual(m1, m2)
3817 m1.release()
3818 self.assertNotEqual(m1, m2)
3819 self.assertNotEqual(m1, a)
3820 self.assertEqual(m1, m1)
3821
3822 def test_memoryview_tobytes(self):
3823 # Many implicit tests are already in self.verify().
3824
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003825 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003826
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003827 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003828 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003829 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003830 self.assertEqual(m.tobytes(), nd.tobytes())
3831
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003832 nd = ndarray([t], shape=[1], format='>hQiLl')
3833 m = memoryview(nd)
3834 self.assertEqual(m, nd)
3835 self.assertEqual(m.tobytes(), nd.tobytes())
3836
3837 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3838 m = memoryview(nd)
3839 self.assertEqual(m, nd)
3840 self.assertEqual(m.tobytes(), nd.tobytes())
3841
3842 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3843 format='<hQiLl')
3844 m = memoryview(nd)
3845 self.assertEqual(m, nd)
3846 self.assertEqual(m.tobytes(), nd.tobytes())
3847
3848 # Unknown formats are handled: tobytes() purely depends on itemsize.
3849 if ctypes:
3850 # format: "T{>l:x:>l:y:}"
3851 class BEPoint(ctypes.BigEndianStructure):
3852 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3853 point = BEPoint(100, 200)
3854 a = memoryview(point)
3855 self.assertEqual(a.tobytes(), bytes(point))
3856
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003857 def test_memoryview_get_contiguous(self):
3858 # Many implicit tests are already in self.verify().
3859
3860 # no buffer interface
3861 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3862
3863 # writable request to read-only object
3864 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3865
3866 # writable request to non-contiguous object
3867 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3868 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3869
3870 # scalar, read-only request from read-only exporter
3871 nd = ndarray(9, shape=(), format="L")
3872 for order in ['C', 'F', 'A']:
3873 m = get_contiguous(nd, PyBUF_READ, order)
3874 self.assertEqual(m, nd)
3875 self.assertEqual(m[()], 9)
3876
3877 # scalar, read-only request from writable exporter
3878 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3879 for order in ['C', 'F', 'A']:
3880 m = get_contiguous(nd, PyBUF_READ, order)
3881 self.assertEqual(m, nd)
3882 self.assertEqual(m[()], 9)
3883
3884 # scalar, writable request
3885 for order in ['C', 'F', 'A']:
3886 nd[()] = 9
3887 m = get_contiguous(nd, PyBUF_WRITE, order)
3888 self.assertEqual(m, nd)
3889 self.assertEqual(m[()], 9)
3890
3891 m[()] = 10
3892 self.assertEqual(m[()], 10)
3893 self.assertEqual(nd[()], 10)
3894
3895 # zeros in shape
3896 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3897 for order in ['C', 'F', 'A']:
3898 m = get_contiguous(nd, PyBUF_READ, order)
3899 self.assertRaises(IndexError, m.__getitem__, 0)
3900 self.assertEqual(m, nd)
3901 self.assertEqual(m.tolist(), [])
3902
3903 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
3904 flags=ND_WRITABLE)
3905 for order in ['C', 'F', 'A']:
3906 m = get_contiguous(nd, PyBUF_READ, order)
3907 self.assertEqual(ndarray(m).tolist(), [[], []])
3908
3909 # one-dimensional
3910 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
3911 for order in ['C', 'F', 'A']:
3912 m = get_contiguous(nd, PyBUF_WRITE, order)
3913 self.assertEqual(m, nd)
3914 self.assertEqual(m.tolist(), nd.tolist())
3915
3916 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
3917 for order in ['C', 'F', 'A']:
3918 m = get_contiguous(nd, PyBUF_WRITE, order)
3919 self.assertEqual(m, nd)
3920 self.assertEqual(m.tolist(), nd.tolist())
3921
3922 # one-dimensional, non-contiguous
3923 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
3924 for order in ['C', 'F', 'A']:
3925 m = get_contiguous(nd, PyBUF_READ, order)
3926 self.assertEqual(m, nd)
3927 self.assertEqual(m.tolist(), nd.tolist())
3928 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3929 self.assertEqual(m[1], 3)
3930 self.assertEqual(nd[1], 3)
3931
3932 nd = nd[::-1]
3933 for order in ['C', 'F', 'A']:
3934 m = get_contiguous(nd, PyBUF_READ, order)
3935 self.assertEqual(m, nd)
3936 self.assertEqual(m.tolist(), nd.tolist())
3937 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3938 self.assertEqual(m[1], 1)
3939 self.assertEqual(nd[1], 1)
3940
3941 # multi-dimensional, contiguous input
3942 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
3943 for order in ['C', 'A']:
3944 m = get_contiguous(nd, PyBUF_WRITE, order)
3945 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3946
3947 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
3948 m = get_contiguous(nd, PyBUF_READ, order)
3949 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3950
3951 nd = ndarray(list(range(12)), shape=[3, 4],
3952 flags=ND_WRITABLE|ND_FORTRAN)
3953 for order in ['F', 'A']:
3954 m = get_contiguous(nd, PyBUF_WRITE, order)
3955 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3956
3957 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
3958 m = get_contiguous(nd, PyBUF_READ, order)
3959 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3960
3961 # multi-dimensional, non-contiguous input
3962 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
3963 for order in ['C', 'F', 'A']:
3964 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
3965 order)
3966 m = get_contiguous(nd, PyBUF_READ, order)
3967 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3968
3969 # flags
3970 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
3971 m = get_contiguous(nd, PyBUF_READ, 'C')
3972 self.assertTrue(m.c_contiguous)
3973
3974 def test_memoryview_serializing(self):
3975
3976 # C-contiguous
3977 size = struct.calcsize('i')
3978 a = array.array('i', [1,2,3,4,5])
3979 m = memoryview(a)
3980 buf = io.BytesIO(m)
3981 b = bytearray(5*size)
3982 buf.readinto(b)
3983 self.assertEqual(m.tobytes(), b)
3984
3985 # C-contiguous, multi-dimensional
3986 size = struct.calcsize('L')
3987 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
3988 m = memoryview(nd)
3989 buf = io.BytesIO(m)
3990 b = bytearray(2*3*2*size)
3991 buf.readinto(b)
3992 self.assertEqual(m.tobytes(), b)
3993
3994 # Fortran contiguous, multi-dimensional
3995 #size = struct.calcsize('L')
3996 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
3997 # flags=ND_FORTRAN)
3998 #m = memoryview(nd)
3999 #buf = io.BytesIO(m)
4000 #b = bytearray(2*3*2*size)
4001 #buf.readinto(b)
4002 #self.assertEqual(m.tobytes(), b)
4003
4004 def test_memoryview_hash(self):
4005
4006 # bytes exporter
4007 b = bytes(list(range(12)))
4008 m = memoryview(b)
4009 self.assertEqual(hash(b), hash(m))
4010
4011 # C-contiguous
4012 mc = m.cast('c', shape=[3,4])
4013 self.assertEqual(hash(mc), hash(b))
4014
4015 # non-contiguous
4016 mx = m[::-2]
4017 b = bytes(list(range(12))[::-2])
4018 self.assertEqual(hash(mx), hash(b))
4019
4020 # Fortran contiguous
4021 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
4022 m = memoryview(nd)
4023 self.assertEqual(hash(m), hash(nd))
4024
4025 # multi-dimensional slice
4026 nd = ndarray(list(range(30)), shape=[3,2,5])
4027 x = nd[::2, ::, ::-1]
4028 m = memoryview(x)
4029 self.assertEqual(hash(m), hash(x))
4030
4031 # multi-dimensional slice with suboffsets
4032 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
4033 x = nd[::2, ::, ::-1]
4034 m = memoryview(x)
4035 self.assertEqual(hash(m), hash(x))
4036
Stefan Krah4af77a02012-11-02 17:49:22 +01004037 # equality-hash invariant
4038 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004039 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004040
4041 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004042 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004043
Stefan Krahb716f842012-11-04 20:53:50 +01004044 self.assertEqual(a, b)
4045 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004046
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004047 # non-byte formats
4048 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4049 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004050 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004051
4052 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4053 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004054 self.assertRaises(ValueError, m.__hash__)
4055
4056 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4057 m = memoryview(nd)
4058 self.assertRaises(ValueError, m.__hash__)
4059
4060 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4061 m = memoryview(nd)
4062 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004063
4064 def test_memoryview_release(self):
4065
4066 # Create re-exporter from getbuffer(memoryview), then release the view.
4067 a = bytearray([1,2,3])
4068 m = memoryview(a)
4069 nd = ndarray(m) # re-exporter
4070 self.assertRaises(BufferError, m.release)
4071 del nd
4072 m.release()
4073
Stefan Krah4e99a312012-03-05 09:30:47 +01004074 a = bytearray([1,2,3])
4075 m = memoryview(a)
4076 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4077 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4078 self.assertIs(nd2.obj, m)
4079 self.assertRaises(BufferError, m.release)
4080 del nd1, nd2
4081 m.release()
4082
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004083 # chained views
4084 a = bytearray([1,2,3])
4085 m1 = memoryview(a)
4086 m2 = memoryview(m1)
4087 nd = ndarray(m2) # re-exporter
4088 m1.release()
4089 self.assertRaises(BufferError, m2.release)
4090 del nd
4091 m2.release()
4092
Stefan Krah4e99a312012-03-05 09:30:47 +01004093 a = bytearray([1,2,3])
4094 m1 = memoryview(a)
4095 m2 = memoryview(m1)
4096 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4097 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4098 self.assertIs(nd2.obj, m2)
4099 m1.release()
4100 self.assertRaises(BufferError, m2.release)
4101 del nd1, nd2
4102 m2.release()
4103
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004104 # Allow changing layout while buffers are exported.
4105 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4106 m1 = memoryview(nd)
4107
4108 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4109 m2 = memoryview(nd)
4110
4111 x = memoryview(m1)
4112 self.assertEqual(x.tolist(), m1.tolist())
4113
4114 y = memoryview(m2)
4115 self.assertEqual(y.tolist(), m2.tolist())
4116 self.assertEqual(y.tolist(), nd.tolist())
4117 m2.release()
4118 y.release()
4119
4120 nd.pop() # pop the current view
4121 self.assertEqual(x.tolist(), nd.tolist())
4122
4123 del nd
4124 m1.release()
4125 x.release()
4126
4127 # If multiple memoryviews share the same managed buffer, implicit
4128 # release() in the context manager's __exit__() method should still
4129 # work.
4130 def catch22(b):
4131 with memoryview(b) as m2:
4132 pass
4133
4134 x = bytearray(b'123')
4135 with memoryview(x) as m1:
4136 catch22(m1)
4137 self.assertEqual(m1[0], ord(b'1'))
4138
Stefan Krah4e99a312012-03-05 09:30:47 +01004139 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4140 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4141 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4142 self.assertIs(z.obj, x)
4143 with memoryview(z) as m:
4144 catch22(m)
4145 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4146
4147 # Test garbage collection.
4148 for flags in (0, ND_REDIRECT):
4149 x = bytearray(b'123')
4150 with memoryview(x) as m1:
4151 del x
4152 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4153 with memoryview(y) as m2:
4154 del y
4155 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4156 with memoryview(z) as m3:
4157 del z
4158 catch22(m3)
4159 catch22(m2)
4160 catch22(m1)
4161 self.assertEqual(m1[0], ord(b'1'))
4162 self.assertEqual(m2[1], ord(b'2'))
4163 self.assertEqual(m3[2], ord(b'3'))
4164 del m3
4165 del m2
4166 del m1
4167
4168 x = bytearray(b'123')
4169 with memoryview(x) as m1:
4170 del x
4171 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4172 with memoryview(y) as m2:
4173 del y
4174 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4175 with memoryview(z) as m3:
4176 del z
4177 catch22(m1)
4178 catch22(m2)
4179 catch22(m3)
4180 self.assertEqual(m1[0], ord(b'1'))
4181 self.assertEqual(m2[1], ord(b'2'))
4182 self.assertEqual(m3[2], ord(b'3'))
4183 del m1, m2, m3
4184
Stefan Krahfcbb4162012-03-05 10:45:31 +01004185 # memoryview.release() fails if the view has exported buffers.
4186 x = bytearray(b'123')
4187 with self.assertRaises(BufferError):
4188 with memoryview(x) as m:
4189 ex = ndarray(m)
4190 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004191
Stefan Krah4e99a312012-03-05 09:30:47 +01004192 def test_memoryview_redirect(self):
4193
4194 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4195 a = array.array('d', [1.0 * x for x in range(12)])
4196
4197 for x in (nd, a):
4198 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4199 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4200 m = memoryview(z)
4201
4202 self.assertIs(y.obj, x)
4203 self.assertIs(z.obj, x)
4204 self.assertIs(m.obj, x)
4205
4206 self.assertEqual(m, x)
4207 self.assertEqual(m, y)
4208 self.assertEqual(m, z)
4209
4210 self.assertEqual(m[1:3], x[1:3])
4211 self.assertEqual(m[1:3], y[1:3])
4212 self.assertEqual(m[1:3], z[1:3])
4213 del y, z
4214 self.assertEqual(m[1:3], x[1:3])
4215
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004216 def test_memoryview_from_static_exporter(self):
4217
4218 fmt = 'B'
4219 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4220
4221 # exceptions
4222 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4223
4224 # view.obj==x
4225 x = staticarray()
4226 y = memoryview(x)
4227 self.verify(y, obj=x,
4228 itemsize=1, fmt=fmt, readonly=1,
4229 ndim=1, shape=[12], strides=[1],
4230 lst=lst)
4231 for i in range(12):
4232 self.assertEqual(y[i], i)
4233 del x
4234 del y
4235
4236 x = staticarray()
4237 y = memoryview(x)
4238 del y
4239 del x
4240
4241 x = staticarray()
4242 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4243 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4244 m = memoryview(z)
4245 self.assertIs(y.obj, x)
4246 self.assertIs(m.obj, z)
4247 self.verify(m, obj=z,
4248 itemsize=1, fmt=fmt, readonly=1,
4249 ndim=1, shape=[12], strides=[1],
4250 lst=lst)
4251 del x, y, z, m
4252
4253 x = staticarray()
4254 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4255 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4256 m = memoryview(z)
4257 self.assertIs(y.obj, x)
4258 self.assertIs(z.obj, x)
4259 self.assertIs(m.obj, x)
4260 self.verify(m, obj=x,
4261 itemsize=1, fmt=fmt, readonly=1,
4262 ndim=1, shape=[12], strides=[1],
4263 lst=lst)
4264 del x, y, z, m
4265
4266 # view.obj==NULL
4267 x = staticarray(legacy_mode=True)
4268 y = memoryview(x)
4269 self.verify(y, obj=None,
4270 itemsize=1, fmt=fmt, readonly=1,
4271 ndim=1, shape=[12], strides=[1],
4272 lst=lst)
4273 for i in range(12):
4274 self.assertEqual(y[i], i)
4275 del x
4276 del y
4277
4278 x = staticarray(legacy_mode=True)
4279 y = memoryview(x)
4280 del y
4281 del x
4282
4283 x = staticarray(legacy_mode=True)
4284 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4285 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4286 m = memoryview(z)
4287 self.assertIs(y.obj, None)
4288 self.assertIs(m.obj, z)
4289 self.verify(m, obj=z,
4290 itemsize=1, fmt=fmt, readonly=1,
4291 ndim=1, shape=[12], strides=[1],
4292 lst=lst)
4293 del x, y, z, m
4294
4295 x = staticarray(legacy_mode=True)
4296 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4297 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4298 m = memoryview(z)
4299 # Clearly setting view.obj==NULL is inferior, since it
4300 # messes up the redirection chain:
4301 self.assertIs(y.obj, None)
4302 self.assertIs(z.obj, y)
4303 self.assertIs(m.obj, y)
4304 self.verify(m, obj=y,
4305 itemsize=1, fmt=fmt, readonly=1,
4306 ndim=1, shape=[12], strides=[1],
4307 lst=lst)
4308 del x, y, z, m
4309
Stefan Krah1649c1b2012-03-05 17:45:17 +01004310 def test_memoryview_getbuffer_undefined(self):
4311
4312 # getbufferproc does not adhere to the new documentation
4313 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4314 self.assertRaises(BufferError, memoryview, nd)
4315
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004316 def test_issue_7385(self):
4317 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4318 self.assertRaises(BufferError, memoryview, x)
4319
4320
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004321if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004322 unittest.main()