mirror of
https://github.com/clearml/clearml
synced 2025-02-01 01:26:49 +00:00
113 lines
4.1 KiB
Python
113 lines
4.1 KiB
Python
import six
|
|
|
|
|
|
class ProxyDictPostWrite(dict):
|
|
""" Dictionary wrapper that updates an arguments instance on any item set in the dictionary """
|
|
|
|
def __init__(self, update_obj, update_func, *args, **kwargs):
|
|
super(ProxyDictPostWrite, self).__init__(*args, **kwargs)
|
|
self._update_obj = update_obj
|
|
self._update_func = None
|
|
for k, i in self.items():
|
|
if isinstance(i, dict):
|
|
super(ProxyDictPostWrite, self).update({k: ProxyDictPostWrite(update_obj, self._set_callback, i)})
|
|
self._update_func = update_func
|
|
|
|
def __setitem__(self, key, value):
|
|
super(ProxyDictPostWrite, self).__setitem__(key, value)
|
|
self._set_callback()
|
|
|
|
def __reduce__(self):
|
|
return dict, (), None, None, iter(self._to_dict().items())
|
|
|
|
def _set_callback(self, *_):
|
|
if self._update_func:
|
|
self._update_func(self._update_obj, self)
|
|
|
|
def _to_dict(self):
|
|
a_dict = {}
|
|
for k, i in self.items():
|
|
if isinstance(i, ProxyDictPostWrite):
|
|
a_dict[k] = i._to_dict()
|
|
else:
|
|
a_dict[k] = i
|
|
return a_dict
|
|
|
|
def update(self, E=None, **F):
|
|
return super(ProxyDictPostWrite, self).update(
|
|
ProxyDictPostWrite(self._update_obj, self._set_callback, E) if E is not None else
|
|
ProxyDictPostWrite(self._update_obj, self._set_callback, **F))
|
|
|
|
|
|
class ProxyDictPreWrite(dict):
|
|
""" Dictionary wrapper that prevents modifications to the dictionary """
|
|
|
|
def __init__(self, update_obj, update_func, *args, **kwargs):
|
|
super(ProxyDictPreWrite, self).__init__(*args, **kwargs)
|
|
self._update_func = None
|
|
for k, i in self.items():
|
|
if isinstance(i, dict):
|
|
self.update({k: ProxyDictPreWrite(k, self._nested_callback, i)})
|
|
self._update_obj = update_obj
|
|
self._update_func = update_func
|
|
|
|
def __reduce__(self):
|
|
return dict, (), None, None, iter(self.items())
|
|
|
|
def __setitem__(self, key, value):
|
|
key_value = self._set_callback((key, value,))
|
|
if key_value:
|
|
super(ProxyDictPreWrite, self).__setitem__(*key_value)
|
|
|
|
def _set_callback(self, key_value, *_):
|
|
if self._update_func is not None:
|
|
if callable(self._update_func):
|
|
res = self._update_func(self._update_obj, key_value)
|
|
else:
|
|
res = self._update_func
|
|
|
|
if not res:
|
|
return None
|
|
return res
|
|
return key_value
|
|
|
|
def _nested_callback(self, prefix, key_value):
|
|
return self._set_callback((prefix+'.'+key_value[0], key_value[1],))
|
|
|
|
|
|
def flatten_dictionary(a_dict, prefix=''):
|
|
flat_dict = {}
|
|
sep = '/'
|
|
basic_types = (float, int, bool, six.string_types, )
|
|
for k, v in a_dict.items():
|
|
k = str(k)
|
|
if isinstance(v, (float, int, bool, six.string_types)):
|
|
flat_dict[prefix+k] = v
|
|
elif isinstance(v, (list, tuple)) and all([isinstance(i, basic_types) for i in v]):
|
|
flat_dict[prefix+k] = v
|
|
elif isinstance(v, dict):
|
|
flat_dict.update(flatten_dictionary(v, prefix=prefix+k+sep))
|
|
else:
|
|
# this is a mixture of list and dict, or any other object,
|
|
# leave it as is, we have nothing to do with it.
|
|
flat_dict[prefix+k] = v
|
|
return flat_dict
|
|
|
|
|
|
def nested_from_flat_dictionary(a_dict, flat_dict, prefix=''):
|
|
basic_types = (float, int, bool, six.string_types, )
|
|
sep = '/'
|
|
for k, v in a_dict.items():
|
|
k = str(k)
|
|
if isinstance(v, (float, int, bool, six.string_types)):
|
|
a_dict[k] = flat_dict.get(prefix+k, v)
|
|
elif isinstance(v, (list, tuple)) and all([isinstance(i, basic_types) for i in v]):
|
|
a_dict[k] = flat_dict.get(prefix+k, v)
|
|
elif isinstance(v, dict):
|
|
a_dict[k] = nested_from_flat_dictionary(v, flat_dict, prefix=prefix+k+sep) or v
|
|
else:
|
|
# this is a mixture of list and dict, or any other object,
|
|
# leave it as is, we have nothing to do with it.
|
|
a_dict[k] = flat_dict.get(prefix+k, v)
|
|
return a_dict
|