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