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