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