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