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