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