@@ -551,30 +551,44 @@ def __len__(self) -> int:
551
551
def __getitem__ (self , key : slice ) -> Self :
552
552
check_item_key_is_1d_contiguous (key )
553
553
start , stop = key .start , key .stop
554
+ this_len = len (self )
554
555
if start is None :
555
556
start = 0
557
+ if start < 0 :
558
+ start = this_len + start
556
559
if stop is None :
557
- stop = len (self )
560
+ stop = this_len
561
+ if stop < 0 :
562
+ stop = this_len + stop
563
+ if stop > this_len :
564
+ stop = this_len
565
+ if stop <= start :
566
+ return Buffer .from_buffer (b'' )
567
+
558
568
new_list = []
559
569
offset = 0
560
570
found_last = False
561
571
for chunk in self ._data_list :
562
572
chunk_size = len (chunk )
563
573
skip = False
564
- if offset <= start < offset + chunk_size :
574
+ if 0 <= start - offset < chunk_size :
565
575
# first chunk
566
- if stop <= offset + chunk_size :
576
+ if stop - offset <= chunk_size :
567
577
# also last chunk
568
578
chunk = chunk [start - offset :stop - offset ]
569
579
found_last = True
570
580
else :
571
581
chunk = chunk [start - offset :]
572
- elif offset <= stop <= offset + chunk_size :
582
+ elif 0 <= stop - offset <= chunk_size :
573
583
# last chunk
574
584
chunk = chunk [:stop - offset ]
575
585
found_last = True
576
- elif offset + chunk_size <= start :
586
+ elif chunk_size <= start - offset :
587
+ # before first chunk
577
588
skip = True
589
+ else :
590
+ # middle chunk
591
+ pass
578
592
579
593
if not skip :
580
594
new_list .append (chunk )
@@ -590,29 +604,39 @@ def __setitem__(self, key: slice, value: Any) -> None:
590
604
start , stop = key .start , key .stop
591
605
if start is None :
592
606
start = 0
607
+ if start < 0 :
608
+ start = len (self ) + start
593
609
if stop is None :
594
610
stop = len (self )
595
- new_list = []
611
+ if stop < 0 :
612
+ stop = len (self ) + stop
613
+ if stop <= start :
614
+ return
615
+
596
616
offset = 0
597
617
found_last = False
598
618
value = memoryview (np .asanyarray (value ))
599
619
for chunk in self ._data_list :
600
620
chunk_size = len (chunk )
601
621
skip = False
602
- if offset <= start < offset + chunk_size :
622
+ if 0 <= start - offset < chunk_size :
603
623
# first chunk
604
- if stop <= offset + chunk_size :
624
+ if stop - offset <= chunk_size :
605
625
# also last chunk
606
626
chunk = chunk [start - offset :stop - offset ]
607
627
found_last = True
608
628
else :
609
629
chunk = chunk [start - offset :]
610
- elif offset <= stop <= offset + chunk_size :
630
+ elif 0 <= stop - offset <= chunk_size :
611
631
# last chunk
612
632
chunk = chunk [:stop - offset ]
613
633
found_last = True
614
- elif offset + chunk_size <= start :
634
+ elif chunk_size <= start - offset :
635
+ # before first chunk
615
636
skip = True
637
+ else :
638
+ # middle chunk
639
+ pass
616
640
617
641
if not skip :
618
642
chunk [:] = value [:len (chunk )]
@@ -623,7 +647,6 @@ def __setitem__(self, key: slice, value: Any) -> None:
623
647
if found_last :
624
648
break
625
649
offset += chunk_size
626
- return self .__class__ (new_list )
627
650
628
651
629
652
# The default buffer prototype used throughout the Zarr codebase.
0 commit comments