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