1# mode: run 2# tag: list, tuple, slice, slicing 3 4cimport cython 5 6 7@cython.test_fail_if_path_exists("//CondExprNode") 8def slice_list(list l, int start, int stop): 9 """ 10 >>> slice_list([1,2,3,4], 1, 3) 11 [2, 3] 12 >>> slice_list([1,2,3,4], 1, 7) 13 [2, 3, 4] 14 >>> slice_list([], 1, 3) 15 [] 16 >>> slice_list([1], 1, 3) 17 [] 18 >>> slice_list([1,2,3,4], -3, -1) 19 [2, 3] 20 >>> slice_list([1,2,3,4], -10, -1) 21 [1, 2, 3] 22 >>> slice_list([], -3, -1) 23 [] 24 >>> slice_list([1], -3, -1) 25 [] 26 """ 27 return l[start:stop] 28 29@cython.test_fail_if_path_exists("//CondExprNode") 30def slice_list_start(list l, int start): 31 """ 32 >>> slice_list_start([1,2,3,4], 1) 33 [2, 3, 4] 34 >>> slice_list_start([], 1) 35 [] 36 >>> slice_list_start([1], 1) 37 [] 38 >>> slice_list_start([1], 2) 39 [] 40 >>> slice_list_start([1,2,3,4], -3) 41 [2, 3, 4] 42 >>> slice_list_start([1,2,3,4], -10) 43 [1, 2, 3, 4] 44 >>> slice_list_start([], -3) 45 [] 46 >>> slice_list_start([1], -3) 47 [1] 48 """ 49 return l[start:] 50 51 52@cython.test_fail_if_path_exists("//CondExprNode") 53def slice_list_stop(list l, int stop): 54 """ 55 >>> slice_list_stop([1,2,3,4], 3) 56 [1, 2, 3] 57 >>> slice_list_stop([1,2,3,4], 7) 58 [1, 2, 3, 4] 59 >>> slice_list_stop([], 3) 60 [] 61 >>> slice_list_stop([1], 3) 62 [1] 63 >>> slice_list_stop([1,2,3,4], -3) 64 [1] 65 >>> slice_list_stop([1,2,3,4], -10) 66 [] 67 >>> slice_list_stop([], -1) 68 [] 69 >>> slice_list_stop([1], -1) 70 [] 71 >>> slice_list_stop([1, 2], -3) 72 [] 73 """ 74 return l[:stop] 75 76 77@cython.test_fail_if_path_exists("//CondExprNode") 78def slice_list_copy(list l): 79 """ 80 >>> slice_list_copy([]) 81 [] 82 >>> slice_list_copy([1,2,3]) 83 [1, 2, 3] 84 """ 85 return l[:] 86 87 88@cython.test_fail_if_path_exists("//CondExprNode") 89def slice_tuple_copy(tuple l): 90 """ 91 >>> slice_tuple_copy(()) 92 () 93 >>> slice_tuple_copy((1,2,3)) 94 (1, 2, 3) 95 """ 96 return l[:] 97 98 99@cython.test_fail_if_path_exists("//CondExprNode") 100def slice_tuple(tuple t, int start, int stop): 101 """ 102 >>> slice_tuple((1,2,3,4), 1, 3) 103 (2, 3) 104 >>> slice_tuple((1,2,3,4), 1, 7) 105 (2, 3, 4) 106 >>> slice_tuple((), 1, 3) 107 () 108 >>> slice_tuple((1,), 1, 3) 109 () 110 >>> slice_tuple((1,2,3,4), -3, -1) 111 (2, 3) 112 >>> slice_tuple((1,2,3,4), -10, -1) 113 (1, 2, 3) 114 >>> slice_tuple((), -3, -1) 115 () 116 >>> slice_tuple((1,), -3, -1) 117 () 118 """ 119 return t[start:stop] 120 121 122@cython.test_fail_if_path_exists("//CondExprNode") 123def slice_tuple_start(tuple t, int start): 124 """ 125 >>> slice_tuple_start((1,2,3,4), 1) 126 (2, 3, 4) 127 >>> slice_tuple_start((), 1) 128 () 129 >>> slice_tuple_start((1,), 1) 130 () 131 >>> slice_tuple_start((1,2,3,4), -3) 132 (2, 3, 4) 133 >>> slice_tuple_start((1,2,3,4), -10) 134 (1, 2, 3, 4) 135 >>> slice_tuple_start((), -3) 136 () 137 >>> slice_tuple_start((1,), -3) 138 (1,) 139 """ 140 return t[start:] 141 142 143@cython.test_fail_if_path_exists("//CondExprNode") 144def slice_tuple_stop(tuple t, int stop): 145 """ 146 >>> slice_tuple_stop((1,2,3,4), 3) 147 (1, 2, 3) 148 >>> slice_tuple_stop((1,2,3,4), 7) 149 (1, 2, 3, 4) 150 >>> slice_tuple_stop((), 3) 151 () 152 >>> slice_tuple_stop((1,), 3) 153 (1,) 154 >>> slice_tuple_stop((1,2,3,4), -1) 155 (1, 2, 3) 156 >>> slice_tuple_stop((), -1) 157 () 158 """ 159 return t[:stop] 160 161 162@cython.test_fail_if_path_exists("//CondExprNode") 163def slice_list_assign_list(list l): 164 """ 165 >>> l = [1,2,3,4] 166 >>> l2 = l[:] 167 >>> slice_list_assign_list(l2) 168 [1, 1, 2, 3, 4, 4] 169 """ 170 l[1:3] = [1,2,3,4] 171 return l 172 173 174@cython.test_fail_if_path_exists("//CondExprNode") 175def slice_list_assign_tuple(list l): 176 """ 177 >>> l = [1,2,3,4] 178 >>> l2 = l[:] 179 >>> slice_list_assign_tuple(l2) 180 [1, 1, 2, 3, 4, 4] 181 """ 182 l[1:3] = (1,2,3,4) 183 return l 184 185 186@cython.test_fail_if_path_exists("//CondExprNode") 187def slice_list_assign(list l, value): 188 """ 189 >>> l = [1,2,3,4] 190 >>> l2 = l[:] 191 >>> slice_list_assign(l2, (1,2,3,4)) 192 [1, 1, 2, 3, 4, 4] 193 >>> l2 = l[:] 194 >>> slice_list_assign(l2, dict(zip(l,l))) 195 [1, 1, 2, 3, 4, 4] 196 """ 197 l[1:3] = value 198 return l 199 200 201def slice_charp(py_string_arg): 202 """ 203 >>> print("%s" % slice_charp('abcdefg')) 204 bc 205 """ 206 cdef bytes py_string = py_string_arg.encode(u'ASCII') 207 cdef char* s = py_string 208 return s[1:3].decode(u'ASCII') 209 210 211def slice_charp_repeat(py_string_arg): 212 """ 213 >>> print("%s" % slice_charp_repeat('abcdefg')) 214 cd 215 """ 216 cdef bytes py_string = py_string_arg.encode(u'ASCII') 217 cdef char* s = py_string 218 cdef bytes slice_val = s[1:6] 219 s = slice_val 220 return s[1:3].decode(u'ASCII') 221 222 223# Readers will find the common boilerplate in the tests below: 224# >>> l = [1,2,3,4,5] 225# >>> t = tuple(l) 226# >>> b = ''.join(map(str, l)).encode('ASCII') 227# >>> u = b.decode('ASCII') 228# >>> o = (l, t, b, u) 229# >>> n = ('list', 'tuple', 'bytes', 'unicode') 230# >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 231# >>> r = lambda i, *a: '%s[%s] -> %s' % (n[i], ':'.join(map(repr, a)), FUNCTION_NAME(o[i], *a)) 232# Originally, this was planned to be a basic iteration over 233# the various object types contained within the slicable fused 234# type, but Python2 -> Python3 semantics changed the class names 235# and string representations used for raw bytes and unicode. 236# As a result, we dynamically adjust the printed string output 237# for each test in order to ensure consistent results when running 238# both Python2 and Python3. 239 240ctypedef fused slicable: 241 list 242 tuple 243 bytes 244 unicode 245 246 247@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode") 248def slice_fused_type_start(slicable seq, start): 249 """ 250 >>> l = [1,2,3,4,5] 251 >>> t = tuple(l) 252 >>> b = ''.join(map(str, l)).encode('ASCII') 253 >>> u = b.decode('ASCII') 254 >>> o = (l, t, b, u) 255 >>> n = ('list', 'tuple', 'bytes', 'unicode') 256 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 257 >>> r = lambda i, s: '%s[%r:] -> %s' % (n[i], s, p(slice_fused_type_start(o[i], s))) 258 >>> for i in range(len(o)): 259 ... for s in (0, len(l) - 1, len(l), -1, -len(l), None): 260 ... print(r(i, s)) 261 ... 262 list[0:] -> [1, 2, 3, 4, 5] 263 list[4:] -> [5] 264 list[5:] -> [] 265 list[-1:] -> [5] 266 list[-5:] -> [1, 2, 3, 4, 5] 267 list[None:] -> [1, 2, 3, 4, 5] 268 tuple[0:] -> (1, 2, 3, 4, 5) 269 tuple[4:] -> (5,) 270 tuple[5:] -> () 271 tuple[-1:] -> (5,) 272 tuple[-5:] -> (1, 2, 3, 4, 5) 273 tuple[None:] -> (1, 2, 3, 4, 5) 274 bytes[0:] -> 12345 275 bytes[4:] -> 5 276 bytes[5:] -> 277 bytes[-1:] -> 5 278 bytes[-5:] -> 12345 279 bytes[None:] -> 12345 280 unicode[0:] -> 12345 281 unicode[4:] -> 5 282 unicode[5:] -> 283 unicode[-1:] -> 5 284 unicode[-5:] -> 12345 285 unicode[None:] -> 12345 286 """ 287 obj = seq[start:] 288 return obj 289 290 291@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode") 292def slice_fused_type_stop(slicable seq, stop): 293 """ 294 >>> l = [1,2,3,4,5] 295 >>> t = tuple(l) 296 >>> b = ''.join(map(str, l)).encode('ASCII') 297 >>> u = b.decode('ASCII') 298 >>> o = (l, t, b, u) 299 >>> n = ('list', 'tuple', 'bytes', 'unicode') 300 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 301 >>> r = lambda i, s: '%s[:%r] -> %s' % (n[i], s, p(slice_fused_type_stop(o[i], s))) 302 >>> for i in range(len(o)): 303 ... for s in (0, len(l) - 1, len(l), -1, -len(l), None): 304 ... print(r(i, s)) 305 ... 306 list[:0] -> [] 307 list[:4] -> [1, 2, 3, 4] 308 list[:5] -> [1, 2, 3, 4, 5] 309 list[:-1] -> [1, 2, 3, 4] 310 list[:-5] -> [] 311 list[:None] -> [1, 2, 3, 4, 5] 312 tuple[:0] -> () 313 tuple[:4] -> (1, 2, 3, 4) 314 tuple[:5] -> (1, 2, 3, 4, 5) 315 tuple[:-1] -> (1, 2, 3, 4) 316 tuple[:-5] -> () 317 tuple[:None] -> (1, 2, 3, 4, 5) 318 bytes[:0] -> 319 bytes[:4] -> 1234 320 bytes[:5] -> 12345 321 bytes[:-1] -> 1234 322 bytes[:-5] -> 323 bytes[:None] -> 12345 324 unicode[:0] -> 325 unicode[:4] -> 1234 326 unicode[:5] -> 12345 327 unicode[:-1] -> 1234 328 unicode[:-5] -> 329 unicode[:None] -> 12345 330 """ 331 obj = seq[:stop] 332 return obj 333 334 335@cython.test_assert_path_exists("//SliceIndexNode//CondExprNode") 336def slice_fused_type_start_and_stop(slicable seq, start, stop): 337 """ 338 >>> l = [1,2,3,4,5] 339 >>> t = tuple(l) 340 >>> b = ''.join(map(str, l)).encode('ASCII') 341 >>> u = b.decode('ASCII') 342 >>> o = (l, t, b, u) 343 >>> n = ('list', 'tuple', 'bytes', 'unicode') 344 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 345 >>> r = lambda i, t, s: '%s[%r:%r] -> %s' % (n[i], t, s, p(slice_fused_type_start_and_stop(o[i], t, s))) 346 >>> for i in range(len(o)): 347 ... for start, stop in ((0, len(l)), (0, None), (None, len(l)), 348 ... (-len(l), 0), (1, 0), (0, 1)): 349 ... print(r(i, start, stop)) 350 ... 351 list[0:5] -> [1, 2, 3, 4, 5] 352 list[0:None] -> [1, 2, 3, 4, 5] 353 list[None:5] -> [1, 2, 3, 4, 5] 354 list[-5:0] -> [] 355 list[1:0] -> [] 356 list[0:1] -> [1] 357 tuple[0:5] -> (1, 2, 3, 4, 5) 358 tuple[0:None] -> (1, 2, 3, 4, 5) 359 tuple[None:5] -> (1, 2, 3, 4, 5) 360 tuple[-5:0] -> () 361 tuple[1:0] -> () 362 tuple[0:1] -> (1,) 363 bytes[0:5] -> 12345 364 bytes[0:None] -> 12345 365 bytes[None:5] -> 12345 366 bytes[-5:0] -> 367 bytes[1:0] -> 368 bytes[0:1] -> 1 369 unicode[0:5] -> 12345 370 unicode[0:None] -> 12345 371 unicode[None:5] -> 12345 372 unicode[-5:0] -> 373 unicode[1:0] -> 374 unicode[0:1] -> 1 375 """ 376 obj = seq[start:stop] 377 return obj 378 379 380def slice_fused_type_step(slicable seq, step): 381 """ 382 >>> l = [1,2,3,4,5] 383 >>> t = tuple(l) 384 >>> b = ''.join(map(str, l)).encode('ASCII') 385 >>> u = b.decode('ASCII') 386 >>> o = (l, t, b, u) 387 >>> n = ('list', 'tuple', 'bytes', 'unicode') 388 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 389 >>> r = lambda i, s: '%s[::%r] -> %s' % (n[i], s, p(slice_fused_type_step(o[i], s))) 390 >>> for i in range(len(o)): 391 ... for s in (1, -1, 2, -3, 5, -5, None): 392 ... print(r(i, s)) 393 ... 394 list[::1] -> [1, 2, 3, 4, 5] 395 list[::-1] -> [5, 4, 3, 2, 1] 396 list[::2] -> [1, 3, 5] 397 list[::-3] -> [5, 2] 398 list[::5] -> [1] 399 list[::-5] -> [5] 400 list[::None] -> [1, 2, 3, 4, 5] 401 tuple[::1] -> (1, 2, 3, 4, 5) 402 tuple[::-1] -> (5, 4, 3, 2, 1) 403 tuple[::2] -> (1, 3, 5) 404 tuple[::-3] -> (5, 2) 405 tuple[::5] -> (1,) 406 tuple[::-5] -> (5,) 407 tuple[::None] -> (1, 2, 3, 4, 5) 408 bytes[::1] -> 12345 409 bytes[::-1] -> 54321 410 bytes[::2] -> 135 411 bytes[::-3] -> 52 412 bytes[::5] -> 1 413 bytes[::-5] -> 5 414 bytes[::None] -> 12345 415 unicode[::1] -> 12345 416 unicode[::-1] -> 54321 417 unicode[::2] -> 135 418 unicode[::-3] -> 52 419 unicode[::5] -> 1 420 unicode[::-5] -> 5 421 unicode[::None] -> 12345 422 >>> for v in o: 423 ... try: slice_fused_type_step(v, 0) 424 ... except ValueError: pass 425 ... try: slice_fused_type_step(v, v) 426 ... except TypeError: pass 427 """ 428 obj = seq[::step] 429 return obj 430 431 432def slice_fused_type_start_and_step(slicable seq, start, step): 433 """ 434 >>> l = [1,2,3,4,5] 435 >>> t = tuple(l) 436 >>> b = ''.join(map(str, l)).encode('ASCII') 437 >>> u = b.decode('ASCII') 438 >>> o = (l, t, b, u) 439 >>> n = ('list', 'tuple', 'bytes', 'unicode') 440 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 441 >>> r = lambda i, s, t: '%s[%r::%r] -> %s' % (n[i], s, t, p(slice_fused_type_start_and_step(o[i], s, t))) 442 >>> for i in range(len(o)): 443 ... for start, step in ((0, 1), (0, -1), (1, 1), (1, -1), 444 ... (None, 1), (None, -1), (None, None), 445 ... (1, 2), (len(l), -2), (len(l), len(l))): 446 ... print(r(i, start, step)) 447 ... 448 list[0::1] -> [1, 2, 3, 4, 5] 449 list[0::-1] -> [1] 450 list[1::1] -> [2, 3, 4, 5] 451 list[1::-1] -> [2, 1] 452 list[None::1] -> [1, 2, 3, 4, 5] 453 list[None::-1] -> [5, 4, 3, 2, 1] 454 list[None::None] -> [1, 2, 3, 4, 5] 455 list[1::2] -> [2, 4] 456 list[5::-2] -> [5, 3, 1] 457 list[5::5] -> [] 458 tuple[0::1] -> (1, 2, 3, 4, 5) 459 tuple[0::-1] -> (1,) 460 tuple[1::1] -> (2, 3, 4, 5) 461 tuple[1::-1] -> (2, 1) 462 tuple[None::1] -> (1, 2, 3, 4, 5) 463 tuple[None::-1] -> (5, 4, 3, 2, 1) 464 tuple[None::None] -> (1, 2, 3, 4, 5) 465 tuple[1::2] -> (2, 4) 466 tuple[5::-2] -> (5, 3, 1) 467 tuple[5::5] -> () 468 bytes[0::1] -> 12345 469 bytes[0::-1] -> 1 470 bytes[1::1] -> 2345 471 bytes[1::-1] -> 21 472 bytes[None::1] -> 12345 473 bytes[None::-1] -> 54321 474 bytes[None::None] -> 12345 475 bytes[1::2] -> 24 476 bytes[5::-2] -> 531 477 bytes[5::5] -> 478 unicode[0::1] -> 12345 479 unicode[0::-1] -> 1 480 unicode[1::1] -> 2345 481 unicode[1::-1] -> 21 482 unicode[None::1] -> 12345 483 unicode[None::-1] -> 54321 484 unicode[None::None] -> 12345 485 unicode[1::2] -> 24 486 unicode[5::-2] -> 531 487 unicode[5::5] -> 488 >>> for o in (l, t, b): 489 ... try: slice_fused_type_start_and_step(o, 0, 0) 490 ... except ValueError: pass 491 """ 492 obj = seq[start::step] 493 return obj 494 495 496def slice_fused_type_stop_and_step(slicable seq, stop, step): 497 """ 498 >>> l = [1,2,3,4,5] 499 >>> t = tuple(l) 500 >>> b = ''.join(map(str, l)).encode('ASCII') 501 >>> u = b.decode('ASCII') 502 >>> o = (l, t, b, u) 503 >>> n = ('list', 'tuple', 'bytes', 'unicode') 504 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 505 >>> r = lambda i, s, t: '%s[:%r:%r] -> %s' % (n[i], s, t, p(slice_fused_type_stop_and_step(o[i], s, t))) 506 >>> for i in range(len(o)): 507 ... for stop, step in ((len(l), 1), (len(l), None), (None, 1), 508 ... (len(l), -1), (len(l) - 1, 2), (len(l), -2), 509 ... (len(l), len(l))): 510 ... print(r(i, stop, step)) 511 ... 512 list[:5:1] -> [1, 2, 3, 4, 5] 513 list[:5:None] -> [1, 2, 3, 4, 5] 514 list[:None:1] -> [1, 2, 3, 4, 5] 515 list[:5:-1] -> [] 516 list[:4:2] -> [1, 3] 517 list[:5:-2] -> [] 518 list[:5:5] -> [1] 519 tuple[:5:1] -> (1, 2, 3, 4, 5) 520 tuple[:5:None] -> (1, 2, 3, 4, 5) 521 tuple[:None:1] -> (1, 2, 3, 4, 5) 522 tuple[:5:-1] -> () 523 tuple[:4:2] -> (1, 3) 524 tuple[:5:-2] -> () 525 tuple[:5:5] -> (1,) 526 bytes[:5:1] -> 12345 527 bytes[:5:None] -> 12345 528 bytes[:None:1] -> 12345 529 bytes[:5:-1] -> 530 bytes[:4:2] -> 13 531 bytes[:5:-2] -> 532 bytes[:5:5] -> 1 533 unicode[:5:1] -> 12345 534 unicode[:5:None] -> 12345 535 unicode[:None:1] -> 12345 536 unicode[:5:-1] -> 537 unicode[:4:2] -> 13 538 unicode[:5:-2] -> 539 unicode[:5:5] -> 1 540 >>> for v in o: 541 ... try: slice_fused_type_stop_and_step(v, len(l), 0) 542 ... except ValueError: pass 543 ... try: slice_fused_type_stop_and_step(v, len(l), v) 544 ... except TypeError: pass 545 """ 546 obj = seq[:stop:step] 547 return obj 548 549 550def slice_fused_type_all(slicable seq, start, stop, step): 551 """ 552 >>> l = [1,2,3,4,5] 553 >>> t = tuple(l) 554 >>> b = ''.join(map(str, l)).encode('ASCII') 555 >>> u = b.decode('ASCII') 556 >>> o = (l, t, b, u) 557 >>> n = ('list', 'tuple', 'bytes', 'unicode') 558 >>> p = lambda o: o.decode() if isinstance(o, type(b)) else str(o) 559 >>> r = lambda i, s, t, e: '%s[%r:%r:%r] -> %s' % (n[i], s, t, e, p(slice_fused_type_all(o[i], s, t, e))) 560 >>> for i in range(len(o)): 561 ... for args in ((0, len(l), 1), (len(l), 0, -1), (None, len(l), 1), 562 ... (len(l), None, -1), (-len(l), len(l), None), (None, None, None), 563 ... (1, 3, 2), (len(l), 1, -3), (len(l), 0, 1)): 564 ... print(r(i, *args)) 565 ... 566 list[0:5:1] -> [1, 2, 3, 4, 5] 567 list[5:0:-1] -> [5, 4, 3, 2] 568 list[None:5:1] -> [1, 2, 3, 4, 5] 569 list[5:None:-1] -> [5, 4, 3, 2, 1] 570 list[-5:5:None] -> [1, 2, 3, 4, 5] 571 list[None:None:None] -> [1, 2, 3, 4, 5] 572 list[1:3:2] -> [2] 573 list[5:1:-3] -> [5] 574 list[5:0:1] -> [] 575 tuple[0:5:1] -> (1, 2, 3, 4, 5) 576 tuple[5:0:-1] -> (5, 4, 3, 2) 577 tuple[None:5:1] -> (1, 2, 3, 4, 5) 578 tuple[5:None:-1] -> (5, 4, 3, 2, 1) 579 tuple[-5:5:None] -> (1, 2, 3, 4, 5) 580 tuple[None:None:None] -> (1, 2, 3, 4, 5) 581 tuple[1:3:2] -> (2,) 582 tuple[5:1:-3] -> (5,) 583 tuple[5:0:1] -> () 584 bytes[0:5:1] -> 12345 585 bytes[5:0:-1] -> 5432 586 bytes[None:5:1] -> 12345 587 bytes[5:None:-1] -> 54321 588 bytes[-5:5:None] -> 12345 589 bytes[None:None:None] -> 12345 590 bytes[1:3:2] -> 2 591 bytes[5:1:-3] -> 5 592 bytes[5:0:1] -> 593 unicode[0:5:1] -> 12345 594 unicode[5:0:-1] -> 5432 595 unicode[None:5:1] -> 12345 596 unicode[5:None:-1] -> 54321 597 unicode[-5:5:None] -> 12345 598 unicode[None:None:None] -> 12345 599 unicode[1:3:2] -> 2 600 unicode[5:1:-3] -> 5 601 unicode[5:0:1] -> 602 >>> for v in o: 603 ... try: slice_fused_type_stop_and_step(v, len(l), 0) 604 ... except ValueError: pass 605 ... try: slice_fused_type_stop_and_step(v, len(l), v) 606 ... except TypeError: pass 607 """ 608 obj = seq[start:stop:step] 609 return obj 610