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