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