22import logging
33from enum import Enum
44from functools import cached_property
5- from typing import Any , ClassVar , Generator , Literal , Optional , Union
5+ from typing import Any , cast , ClassVar , Dict , Generator , List , Literal , Optional , Union
66
77from pydantic import BaseModel , Field
88
1818
1919
2020class _Attributes (BaseModel ):
21- name : str
21+ name : Optional [ str ] = None
2222 description : Optional [str ] = None
23+ organization : Optional [str ] = None
24+ department : Optional [str ] = None
25+ project : Optional [str ] = None
26+ modality : Optional [str ] = None
2327
2428
2529class _Relationships (BaseModel ):
@@ -58,12 +62,13 @@ def _get_entity_type(cls) -> EntityType:
5862 def create (
5963 cls ,
6064 * ,
61- name : str ,
65+ name : Optional [ str ] = None ,
6266 description : Optional [str ] = None ,
6367 template : Optional ['Experiment' ] = None ,
6468 notebook : Optional [Notebook ] = None ,
65- digest : str = None ,
69+ digest : Optional [ str ] = None ,
6670 force : bool = True ,
71+ attributes : Optional [Dict [str , Any ]] = None ,
6772 ) -> 'Experiment' :
6873 """Create new Experiment in Signals Notebook
6974
@@ -74,6 +79,7 @@ def create(
7479 notebook: notebook where create experiment
7580 digest: Indicate digest
7681 force: Force to create without doing digest check
82+ attributes:
7783
7884 Returns:
7985 Experiment
@@ -89,20 +95,13 @@ def create(
8995 request = _RequestPayload (
9096 data = _RequestBody (
9197 type = cls ._get_entity_type (),
92- attributes = _Attributes (
93- name = name ,
94- description = description ,
95- ),
98+ attributes = _Attributes (name = name , description = description , ** (attributes or {})),
9699 relationships = relationships ,
97100 )
98101 )
99102
100103 log .debug ('Creating Notebook for: %s' , cls .__name__ )
101- return super ()._create (
102- digest = digest ,
103- force = force ,
104- request = request ,
105- )
104+ return cast ('Experiment' , super ()._create (digest = digest , force = force , request = request ))
106105
107106 @cached_property
108107 def stoichiometry (self ) -> Union [Stoichiometry , list [Stoichiometry ]]:
@@ -160,12 +159,62 @@ def _load(cls, path: str, fs_handler: FSHandler, parent: Any) -> None:
160159 from signals_notebook .item_mapper import ItemMapper
161160
162161 metadata = json .loads (fs_handler .read (fs_handler .join_path (path , 'metadata.json' )))
163- experiment = cls .create (
164- notebook = parent , name = metadata ['name' ], description = metadata ['description' ], force = True
165- )
162+ try :
163+ experiment = cls .create (
164+ notebook = parent ,
165+ name = metadata ['name' ],
166+ description = metadata ['description' ],
167+ force = True ,
168+ attributes = dict (
169+ organization = metadata ['Organization' ],
170+ project = metadata ['Project' ],
171+ modality = metadata ['Modality' ],
172+ department = metadata ['Department' ],
173+ ),
174+ )
175+ except Exception as e :
176+ log .error (str (e ))
177+ if 'According to template, name is auto generated, can not be specified' in str (e ):
178+ log .error ('Retrying create' )
179+ experiment = cls .create (
180+ notebook = parent ,
181+ description = metadata ['description' ],
182+ force = True ,
183+ attributes = dict (
184+ organization = metadata ['Organization' ],
185+ project = metadata ['Project' ],
186+ modality = metadata ['Modality' ],
187+ department = metadata ['Department' ],
188+ ),
189+ )
190+ else :
191+ raise e
166192 child_entities_folders = fs_handler .list_subfolders (path )
167193 for child_entity in child_entities_folders :
168194 child_entity_type = child_entity .split (':' )[0 ]
169- ItemMapper .get_item_class (child_entity_type )._load (
170- fs_handler .join_path (path , child_entity ), fs_handler , experiment
171- )
195+ try :
196+ ItemMapper .get_item_class (child_entity_type )._load (
197+ fs_handler .join_path (path , child_entity ), fs_handler , experiment
198+ )
199+ except NotImplementedError :
200+ log .error ('Failed to load entity %s. Not supported' % child_entity_type )
201+
202+ def dump (self , base_path : str , fs_handler : FSHandler , alias : Optional [List [str ]] = None ) -> None :
203+ metadata = {k : v for k , v in self .dict ().items () if k in ('name' , 'description' , 'eid' )}
204+ self ._reload_properties ()
205+ for prop in self ._properties :
206+ if prop .name in ('Department' , 'Project' , 'Modality' , 'Organization' ):
207+ metadata [prop .name ] = prop .value
208+
209+ fs_handler .write (
210+ fs_handler .join_path (base_path , self .eid , 'metadata.json' ),
211+ json .dumps (metadata ),
212+ alias + [self .name , '__Metadata' ] if alias else None ,
213+ )
214+ for child in self .get_children ():
215+ try :
216+ child .dump (
217+ fs_handler .join_path (base_path , self .eid ), fs_handler , alias + [self .name ] if alias else None
218+ )
219+ except Exception as e :
220+ log .error (str (e ))
0 commit comments