Source code for utool.DynamicStruct
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division, print_function, unicode_literals
import copy
import six
from utool import Printable
[docs]class DynStruct(Printable.AbstractPrintable):
"""dynamically add and remove members"""
def __init__(self, child_exclude_list=[], copy_dict=None, copy_class=None):
super(DynStruct, self).__init__(child_print_exclude=child_exclude_list)
if isinstance(copy_dict, dict):
self.add_dict(copy_dict)
# def dynget(self, *prop_list):
# return tuple([self.__dict__[prop_name] for prop_name in prop_list])
# def dynset(self, *propval_list):
# offset = len(propval_list) / 2
# for i in range(offset):
# self.__dict__[propval_list[i]] = propval_list[i + offset]
def __setitem__(self, key, value):
if isinstance(key, tuple):
for k, v in zip(key, value):
setattr(self, k, v)
else:
setattr(self, key, value)
def __getitem__(self, key):
if isinstance(key, tuple):
val = []
for k in key:
val.append(getattr(self, k))
else:
try:
val = getattr(self, key)
except TypeError as ex:
print('[dyn] TYPE_ERROR: %r' % ex)
print('[dyn] key=%r' % key)
raise
return val
[docs] def update(self, **kwargs):
self_keys = set(self.__dict__.keys())
for key, val in six.iteritems(kwargs):
if key in self_keys:
if isinstance(val, list):
val = val[0]
self.__dict__[key] = val
[docs] def add_dict(self, dyn_dict):
'Adds a dictionary to the prefs'
if not isinstance(dyn_dict, dict):
raise Exception(
'DynStruct.add_dict expects a dictionary.'
+ 'Recieved: '
+ six.text_type(type(dyn_dict))
)
for (key, val) in six.iteritems(dyn_dict):
self[key] = val
[docs] def to_dict(self):
"""Converts dynstruct to a dictionary."""
dyn_dict = {}
for (key, val) in six.iteritems(self.__dict__):
if key not in self._printable_exclude:
dyn_dict[key] = val
return dyn_dict
[docs] def flat_dict(self, dyn_dict={}, only_public=True):
for (key, val) in six.iteritems(self.__dict__):
if key in self._printable_exclude:
continue
elif only_public and key.find('_') == 0:
continue
elif isinstance(val, DynStruct):
val.flat_dict(dyn_dict, only_public)
else:
dyn_dict[key] = val
return dyn_dict
[docs] def deepcopy(self, **kwargs):
copy_ = copy.deepcopy(self)
copy_.update(**kwargs)
return copy_
[docs] def copy(self):
return self.to_dict()
[docs] def execstr(self, local_name):
"""returns a string which when evaluated will
add the stored variables to the current namespace
localname is the name of the variable in the current scope
* use locals().update(dyn.to_dict()) instead
"""
execstr = ''
for (key, val) in six.iteritems(self.__dict__):
if key not in self._printable_exclude:
execstr += key + ' = ' + local_name + '.' + key + '\n'
return execstr