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