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