blob: dd84faf371e7d6680619578f8c70cda25320b804 [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['@']:
2754 tfmt = ('', '@')[randrange(2)] + char
2755 tsize = struct.calcsize(tfmt)
2756 n = prod(_tshape) * tsize
2757 obj = 'memoryview' if is_byte_format(tfmt) else 'bytefmt'
2758 for fmt, items, _ in iter_format(n, obj):
2759 size = struct.calcsize(fmt)
2760 shape = [n] if n > 0 else []
2761 tshape = _tshape + [size]
2762
2763 ex = ndarray(items, shape=shape, format=fmt)
2764 m = memoryview(ex)
2765
2766 titems, tshape = cast_items(ex, tfmt, tsize, shape=tshape)
2767
2768 if titems is None:
2769 self.assertRaises(TypeError, m.cast, tfmt, tshape)
2770 continue
2771 if titems == 'nan':
2772 continue # NaNs in lists are a recipe for trouble.
2773
2774 # 1D -> ND
2775 nd = ndarray(titems, shape=tshape, format=tfmt)
2776
2777 m2 = m.cast(tfmt, shape=tshape)
2778 ndim = len(tshape)
2779 strides = nd.strides
2780 lst = nd.tolist()
2781 self.verify(m2, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002782 itemsize=tsize, fmt=tfmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002783 ndim=ndim, shape=tshape, strides=strides,
2784 lst=lst, cast=True)
2785
2786 # ND -> 1D
2787 m3 = m2.cast(fmt)
2788 m4 = m2.cast(fmt, shape=shape)
2789 ndim = len(shape)
2790 strides = ex.strides
2791 lst = ex.tolist()
2792
2793 self.verify(m3, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002794 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002795 ndim=ndim, shape=shape, strides=strides,
2796 lst=lst, cast=True)
2797
2798 self.verify(m4, obj=ex,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002799 itemsize=size, fmt=fmt, readonly=True,
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002800 ndim=ndim, shape=shape, strides=strides,
2801 lst=lst, cast=True)
2802
Stefan Krah0c515952015-08-08 13:38:10 +02002803 if ctypes:
2804 # format: "T{>l:x:>d:y:}"
2805 class BEPoint(ctypes.BigEndianStructure):
2806 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_double)]
2807 point = BEPoint(100, 200.1)
2808 m1 = memoryview(point)
2809 m2 = m1.cast('B')
2810 self.assertEqual(m2.obj, point)
2811 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002812 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002813 self.assertEqual(m2.ndim, 1)
2814 self.assertEqual(m2.shape, (m2.nbytes,))
2815 self.assertEqual(m2.strides, (1,))
2816 self.assertEqual(m2.suboffsets, ())
2817
2818 x = ctypes.c_double(1.2)
2819 m1 = memoryview(x)
2820 m2 = m1.cast('c')
2821 self.assertEqual(m2.obj, x)
2822 self.assertEqual(m2.itemsize, 1)
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002823 self.assertIs(m2.readonly, False)
Stefan Krah0c515952015-08-08 13:38:10 +02002824 self.assertEqual(m2.ndim, 1)
2825 self.assertEqual(m2.shape, (m2.nbytes,))
2826 self.assertEqual(m2.strides, (1,))
2827 self.assertEqual(m2.suboffsets, ())
2828
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002829 def test_memoryview_tolist(self):
2830
2831 # Most tolist() tests are in self.verify() etc.
2832
2833 a = array.array('h', list(range(-6, 6)))
2834 m = memoryview(a)
2835 self.assertEqual(m, a)
2836 self.assertEqual(m.tolist(), a.tolist())
2837
2838 a = a[2::3]
2839 m = m[2::3]
2840 self.assertEqual(m, a)
2841 self.assertEqual(m.tolist(), a.tolist())
2842
2843 ex = ndarray(list(range(2*3*5*7*11)), shape=[11,2,7,3,5], format='L')
2844 m = memoryview(ex)
2845 self.assertEqual(m.tolist(), ex.tolist())
2846
2847 ex = ndarray([(2, 5), (7, 11)], shape=[2], format='lh')
2848 m = memoryview(ex)
2849 self.assertRaises(NotImplementedError, m.tolist)
2850
2851 ex = ndarray([b'12345'], shape=[1], format="s")
2852 m = memoryview(ex)
2853 self.assertRaises(NotImplementedError, m.tolist)
2854
2855 ex = ndarray([b"a",b"b",b"c",b"d",b"e",b"f"], shape=[2,3], format='s')
2856 m = memoryview(ex)
2857 self.assertRaises(NotImplementedError, m.tolist)
2858
2859 def test_memoryview_repr(self):
2860 m = memoryview(bytearray(9))
2861 r = m.__repr__()
2862 self.assertTrue(r.startswith("<memory"))
2863
2864 m.release()
2865 r = m.__repr__()
2866 self.assertTrue(r.startswith("<released"))
2867
2868 def test_memoryview_sequence(self):
2869
2870 for fmt in ('d', 'f'):
2871 inf = float(3e400)
2872 ex = array.array(fmt, [1.0, inf, 3.0])
2873 m = memoryview(ex)
2874 self.assertIn(1.0, m)
2875 self.assertIn(5e700, m)
2876 self.assertIn(3.0, m)
2877
2878 ex = ndarray(9.0, [], format='f')
2879 m = memoryview(ex)
2880 self.assertRaises(TypeError, eval, "9.0 in m", locals())
2881
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002882 @contextlib.contextmanager
2883 def assert_out_of_bounds_error(self, dim):
2884 with self.assertRaises(IndexError) as cm:
2885 yield
2886 self.assertEqual(str(cm.exception),
2887 "index out of bounds on dimension %d" % (dim,))
2888
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002889 def test_memoryview_index(self):
2890
2891 # ndim = 0
2892 ex = ndarray(12.5, shape=[], format='d')
2893 m = memoryview(ex)
2894 self.assertEqual(m[()], 12.5)
2895 self.assertEqual(m[...], m)
2896 self.assertEqual(m[...], ex)
2897 self.assertRaises(TypeError, m.__getitem__, 0)
2898
2899 ex = ndarray((1,2,3), shape=[], format='iii')
2900 m = memoryview(ex)
2901 self.assertRaises(NotImplementedError, m.__getitem__, ())
2902
2903 # range
2904 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2905 m = memoryview(ex)
2906
2907 self.assertRaises(IndexError, m.__getitem__, 2**64)
2908 self.assertRaises(TypeError, m.__getitem__, 2.0)
2909 self.assertRaises(TypeError, m.__getitem__, 0.0)
2910
2911 # out of bounds
2912 self.assertRaises(IndexError, m.__getitem__, -8)
2913 self.assertRaises(IndexError, m.__getitem__, 8)
2914
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002915 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002916 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
2917 m = memoryview(ex)
2918
Antoine Pitrou31084ba2015-03-19 23:29:36 +01002919 self.assertEqual(m[0, 0], 0)
2920 self.assertEqual(m[2, 0], 8)
2921 self.assertEqual(m[2, 3], 11)
2922 self.assertEqual(m[-1, -1], 11)
2923 self.assertEqual(m[-3, -4], 0)
2924
2925 # out of bounds
2926 for index in (3, -4):
2927 with self.assert_out_of_bounds_error(dim=1):
2928 m[index, 0]
2929 for index in (4, -5):
2930 with self.assert_out_of_bounds_error(dim=2):
2931 m[0, index]
2932 self.assertRaises(IndexError, m.__getitem__, (2**64, 0))
2933 self.assertRaises(IndexError, m.__getitem__, (0, 2**64))
2934
2935 self.assertRaises(TypeError, m.__getitem__, (0, 0, 0))
2936 self.assertRaises(TypeError, m.__getitem__, (0.0, 0.0))
2937
2938 # Not implemented: multidimensional sub-views
2939 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002940 self.assertRaises(NotImplementedError, m.__getitem__, 0)
2941
2942 def test_memoryview_assign(self):
2943
2944 # ndim = 0
2945 ex = ndarray(12.5, shape=[], format='f', flags=ND_WRITABLE)
2946 m = memoryview(ex)
2947 m[()] = 22.5
2948 self.assertEqual(m[()], 22.5)
2949 m[...] = 23.5
2950 self.assertEqual(m[()], 23.5)
2951 self.assertRaises(TypeError, m.__setitem__, 0, 24.7)
2952
2953 # read-only
2954 ex = ndarray(list(range(7)), shape=[7])
2955 m = memoryview(ex)
2956 self.assertRaises(TypeError, m.__setitem__, 2, 10)
2957
2958 # range
2959 ex = ndarray(list(range(7)), shape=[7], flags=ND_WRITABLE)
2960 m = memoryview(ex)
2961
2962 self.assertRaises(IndexError, m.__setitem__, 2**64, 9)
2963 self.assertRaises(TypeError, m.__setitem__, 2.0, 10)
2964 self.assertRaises(TypeError, m.__setitem__, 0.0, 11)
2965
2966 # out of bounds
2967 self.assertRaises(IndexError, m.__setitem__, -8, 20)
2968 self.assertRaises(IndexError, m.__setitem__, 8, 25)
2969
2970 # pack_single() success:
2971 for fmt in fmtdict['@']:
2972 if fmt == 'c' or fmt == '?':
2973 continue
2974 ex = ndarray([1,2,3], shape=[3], format=fmt, flags=ND_WRITABLE)
2975 m = memoryview(ex)
2976 i = randrange(-3, 3)
2977 m[i] = 8
2978 self.assertEqual(m[i], 8)
2979 self.assertEqual(m[i], ex[i])
2980
2981 ex = ndarray([b'1', b'2', b'3'], shape=[3], format='c',
2982 flags=ND_WRITABLE)
2983 m = memoryview(ex)
2984 m[2] = b'9'
2985 self.assertEqual(m[2], b'9')
2986
2987 ex = ndarray([True, False, True], shape=[3], format='?',
2988 flags=ND_WRITABLE)
2989 m = memoryview(ex)
2990 m[1] = True
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03002991 self.assertIs(m[1], True)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01002992
2993 # pack_single() exceptions:
2994 nd = ndarray([b'x'], shape=[1], format='c', flags=ND_WRITABLE)
2995 m = memoryview(nd)
2996 self.assertRaises(TypeError, m.__setitem__, 0, 100)
2997
2998 ex = ndarray(list(range(120)), shape=[1,2,3,4,5], flags=ND_WRITABLE)
2999 m1 = memoryview(ex)
3000
3001 for fmt, _range in fmtdict['@'].items():
3002 if (fmt == '?'): # PyObject_IsTrue() accepts anything
3003 continue
3004 if fmt == 'c': # special case tested above
3005 continue
3006 m2 = m1.cast(fmt)
3007 lo, hi = _range
3008 if fmt == 'd' or fmt == 'f':
3009 lo, hi = -2**1024, 2**1024
3010 if fmt != 'P': # PyLong_AsVoidPtr() accepts negative numbers
3011 self.assertRaises(ValueError, m2.__setitem__, 0, lo-1)
3012 self.assertRaises(TypeError, m2.__setitem__, 0, "xyz")
3013 self.assertRaises(ValueError, m2.__setitem__, 0, hi)
3014
3015 # invalid item
3016 m2 = m1.cast('c')
3017 self.assertRaises(ValueError, m2.__setitem__, 0, b'\xff\xff')
3018
3019 # format not implemented
3020 ex = ndarray(list(range(1)), shape=[1], format="xL", flags=ND_WRITABLE)
3021 m = memoryview(ex)
3022 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3023
3024 ex = ndarray([b'12345'], shape=[1], format="s", flags=ND_WRITABLE)
3025 m = memoryview(ex)
3026 self.assertRaises(NotImplementedError, m.__setitem__, 0, 1)
3027
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003028 # multi-dimensional
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003029 ex = ndarray(list(range(12)), shape=[3,4], flags=ND_WRITABLE)
3030 m = memoryview(ex)
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003031 m[0,1] = 42
3032 self.assertEqual(ex[0][1], 42)
3033 m[-1,-1] = 43
3034 self.assertEqual(ex[2][3], 43)
3035 # errors
3036 for index in (3, -4):
3037 with self.assert_out_of_bounds_error(dim=1):
3038 m[index, 0] = 0
3039 for index in (4, -5):
3040 with self.assert_out_of_bounds_error(dim=2):
3041 m[0, index] = 0
3042 self.assertRaises(IndexError, m.__setitem__, (2**64, 0), 0)
3043 self.assertRaises(IndexError, m.__setitem__, (0, 2**64), 0)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003044
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003045 self.assertRaises(TypeError, m.__setitem__, (0, 0, 0), 0)
3046 self.assertRaises(TypeError, m.__setitem__, (0.0, 0.0), 0)
3047
3048 # Not implemented: multidimensional sub-views
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003049 self.assertRaises(NotImplementedError, m.__setitem__, 0, [2, 3])
3050
3051 def test_memoryview_slice(self):
3052
3053 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3054 m = memoryview(ex)
3055
3056 # zero step
3057 self.assertRaises(ValueError, m.__getitem__, slice(0,2,0))
3058 self.assertRaises(ValueError, m.__setitem__, slice(0,2,0),
3059 bytearray([1,2]))
3060
Antoine Pitrou31084ba2015-03-19 23:29:36 +01003061 # 0-dim slicing (identity function)
3062 self.assertRaises(NotImplementedError, m.__getitem__, ())
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003063
3064 # multidimensional slices
3065 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE)
3066 m = memoryview(ex)
3067
3068 self.assertRaises(NotImplementedError, m.__getitem__,
3069 (slice(0,2,1), slice(0,2,1)))
3070 self.assertRaises(NotImplementedError, m.__setitem__,
3071 (slice(0,2,1), slice(0,2,1)), bytearray([1,2]))
3072
3073 # invalid slice tuple
3074 self.assertRaises(TypeError, m.__getitem__, (slice(0,2,1), {}))
3075 self.assertRaises(TypeError, m.__setitem__, (slice(0,2,1), {}),
3076 bytearray([1,2]))
3077
3078 # rvalue is not an exporter
3079 self.assertRaises(TypeError, m.__setitem__, slice(0,1,1), [1])
3080
3081 # non-contiguous slice assignment
3082 for flags in (0, ND_PIL):
3083 ex1 = ndarray(list(range(12)), shape=[12], strides=[-1], offset=11,
3084 flags=ND_WRITABLE|flags)
3085 ex2 = ndarray(list(range(24)), shape=[12], strides=[2], flags=flags)
3086 m1 = memoryview(ex1)
3087 m2 = memoryview(ex2)
3088
3089 ex1[2:5] = ex1[2:5]
3090 m1[2:5] = m2[2:5]
3091
3092 self.assertEqual(m1, ex1)
3093 self.assertEqual(m2, ex2)
3094
3095 ex1[1:3][::-1] = ex2[0:2][::1]
3096 m1[1:3][::-1] = m2[0:2][::1]
3097
3098 self.assertEqual(m1, ex1)
3099 self.assertEqual(m2, ex2)
3100
3101 ex1[4:1:-2][::-1] = ex1[1:4:2][::1]
3102 m1[4:1:-2][::-1] = m1[1:4:2][::1]
3103
3104 self.assertEqual(m1, ex1)
3105 self.assertEqual(m2, ex2)
3106
3107 def test_memoryview_array(self):
3108
3109 def cmptest(testcase, a, b, m, singleitem):
3110 for i, _ in enumerate(a):
3111 ai = a[i]
3112 mi = m[i]
3113 testcase.assertEqual(ai, mi)
3114 a[i] = singleitem
3115 if singleitem != ai:
3116 testcase.assertNotEqual(a, m)
3117 testcase.assertNotEqual(a, b)
3118 else:
3119 testcase.assertEqual(a, m)
3120 testcase.assertEqual(a, b)
3121 m[i] = singleitem
3122 testcase.assertEqual(a, m)
3123 testcase.assertEqual(b, m)
3124 a[i] = ai
3125 m[i] = mi
3126
3127 for n in range(1, 5):
3128 for fmt, items, singleitem in iter_format(n, 'array'):
3129 for lslice in genslices(n):
3130 for rslice in genslices(n):
3131
3132 a = array.array(fmt, items)
3133 b = array.array(fmt, items)
3134 m = memoryview(b)
3135
3136 self.assertEqual(m, a)
3137 self.assertEqual(m.tolist(), a.tolist())
3138 self.assertEqual(m.tobytes(), a.tobytes())
3139 self.assertEqual(len(m), len(a))
3140
3141 cmptest(self, a, b, m, singleitem)
3142
3143 array_err = None
3144 have_resize = None
3145 try:
3146 al = a[lslice]
3147 ar = a[rslice]
3148 a[lslice] = a[rslice]
3149 have_resize = len(al) != len(ar)
3150 except Exception as e:
3151 array_err = e.__class__
3152
3153 m_err = None
3154 try:
3155 m[lslice] = m[rslice]
3156 except Exception as e:
3157 m_err = e.__class__
3158
3159 if have_resize: # memoryview cannot change shape
3160 self.assertIs(m_err, ValueError)
3161 elif m_err or array_err:
3162 self.assertIs(m_err, array_err)
3163 else:
3164 self.assertEqual(m, a)
3165 self.assertEqual(m.tolist(), a.tolist())
3166 self.assertEqual(m.tobytes(), a.tobytes())
3167 cmptest(self, a, b, m, singleitem)
3168
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003169 def test_memoryview_compare_special_cases(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003170
3171 a = array.array('L', [1, 2, 3])
3172 b = array.array('L', [1, 2, 7])
3173
3174 # Ordering comparisons raise:
3175 v = memoryview(a)
3176 w = memoryview(b)
3177 for attr in ('__lt__', '__le__', '__gt__', '__ge__'):
3178 self.assertIs(getattr(v, attr)(w), NotImplemented)
3179 self.assertIs(getattr(a, attr)(v), NotImplemented)
3180
3181 # Released views compare equal to themselves:
3182 v = memoryview(a)
3183 v.release()
3184 self.assertEqual(v, v)
3185 self.assertNotEqual(v, a)
3186 self.assertNotEqual(a, v)
3187
3188 v = memoryview(a)
3189 w = memoryview(a)
3190 w.release()
3191 self.assertNotEqual(v, w)
3192 self.assertNotEqual(w, v)
3193
3194 # Operand does not implement the buffer protocol:
3195 v = memoryview(a)
3196 self.assertNotEqual(v, [1, 2, 3])
3197
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003198 # NaNs
3199 nd = ndarray([(0, 0)], shape=[1], format='l x d x', flags=ND_WRITABLE)
3200 nd[0] = (-1, float('nan'))
3201 self.assertNotEqual(memoryview(nd), nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003202
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003203 # Depends on issue #15625: the struct module does not understand 'u'.
3204 a = array.array('u', 'xyz')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003205 v = memoryview(a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003206 self.assertNotEqual(a, v)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003207 self.assertNotEqual(v, a)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003208
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003209 # Some ctypes format strings are unknown to the struct module.
3210 if ctypes:
3211 # format: "T{>l:x:>l:y:}"
3212 class BEPoint(ctypes.BigEndianStructure):
3213 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3214 point = BEPoint(100, 200)
3215 a = memoryview(point)
3216 b = memoryview(point)
3217 self.assertNotEqual(a, b)
3218 self.assertNotEqual(a, point)
3219 self.assertNotEqual(point, a)
3220 self.assertRaises(NotImplementedError, a.tolist)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003221
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003222 def test_memoryview_compare_ndim_zero(self):
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003223
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003224 nd1 = ndarray(1729, shape=[], format='@L')
3225 nd2 = ndarray(1729, shape=[], format='L', flags=ND_WRITABLE)
3226 v = memoryview(nd1)
3227 w = memoryview(nd2)
3228 self.assertEqual(v, w)
3229 self.assertEqual(w, v)
3230 self.assertEqual(v, nd2)
3231 self.assertEqual(nd2, v)
3232 self.assertEqual(w, nd1)
3233 self.assertEqual(nd1, w)
3234
3235 self.assertFalse(v.__ne__(w))
3236 self.assertFalse(w.__ne__(v))
3237
3238 w[()] = 1728
3239 self.assertNotEqual(v, w)
3240 self.assertNotEqual(w, v)
3241 self.assertNotEqual(v, nd2)
3242 self.assertNotEqual(nd2, v)
3243 self.assertNotEqual(w, nd1)
3244 self.assertNotEqual(nd1, w)
3245
3246 self.assertFalse(v.__eq__(w))
3247 self.assertFalse(w.__eq__(v))
3248
3249 nd = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3250 ex = ndarray(list(range(12)), shape=[12], flags=ND_WRITABLE|ND_PIL)
3251 m = memoryview(ex)
3252
3253 self.assertEqual(m, nd)
3254 m[9] = 100
3255 self.assertNotEqual(m, nd)
3256
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003257 # struct module: equal
3258 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3259 nd2 = ndarray((1729, 1.2, b'12345'), shape=[], format='hf5s',
3260 flags=ND_WRITABLE)
3261 v = memoryview(nd1)
3262 w = memoryview(nd2)
3263 self.assertEqual(v, w)
3264 self.assertEqual(w, v)
3265 self.assertEqual(v, nd2)
3266 self.assertEqual(nd2, v)
3267 self.assertEqual(w, nd1)
3268 self.assertEqual(nd1, w)
3269
3270 # struct module: not equal
3271 nd1 = ndarray((1729, 1.2, b'12345'), shape=[], format='Lf5s')
3272 nd2 = ndarray((-1729, 1.2, b'12345'), shape=[], format='hf5s',
3273 flags=ND_WRITABLE)
3274 v = memoryview(nd1)
3275 w = memoryview(nd2)
3276 self.assertNotEqual(v, w)
3277 self.assertNotEqual(w, v)
3278 self.assertNotEqual(v, nd2)
3279 self.assertNotEqual(nd2, v)
3280 self.assertNotEqual(w, nd1)
3281 self.assertNotEqual(nd1, w)
3282 self.assertEqual(v, nd1)
3283 self.assertEqual(w, nd2)
3284
3285 def test_memoryview_compare_ndim_one(self):
3286
3287 # contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003288 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3289 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='@h')
3290 v = memoryview(nd1)
3291 w = memoryview(nd2)
3292
3293 self.assertEqual(v, nd1)
3294 self.assertEqual(w, nd2)
3295 self.assertNotEqual(v, nd2)
3296 self.assertNotEqual(w, nd1)
3297 self.assertNotEqual(v, w)
3298
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003299 # contiguous, struct module
3300 nd1 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<i')
3301 nd2 = ndarray([-529, 576, -625, 676, 729], shape=[5], format='>h')
3302 v = memoryview(nd1)
3303 w = memoryview(nd2)
3304
3305 self.assertEqual(v, nd1)
3306 self.assertEqual(w, nd2)
3307 self.assertNotEqual(v, nd2)
3308 self.assertNotEqual(w, nd1)
3309 self.assertNotEqual(v, w)
3310
3311 # non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003312 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3313 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h')
3314 v = memoryview(nd1)
3315 w = memoryview(nd2)
3316
3317 self.assertEqual(v, nd2[::2])
3318 self.assertEqual(w[::2], nd1)
3319 self.assertEqual(v, w[::2])
3320 self.assertEqual(v[::-1], w[::-2])
3321
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003322 # non-contiguous, struct module
3323 nd1 = ndarray([-529, -625, -729], shape=[3], format='!h')
3324 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='<l')
3325 v = memoryview(nd1)
3326 w = memoryview(nd2)
3327
3328 self.assertEqual(v, nd2[::2])
3329 self.assertEqual(w[::2], nd1)
3330 self.assertEqual(v, w[::2])
3331 self.assertEqual(v[::-1], w[::-2])
3332
3333 # non-contiguous, suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003334 nd1 = ndarray([-529, -625, -729], shape=[3], format='@h')
3335 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='@h',
3336 flags=ND_PIL)
3337 v = memoryview(nd1)
3338 w = memoryview(nd2)
3339
3340 self.assertEqual(v, nd2[::2])
3341 self.assertEqual(w[::2], nd1)
3342 self.assertEqual(v, w[::2])
3343 self.assertEqual(v[::-1], w[::-2])
3344
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003345 # non-contiguous, suboffsets, struct module
3346 nd1 = ndarray([-529, -625, -729], shape=[3], format='h 0c')
3347 nd2 = ndarray([-529, 576, -625, 676, -729], shape=[5], format='> h',
3348 flags=ND_PIL)
3349 v = memoryview(nd1)
3350 w = memoryview(nd2)
3351
3352 self.assertEqual(v, nd2[::2])
3353 self.assertEqual(w[::2], nd1)
3354 self.assertEqual(v, w[::2])
3355 self.assertEqual(v[::-1], w[::-2])
3356
3357 def test_memoryview_compare_zero_shape(self):
3358
3359 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003360 nd1 = ndarray([900, 961], shape=[0], format='@h')
3361 nd2 = ndarray([-900, -961], shape=[0], format='@h')
3362 v = memoryview(nd1)
3363 w = memoryview(nd2)
3364
3365 self.assertEqual(v, nd1)
3366 self.assertEqual(w, nd2)
3367 self.assertEqual(v, nd2)
3368 self.assertEqual(w, nd1)
3369 self.assertEqual(v, w)
3370
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003371 # zeros in shape, struct module
3372 nd1 = ndarray([900, 961], shape=[0], format='= h0c')
3373 nd2 = ndarray([-900, -961], shape=[0], format='@ i')
3374 v = memoryview(nd1)
3375 w = memoryview(nd2)
3376
3377 self.assertEqual(v, nd1)
3378 self.assertEqual(w, nd2)
3379 self.assertEqual(v, nd2)
3380 self.assertEqual(w, nd1)
3381 self.assertEqual(v, w)
3382
3383 def test_memoryview_compare_zero_strides(self):
3384
3385 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003386 nd1 = ndarray([900, 900, 900, 900], shape=[4], format='@L')
3387 nd2 = ndarray([900], shape=[4], strides=[0], format='L')
3388 v = memoryview(nd1)
3389 w = memoryview(nd2)
3390
3391 self.assertEqual(v, nd1)
3392 self.assertEqual(w, nd2)
3393 self.assertEqual(v, nd2)
3394 self.assertEqual(w, nd1)
3395 self.assertEqual(v, w)
3396
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003397 # zero strides, struct module
3398 nd1 = ndarray([(900, 900)]*4, shape=[4], format='@ Li')
3399 nd2 = ndarray([(900, 900)], shape=[4], strides=[0], format='!L h')
3400 v = memoryview(nd1)
3401 w = memoryview(nd2)
3402
3403 self.assertEqual(v, nd1)
3404 self.assertEqual(w, nd2)
3405 self.assertEqual(v, nd2)
3406 self.assertEqual(w, nd1)
3407 self.assertEqual(v, w)
3408
3409 def test_memoryview_compare_random_formats(self):
3410
3411 # random single character native formats
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003412 n = 10
3413 for char in fmtdict['@m']:
3414 fmt, items, singleitem = randitems(n, 'memoryview', '@', char)
3415 for flags in (0, ND_PIL):
3416 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3417 m = memoryview(nd)
3418 self.assertEqual(m, nd)
3419
3420 nd = nd[::-3]
3421 m = memoryview(nd)
3422 self.assertEqual(m, nd)
3423
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003424 # random formats
3425 n = 10
3426 for _ in range(100):
3427 fmt, items, singleitem = randitems(n)
3428 for flags in (0, ND_PIL):
3429 nd = ndarray(items, shape=[n], format=fmt, flags=flags)
3430 m = memoryview(nd)
3431 self.assertEqual(m, nd)
3432
3433 nd = nd[::-3]
3434 m = memoryview(nd)
3435 self.assertEqual(m, nd)
3436
3437 def test_memoryview_compare_multidim_c(self):
3438
3439 # C-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003440 nd1 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='@h')
3441 nd2 = ndarray(list(range(0, 30)), shape=[3, 2, 5], format='@h')
3442 v = memoryview(nd1)
3443 w = memoryview(nd2)
3444
3445 self.assertEqual(v, nd1)
3446 self.assertEqual(w, nd2)
3447 self.assertNotEqual(v, nd2)
3448 self.assertNotEqual(w, nd1)
3449 self.assertNotEqual(v, w)
3450
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003451 # C-contiguous, different values, struct module
3452 nd1 = ndarray([(0, 1, 2)]*30, shape=[3, 2, 5], format='=f q xxL')
3453 nd2 = ndarray([(-1.2, 1, 2)]*30, shape=[3, 2, 5], format='< f 2Q')
3454 v = memoryview(nd1)
3455 w = memoryview(nd2)
3456
3457 self.assertEqual(v, nd1)
3458 self.assertEqual(w, nd2)
3459 self.assertNotEqual(v, nd2)
3460 self.assertNotEqual(w, nd1)
3461 self.assertNotEqual(v, w)
3462
3463 # C-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003464 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3465 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='L')
3466 v = memoryview(nd1)
3467 w = memoryview(nd2)
3468
3469 self.assertEqual(v, nd1)
3470 self.assertEqual(w, nd2)
3471 self.assertNotEqual(v, nd2)
3472 self.assertNotEqual(w, nd1)
3473 self.assertNotEqual(v, w)
3474
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003475 # C-contiguous, different shape, struct module
3476 nd1 = ndarray([(0, 1, 2)]*21, shape=[3, 7], format='! b B xL')
3477 nd2 = ndarray([(0, 1, 2)]*21, shape=[7, 3], format='= Qx l xxL')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003478 v = memoryview(nd1)
3479 w = memoryview(nd2)
3480
3481 self.assertEqual(v, nd1)
3482 self.assertEqual(w, nd2)
3483 self.assertNotEqual(v, nd2)
3484 self.assertNotEqual(w, nd1)
3485 self.assertNotEqual(v, w)
3486
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003487 # C-contiguous, different format, struct module
3488 nd1 = ndarray(list(range(30)), shape=[2, 3, 5], format='L')
3489 nd2 = ndarray(list(range(30)), shape=[2, 3, 5], format='l')
3490 v = memoryview(nd1)
3491 w = memoryview(nd2)
3492
3493 self.assertEqual(v, nd1)
3494 self.assertEqual(w, nd2)
3495 self.assertEqual(v, nd2)
3496 self.assertEqual(w, nd1)
3497 self.assertEqual(v, w)
3498
3499 def test_memoryview_compare_multidim_fortran(self):
3500
3501 # Fortran-contiguous, different values
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003502 nd1 = ndarray(list(range(-15, 15)), shape=[5, 2, 3], format='@h',
3503 flags=ND_FORTRAN)
3504 nd2 = ndarray(list(range(0, 30)), shape=[5, 2, 3], format='@h',
3505 flags=ND_FORTRAN)
3506 v = memoryview(nd1)
3507 w = memoryview(nd2)
3508
3509 self.assertEqual(v, nd1)
3510 self.assertEqual(w, nd2)
3511 self.assertNotEqual(v, nd2)
3512 self.assertNotEqual(w, nd1)
3513 self.assertNotEqual(v, w)
3514
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003515 # Fortran-contiguous, different values, struct module
3516 nd1 = ndarray([(2**64-1, -1)]*6, shape=[2, 3], format='=Qq',
3517 flags=ND_FORTRAN)
3518 nd2 = ndarray([(-1, 2**64-1)]*6, shape=[2, 3], format='=qQ',
3519 flags=ND_FORTRAN)
3520 v = memoryview(nd1)
3521 w = memoryview(nd2)
3522
3523 self.assertEqual(v, nd1)
3524 self.assertEqual(w, nd2)
3525 self.assertNotEqual(v, nd2)
3526 self.assertNotEqual(w, nd1)
3527 self.assertNotEqual(v, w)
3528
3529 # Fortran-contiguous, different shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003530 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='l',
3531 flags=ND_FORTRAN)
3532 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
3533 flags=ND_FORTRAN)
3534 v = memoryview(nd1)
3535 w = memoryview(nd2)
3536
3537 self.assertEqual(v, nd1)
3538 self.assertEqual(w, nd2)
3539 self.assertNotEqual(v, nd2)
3540 self.assertNotEqual(w, nd1)
3541 self.assertNotEqual(v, w)
3542
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003543 # Fortran-contiguous, different shape, struct module
3544 nd1 = ndarray(list(range(-15, 15)), shape=[2, 3, 5], format='0ll',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003545 flags=ND_FORTRAN)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003546 nd2 = ndarray(list(range(-15, 15)), shape=[3, 2, 5], format='l',
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003547 flags=ND_FORTRAN)
3548 v = memoryview(nd1)
3549 w = memoryview(nd2)
3550
3551 self.assertEqual(v, nd1)
3552 self.assertEqual(w, nd2)
3553 self.assertNotEqual(v, nd2)
3554 self.assertNotEqual(w, nd1)
3555 self.assertNotEqual(v, w)
3556
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003557 # Fortran-contiguous, different format, struct module
3558 nd1 = ndarray(list(range(30)), shape=[5, 2, 3], format='@h',
3559 flags=ND_FORTRAN)
3560 nd2 = ndarray(list(range(30)), shape=[5, 2, 3], format='@b',
3561 flags=ND_FORTRAN)
3562 v = memoryview(nd1)
3563 w = memoryview(nd2)
3564
3565 self.assertEqual(v, nd1)
3566 self.assertEqual(w, nd2)
3567 self.assertEqual(v, nd2)
3568 self.assertEqual(w, nd1)
3569 self.assertEqual(v, w)
3570
3571 def test_memoryview_compare_multidim_mixed(self):
3572
3573 # mixed C/Fortran contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003574 lst1 = list(range(-15, 15))
3575 lst2 = transpose(lst1, [3, 2, 5])
3576 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l')
3577 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN)
3578 v = memoryview(nd1)
3579 w = memoryview(nd2)
3580
3581 self.assertEqual(v, nd1)
3582 self.assertEqual(w, nd2)
3583 self.assertEqual(v, w)
3584
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003585 # mixed C/Fortran contiguous, struct module
3586 lst1 = [(-3.3, -22, b'x')]*30
3587 lst1[5] = (-2.2, -22, b'x')
3588 lst2 = transpose(lst1, [3, 2, 5])
3589 nd1 = ndarray(lst1, shape=[3, 2, 5], format='d b c')
3590 nd2 = ndarray(lst2, shape=[3, 2, 5], format='d h c', flags=ND_FORTRAN)
3591 v = memoryview(nd1)
3592 w = memoryview(nd2)
3593
3594 self.assertEqual(v, nd1)
3595 self.assertEqual(w, nd2)
3596 self.assertEqual(v, w)
3597
3598 # different values, non-contiguous
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003599 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3600 nd1 = ex1[3:1:-1, ::-2]
3601 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I')
3602 nd2 = ex2[1:3:1, ::-2]
3603 v = memoryview(nd1)
3604 w = memoryview(nd2)
3605
3606 self.assertEqual(v, nd1)
3607 self.assertEqual(w, nd2)
3608 self.assertNotEqual(v, nd2)
3609 self.assertNotEqual(w, nd1)
3610 self.assertNotEqual(v, w)
3611
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003612 # same values, non-contiguous, struct module
3613 ex1 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='=ii')
3614 nd1 = ex1[3:1:-1, ::-2]
3615 ex2 = ndarray([(2**31-1, -2**31)]*22, shape=[11, 2], format='>ii')
3616 nd2 = ex2[1:3:1, ::-2]
3617 v = memoryview(nd1)
3618 w = memoryview(nd2)
3619
3620 self.assertEqual(v, nd1)
3621 self.assertEqual(w, nd2)
3622 self.assertEqual(v, nd2)
3623 self.assertEqual(w, nd1)
3624 self.assertEqual(v, w)
3625
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003626 # different shape
3627 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b')
3628 nd1 = ex1[1:3:, ::-2]
3629 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3630 nd2 = ex2[1:3:, ::-2]
3631 v = memoryview(nd1)
3632 w = memoryview(nd2)
3633
3634 self.assertEqual(v, nd1)
3635 self.assertEqual(w, nd2)
3636 self.assertNotEqual(v, nd2)
3637 self.assertNotEqual(w, nd1)
3638 self.assertNotEqual(v, w)
3639
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003640 # different shape, struct module
3641 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='B')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003642 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003643 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003644 nd2 = ex2[1:3:, ::-2]
3645 v = memoryview(nd1)
3646 w = memoryview(nd2)
3647
3648 self.assertEqual(v, nd1)
3649 self.assertEqual(w, nd2)
3650 self.assertNotEqual(v, nd2)
3651 self.assertNotEqual(w, nd1)
3652 self.assertNotEqual(v, w)
3653
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003654 # different format, struct module
3655 ex1 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='b3s')
3656 nd1 = ex1[1:3:, ::-2]
3657 nd2 = ndarray([(2, b'123')]*30, shape=[5, 3, 2], format='i3s')
3658 nd2 = ex2[1:3:, ::-2]
3659 v = memoryview(nd1)
3660 w = memoryview(nd2)
3661
3662 self.assertEqual(v, nd1)
3663 self.assertEqual(w, nd2)
3664 self.assertNotEqual(v, nd2)
3665 self.assertNotEqual(w, nd1)
3666 self.assertNotEqual(v, w)
3667
3668 def test_memoryview_compare_multidim_zero_shape(self):
3669
3670 # zeros in shape
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003671 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3672 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3673 v = memoryview(nd1)
3674 w = memoryview(nd2)
3675
3676 self.assertEqual(v, nd1)
3677 self.assertEqual(w, nd2)
3678 self.assertNotEqual(v, nd2)
3679 self.assertNotEqual(w, nd1)
3680 self.assertNotEqual(v, w)
3681
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003682 # zeros in shape, struct module
3683 nd1 = ndarray(list(range(30)), shape=[0, 3, 2], format='i')
3684 nd2 = ndarray(list(range(30)), shape=[5, 0, 2], format='@i')
3685 v = memoryview(nd1)
3686 w = memoryview(nd2)
3687
3688 self.assertEqual(v, nd1)
3689 self.assertEqual(w, nd2)
3690 self.assertNotEqual(v, nd2)
3691 self.assertNotEqual(w, nd1)
3692 self.assertNotEqual(v, w)
3693
3694 def test_memoryview_compare_multidim_zero_strides(self):
3695
3696 # zero strides
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003697 nd1 = ndarray([900]*80, shape=[4, 5, 4], format='@L')
3698 nd2 = ndarray([900], shape=[4, 5, 4], strides=[0, 0, 0], format='L')
3699 v = memoryview(nd1)
3700 w = memoryview(nd2)
3701
3702 self.assertEqual(v, nd1)
3703 self.assertEqual(w, nd2)
3704 self.assertEqual(v, nd2)
3705 self.assertEqual(w, nd1)
3706 self.assertEqual(v, w)
3707 self.assertEqual(v.tolist(), w.tolist())
3708
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003709 # zero strides, struct module
3710 nd1 = ndarray([(1, 2)]*10, shape=[2, 5], format='=lQ')
3711 nd2 = ndarray([(1, 2)], shape=[2, 5], strides=[0, 0], format='<lQ')
3712 v = memoryview(nd1)
3713 w = memoryview(nd2)
3714
3715 self.assertEqual(v, nd1)
3716 self.assertEqual(w, nd2)
3717 self.assertEqual(v, nd2)
3718 self.assertEqual(w, nd1)
3719 self.assertEqual(v, w)
3720
3721 def test_memoryview_compare_multidim_suboffsets(self):
3722
3723 # suboffsets
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003724 ex1 = ndarray(list(range(40)), shape=[5, 8], format='@I')
3725 nd1 = ex1[3:1:-1, ::-2]
3726 ex2 = ndarray(list(range(40)), shape=[5, 8], format='I', flags=ND_PIL)
3727 nd2 = ex2[1:3:1, ::-2]
3728 v = memoryview(nd1)
3729 w = memoryview(nd2)
3730
3731 self.assertEqual(v, nd1)
3732 self.assertEqual(w, nd2)
3733 self.assertNotEqual(v, nd2)
3734 self.assertNotEqual(w, nd1)
3735 self.assertNotEqual(v, w)
3736
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003737 # suboffsets, struct module
3738 ex1 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='=Qq',
3739 flags=ND_WRITABLE)
3740 ex1[2][7] = (1, -2)
3741 nd1 = ex1[3:1:-1, ::-2]
3742
3743 ex2 = ndarray([(2**64-1, -1)]*40, shape=[5, 8], format='>Qq',
3744 flags=ND_PIL|ND_WRITABLE)
3745 ex2[2][7] = (1, -2)
3746 nd2 = ex2[1:3:1, ::-2]
3747
3748 v = memoryview(nd1)
3749 w = memoryview(nd2)
3750
3751 self.assertEqual(v, nd1)
3752 self.assertEqual(w, nd2)
3753 self.assertEqual(v, nd2)
3754 self.assertEqual(w, nd1)
3755 self.assertEqual(v, w)
3756
3757 # suboffsets, different shape
3758 ex1 = ndarray(list(range(30)), shape=[2, 3, 5], format='b',
3759 flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003760 nd1 = ex1[1:3:, ::-2]
3761 nd2 = ndarray(list(range(30)), shape=[3, 2, 5], format='b')
3762 nd2 = ex2[1:3:, ::-2]
3763 v = memoryview(nd1)
3764 w = memoryview(nd2)
3765
3766 self.assertEqual(v, nd1)
3767 self.assertEqual(w, nd2)
3768 self.assertNotEqual(v, nd2)
3769 self.assertNotEqual(w, nd1)
3770 self.assertNotEqual(v, w)
3771
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003772 # suboffsets, different shape, struct module
3773 ex1 = ndarray([(2**8-1, -1)]*40, shape=[2, 3, 5], format='Bb',
3774 flags=ND_PIL|ND_WRITABLE)
3775 nd1 = ex1[1:2:, ::-2]
3776
3777 ex2 = ndarray([(2**8-1, -1)]*40, shape=[3, 2, 5], format='Bb')
3778 nd2 = ex2[1:2:, ::-2]
3779
3780 v = memoryview(nd1)
3781 w = memoryview(nd2)
3782
3783 self.assertEqual(v, nd1)
3784 self.assertEqual(w, nd2)
3785 self.assertNotEqual(v, nd2)
3786 self.assertNotEqual(w, nd1)
3787 self.assertNotEqual(v, w)
3788
3789 # suboffsets, different format
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003790 ex1 = ndarray(list(range(30)), shape=[5, 3, 2], format='i', flags=ND_PIL)
3791 nd1 = ex1[1:3:, ::-2]
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003792 ex2 = ndarray(list(range(30)), shape=[5, 3, 2], format='@I', flags=ND_PIL)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003793 nd2 = ex2[1:3:, ::-2]
3794 v = memoryview(nd1)
3795 w = memoryview(nd2)
3796
3797 self.assertEqual(v, nd1)
3798 self.assertEqual(w, nd2)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003799 self.assertEqual(v, nd2)
3800 self.assertEqual(w, nd1)
3801 self.assertEqual(v, w)
3802
3803 # suboffsets, different format, struct module
3804 ex1 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3805 flags=ND_PIL|ND_WRITABLE)
3806 ex1[1][2][2] = (b'sushi', b'', 1)
3807 nd1 = ex1[1:3:, ::-2]
3808
3809 ex2 = ndarray([(b'hello', b'', 1)]*27, shape=[3, 3, 3], format='5s0sP',
3810 flags=ND_PIL|ND_WRITABLE)
3811 ex1[1][2][2] = (b'sushi', b'', 1)
3812 nd2 = ex2[1:3:, ::-2]
3813
3814 v = memoryview(nd1)
3815 w = memoryview(nd2)
3816
3817 self.assertEqual(v, nd1)
3818 self.assertEqual(w, nd2)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003819 self.assertNotEqual(v, nd2)
3820 self.assertNotEqual(w, nd1)
3821 self.assertNotEqual(v, w)
3822
3823 # initialize mixed C/Fortran + suboffsets
3824 lst1 = list(range(-15, 15))
3825 lst2 = transpose(lst1, [3, 2, 5])
3826 nd1 = ndarray(lst1, shape=[3, 2, 5], format='@l', flags=ND_PIL)
3827 nd2 = ndarray(lst2, shape=[3, 2, 5], format='l', flags=ND_FORTRAN|ND_PIL)
3828 v = memoryview(nd1)
3829 w = memoryview(nd2)
3830
3831 self.assertEqual(v, nd1)
3832 self.assertEqual(w, nd2)
3833 self.assertEqual(v, w)
3834
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003835 # initialize mixed C/Fortran + suboffsets, struct module
3836 lst1 = [(b'sashimi', b'sliced', 20.05)]*30
3837 lst1[11] = (b'ramen', b'spicy', 9.45)
3838 lst2 = transpose(lst1, [3, 2, 5])
3839
3840 nd1 = ndarray(lst1, shape=[3, 2, 5], format='< 10p 9p d', flags=ND_PIL)
3841 nd2 = ndarray(lst2, shape=[3, 2, 5], format='> 10p 9p d',
3842 flags=ND_FORTRAN|ND_PIL)
3843 v = memoryview(nd1)
3844 w = memoryview(nd2)
3845
3846 self.assertEqual(v, nd1)
3847 self.assertEqual(w, nd2)
3848 self.assertEqual(v, w)
3849
3850 def test_memoryview_compare_not_equal(self):
3851
3852 # items not equal
3853 for byteorder in ['=', '<', '>', '!']:
3854 x = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q')
3855 y = ndarray([2**63]*120, shape=[3,5,2,2,2], format=byteorder+'Q',
3856 flags=ND_WRITABLE|ND_FORTRAN)
3857 y[2][3][1][1][1] = 1
3858 a = memoryview(x)
3859 b = memoryview(y)
3860 self.assertEqual(a, x)
3861 self.assertEqual(b, y)
3862 self.assertNotEqual(a, b)
3863 self.assertNotEqual(a, y)
3864 self.assertNotEqual(b, x)
3865
3866 x = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3867 format=byteorder+'QLH')
3868 y = ndarray([(2**63, 2**31, 2**15)]*120, shape=[3,5,2,2,2],
3869 format=byteorder+'QLH', flags=ND_WRITABLE|ND_FORTRAN)
3870 y[2][3][1][1][1] = (1, 1, 1)
3871 a = memoryview(x)
3872 b = memoryview(y)
3873 self.assertEqual(a, x)
3874 self.assertEqual(b, y)
3875 self.assertNotEqual(a, b)
3876 self.assertNotEqual(a, y)
3877 self.assertNotEqual(b, x)
3878
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003879 def test_memoryview_check_released(self):
3880
3881 a = array.array('d', [1.1, 2.2, 3.3])
3882
3883 m = memoryview(a)
3884 m.release()
3885
3886 # PyMemoryView_FromObject()
3887 self.assertRaises(ValueError, memoryview, m)
3888 # memoryview.cast()
3889 self.assertRaises(ValueError, m.cast, 'c')
3890 # getbuffer()
3891 self.assertRaises(ValueError, ndarray, m)
3892 # memoryview.tolist()
3893 self.assertRaises(ValueError, m.tolist)
3894 # memoryview.tobytes()
3895 self.assertRaises(ValueError, m.tobytes)
3896 # sequence
3897 self.assertRaises(ValueError, eval, "1.0 in m", locals())
3898 # subscript
3899 self.assertRaises(ValueError, m.__getitem__, 0)
3900 # assignment
3901 self.assertRaises(ValueError, m.__setitem__, 0, 1)
3902
3903 for attr in ('obj', 'nbytes', 'readonly', 'itemsize', 'format', 'ndim',
3904 'shape', 'strides', 'suboffsets', 'c_contiguous',
3905 'f_contiguous', 'contiguous'):
3906 self.assertRaises(ValueError, m.__getattribute__, attr)
3907
3908 # richcompare
3909 b = array.array('d', [1.1, 2.2, 3.3])
3910 m1 = memoryview(a)
3911 m2 = memoryview(b)
3912
3913 self.assertEqual(m1, m2)
3914 m1.release()
3915 self.assertNotEqual(m1, m2)
3916 self.assertNotEqual(m1, a)
3917 self.assertEqual(m1, m1)
3918
3919 def test_memoryview_tobytes(self):
3920 # Many implicit tests are already in self.verify().
3921
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003922 t = (-529, 576, -625, 676, -729)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003923
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003924 nd = ndarray(t, shape=[5], format='@h')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003925 m = memoryview(nd)
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003926 self.assertEqual(m, nd)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003927 self.assertEqual(m.tobytes(), nd.tobytes())
3928
Nick Coghlan06e1ab02012-08-25 17:59:50 +10003929 nd = ndarray([t], shape=[1], format='>hQiLl')
3930 m = memoryview(nd)
3931 self.assertEqual(m, nd)
3932 self.assertEqual(m.tobytes(), nd.tobytes())
3933
3934 nd = ndarray([t for _ in range(12)], shape=[2,2,3], format='=hQiLl')
3935 m = memoryview(nd)
3936 self.assertEqual(m, nd)
3937 self.assertEqual(m.tobytes(), nd.tobytes())
3938
3939 nd = ndarray([t for _ in range(120)], shape=[5,2,2,3,2],
3940 format='<hQiLl')
3941 m = memoryview(nd)
3942 self.assertEqual(m, nd)
3943 self.assertEqual(m.tobytes(), nd.tobytes())
3944
3945 # Unknown formats are handled: tobytes() purely depends on itemsize.
3946 if ctypes:
3947 # format: "T{>l:x:>l:y:}"
3948 class BEPoint(ctypes.BigEndianStructure):
3949 _fields_ = [("x", ctypes.c_long), ("y", ctypes.c_long)]
3950 point = BEPoint(100, 200)
3951 a = memoryview(point)
3952 self.assertEqual(a.tobytes(), bytes(point))
3953
Stefan Krah9a2d99e2012-02-25 12:24:21 +01003954 def test_memoryview_get_contiguous(self):
3955 # Many implicit tests are already in self.verify().
3956
3957 # no buffer interface
3958 self.assertRaises(TypeError, get_contiguous, {}, PyBUF_READ, 'F')
3959
3960 # writable request to read-only object
3961 self.assertRaises(BufferError, get_contiguous, b'x', PyBUF_WRITE, 'C')
3962
3963 # writable request to non-contiguous object
3964 nd = ndarray([1, 2, 3], shape=[2], strides=[2])
3965 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'A')
3966
3967 # scalar, read-only request from read-only exporter
3968 nd = ndarray(9, shape=(), format="L")
3969 for order in ['C', 'F', 'A']:
3970 m = get_contiguous(nd, PyBUF_READ, order)
3971 self.assertEqual(m, nd)
3972 self.assertEqual(m[()], 9)
3973
3974 # scalar, read-only request from writable exporter
3975 nd = ndarray(9, shape=(), format="L", flags=ND_WRITABLE)
3976 for order in ['C', 'F', 'A']:
3977 m = get_contiguous(nd, PyBUF_READ, order)
3978 self.assertEqual(m, nd)
3979 self.assertEqual(m[()], 9)
3980
3981 # scalar, writable request
3982 for order in ['C', 'F', 'A']:
3983 nd[()] = 9
3984 m = get_contiguous(nd, PyBUF_WRITE, order)
3985 self.assertEqual(m, nd)
3986 self.assertEqual(m[()], 9)
3987
3988 m[()] = 10
3989 self.assertEqual(m[()], 10)
3990 self.assertEqual(nd[()], 10)
3991
3992 # zeros in shape
3993 nd = ndarray([1], shape=[0], format="L", flags=ND_WRITABLE)
3994 for order in ['C', 'F', 'A']:
3995 m = get_contiguous(nd, PyBUF_READ, order)
3996 self.assertRaises(IndexError, m.__getitem__, 0)
3997 self.assertEqual(m, nd)
3998 self.assertEqual(m.tolist(), [])
3999
4000 nd = ndarray(list(range(8)), shape=[2, 0, 7], format="L",
4001 flags=ND_WRITABLE)
4002 for order in ['C', 'F', 'A']:
4003 m = get_contiguous(nd, PyBUF_READ, order)
4004 self.assertEqual(ndarray(m).tolist(), [[], []])
4005
4006 # one-dimensional
4007 nd = ndarray([1], shape=[1], format="h", flags=ND_WRITABLE)
4008 for order in ['C', 'F', 'A']:
4009 m = get_contiguous(nd, PyBUF_WRITE, order)
4010 self.assertEqual(m, nd)
4011 self.assertEqual(m.tolist(), nd.tolist())
4012
4013 nd = ndarray([1, 2, 3], shape=[3], format="b", flags=ND_WRITABLE)
4014 for order in ['C', 'F', 'A']:
4015 m = get_contiguous(nd, PyBUF_WRITE, order)
4016 self.assertEqual(m, nd)
4017 self.assertEqual(m.tolist(), nd.tolist())
4018
4019 # one-dimensional, non-contiguous
4020 nd = ndarray([1, 2, 3], shape=[2], strides=[2], flags=ND_WRITABLE)
4021 for order in ['C', 'F', 'A']:
4022 m = get_contiguous(nd, PyBUF_READ, order)
4023 self.assertEqual(m, nd)
4024 self.assertEqual(m.tolist(), nd.tolist())
4025 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4026 self.assertEqual(m[1], 3)
4027 self.assertEqual(nd[1], 3)
4028
4029 nd = nd[::-1]
4030 for order in ['C', 'F', 'A']:
4031 m = get_contiguous(nd, PyBUF_READ, order)
4032 self.assertEqual(m, nd)
4033 self.assertEqual(m.tolist(), nd.tolist())
4034 self.assertRaises(TypeError, m.__setitem__, 1, 20)
4035 self.assertEqual(m[1], 1)
4036 self.assertEqual(nd[1], 1)
4037
4038 # multi-dimensional, contiguous input
4039 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE)
4040 for order in ['C', 'A']:
4041 m = get_contiguous(nd, PyBUF_WRITE, order)
4042 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4043
4044 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'F')
4045 m = get_contiguous(nd, PyBUF_READ, order)
4046 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4047
4048 nd = ndarray(list(range(12)), shape=[3, 4],
4049 flags=ND_WRITABLE|ND_FORTRAN)
4050 for order in ['F', 'A']:
4051 m = get_contiguous(nd, PyBUF_WRITE, order)
4052 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4053
4054 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE, 'C')
4055 m = get_contiguous(nd, PyBUF_READ, order)
4056 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4057
4058 # multi-dimensional, non-contiguous input
4059 nd = ndarray(list(range(12)), shape=[3, 4], flags=ND_WRITABLE|ND_PIL)
4060 for order in ['C', 'F', 'A']:
4061 self.assertRaises(BufferError, get_contiguous, nd, PyBUF_WRITE,
4062 order)
4063 m = get_contiguous(nd, PyBUF_READ, order)
4064 self.assertEqual(ndarray(m).tolist(), nd.tolist())
4065
4066 # flags
4067 nd = ndarray([1,2,3,4,5], shape=[3], strides=[2])
4068 m = get_contiguous(nd, PyBUF_READ, 'C')
4069 self.assertTrue(m.c_contiguous)
4070
4071 def test_memoryview_serializing(self):
4072
4073 # C-contiguous
4074 size = struct.calcsize('i')
4075 a = array.array('i', [1,2,3,4,5])
4076 m = memoryview(a)
4077 buf = io.BytesIO(m)
4078 b = bytearray(5*size)
4079 buf.readinto(b)
4080 self.assertEqual(m.tobytes(), b)
4081
4082 # C-contiguous, multi-dimensional
4083 size = struct.calcsize('L')
4084 nd = ndarray(list(range(12)), shape=[2,3,2], format="L")
4085 m = memoryview(nd)
4086 buf = io.BytesIO(m)
4087 b = bytearray(2*3*2*size)
4088 buf.readinto(b)
4089 self.assertEqual(m.tobytes(), b)
4090
4091 # Fortran contiguous, multi-dimensional
4092 #size = struct.calcsize('L')
4093 #nd = ndarray(list(range(12)), shape=[2,3,2], format="L",
4094 # flags=ND_FORTRAN)
4095 #m = memoryview(nd)
4096 #buf = io.BytesIO(m)
4097 #b = bytearray(2*3*2*size)
4098 #buf.readinto(b)
4099 #self.assertEqual(m.tobytes(), b)
4100
4101 def test_memoryview_hash(self):
4102
4103 # bytes exporter
4104 b = bytes(list(range(12)))
4105 m = memoryview(b)
4106 self.assertEqual(hash(b), hash(m))
4107
4108 # C-contiguous
4109 mc = m.cast('c', shape=[3,4])
4110 self.assertEqual(hash(mc), hash(b))
4111
4112 # non-contiguous
4113 mx = m[::-2]
4114 b = bytes(list(range(12))[::-2])
4115 self.assertEqual(hash(mx), hash(b))
4116
4117 # Fortran contiguous
4118 nd = ndarray(list(range(30)), shape=[3,2,5], flags=ND_FORTRAN)
4119 m = memoryview(nd)
4120 self.assertEqual(hash(m), hash(nd))
4121
4122 # multi-dimensional slice
4123 nd = ndarray(list(range(30)), shape=[3,2,5])
4124 x = nd[::2, ::, ::-1]
4125 m = memoryview(x)
4126 self.assertEqual(hash(m), hash(x))
4127
4128 # multi-dimensional slice with suboffsets
4129 nd = ndarray(list(range(30)), shape=[2,5,3], flags=ND_PIL)
4130 x = nd[::2, ::, ::-1]
4131 m = memoryview(x)
4132 self.assertEqual(hash(m), hash(x))
4133
Stefan Krah4af77a02012-11-02 17:49:22 +01004134 # equality-hash invariant
4135 x = ndarray(list(range(12)), shape=[12], format='B')
Stefan Krahb716f842012-11-04 20:53:50 +01004136 a = memoryview(x)
Stefan Krah4af77a02012-11-02 17:49:22 +01004137
4138 y = ndarray(list(range(12)), shape=[12], format='b')
Stefan Krahb716f842012-11-04 20:53:50 +01004139 b = memoryview(y)
Stefan Krah4af77a02012-11-02 17:49:22 +01004140
Stefan Krahb716f842012-11-04 20:53:50 +01004141 self.assertEqual(a, b)
4142 self.assertEqual(hash(a), hash(b))
Stefan Krah4af77a02012-11-02 17:49:22 +01004143
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004144 # non-byte formats
4145 nd = ndarray(list(range(12)), shape=[2,2,3], format='L')
4146 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004147 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004148
4149 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='h')
4150 m = memoryview(nd)
Stefan Krah4af77a02012-11-02 17:49:22 +01004151 self.assertRaises(ValueError, m.__hash__)
4152
4153 nd = ndarray(list(range(12)), shape=[2,2,3], format='= L')
4154 m = memoryview(nd)
4155 self.assertRaises(ValueError, m.__hash__)
4156
4157 nd = ndarray(list(range(-6, 6)), shape=[2,2,3], format='< h')
4158 m = memoryview(nd)
4159 self.assertRaises(ValueError, m.__hash__)
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004160
4161 def test_memoryview_release(self):
4162
4163 # Create re-exporter from getbuffer(memoryview), then release the view.
4164 a = bytearray([1,2,3])
4165 m = memoryview(a)
4166 nd = ndarray(m) # re-exporter
4167 self.assertRaises(BufferError, m.release)
4168 del nd
4169 m.release()
4170
Stefan Krah4e99a312012-03-05 09:30:47 +01004171 a = bytearray([1,2,3])
4172 m = memoryview(a)
4173 nd1 = ndarray(m, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4174 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4175 self.assertIs(nd2.obj, m)
4176 self.assertRaises(BufferError, m.release)
4177 del nd1, nd2
4178 m.release()
4179
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004180 # chained views
4181 a = bytearray([1,2,3])
4182 m1 = memoryview(a)
4183 m2 = memoryview(m1)
4184 nd = ndarray(m2) # re-exporter
4185 m1.release()
4186 self.assertRaises(BufferError, m2.release)
4187 del nd
4188 m2.release()
4189
Stefan Krah4e99a312012-03-05 09:30:47 +01004190 a = bytearray([1,2,3])
4191 m1 = memoryview(a)
4192 m2 = memoryview(m1)
4193 nd1 = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4194 nd2 = ndarray(nd1, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4195 self.assertIs(nd2.obj, m2)
4196 m1.release()
4197 self.assertRaises(BufferError, m2.release)
4198 del nd1, nd2
4199 m2.release()
4200
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004201 # Allow changing layout while buffers are exported.
4202 nd = ndarray([1,2,3], shape=[3], flags=ND_VAREXPORT)
4203 m1 = memoryview(nd)
4204
4205 nd.push([4,5,6,7,8], shape=[5]) # mutate nd
4206 m2 = memoryview(nd)
4207
4208 x = memoryview(m1)
4209 self.assertEqual(x.tolist(), m1.tolist())
4210
4211 y = memoryview(m2)
4212 self.assertEqual(y.tolist(), m2.tolist())
4213 self.assertEqual(y.tolist(), nd.tolist())
4214 m2.release()
4215 y.release()
4216
4217 nd.pop() # pop the current view
4218 self.assertEqual(x.tolist(), nd.tolist())
4219
4220 del nd
4221 m1.release()
4222 x.release()
4223
4224 # If multiple memoryviews share the same managed buffer, implicit
4225 # release() in the context manager's __exit__() method should still
4226 # work.
4227 def catch22(b):
4228 with memoryview(b) as m2:
4229 pass
4230
4231 x = bytearray(b'123')
4232 with memoryview(x) as m1:
4233 catch22(m1)
4234 self.assertEqual(m1[0], ord(b'1'))
4235
Stefan Krah4e99a312012-03-05 09:30:47 +01004236 x = ndarray(list(range(12)), shape=[2,2,3], format='l')
4237 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4238 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4239 self.assertIs(z.obj, x)
4240 with memoryview(z) as m:
4241 catch22(m)
4242 self.assertEqual(m[0:1].tolist(), [[[0, 1, 2], [3, 4, 5]]])
4243
4244 # Test garbage collection.
4245 for flags in (0, ND_REDIRECT):
4246 x = bytearray(b'123')
4247 with memoryview(x) as m1:
4248 del x
4249 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4250 with memoryview(y) as m2:
4251 del y
4252 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4253 with memoryview(z) as m3:
4254 del z
4255 catch22(m3)
4256 catch22(m2)
4257 catch22(m1)
4258 self.assertEqual(m1[0], ord(b'1'))
4259 self.assertEqual(m2[1], ord(b'2'))
4260 self.assertEqual(m3[2], ord(b'3'))
4261 del m3
4262 del m2
4263 del m1
4264
4265 x = bytearray(b'123')
4266 with memoryview(x) as m1:
4267 del x
4268 y = ndarray(m1, getbuf=PyBUF_FULL_RO, flags=flags)
4269 with memoryview(y) as m2:
4270 del y
4271 z = ndarray(m2, getbuf=PyBUF_FULL_RO, flags=flags)
4272 with memoryview(z) as m3:
4273 del z
4274 catch22(m1)
4275 catch22(m2)
4276 catch22(m3)
4277 self.assertEqual(m1[0], ord(b'1'))
4278 self.assertEqual(m2[1], ord(b'2'))
4279 self.assertEqual(m3[2], ord(b'3'))
4280 del m1, m2, m3
4281
Stefan Krahfcbb4162012-03-05 10:45:31 +01004282 # memoryview.release() fails if the view has exported buffers.
4283 x = bytearray(b'123')
4284 with self.assertRaises(BufferError):
4285 with memoryview(x) as m:
4286 ex = ndarray(m)
4287 m[0] == ord(b'1')
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004288
Stefan Krah4e99a312012-03-05 09:30:47 +01004289 def test_memoryview_redirect(self):
4290
4291 nd = ndarray([1.0 * x for x in range(12)], shape=[12], format='d')
4292 a = array.array('d', [1.0 * x for x in range(12)])
4293
4294 for x in (nd, a):
4295 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4296 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4297 m = memoryview(z)
4298
4299 self.assertIs(y.obj, x)
4300 self.assertIs(z.obj, x)
4301 self.assertIs(m.obj, x)
4302
4303 self.assertEqual(m, x)
4304 self.assertEqual(m, y)
4305 self.assertEqual(m, z)
4306
4307 self.assertEqual(m[1:3], x[1:3])
4308 self.assertEqual(m[1:3], y[1:3])
4309 self.assertEqual(m[1:3], z[1:3])
4310 del y, z
4311 self.assertEqual(m[1:3], x[1:3])
4312
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004313 def test_memoryview_from_static_exporter(self):
4314
4315 fmt = 'B'
4316 lst = [0,1,2,3,4,5,6,7,8,9,10,11]
4317
4318 # exceptions
4319 self.assertRaises(TypeError, staticarray, 1, 2, 3)
4320
4321 # view.obj==x
4322 x = staticarray()
4323 y = memoryview(x)
4324 self.verify(y, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004325 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004326 ndim=1, shape=[12], strides=[1],
4327 lst=lst)
4328 for i in range(12):
4329 self.assertEqual(y[i], i)
4330 del x
4331 del y
4332
4333 x = staticarray()
4334 y = memoryview(x)
4335 del y
4336 del x
4337
4338 x = staticarray()
4339 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4340 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4341 m = memoryview(z)
4342 self.assertIs(y.obj, x)
4343 self.assertIs(m.obj, z)
4344 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004345 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004346 ndim=1, shape=[12], strides=[1],
4347 lst=lst)
4348 del x, y, z, m
4349
4350 x = staticarray()
4351 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4352 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4353 m = memoryview(z)
4354 self.assertIs(y.obj, x)
4355 self.assertIs(z.obj, x)
4356 self.assertIs(m.obj, x)
4357 self.verify(m, obj=x,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004358 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004359 ndim=1, shape=[12], strides=[1],
4360 lst=lst)
4361 del x, y, z, m
4362
4363 # view.obj==NULL
4364 x = staticarray(legacy_mode=True)
4365 y = memoryview(x)
4366 self.verify(y, obj=None,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004367 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004368 ndim=1, shape=[12], strides=[1],
4369 lst=lst)
4370 for i in range(12):
4371 self.assertEqual(y[i], i)
4372 del x
4373 del y
4374
4375 x = staticarray(legacy_mode=True)
4376 y = memoryview(x)
4377 del y
4378 del x
4379
4380 x = staticarray(legacy_mode=True)
4381 y = ndarray(x, getbuf=PyBUF_FULL_RO)
4382 z = ndarray(y, getbuf=PyBUF_FULL_RO)
4383 m = memoryview(z)
4384 self.assertIs(y.obj, None)
4385 self.assertIs(m.obj, z)
4386 self.verify(m, obj=z,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004387 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004388 ndim=1, shape=[12], strides=[1],
4389 lst=lst)
4390 del x, y, z, m
4391
4392 x = staticarray(legacy_mode=True)
4393 y = ndarray(x, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4394 z = ndarray(y, getbuf=PyBUF_FULL_RO, flags=ND_REDIRECT)
4395 m = memoryview(z)
4396 # Clearly setting view.obj==NULL is inferior, since it
4397 # messes up the redirection chain:
4398 self.assertIs(y.obj, None)
4399 self.assertIs(z.obj, y)
4400 self.assertIs(m.obj, y)
4401 self.verify(m, obj=y,
Serhiy Storchakae0d67f12018-07-26 13:23:03 +03004402 itemsize=1, fmt=fmt, readonly=True,
Stefan Krahbf6c7ec2012-03-05 14:37:34 +01004403 ndim=1, shape=[12], strides=[1],
4404 lst=lst)
4405 del x, y, z, m
4406
Stefan Krah1649c1b2012-03-05 17:45:17 +01004407 def test_memoryview_getbuffer_undefined(self):
4408
4409 # getbufferproc does not adhere to the new documentation
4410 nd = ndarray([1,2,3], [3], flags=ND_GETBUF_FAIL|ND_GETBUF_UNDEFINED)
4411 self.assertRaises(BufferError, memoryview, nd)
4412
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004413 def test_issue_7385(self):
4414 x = ndarray([1,2,3], shape=[3], flags=ND_GETBUF_FAIL)
4415 self.assertRaises(BufferError, memoryview, x)
4416
4417
Stefan Krah9a2d99e2012-02-25 12:24:21 +01004418if __name__ == "__main__":
Brett Cannon3e9a9ae2013-06-12 21:25:59 -04004419 unittest.main()