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