blob: 6803156be52f8ad56d8c1649da94cce61bd39d0d [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):
2562 if (not is_memoryview_format(sfmt) or
2563 not is_memoryview_format(dfmt)):
2564 self.assertRaises(ValueError, msrc.cast, dfmt,
2565 [32//dsize])
2566 else:
2567 if not is_byte_format(sfmt) and not is_byte_format(dfmt):
2568 self.assertRaises(TypeError, msrc.cast, dfmt,
2569 [32//dsize])
2570
2571 # invalid shape
2572 size_h = struct.calcsize('h')
2573 size_d = struct.calcsize('d')
2574 ex = ndarray(list(range(2*2*size_d)), shape=[2,2,size_d], format='h')
2575 msrc = memoryview(ex)
2576 self.assertRaises(TypeError, msrc.cast, shape=[2,2,size_h], format='d')
2577
2578 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2579 m = memoryview(ex)
2580
2581 # incorrect number of args
2582 self.assertRaises(TypeError, m.cast)
2583 self.assertRaises(TypeError, m.cast, 1, 2, 3)
2584
2585 # incorrect dest format type
2586 self.assertRaises(TypeError, m.cast, {})
2587
2588 # incorrect dest format
2589 self.assertRaises(ValueError, m.cast, "X")
2590 self.assertRaises(ValueError, m.cast, "@X")
2591 self.assertRaises(ValueError, m.cast, "@XY")
2592
2593 # dest format not implemented
2594 self.assertRaises(ValueError, m.cast, "=B")
2595 self.assertRaises(ValueError, m.cast, "!L")
2596 self.assertRaises(ValueError, m.cast, "<P")
2597 self.assertRaises(ValueError, m.cast, ">l")
2598 self.assertRaises(ValueError, m.cast, "BI")
2599 self.assertRaises(ValueError, m.cast, "xBI")
2600
2601 # src format not implemented
2602 ex = ndarray([(1,2), (3,4)], shape=[2], format="II")
2603 m = memoryview(ex)
2604 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2605 self.assertRaises(NotImplementedError, m.__setitem__, 0, 8)
2606 self.assertRaises(NotImplementedError, m.tolist)
2607
2608 # incorrect shape type
2609 ex = ndarray(list(range(120)), shape=[1,2,3,4,5])
2610 m = memoryview(ex)
2611 self.assertRaises(TypeError, m.cast, "B", shape={})
2612
2613 # incorrect shape elements
2614 ex = ndarray(list(range(120)), shape=[2*3*4*5])
2615 m = memoryview(ex)
2616 self.assertRaises(OverflowError, m.cast, "B", shape=[2**64])
2617 self.assertRaises(ValueError, m.cast, "B", shape=[-1])
2618 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,-1])
2619 self.assertRaises(ValueError, m.cast, "B", shape=[2,3,4,5,6,7,0])
2620 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5,6,7,'x'])
2621
2622 # N-D -> N-D cast
2623 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3,5,7,11])
2624 m = memoryview(ex)
2625 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2626
2627 # cast with ndim > 64
2628 nd = ndarray(list(range(128)), shape=[128], format='I')
2629 m = memoryview(nd)
2630 self.assertRaises(ValueError, m.cast, 'I', [1]*128)
2631
2632 # view->len not a multiple of itemsize
2633 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2634 m = memoryview(ex)
2635 self.assertRaises(TypeError, m.cast, "I", shape=[2,3,4,5])
2636
2637 # product(shape) * itemsize != buffer size
2638 ex = ndarray(list([9 for _ in range(3*5*7*11)]), shape=[3*5*7*11])
2639 m = memoryview(ex)
2640 self.assertRaises(TypeError, m.cast, "B", shape=[2,3,4,5])
2641
2642 # product(shape) * itemsize overflow
2643 nd = ndarray(list(range(128)), shape=[128], format='I')
2644 m1 = memoryview(nd)
2645 nd = ndarray(list(range(128)), shape=[128], format='B')
2646 m2 = memoryview(nd)
2647 if sys.maxsize == 2**63-1:
2648 self.assertRaises(TypeError, m1.cast, 'B',
2649 [7, 7, 73, 127, 337, 92737, 649657])
2650 self.assertRaises(ValueError, m1.cast, 'B',
2651 [2**20, 2**20, 2**10, 2**10, 2**3])
2652 self.assertRaises(ValueError, m2.cast, 'I',
2653 [2**20, 2**20, 2**10, 2**10, 2**1])
2654 else:
2655 self.assertRaises(TypeError, m1.cast, 'B',
2656 [1, 2147483647])
2657 self.assertRaises(ValueError, m1.cast, 'B',
2658 [2**10, 2**10, 2**5, 2**5, 2**1])
2659 self.assertRaises(ValueError, m2.cast, 'I',
2660 [2**10, 2**10, 2**5, 2**3, 2**1])
2661
2662 def test_memoryview_cast(self):
2663 bytespec = (
2664 ('B', lambda ex: list(ex.tobytes())),
2665 ('b', lambda ex: [x-256 if x > 127 else x for x in list(ex.tobytes())]),
2666 ('c', lambda ex: [bytes(chr(x), 'latin-1') for x in list(ex.tobytes())]),
2667 )
2668
2669 def iter_roundtrip(ex, m, items, fmt):
2670 srcsize = struct.calcsize(fmt)
2671 for bytefmt, to_bytelist in bytespec:
2672
2673 m2 = m.cast(bytefmt)
2674 lst = to_bytelist(ex)
2675 self.verify(m2, obj=ex,
2676 itemsize=1, fmt=bytefmt, readonly=0,
2677 ndim=1, shape=[31*srcsize], strides=(1,),
2678 lst=lst, cast=True)
2679
2680 m3 = m2.cast(fmt)
2681 self.assertEqual(m3, ex)
2682 lst = ex.tolist()
2683 self.verify(m3, obj=ex,
2684 itemsize=srcsize, fmt=fmt, readonly=0,
2685 ndim=1, shape=[31], strides=(srcsize,),
2686 lst=lst, cast=True)
2687
2688 # cast from ndim = 0 to ndim = 1
2689 srcsize = struct.calcsize('I')
2690 ex = ndarray(9, shape=[], format='I')
2691 destitems, destshape = cast_items(ex, 'B', 1)
2692 m = memoryview(ex)
2693 m2 = m.cast('B')
2694 self.verify(m2, obj=ex,
2695 itemsize=1, fmt='B', readonly=1,
2696 ndim=1, shape=destshape, strides=(1,),
2697 lst=destitems, cast=True)
2698
2699 # cast from ndim = 1 to ndim = 0
2700 destsize = struct.calcsize('I')
2701 ex = ndarray([9]*destsize, shape=[destsize], format='B')
2702 destitems, destshape = cast_items(ex, 'I', destsize, shape=[])
2703 m = memoryview(ex)
2704 m2 = m.cast('I', shape=[])
2705 self.verify(m2, obj=ex,
2706 itemsize=destsize, fmt='I', readonly=1,
2707 ndim=0, shape=(), strides=(),
2708 lst=destitems, cast=True)
2709
2710 # array.array: roundtrip to/from bytes
2711 for fmt, items, _ in iter_format(31, 'array'):
2712 ex = array.array(fmt, items)
2713 m = memoryview(ex)
2714 iter_roundtrip(ex, m, items, fmt)
2715
2716 # ndarray: roundtrip to/from bytes
2717 for fmt, items, _ in iter_format(31, 'memoryview'):
2718 ex = ndarray(items, shape=[31], format=fmt, flags=ND_WRITABLE)
2719 m = memoryview(ex)
2720 iter_roundtrip(ex, m, items, fmt)
2721
2722 def test_memoryview_cast_1D_ND(self):
2723 # Cast between C-contiguous buffers. At least one buffer must
2724 # be 1D, at least one format must be 'c', 'b' or 'B'.
2725 for _tshape in gencastshapes():
2726 for char in fmtdict['@']:
2727 tfmt = ('', '@')[randrange(2)] + char
2728 tsize = struct.calcsize(tfmt)
2729 n = prod(_tshape) * tsize
2730 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2731 for fmt, items, _ in iter_format(n, obj):
2732 size = struct.calcsize(fmt)
2733 shape = [n] if n > 0 else []
2734 tshape = _tshape + [size]
2735
2736 ex = ndarray(items, shape=shape, format=fmt)
2737 m = memoryview(ex)
2738
2739 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2740
2741 if titems is None:
2742 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2743 continue
2744 if titems == 'nan':
2745 continue # NaNs in lists are a recipe for trouble.
2746
2747 # 1D -> ND
2748 nd = ndarray(titems, shape=tshape, format=tfmt)
2749
2750 m2 = m.cast(tfmt, shape=tshape)
2751 ndim = len(tshape)
2752 strides = nd.strides
2753 lst = nd.tolist()
2754 self.verify(m2, obj=ex,
2755 itemsize=tsize, fmt=tfmt, readonly=1,
2756 ndim=ndim, shape=tshape, strides=strides,
2757 lst=lst, cast=True)
2758
2759 # ND -> 1D
2760 m3 = m2.cast(fmt)
2761 m4 = m2.cast(fmt, shape=shape)
2762 ndim = len(shape)
2763 strides = ex.strides
2764 lst = ex.tolist()
2765
2766 self.verify(m3, obj=ex,
2767 itemsize=size, fmt=fmt, readonly=1,
2768 ndim=ndim, shape=shape, strides=strides,
2769 lst=lst, cast=True)
2770
2771 self.verify(m4, obj=ex,
2772 itemsize=size, fmt=fmt, readonly=1,
2773 ndim=ndim, shape=shape, strides=strides,
2774 lst=lst, cast=True)
2775
2776 def test_memoryview_tolist(self):
2777
2778 # Most tolist() tests are in self.verify() etc.
2779
2780 a = array.array('h', list(range(-6, 6)))
2781 m = memoryview(a)
2782 self.assertEqual(m, a)
2783 self.assertEqual(m.tolist(), a.tolist())
2784
2785 a = a[2::3]
2786 m = m[2::3]
2787 self.assertEqual(m, a)
2788 self.assertEqual(m.tolist(), a.tolist())
2789
2790 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2791 m = memoryview(ex)
2792 self.assertEqual(m.tolist(), ex.tolist())
2793
2794 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2795 m = memoryview(ex)
2796 self.assertRaises(NotImplementedError, m.tolist)
2797
2798 ex = ndarray([b'12345'], shape=[1], format="s")
2799 m = memoryview(ex)
2800 self.assertRaises(NotImplementedError, m.tolist)
2801
2802 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2803 m = memoryview(ex)
2804 self.assertRaises(NotImplementedError, m.tolist)
2805
2806 def test_memoryview_repr(self):
2807 m = memoryview(bytearray(9))
2808 r = m.__repr__()
2809 self.assertTrue(r.startswith("<memory"))
2810
2811 m.release()
2812 r = m.__repr__()
2813 self.assertTrue(r.startswith("<released"))
2814
2815 def test_memoryview_sequence(self):
2816
2817 for fmt in ('d', 'f'):
2818 inf = float(3e400)
2819 ex = array.array(fmt, [1.0, inf, 3.0])
2820 m = memoryview(ex)
2821 self.assertIn(1.0, m)
2822 self.assertIn(5e700, m)
2823 self.assertIn(3.0, m)
2824
2825 ex = ndarray(9.0, [], format='f')
2826 m = memoryview(ex)
2827 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2828
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002829 @contextlib.contextmanager
2830 def assert_out_of_bounds_error(self, dim):
2831 with self.assertRaises(IndexError) as cm:
2832 yield
2833 self.assertEqual(str(cm.exception),
2834 "index out of bounds on dimension %d" % (dim,))
2835
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002836 def test_memoryview_index(self):
2837
2838 # ndim = 0
2839 ex = ndarray(12.5, shape=[], format='d')
2840 m = memoryview(ex)
2841 self.assertEqual(m[()], 12.5)
2842 self.assertEqual(m[...], m)
2843 self.assertEqual(m[...], ex)
2844 self.assertRaises(TypeError, m.__getitem__, 0)
2845
2846 ex = ndarray((1,2,3), shape=[], format='iii')
2847 m = memoryview(ex)
2848 self.assertRaises(NotImplementedError, m.__getitem__, ())
2849
2850 # range
2851 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2852 m = memoryview(ex)
2853
2854 self.assertRaises(IndexError, m.__getitem__, 2**64)
2855 self.assertRaises(TypeError, m.__getitem__, 2.0)
2856 self.assertRaises(TypeError, m.__getitem__, 0.0)
2857
2858 # out of bounds
2859 self.assertRaises(IndexError, m.__getitem__, -8)
2860 self.assertRaises(IndexError, m.__getitem__, 8)
2861
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002862 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002863 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2864 m = memoryview(ex)
2865
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002866 self.assertEqual(m[0, 0], 0)
2867 self.assertEqual(m[2, 0], 8)
2868 self.assertEqual(m[2, 3], 11)
2869 self.assertEqual(m[-1, -1], 11)
2870 self.assertEqual(m[-3, -4], 0)
2871
2872 # out of bounds
2873 for index in (3, -4):
2874 with self.assert_out_of_bounds_error(dim=1):
2875 m[index, 0]
2876 for index in (4, -5):
2877 with self.assert_out_of_bounds_error(dim=2):
2878 m[0, index]
2879 self.assertRaises(IndexError, m.__getitem__, (2**64, 0))
2880 self.assertRaises(IndexError, m.__getitem__, (0, 2**64))
2881
2882 self.assertRaises(TypeError, m.__getitem__, (0, 0, 0))
2883 self.assertRaises(TypeError, m.__getitem__, (0.0, 0.0))
2884
2885 # Not implemented: multidimensional sub-views
2886 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002887 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2888
2889 def test_memoryview_assign(self):
2890
2891 # ndim = 0
2892 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2893 m = memoryview(ex)
2894 m[()] = 22.5
2895 self.assertEqual(m[()], 22.5)
2896 m[...] = 23.5
2897 self.assertEqual(m[()], 23.5)
2898 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2899
2900 # read-only
2901 ex = ndarray(list(range(7)), shape=[7])
2902 m = memoryview(ex)
2903 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2904
2905 # range
2906 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2907 m = memoryview(ex)
2908
2909 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2910 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2911 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2912
2913 # out of bounds
2914 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2915 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2916
2917 # pack_single() success:
2918 for fmt in fmtdict['@']:
2919 if fmt == 'c' or fmt == '?':
2920 continue
2921 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2922 m = memoryview(ex)
2923 i = randrange(-3, 3)
2924 m[i] = 8
2925 self.assertEqual(m[i], 8)
2926 self.assertEqual(m[i], ex[i])
2927
2928 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2929 flags=ND_WRITABLE)
2930 m = memoryview(ex)
2931 m[2] = b'9'
2932 self.assertEqual(m[2], b'9')
2933
2934 ex = ndarray([True, False, True], shape=[3], format='?',
2935 flags=ND_WRITABLE)
2936 m = memoryview(ex)
2937 m[1] = True
2938 self.assertEqual(m[1], True)
2939
2940 # pack_single() exceptions:
2941 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2942 m = memoryview(nd)
2943 self.assertRaises(TypeError, m.__setitem__, 0, 100)
2944
2945 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
2946 m1 = memoryview(ex)
2947
2948 for fmt, _range in fmtdict['@'].items():
2949 if (fmt == '?'): # PyObject_IsTrue() accepts anything
2950 continue
2951 if fmt == 'c': # special case tested above
2952 continue
2953 m2 = m1.cast(fmt)
2954 lo, hi = _range
2955 if fmt == 'd' or fmt == 'f':
2956 lo, hi = -2**1024, 2**1024
2957 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
2958 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
2959 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
2960 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
2961
2962 # invalid item
2963 m2 = m1.cast('c')
2964 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
2965
2966 # format not implemented
2967 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
2968 m = memoryview(ex)
2969 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2970
2971 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
2972 m = memoryview(ex)
2973 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
2974
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002975 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002976 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2977 m = memoryview(ex)
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002978 m[0,1] = 42
2979 self.assertEqual(ex[0][1], 42)
2980 m[-1,-1] = 43
2981 self.assertEqual(ex[2][3], 43)
2982 # errors
2983 for index in (3, -4):
2984 with self.assert_out_of_bounds_error(dim=1):
2985 m[index, 0] = 0
2986 for index in (4, -5):
2987 with self.assert_out_of_bounds_error(dim=2):
2988 m[0, index] = 0
2989 self.assertRaises(IndexError, m.__setitem__, (2**64, 0), 0)
2990 self.assertRaises(IndexError, m.__setitem__, (0, 2**64), 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002991
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002992 self.assertRaises(TypeError, m.__setitem__, (0, 0, 0), 0)
2993 self.assertRaises(TypeError, m.__setitem__, (0.0, 0.0), 0)
2994
2995 # Not implemented: multidimensional sub-views
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002996 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
2997
2998 def test_memoryview_slice(self):
2999
3000 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3001 m = memoryview(ex)
3002
3003 # zero step
3004 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
3005 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
3006 bytearray([1,2]))
3007
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003008 # 0-dim slicing (identity function)
3009 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003010
3011 # multidimensional slices
3012 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3013 m = memoryview(ex)
3014
3015 self.assertRaises(NotImplementedError, m.__getitem__,
3016 (slice(0,2,1), slice(0,2,1)))
3017 self.assertRaises(NotImplementedError, m.__setitem__,
3018 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
3019
3020 # invalid slice tuple
3021 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
3022 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
3023 bytearray([1,2]))
3024
3025 # rvalue is not an exporter
3026 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
3027
3028 # non-contiguous slice assignment
3029 for flags in (0, ND_PIL):
3030 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
3031 flags=ND_WRITABLE|flags)
3032 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
3033 m1 = memoryview(ex1)
3034 m2 = memoryview(ex2)
3035
3036 ex1[2:5] = ex1[2:5]
3037 m1[2:5] = m2[2:5]
3038
3039 self.assertEqual(m1, ex1)
3040 self.assertEqual(m2, ex2)
3041
3042 ex1[1:3][::-1] = ex2[0:2][::1]
3043 m1[1:3][::-1] = m2[0:2][::1]
3044
3045 self.assertEqual(m1, ex1)
3046 self.assertEqual(m2, ex2)
3047
3048 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
3049 m1[4:1:-2][::-1] = m1[1:4:2][::1]
3050
3051 self.assertEqual(m1, ex1)
3052 self.assertEqual(m2, ex2)
3053
3054 def test_memoryview_array(self):
3055
3056 def cmptest(testcase, a, b, m, singleitem):
3057 for i, _ in enumerate(a):
3058 ai = a[i]
3059 mi = m[i]
3060 testcase.assertEqual(ai, mi)
3061 a[i] = singleitem
3062 if singleitem != ai:
3063 testcase.assertNotEqual(a, m)
3064 testcase.assertNotEqual(a, b)
3065 else:
3066 testcase.assertEqual(a, m)
3067 testcase.assertEqual(a, b)
3068 m[i] = singleitem
3069 testcase.assertEqual(a, m)
3070 testcase.assertEqual(b, m)
3071 a[i] = ai
3072 m[i] = mi
3073
3074 for n in range(1, 5):
3075 for fmt, items, singleitem in iter_format(n, 'array'):
3076 for lslice in genslices(n):
3077 for rslice in genslices(n):
3078
3079 a = array.array(fmt, items)
3080 b = array.array(fmt, items)
3081 m = memoryview(b)
3082
3083 self.assertEqual(m, a)
3084 self.assertEqual(m.tolist(), a.tolist())
3085 self.assertEqual(m.tobytes(), a.tobytes())
3086 self.assertEqual(len(m), len(a))
3087
3088 cmptest(self, a, b, m, singleitem)
3089
3090 array_err = None
3091 have_resize = None
3092 try:
3093 al = a[lslice]
3094 ar = a[rslice]
3095 a[lslice] = a[rslice]
3096 have_resize = len(al) != len(ar)
3097 except Exception as e:
3098 array_err = e.__class__
3099
3100 m_err = None
3101 try:
3102 m[lslice] = m[rslice]
3103 except Exception as e:
3104 m_err = e.__class__
3105
3106 if have_resize: # memoryview cannot change shape
3107 self.assertIs(m_err, ValueError)
3108 elif m_err or array_err:
3109 self.assertIs(m_err, array_err)
3110 else:
3111 self.assertEqual(m, a)
3112 self.assertEqual(m.tolist(), a.tolist())
3113 self.assertEqual(m.tobytes(), a.tobytes())
3114 cmptest(self, a, b, m, singleitem)
3115
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003116 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003117
3118 a = array.array('L', [1, 2, 3])
3119 b = array.array('L', [1, 2, 7])
3120
3121 # Ordering comparisons raise:
3122 v = memoryview(a)
3123 w = memoryview(b)
3124 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3125 self.assertIs(getattr(v, attr)(w), NotImplemented)
3126 self.assertIs(getattr(a, attr)(v), NotImplemented)
3127
3128 # Released views compare equal to themselves:
3129 v = memoryview(a)
3130 v.release()
3131 self.assertEqual(v, v)
3132 self.assertNotEqual(v, a)
3133 self.assertNotEqual(a, v)
3134
3135 v = memoryview(a)
3136 w = memoryview(a)
3137 w.release()
3138 self.assertNotEqual(v, w)
3139 self.assertNotEqual(w, v)
3140
3141 # Operand does not implement the buffer protocol:
3142 v = memoryview(a)
3143 self.assertNotEqual(v, [1, 2, 3])
3144
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003145 # NaNs
3146 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3147 nd[0] = (-1, float('nan'))
3148 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003149
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003150 # Depends on issue #15625: the struct module does not understand 'u'.
3151 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003152 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003153 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003154 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003155
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003156 # Some ctypes format strings are unknown to the struct module.
3157 if ctypes:
3158 # format: "T{>l:x:>l:y:}"
3159 class BEPoint(ctypes.BigEndianStructure):
3160 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3161 point = BEPoint(100, 200)
3162 a = memoryview(point)
3163 b = memoryview(point)
3164 self.assertNotEqual(a, b)
3165 self.assertNotEqual(a, point)
3166 self.assertNotEqual(point, a)
3167 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003168
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003169 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003170
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003171 nd1 = ndarray(1729, shape=[], format='@L')
3172 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
3173 v = memoryview(nd1)
3174 w = memoryview(nd2)
3175 self.assertEqual(v, w)
3176 self.assertEqual(w, v)
3177 self.assertEqual(v, nd2)
3178 self.assertEqual(nd2, v)
3179 self.assertEqual(w, nd1)
3180 self.assertEqual(nd1, w)
3181
3182 self.assertFalse(v.__ne__(w))
3183 self.assertFalse(w.__ne__(v))
3184
3185 w[()] = 1728
3186 self.assertNotEqual(v, w)
3187 self.assertNotEqual(w, v)
3188 self.assertNotEqual(v, nd2)
3189 self.assertNotEqual(nd2, v)
3190 self.assertNotEqual(w, nd1)
3191 self.assertNotEqual(nd1, w)
3192
3193 self.assertFalse(v.__eq__(w))
3194 self.assertFalse(w.__eq__(v))
3195
3196 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3197 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3198 m = memoryview(ex)
3199
3200 self.assertEqual(m, nd)
3201 m[9] = 100
3202 self.assertNotEqual(m, nd)
3203
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003204 # struct module: equal
3205 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3206 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3207 flags=ND_WRITABLE)
3208 v = memoryview(nd1)
3209 w = memoryview(nd2)
3210 self.assertEqual(v, w)
3211 self.assertEqual(w, v)
3212 self.assertEqual(v, nd2)
3213 self.assertEqual(nd2, v)
3214 self.assertEqual(w, nd1)
3215 self.assertEqual(nd1, w)
3216
3217 # struct module: not equal
3218 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3219 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3220 flags=ND_WRITABLE)
3221 v = memoryview(nd1)
3222 w = memoryview(nd2)
3223 self.assertNotEqual(v, w)
3224 self.assertNotEqual(w, v)
3225 self.assertNotEqual(v, nd2)
3226 self.assertNotEqual(nd2, v)
3227 self.assertNotEqual(w, nd1)
3228 self.assertNotEqual(nd1, w)
3229 self.assertEqual(v, nd1)
3230 self.assertEqual(w, nd2)
3231
3232 def test_memoryview_compare_ndim_one(self):
3233
3234 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003235 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3236 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3237 v = memoryview(nd1)
3238 w = memoryview(nd2)
3239
3240 self.assertEqual(v, nd1)
3241 self.assertEqual(w, nd2)
3242 self.assertNotEqual(v, nd2)
3243 self.assertNotEqual(w, nd1)
3244 self.assertNotEqual(v, w)
3245
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003246 # contiguous, struct module
3247 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3248 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3249 v = memoryview(nd1)
3250 w = memoryview(nd2)
3251
3252 self.assertEqual(v, nd1)
3253 self.assertEqual(w, nd2)
3254 self.assertNotEqual(v, nd2)
3255 self.assertNotEqual(w, nd1)
3256 self.assertNotEqual(v, w)
3257
3258 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003259 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3260 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3261 v = memoryview(nd1)
3262 w = memoryview(nd2)
3263
3264 self.assertEqual(v, nd2[::2])
3265 self.assertEqual(w[::2], nd1)
3266 self.assertEqual(v, w[::2])
3267 self.assertEqual(v[::-1], w[::-2])
3268
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003269 # non-contiguous, struct module
3270 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3271 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3272 v = memoryview(nd1)
3273 w = memoryview(nd2)
3274
3275 self.assertEqual(v, nd2[::2])
3276 self.assertEqual(w[::2], nd1)
3277 self.assertEqual(v, w[::2])
3278 self.assertEqual(v[::-1], w[::-2])
3279
3280 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003281 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3282 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3283 flags=ND_PIL)
3284 v = memoryview(nd1)
3285 w = memoryview(nd2)
3286
3287 self.assertEqual(v, nd2[::2])
3288 self.assertEqual(w[::2], nd1)
3289 self.assertEqual(v, w[::2])
3290 self.assertEqual(v[::-1], w[::-2])
3291
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003292 # non-contiguous, suboffsets, struct module
3293 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3294 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3295 flags=ND_PIL)
3296 v = memoryview(nd1)
3297 w = memoryview(nd2)
3298
3299 self.assertEqual(v, nd2[::2])
3300 self.assertEqual(w[::2], nd1)
3301 self.assertEqual(v, w[::2])
3302 self.assertEqual(v[::-1], w[::-2])
3303
3304 def test_memoryview_compare_zero_shape(self):
3305
3306 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003307 nd1 = ndarray([900, 961], shape=[0], format='@h')
3308 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3309 v = memoryview(nd1)
3310 w = memoryview(nd2)
3311
3312 self.assertEqual(v, nd1)
3313 self.assertEqual(w, nd2)
3314 self.assertEqual(v, nd2)
3315 self.assertEqual(w, nd1)
3316 self.assertEqual(v, w)
3317
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003318 # zeros in shape, struct module
3319 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3320 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3321 v = memoryview(nd1)
3322 w = memoryview(nd2)
3323
3324 self.assertEqual(v, nd1)
3325 self.assertEqual(w, nd2)
3326 self.assertEqual(v, nd2)
3327 self.assertEqual(w, nd1)
3328 self.assertEqual(v, w)
3329
3330 def test_memoryview_compare_zero_strides(self):
3331
3332 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003333 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3334 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3335 v = memoryview(nd1)
3336 w = memoryview(nd2)
3337
3338 self.assertEqual(v, nd1)
3339 self.assertEqual(w, nd2)
3340 self.assertEqual(v, nd2)
3341 self.assertEqual(w, nd1)
3342 self.assertEqual(v, w)
3343
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003344 # zero strides, struct module
3345 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3346 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3347 v = memoryview(nd1)
3348 w = memoryview(nd2)
3349
3350 self.assertEqual(v, nd1)
3351 self.assertEqual(w, nd2)
3352 self.assertEqual(v, nd2)
3353 self.assertEqual(w, nd1)
3354 self.assertEqual(v, w)
3355
3356 def test_memoryview_compare_random_formats(self):
3357
3358 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003359 n = 10
3360 for char in fmtdict['@m']:
3361 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3362 for flags in (0, ND_PIL):
3363 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3364 m = memoryview(nd)
3365 self.assertEqual(m, nd)
3366
3367 nd = nd[::-3]
3368 m = memoryview(nd)
3369 self.assertEqual(m, nd)
3370
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003371 # random formats
3372 n = 10
3373 for _ in range(100):
3374 fmt, items, singleitem = randitems(n)
3375 for flags in (0, ND_PIL):
3376 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3377 m = memoryview(nd)
3378 self.assertEqual(m, nd)
3379
3380 nd = nd[::-3]
3381 m = memoryview(nd)
3382 self.assertEqual(m, nd)
3383
3384 def test_memoryview_compare_multidim_c(self):
3385
3386 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003387 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3388 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3389 v = memoryview(nd1)
3390 w = memoryview(nd2)
3391
3392 self.assertEqual(v, nd1)
3393 self.assertEqual(w, nd2)
3394 self.assertNotEqual(v, nd2)
3395 self.assertNotEqual(w, nd1)
3396 self.assertNotEqual(v, w)
3397
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003398 # C-contiguous, different values, struct module
3399 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3400 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3401 v = memoryview(nd1)
3402 w = memoryview(nd2)
3403
3404 self.assertEqual(v, nd1)
3405 self.assertEqual(w, nd2)
3406 self.assertNotEqual(v, nd2)
3407 self.assertNotEqual(w, nd1)
3408 self.assertNotEqual(v, w)
3409
3410 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003411 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3412 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3413 v = memoryview(nd1)
3414 w = memoryview(nd2)
3415
3416 self.assertEqual(v, nd1)
3417 self.assertEqual(w, nd2)
3418 self.assertNotEqual(v, nd2)
3419 self.assertNotEqual(w, nd1)
3420 self.assertNotEqual(v, w)
3421
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003422 # C-contiguous, different shape, struct module
3423 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3424 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003425 v = memoryview(nd1)
3426 w = memoryview(nd2)
3427
3428 self.assertEqual(v, nd1)
3429 self.assertEqual(w, nd2)
3430 self.assertNotEqual(v, nd2)
3431 self.assertNotEqual(w, nd1)
3432 self.assertNotEqual(v, w)
3433
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003434 # C-contiguous, different format, struct module
3435 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3436 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3437 v = memoryview(nd1)
3438 w = memoryview(nd2)
3439
3440 self.assertEqual(v, nd1)
3441 self.assertEqual(w, nd2)
3442 self.assertEqual(v, nd2)
3443 self.assertEqual(w, nd1)
3444 self.assertEqual(v, w)
3445
3446 def test_memoryview_compare_multidim_fortran(self):
3447
3448 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003449 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3450 flags=ND_FORTRAN)
3451 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3452 flags=ND_FORTRAN)
3453 v = memoryview(nd1)
3454 w = memoryview(nd2)
3455
3456 self.assertEqual(v, nd1)
3457 self.assertEqual(w, nd2)
3458 self.assertNotEqual(v, nd2)
3459 self.assertNotEqual(w, nd1)
3460 self.assertNotEqual(v, w)
3461
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003462 # Fortran-contiguous, different values, struct module
3463 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3464 flags=ND_FORTRAN)
3465 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3466 flags=ND_FORTRAN)
3467 v = memoryview(nd1)
3468 w = memoryview(nd2)
3469
3470 self.assertEqual(v, nd1)
3471 self.assertEqual(w, nd2)
3472 self.assertNotEqual(v, nd2)
3473 self.assertNotEqual(w, nd1)
3474 self.assertNotEqual(v, w)
3475
3476 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003477 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3478 flags=ND_FORTRAN)
3479 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3480 flags=ND_FORTRAN)
3481 v = memoryview(nd1)
3482 w = memoryview(nd2)
3483
3484 self.assertEqual(v, nd1)
3485 self.assertEqual(w, nd2)
3486 self.assertNotEqual(v, nd2)
3487 self.assertNotEqual(w, nd1)
3488 self.assertNotEqual(v, w)
3489
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003490 # Fortran-contiguous, different shape, struct module
3491 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003492 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003493 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003494 flags=ND_FORTRAN)
3495 v = memoryview(nd1)
3496 w = memoryview(nd2)
3497
3498 self.assertEqual(v, nd1)
3499 self.assertEqual(w, nd2)
3500 self.assertNotEqual(v, nd2)
3501 self.assertNotEqual(w, nd1)
3502 self.assertNotEqual(v, w)
3503
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003504 # Fortran-contiguous, different format, struct module
3505 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3506 flags=ND_FORTRAN)
3507 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3508 flags=ND_FORTRAN)
3509 v = memoryview(nd1)
3510 w = memoryview(nd2)
3511
3512 self.assertEqual(v, nd1)
3513 self.assertEqual(w, nd2)
3514 self.assertEqual(v, nd2)
3515 self.assertEqual(w, nd1)
3516 self.assertEqual(v, w)
3517
3518 def test_memoryview_compare_multidim_mixed(self):
3519
3520 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003521 lst1 = list(range(-15, 15))
3522 lst2 = transpose(lst1, [3, 2, 5])
3523 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3524 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3525 v = memoryview(nd1)
3526 w = memoryview(nd2)
3527
3528 self.assertEqual(v, nd1)
3529 self.assertEqual(w, nd2)
3530 self.assertEqual(v, w)
3531
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003532 # mixed C/Fortran contiguous, struct module
3533 lst1 = [(-3.3, -22, b'x')]*30
3534 lst1[5] = (-2.2, -22, b'x')
3535 lst2 = transpose(lst1, [3, 2, 5])
3536 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3537 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3538 v = memoryview(nd1)
3539 w = memoryview(nd2)
3540
3541 self.assertEqual(v, nd1)
3542 self.assertEqual(w, nd2)
3543 self.assertEqual(v, w)
3544
3545 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003546 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3547 nd1 = ex1[3:1:-1, ::-2]
3548 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3549 nd2 = ex2[1:3:1, ::-2]
3550 v = memoryview(nd1)
3551 w = memoryview(nd2)
3552
3553 self.assertEqual(v, nd1)
3554 self.assertEqual(w, nd2)
3555 self.assertNotEqual(v, nd2)
3556 self.assertNotEqual(w, nd1)
3557 self.assertNotEqual(v, w)
3558
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003559 # same values, non-contiguous, struct module
3560 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3561 nd1 = ex1[3:1:-1, ::-2]
3562 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3563 nd2 = ex2[1:3:1, ::-2]
3564 v = memoryview(nd1)
3565 w = memoryview(nd2)
3566
3567 self.assertEqual(v, nd1)
3568 self.assertEqual(w, nd2)
3569 self.assertEqual(v, nd2)
3570 self.assertEqual(w, nd1)
3571 self.assertEqual(v, w)
3572
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003573 # different shape
3574 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3575 nd1 = ex1[1:3:, ::-2]
3576 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3577 nd2 = ex2[1:3:, ::-2]
3578 v = memoryview(nd1)
3579 w = memoryview(nd2)
3580
3581 self.assertEqual(v, nd1)
3582 self.assertEqual(w, nd2)
3583 self.assertNotEqual(v, nd2)
3584 self.assertNotEqual(w, nd1)
3585 self.assertNotEqual(v, w)
3586
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003587 # different shape, struct module
3588 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003589 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003590 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003591 nd2 = ex2[1:3:, ::-2]
3592 v = memoryview(nd1)
3593 w = memoryview(nd2)
3594
3595 self.assertEqual(v, nd1)
3596 self.assertEqual(w, nd2)
3597 self.assertNotEqual(v, nd2)
3598 self.assertNotEqual(w, nd1)
3599 self.assertNotEqual(v, w)
3600
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003601 # different format, struct module
3602 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3603 nd1 = ex1[1:3:, ::-2]
3604 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3605 nd2 = ex2[1:3:, ::-2]
3606 v = memoryview(nd1)
3607 w = memoryview(nd2)
3608
3609 self.assertEqual(v, nd1)
3610 self.assertEqual(w, nd2)
3611 self.assertNotEqual(v, nd2)
3612 self.assertNotEqual(w, nd1)
3613 self.assertNotEqual(v, w)
3614
3615 def test_memoryview_compare_multidim_zero_shape(self):
3616
3617 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003618 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3619 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3620 v = memoryview(nd1)
3621 w = memoryview(nd2)
3622
3623 self.assertEqual(v, nd1)
3624 self.assertEqual(w, nd2)
3625 self.assertNotEqual(v, nd2)
3626 self.assertNotEqual(w, nd1)
3627 self.assertNotEqual(v, w)
3628
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003629 # zeros in shape, struct module
3630 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3631 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3632 v = memoryview(nd1)
3633 w = memoryview(nd2)
3634
3635 self.assertEqual(v, nd1)
3636 self.assertEqual(w, nd2)
3637 self.assertNotEqual(v, nd2)
3638 self.assertNotEqual(w, nd1)
3639 self.assertNotEqual(v, w)
3640
3641 def test_memoryview_compare_multidim_zero_strides(self):
3642
3643 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003644 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3645 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3646 v = memoryview(nd1)
3647 w = memoryview(nd2)
3648
3649 self.assertEqual(v, nd1)
3650 self.assertEqual(w, nd2)
3651 self.assertEqual(v, nd2)
3652 self.assertEqual(w, nd1)
3653 self.assertEqual(v, w)
3654 self.assertEqual(v.tolist(), w.tolist())
3655
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003656 # zero strides, struct module
3657 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3658 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3659 v = memoryview(nd1)
3660 w = memoryview(nd2)
3661
3662 self.assertEqual(v, nd1)
3663 self.assertEqual(w, nd2)
3664 self.assertEqual(v, nd2)
3665 self.assertEqual(w, nd1)
3666 self.assertEqual(v, w)
3667
3668 def test_memoryview_compare_multidim_suboffsets(self):
3669
3670 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003671 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3672 nd1 = ex1[3:1:-1, ::-2]
3673 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3674 nd2 = ex2[1:3:1, ::-2]
3675 v = memoryview(nd1)
3676 w = memoryview(nd2)
3677
3678 self.assertEqual(v, nd1)
3679 self.assertEqual(w, nd2)
3680 self.assertNotEqual(v, nd2)
3681 self.assertNotEqual(w, nd1)
3682 self.assertNotEqual(v, w)
3683
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003684 # suboffsets, struct module
3685 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3686 flags=ND_WRITABLE)
3687 ex1[2][7] = (1, -2)
3688 nd1 = ex1[3:1:-1, ::-2]
3689
3690 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3691 flags=ND_PIL|ND_WRITABLE)
3692 ex2[2][7] = (1, -2)
3693 nd2 = ex2[1:3:1, ::-2]
3694
3695 v = memoryview(nd1)
3696 w = memoryview(nd2)
3697
3698 self.assertEqual(v, nd1)
3699 self.assertEqual(w, nd2)
3700 self.assertEqual(v, nd2)
3701 self.assertEqual(w, nd1)
3702 self.assertEqual(v, w)
3703
3704 # suboffsets, different shape
3705 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3706 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003707 nd1 = ex1[1:3:, ::-2]
3708 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3709 nd2 = ex2[1:3:, ::-2]
3710 v = memoryview(nd1)
3711 w = memoryview(nd2)
3712
3713 self.assertEqual(v, nd1)
3714 self.assertEqual(w, nd2)
3715 self.assertNotEqual(v, nd2)
3716 self.assertNotEqual(w, nd1)
3717 self.assertNotEqual(v, w)
3718
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003719 # suboffsets, different shape, struct module
3720 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3721 flags=ND_PIL|ND_WRITABLE)
3722 nd1 = ex1[1:2:, ::-2]
3723
3724 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3725 nd2 = ex2[1:2:, ::-2]
3726
3727 v = memoryview(nd1)
3728 w = memoryview(nd2)
3729
3730 self.assertEqual(v, nd1)
3731 self.assertEqual(w, nd2)
3732 self.assertNotEqual(v, nd2)
3733 self.assertNotEqual(w, nd1)
3734 self.assertNotEqual(v, w)
3735
3736 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003737 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3738 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003739 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003740 nd2 = ex2[1:3:, ::-2]
3741 v = memoryview(nd1)
3742 w = memoryview(nd2)
3743
3744 self.assertEqual(v, nd1)
3745 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003746 self.assertEqual(v, nd2)
3747 self.assertEqual(w, nd1)
3748 self.assertEqual(v, w)
3749
3750 # suboffsets, different format, struct module
3751 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3752 flags=ND_PIL|ND_WRITABLE)
3753 ex1[1][2][2] = (b'sushi', b'', 1)
3754 nd1 = ex1[1:3:, ::-2]
3755
3756 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3757 flags=ND_PIL|ND_WRITABLE)
3758 ex1[1][2][2] = (b'sushi', b'', 1)
3759 nd2 = ex2[1:3:, ::-2]
3760
3761 v = memoryview(nd1)
3762 w = memoryview(nd2)
3763
3764 self.assertEqual(v, nd1)
3765 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003766 self.assertNotEqual(v, nd2)
3767 self.assertNotEqual(w, nd1)
3768 self.assertNotEqual(v, w)
3769
3770 # initialize mixed C/Fortran + suboffsets
3771 lst1 = list(range(-15, 15))
3772 lst2 = transpose(lst1, [3, 2, 5])
3773 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3774 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3775 v = memoryview(nd1)
3776 w = memoryview(nd2)
3777
3778 self.assertEqual(v, nd1)
3779 self.assertEqual(w, nd2)
3780 self.assertEqual(v, w)
3781
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003782 # initialize mixed C/Fortran + suboffsets, struct module
3783 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3784 lst1[11] = (b'ramen', b'spicy', 9.45)
3785 lst2 = transpose(lst1, [3, 2, 5])
3786
3787 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3788 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3789 flags=ND_FORTRAN|ND_PIL)
3790 v = memoryview(nd1)
3791 w = memoryview(nd2)
3792
3793 self.assertEqual(v, nd1)
3794 self.assertEqual(w, nd2)
3795 self.assertEqual(v, w)
3796
3797 def test_memoryview_compare_not_equal(self):
3798
3799 # items not equal
3800 for byteorder in ['=', '<', '>', '!']:
3801 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3802 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3803 flags=ND_WRITABLE|ND_FORTRAN)
3804 y[2][3][1][1][1] = 1
3805 a = memoryview(x)
3806 b = memoryview(y)
3807 self.assertEqual(a, x)
3808 self.assertEqual(b, y)
3809 self.assertNotEqual(a, b)
3810 self.assertNotEqual(a, y)
3811 self.assertNotEqual(b, x)
3812
3813 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3814 format=byteorder+'QLH')
3815 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3816 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3817 y[2][3][1][1][1] = (1, 1, 1)
3818 a = memoryview(x)
3819 b = memoryview(y)
3820 self.assertEqual(a, x)
3821 self.assertEqual(b, y)
3822 self.assertNotEqual(a, b)
3823 self.assertNotEqual(a, y)
3824 self.assertNotEqual(b, x)
3825
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003826 def test_memoryview_check_released(self):
3827
3828 a = array.array('d', [1.1, 2.2, 3.3])
3829
3830 m = memoryview(a)
3831 m.release()
3832
3833 # PyMemoryView_FromObject()
3834 self.assertRaises(ValueError, memoryview, m)
3835 # memoryview.cast()
3836 self.assertRaises(ValueError, m.cast, 'c')
3837 # getbuffer()
3838 self.assertRaises(ValueError, ndarray, m)
3839 # memoryview.tolist()
3840 self.assertRaises(ValueError, m.tolist)
3841 # memoryview.tobytes()
3842 self.assertRaises(ValueError, m.tobytes)
3843 # sequence
3844 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3845 # subscript
3846 self.assertRaises(ValueError, m.__getitem__, 0)
3847 # assignment
3848 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3849
3850 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3851 'shape', 'strides', 'suboffsets', 'c_contiguous',
3852 'f_contiguous', 'contiguous'):
3853 self.assertRaises(ValueError, m.__getattribute__, attr)
3854
3855 # richcompare
3856 b = array.array('d', [1.1, 2.2, 3.3])
3857 m1 = memoryview(a)
3858 m2 = memoryview(b)
3859
3860 self.assertEqual(m1, m2)
3861 m1.release()
3862 self.assertNotEqual(m1, m2)
3863 self.assertNotEqual(m1, a)
3864 self.assertEqual(m1, m1)
3865
3866 def test_memoryview_tobytes(self):
3867 # Many implicit tests are already in self.verify().
3868
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003869 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003870
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003871 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003872 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003873 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003874 self.assertEqual(m.tobytes(), nd.tobytes())
3875
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003876 nd = ndarray([t], shape=[1], format='>hQiLl')
3877 m = memoryview(nd)
3878 self.assertEqual(m, nd)
3879 self.assertEqual(m.tobytes(), nd.tobytes())
3880
3881 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3882 m = memoryview(nd)
3883 self.assertEqual(m, nd)
3884 self.assertEqual(m.tobytes(), nd.tobytes())
3885
3886 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3887 format='<hQiLl')
3888 m = memoryview(nd)
3889 self.assertEqual(m, nd)
3890 self.assertEqual(m.tobytes(), nd.tobytes())
3891
3892 # Unknown formats are handled: tobytes() purely depends on itemsize.
3893 if ctypes:
3894 # format: "T{>l:x:>l:y:}"
3895 class BEPoint(ctypes.BigEndianStructure):
3896 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3897 point = BEPoint(100, 200)
3898 a = memoryview(point)
3899 self.assertEqual(a.tobytes(), bytes(point))
3900
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003901 def test_memoryview_get_contiguous(self):
3902 # Many implicit tests are already in self.verify().
3903
3904 # no buffer interface
3905 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3906
3907 # writable request to read-only object
3908 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3909
3910 # writable request to non-contiguous object
3911 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3912 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3913
3914 # scalar, read-only request from read-only exporter
3915 nd = ndarray(9, shape=(), format="L")
3916 for order in ['C', 'F', 'A']:
3917 m = get_contiguous(nd, PyBUF_READ, order)
3918 self.assertEqual(m, nd)
3919 self.assertEqual(m[()], 9)
3920
3921 # scalar, read-only request from writable exporter
3922 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3923 for order in ['C', 'F', 'A']:
3924 m = get_contiguous(nd, PyBUF_READ, order)
3925 self.assertEqual(m, nd)
3926 self.assertEqual(m[()], 9)
3927
3928 # scalar, writable request
3929 for order in ['C', 'F', 'A']:
3930 nd[()] = 9
3931 m = get_contiguous(nd, PyBUF_WRITE, order)
3932 self.assertEqual(m, nd)
3933 self.assertEqual(m[()], 9)
3934
3935 m[()] = 10
3936 self.assertEqual(m[()], 10)
3937 self.assertEqual(nd[()], 10)
3938
3939 # zeros in shape
3940 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3941 for order in ['C', 'F', 'A']:
3942 m = get_contiguous(nd, PyBUF_READ, order)
3943 self.assertRaises(IndexError, m.__getitem__, 0)
3944 self.assertEqual(m, nd)
3945 self.assertEqual(m.tolist(), [])
3946
3947 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
3948 flags=ND_WRITABLE)
3949 for order in ['C', 'F', 'A']:
3950 m = get_contiguous(nd, PyBUF_READ, order)
3951 self.assertEqual(ndarray(m).tolist(), [[], []])
3952
3953 # one-dimensional
3954 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
3955 for order in ['C', 'F', 'A']:
3956 m = get_contiguous(nd, PyBUF_WRITE, order)
3957 self.assertEqual(m, nd)
3958 self.assertEqual(m.tolist(), nd.tolist())
3959
3960 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
3961 for order in ['C', 'F', 'A']:
3962 m = get_contiguous(nd, PyBUF_WRITE, order)
3963 self.assertEqual(m, nd)
3964 self.assertEqual(m.tolist(), nd.tolist())
3965
3966 # one-dimensional, non-contiguous
3967 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
3968 for order in ['C', 'F', 'A']:
3969 m = get_contiguous(nd, PyBUF_READ, order)
3970 self.assertEqual(m, nd)
3971 self.assertEqual(m.tolist(), nd.tolist())
3972 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3973 self.assertEqual(m[1], 3)
3974 self.assertEqual(nd[1], 3)
3975
3976 nd = nd[::-1]
3977 for order in ['C', 'F', 'A']:
3978 m = get_contiguous(nd, PyBUF_READ, order)
3979 self.assertEqual(m, nd)
3980 self.assertEqual(m.tolist(), nd.tolist())
3981 self.assertRaises(TypeError, m.__setitem__, 1, 20)
3982 self.assertEqual(m[1], 1)
3983 self.assertEqual(nd[1], 1)
3984
3985 # multi-dimensional, contiguous input
3986 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
3987 for order in ['C', 'A']:
3988 m = get_contiguous(nd, PyBUF_WRITE, order)
3989 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3990
3991 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
3992 m = get_contiguous(nd, PyBUF_READ, order)
3993 self.assertEqual(ndarray(m).tolist(), nd.tolist())
3994
3995 nd = ndarray(list(range(12)), shape=[3, 4],
3996 flags=ND_WRITABLE|ND_FORTRAN)
3997 for order in ['F', 'A']:
3998 m = get_contiguous(nd, PyBUF_WRITE, order)
3999 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4000
4001 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
4002 m = get_contiguous(nd, PyBUF_READ, order)
4003 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4004
4005 # multi-dimensional, non-contiguous input
4006 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
4007 for order in ['C', 'F', 'A']:
4008 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
4009 order)
4010 m = get_contiguous(nd, PyBUF_READ, order)
4011 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4012
4013 # flags
4014 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
4015 m = get_contiguous(nd, PyBUF_READ, 'C')
4016 self.assertTrue(m.c_contiguous)
4017
4018 def test_memoryview_serializing(self):
4019
4020 # C-contiguous
4021 size = struct.calcsize('i')
4022 a = array.array('i', [1,2,3,4,5])
4023 m = memoryview(a)
4024 buf = io.BytesIO(m)
4025 b = bytearray(5*size)
4026 buf.readinto(b)
4027 self.assertEqual(m.tobytes(), b)
4028
4029 # C-contiguous, multi-dimensional
4030 size = struct.calcsize('L')
4031 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
4032 m = memoryview(nd)
4033 buf = io.BytesIO(m)
4034 b = bytearray(2*3*2*size)
4035 buf.readinto(b)
4036 self.assertEqual(m.tobytes(), b)
4037
4038 # Fortran contiguous, multi-dimensional
4039 #size = struct.calcsize('L')
4040 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
4041 # flags=ND_FORTRAN)
4042 #m = memoryview(nd)
4043 #buf = io.BytesIO(m)
4044 #b = bytearray(2*3*2*size)
4045 #buf.readinto(b)
4046 #self.assertEqual(m.tobytes(), b)
4047
4048 def test_memoryview_hash(self):
4049
4050 # bytes exporter
4051 b = bytes(list(range(12)))
4052 m = memoryview(b)
4053 self.assertEqual(hash(b), hash(m))
4054
4055 # C-contiguous
4056 mc = m.cast('c', shape=[3,4])
4057 self.assertEqual(hash(mc), hash(b))
4058
4059 # non-contiguous
4060 mx = m[::-2]
4061 b = bytes(list(range(12))[::-2])
4062 self.assertEqual(hash(mx), hash(b))
4063
4064 # Fortran contiguous
4065 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
4066 m = memoryview(nd)
4067 self.assertEqual(hash(m), hash(nd))
4068
4069 # multi-dimensional slice
4070 nd = ndarray(list(range(30)), shape=[3,2,5])
4071 x = nd[::2, ::, ::-1]
4072 m = memoryview(x)
4073 self.assertEqual(hash(m), hash(x))
4074
4075 # multi-dimensional slice with suboffsets
4076 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
4077 x = nd[::2, ::, ::-1]
4078 m = memoryview(x)
4079 self.assertEqual(hash(m), hash(x))
4080
Stefan Krah4af77a02012-11-02 17:49:22 +01004081 # equality-hash invariant
4082 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004083 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004084
4085 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004086 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004087
Stefan Krahb716f842012-11-04 20:53:50 +01004088 self.assertEqual(a, b)
4089 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004090
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004091 # non-byte formats
4092 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4093 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004094 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004095
4096 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4097 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004098 self.assertRaises(ValueError, m.__hash__)
4099
4100 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4101 m = memoryview(nd)
4102 self.assertRaises(ValueError, m.__hash__)
4103
4104 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4105 m = memoryview(nd)
4106 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004107
4108 def test_memoryview_release(self):
4109
4110 # Create re-exporter from getbuffer(memoryview), then release the view.
4111 a = bytearray([1,2,3])
4112 m = memoryview(a)
4113 nd = ndarray(m) # re-exporter
4114 self.assertRaises(BufferError, m.release)
4115 del nd
4116 m.release()
4117
Stefan Krah4e99a312012-03-05 09:30:47 +01004118 a = bytearray([1,2,3])
4119 m = memoryview(a)
4120 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4121 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4122 self.assertIs(nd2.obj, m)
4123 self.assertRaises(BufferError, m.release)
4124 del nd1, nd2
4125 m.release()
4126
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004127 # chained views
4128 a = bytearray([1,2,3])
4129 m1 = memoryview(a)
4130 m2 = memoryview(m1)
4131 nd = ndarray(m2) # re-exporter
4132 m1.release()
4133 self.assertRaises(BufferError, m2.release)
4134 del nd
4135 m2.release()
4136
Stefan Krah4e99a312012-03-05 09:30:47 +01004137 a = bytearray([1,2,3])
4138 m1 = memoryview(a)
4139 m2 = memoryview(m1)
4140 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4141 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4142 self.assertIs(nd2.obj, m2)
4143 m1.release()
4144 self.assertRaises(BufferError, m2.release)
4145 del nd1, nd2
4146 m2.release()
4147
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004148 # Allow changing layout while buffers are exported.
4149 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4150 m1 = memoryview(nd)
4151
4152 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4153 m2 = memoryview(nd)
4154
4155 x = memoryview(m1)
4156 self.assertEqual(x.tolist(), m1.tolist())
4157
4158 y = memoryview(m2)
4159 self.assertEqual(y.tolist(), m2.tolist())
4160 self.assertEqual(y.tolist(), nd.tolist())
4161 m2.release()
4162 y.release()
4163
4164 nd.pop() # pop the current view
4165 self.assertEqual(x.tolist(), nd.tolist())
4166
4167 del nd
4168 m1.release()
4169 x.release()
4170
4171 # If multiple memoryviews share the same managed buffer, implicit
4172 # release() in the context manager's __exit__() method should still
4173 # work.
4174 def catch22(b):
4175 with memoryview(b) as m2:
4176 pass
4177
4178 x = bytearray(b'123')
4179 with memoryview(x) as m1:
4180 catch22(m1)
4181 self.assertEqual(m1[0], ord(b'1'))
4182
Stefan Krah4e99a312012-03-05 09:30:47 +01004183 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4184 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4185 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4186 self.assertIs(z.obj, x)
4187 with memoryview(z) as m:
4188 catch22(m)
4189 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4190
4191 # Test garbage collection.
4192 for flags in (0, ND_REDIRECT):
4193 x = bytearray(b'123')
4194 with memoryview(x) as m1:
4195 del x
4196 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4197 with memoryview(y) as m2:
4198 del y
4199 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4200 with memoryview(z) as m3:
4201 del z
4202 catch22(m3)
4203 catch22(m2)
4204 catch22(m1)
4205 self.assertEqual(m1[0], ord(b'1'))
4206 self.assertEqual(m2[1], ord(b'2'))
4207 self.assertEqual(m3[2], ord(b'3'))
4208 del m3
4209 del m2
4210 del m1
4211
4212 x = bytearray(b'123')
4213 with memoryview(x) as m1:
4214 del x
4215 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4216 with memoryview(y) as m2:
4217 del y
4218 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4219 with memoryview(z) as m3:
4220 del z
4221 catch22(m1)
4222 catch22(m2)
4223 catch22(m3)
4224 self.assertEqual(m1[0], ord(b'1'))
4225 self.assertEqual(m2[1], ord(b'2'))
4226 self.assertEqual(m3[2], ord(b'3'))
4227 del m1, m2, m3
4228
Stefan Krahfcbb4162012-03-05 10:45:31 +01004229 # memoryview.release() fails if the view has exported buffers.
4230 x = bytearray(b'123')
4231 with self.assertRaises(BufferError):
4232 with memoryview(x) as m:
4233 ex = ndarray(m)
4234 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004235
Stefan Krah4e99a312012-03-05 09:30:47 +01004236 def test_memoryview_redirect(self):
4237
4238 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4239 a = array.array('d', [1.0 * x for x in range(12)])
4240
4241 for x in (nd, a):
4242 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4243 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4244 m = memoryview(z)
4245
4246 self.assertIs(y.obj, x)
4247 self.assertIs(z.obj, x)
4248 self.assertIs(m.obj, x)
4249
4250 self.assertEqual(m, x)
4251 self.assertEqual(m, y)
4252 self.assertEqual(m, z)
4253
4254 self.assertEqual(m[1:3], x[1:3])
4255 self.assertEqual(m[1:3], y[1:3])
4256 self.assertEqual(m[1:3], z[1:3])
4257 del y, z
4258 self.assertEqual(m[1:3], x[1:3])
4259
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004260 def test_memoryview_from_static_exporter(self):
4261
4262 fmt = 'B'
4263 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4264
4265 # exceptions
4266 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4267
4268 # view.obj==x
4269 x = staticarray()
4270 y = memoryview(x)
4271 self.verify(y, obj=x,
4272 itemsize=1, fmt=fmt, readonly=1,
4273 ndim=1, shape=[12], strides=[1],
4274 lst=lst)
4275 for i in range(12):
4276 self.assertEqual(y[i], i)
4277 del x
4278 del y
4279
4280 x = staticarray()
4281 y = memoryview(x)
4282 del y
4283 del x
4284
4285 x = staticarray()
4286 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4287 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4288 m = memoryview(z)
4289 self.assertIs(y.obj, x)
4290 self.assertIs(m.obj, z)
4291 self.verify(m, obj=z,
4292 itemsize=1, fmt=fmt, readonly=1,
4293 ndim=1, shape=[12], strides=[1],
4294 lst=lst)
4295 del x, y, z, m
4296
4297 x = staticarray()
4298 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4299 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4300 m = memoryview(z)
4301 self.assertIs(y.obj, x)
4302 self.assertIs(z.obj, x)
4303 self.assertIs(m.obj, x)
4304 self.verify(m, obj=x,
4305 itemsize=1, fmt=fmt, readonly=1,
4306 ndim=1, shape=[12], strides=[1],
4307 lst=lst)
4308 del x, y, z, m
4309
4310 # view.obj==NULL
4311 x = staticarray(legacy_mode=True)
4312 y = memoryview(x)
4313 self.verify(y, obj=None,
4314 itemsize=1, fmt=fmt, readonly=1,
4315 ndim=1, shape=[12], strides=[1],
4316 lst=lst)
4317 for i in range(12):
4318 self.assertEqual(y[i], i)
4319 del x
4320 del y
4321
4322 x = staticarray(legacy_mode=True)
4323 y = memoryview(x)
4324 del y
4325 del x
4326
4327 x = staticarray(legacy_mode=True)
4328 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4329 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4330 m = memoryview(z)
4331 self.assertIs(y.obj, None)
4332 self.assertIs(m.obj, z)
4333 self.verify(m, obj=z,
4334 itemsize=1, fmt=fmt, readonly=1,
4335 ndim=1, shape=[12], strides=[1],
4336 lst=lst)
4337 del x, y, z, m
4338
4339 x = staticarray(legacy_mode=True)
4340 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4341 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4342 m = memoryview(z)
4343 # Clearly setting view.obj==NULL is inferior, since it
4344 # messes up the redirection chain:
4345 self.assertIs(y.obj, None)
4346 self.assertIs(z.obj, y)
4347 self.assertIs(m.obj, y)
4348 self.verify(m, obj=y,
4349 itemsize=1, fmt=fmt, readonly=1,
4350 ndim=1, shape=[12], strides=[1],
4351 lst=lst)
4352 del x, y, z, m
4353
Stefan Krah1649c1b2012-03-05 17:45:17 +01004354 def test_memoryview_getbuffer_undefined(self):
4355
4356 # getbufferproc does not adhere to the new documentation
4357 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4358 self.assertRaises(BufferError, memoryview, nd)
4359
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004360 def test_issue_7385(self):
4361 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4362 self.assertRaises(BufferError, memoryview, x)
4363
4364
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004365if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004366 unittest.main()