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