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