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