11
11
from zarr .compressors import get_compressor_cls
12
12
from zarr .util import is_total_slice , normalize_array_selection , \
13
13
get_chunk_range , human_readable_size , normalize_resize_args
14
+ from zarr .storage import normalize_prefix , normalize_key , array_meta_key , \
15
+ array_attrs_key , ls
14
16
from zarr .meta import decode_metadata , encode_metadata
15
17
from zarr .attrs import Attributes
16
18
from zarr .compat import itervalues
@@ -73,12 +75,13 @@ def __init__(self, store, name=None, readonly=False):
73
75
# configuration metadata fully specified and normalised
74
76
75
77
self ._store = store
76
- self ._name = name
78
+ self ._prefix = normalize_prefix ( name )
77
79
self ._readonly = readonly
78
80
79
81
# initialise metadata
82
+ meta_key = array_meta_key (self ._prefix )
80
83
try :
81
- meta_bytes = store ['meta' ]
84
+ meta_bytes = store [meta_key ]
82
85
except KeyError :
83
86
raise ValueError ('store has no metadata' )
84
87
else :
@@ -95,14 +98,16 @@ def __init__(self, store, name=None, readonly=False):
95
98
self ._compressor = compressor_cls (self ._compression_opts )
96
99
97
100
# initialise attributes
98
- self ._attrs = Attributes (store , readonly = readonly )
101
+ attrs_key = array_attrs_key (self ._prefix )
102
+ self ._attrs = Attributes (store , key = attrs_key , readonly = readonly )
99
103
100
104
def flush_metadata (self ):
101
105
meta = dict (shape = self ._shape , chunks = self ._chunks , dtype = self ._dtype ,
102
106
compression = self ._compression ,
103
107
compression_opts = self ._compression_opts ,
104
108
fill_value = self ._fill_value , order = self ._order )
105
- self ._store ['meta' ] = encode_metadata (meta )
109
+ meta_key = array_meta_key (self ._prefix )
110
+ self ._store [meta_key ] = encode_metadata (meta )
106
111
107
112
@property
108
113
def store (self ):
@@ -112,7 +117,10 @@ def store(self):
112
117
@property
113
118
def name (self ):
114
119
"""TODO"""
115
- return self ._name
120
+ if self ._prefix :
121
+ # follow h5py convention: add leading slash, remove trailing slash
122
+ return '/' + self ._prefix [:- 1 ]
123
+ return None
116
124
117
125
@property
118
126
def readonly (self ):
@@ -186,20 +194,32 @@ def nbytes_stored(self):
186
194
"""The total number of stored bytes of data for the array. This
187
195
includes storage required for configuration metadata and user
188
196
attributes encoded as JSON."""
189
- if hasattr (self ._store , 'nbytes_stored ' ):
197
+ if hasattr (self ._store , 'getsize ' ):
190
198
# pass through
191
- return self ._store .nbytes_stored
199
+ return self ._store .getsize ( self . _prefix )
192
200
elif isinstance (self ._store , dict ):
193
201
# cheap to compute by summing length of values
194
- return sum (len (v ) for v in itervalues (self ._store ))
202
+ size = 0
203
+ for child in ls (self ._store , self ._prefix ):
204
+ key = self ._prefix + child
205
+ try :
206
+ size += len (self ._store [key ])
207
+ except KeyError :
208
+ pass
209
+ return size
195
210
else :
196
211
return - 1
197
212
198
213
@property
199
214
def initialized (self ):
200
215
"""The number of chunks that have been initialized with some data."""
216
+ n = 0
217
+ for child in ls (self ._store , self ._prefix ):
218
+ key = self ._prefix + child
219
+ if key in self ._store :
220
+ n += 1
201
221
# N.B., expect 'meta' and 'attrs' keys in store also, so subtract 2
202
- return len ( self . _store ) - 2
222
+ return n - 2
203
223
204
224
@property
205
225
def cdata_shape (self ):
@@ -489,7 +509,7 @@ def _chunk_getitem(self, cidx, item, dest):
489
509
try :
490
510
491
511
# obtain compressed data for chunk
492
- ckey = '.' .join (map (str , cidx ))
512
+ ckey = self . _prefix + '.' .join (map (str , cidx ))
493
513
cdata = self ._store [ckey ]
494
514
495
515
except KeyError :
@@ -564,7 +584,7 @@ def _chunk_setitem(self, cidx, key, value):
564
584
try :
565
585
566
586
# obtain compressed data for chunk
567
- ckey = '.' .join (map (str , cidx ))
587
+ ckey = self . _prefix + '.' .join (map (str , cidx ))
568
588
cdata = self ._store [ckey ]
569
589
570
590
except KeyError :
@@ -594,28 +614,28 @@ def _chunk_setitem(self, cidx, key, value):
594
614
595
615
def __repr__ (self ):
596
616
r = '%s.%s(' % (type (self ).__module__ , type (self ).__name__ )
597
- if self ._name :
598
- r += '%s, ' % self ._name
599
- r += '%s, ' % str (self ._shape )
600
- r += '%s, ' % str (self ._dtype )
601
- r += 'chunks=%s, ' % str (self ._chunks )
602
- r += 'order=%s' % self ._order
617
+ if self .name :
618
+ r += '%s, ' % self .name
619
+ r += '%s, ' % str (self .shape )
620
+ r += '%s, ' % str (self .dtype )
621
+ r += 'chunks=%s, ' % str (self .chunks )
622
+ r += 'order=%s' % self .order
603
623
r += ')'
604
- r += '\n compression: %s' % self ._compression
605
- r += '; compression_opts: %s' % str (self ._compression_opts )
624
+ r += '\n compression: %s' % self .compression
625
+ r += '; compression_opts: %s' % str (self .compression_opts )
606
626
r += '\n nbytes: %s' % human_readable_size (self .nbytes )
607
627
if self .nbytes_stored > 0 :
608
628
r += '; nbytes_stored: %s' % human_readable_size (
609
629
self .nbytes_stored )
610
630
r += '; ratio: %.1f' % (self .nbytes / self .nbytes_stored )
611
631
n_chunks = reduce (operator .mul , self .cdata_shape )
612
632
r += '; initialized: %s/%s' % (self .initialized , n_chunks )
613
- r += '\n store: %s.%s' % (type (self ._store ).__module__ ,
614
- type (self ._store ).__name__ )
633
+ r += '\n store: %s.%s' % (type (self .store ).__module__ ,
634
+ type (self .store ).__name__ )
615
635
return r
616
636
617
637
def __getstate__ (self ):
618
- return self ._store , self ._readonly
638
+ return self ._store , self ._prefix , self . _readonly
619
639
620
640
def __setstate__ (self , state ):
621
641
self .__init__ (* state )
0 commit comments