from typing import Callable, Literal, Optional, TypeVar, Union
from rocrate.model.dataset import Dataset as ROCrateDataset
from rocrate.model.file import File as ROCrateFile
from rocrate.rocrate import ROCrate
from ..utils import logging
from ..utils.utils import get_study_root_path
print = logging.invalidPrint
logger = logging.getLogger()
[docs]
class ObservableDict:
def __init__(self, data: dict, callback=callable):
"""Proxy RO-Crate metadata dictionary to trigger a callback (e.g. write json) on changes."""
self._data = data
self._callback = callback
def __getattr__(self, key):
return getattr(self._data, key)
def __getitem__(self, key):
return self._data[key]
def __setitem__(self, key, value):
self._data[key] = value
self._callback()
def __delitem__(self, key):
del self._data[key]
self._callback()
[docs]
def clear(self):
self._data.clear()
self._callback()
[docs]
def update(self, data):
deleted_keys = set(self._data.keys()) - set(data.keys())
for key in deleted_keys:
del self._data[key]
self._data.update(data)
self._callback()
[docs]
def replace(self, data):
"""Replace the dictionary with a new one."""
self._data.clear()
self._data.update(data)
self._callback()
[docs]
def pop(self, key):
value = self._data.pop(key)
self._callback()
return value
[docs]
def items(self):
return self._data.items()
def __repr__(self):
return repr(self._data)
def __eq__(self, other):
return self._data == other
[docs]
class ROCrateProxy:
def __init__(self):
"""RO-Crate crate object proxy."""
self._crate: Optional[ROCrate] = None
@property
def crate(self) -> ROCrate:
if self._crate is not None:
return self._crate
try:
self._crate = ROCrate(get_study_root_path())
except ValueError: # Not a valid RO-Crate: missing ro-crate-metadata.json
self._crate = ROCrate()
return self._crate
[docs]
def write_json(self):
study_root_path = get_study_root_path()
logger.info(f"Writing RO-Crate metadata {study_root_path}")
self.crate.write(study_root_path)
def __getattr__(self, key: str):
attr = getattr(self.crate, key)
if key not in ["add_dataset", "add_file", "add_tree"]:
return attr
def exec_and_write_json(*args, **kwargs):
result = attr(*args, **kwargs)
self.write_json()
return result
return exec_and_write_json
rocrate = ROCrateProxy()
T = TypeVar("T")