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