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