1212
1313from __future__ import annotations
1414
15- from typing import Any
15+ from dataclasses import dataclass , field
1616
1717from typing_extensions import Self
1818
@@ -28,23 +28,29 @@ class ArrayModel(ArrayV3Metadata):
2828 """
2929
3030 @classmethod
31- def from_stored (cls : type [Self ], node : Array ):
31+ def from_stored (cls : type [Self ], node : Array ) -> Self :
32+ """
33+ Create an array model from a stored array.
34+ """
3235 return cls .from_dict (node .metadata .to_dict ())
3336
34- def to_stored (self , store_path : StorePath ) -> Array :
37+ def to_stored (self , store_path : StorePath , exists_ok : bool = False ) -> Array :
38+ """
39+ Create a stored version of this array.
40+ """
41+ # exists_ok kwarg is unhandled until we wire it up to the
42+ # array creation routines
43+
3544 return Array .from_dict (store_path = store_path , data = self .to_dict ())
3645
3746
47+ @dataclass (frozen = True )
3848class GroupModel (GroupMetadata ):
3949 """
4050 A model of a Zarr v3 group.
4151 """
4252
43- members : dict [str , GroupModel | ArrayModel ] | None
44-
45- @classmethod
46- def from_dict (cls : type [Self ], data : dict [str , Any ]):
47- return cls (** data )
53+ members : dict [str , GroupModel | ArrayModel ] | None = field (default_factory = dict )
4854
4955 @classmethod
5056 def from_stored (cls : type [Self ], node : Group , * , depth : int | None = None ) -> Self :
@@ -53,7 +59,7 @@ def from_stored(cls: type[Self], node: Group, *, depth: int | None = None) -> Se
5359 controlled by the `depth` argument, which is either None (no depth limit) or a finite natural number
5460 specifying how deep into the hierarchy to parse.
5561 """
56- members : dict [str , GroupModel | ArrayModel ]
62+ members : dict [str , GroupModel | ArrayModel ] = {}
5763
5864 if depth is None :
5965 new_depth = depth
@@ -64,16 +70,18 @@ def from_stored(cls: type[Self], node: Group, *, depth: int | None = None) -> Se
6470 return cls (** node .metadata .to_dict (), members = None )
6571
6672 else :
67- for name , member in node .members ():
73+ for name , member in node .members :
74+ item_out : ArrayModel | GroupModel
6875 if isinstance (member , Array ):
6976 item_out = ArrayModel .from_stored (member )
7077 else :
7178 item_out = GroupModel .from_stored (member , depth = new_depth )
7279
7380 members [name ] = item_out
7481
75- return cls (** node .metadata .to_dict () , members = members )
82+ return cls (attributes = node .metadata .attributes , members = members )
7683
84+ # todo: make this async
7785 def to_stored (self , store_path : StorePath , * , exists_ok : bool = False ) -> Group :
7886 """
7987 Serialize this GroupModel to storage.
@@ -90,15 +98,18 @@ def to_stored(self, store_path: StorePath, *, exists_ok: bool = False) -> Group:
9098def to_flat (
9199 node : ArrayModel | GroupModel , root_path : str = ""
92100) -> dict [str , ArrayModel | GroupModel ]:
101+ """
102+ Generate a dict representation of an ArrayModel or GroupModel, where the hierarchy structure
103+ is represented by the keys of the dict.
104+ """
93105 result = {}
94106 model_copy : ArrayModel | GroupModel
95107 node_dict = node .to_dict ()
96108 if isinstance (node , ArrayModel ):
97109 model_copy = ArrayModel (** node_dict )
98110 else :
99- members = node_dict .pop ("members" )
100- model_copy = GroupModel (node_dict )
101- if members is not None :
111+ model_copy = GroupModel (** node_dict )
112+ if node .members is not None :
102113 for name , value in node .members .items ():
103114 result .update (to_flat (value , "/" .join ([root_path , name ])))
104115
@@ -109,6 +120,9 @@ def to_flat(
109120
110121
111122def from_flat (data : dict [str , ArrayModel | GroupModel ]) -> ArrayModel | GroupModel :
123+ """
124+ Create a GroupModel or ArrayModel from a dict representation.
125+ """
112126 # minimal check that the keys are valid
113127 invalid_keys = []
114128 for key in data .keys ():
@@ -125,6 +139,10 @@ def from_flat(data: dict[str, ArrayModel | GroupModel]) -> ArrayModel | GroupMod
125139
126140
127141def from_flat_group (data : dict [str , ArrayModel | GroupModel ]) -> GroupModel :
142+ """
143+ Create a GroupModel from a hierarchy represented as a dict with string keys and ArrayModel
144+ or GroupModel values.
145+ """
128146 root_name = ""
129147 sep = "/"
130148 # arrays that will be members of the returned GroupModel
0 commit comments