Source code for syned.syned_object

import copy
from collections import OrderedDict
import pickle

import json_tricks # to save numpy arrays

# TODO: although basic functionality is implemented, the use of exec should be replace by introspection tools
[docs]class SynedObject(object): # --------------------------------------------------------------------------------------------------------- # This override is necessary to avoid TypeError: cannot pickle '_thread.lock' object while duplicating # that occurs while enabling/disabling connectors # # When an attribute is an object that contains non pickable attributes, we make a shallow copy of it # --------------------------------------------------------------------------------------------------------- def __deepcopy__(self, memodict={}): cls = self.__class__ result = cls.__new__(cls) memodict[id(self)] = result for k, v in self.__dict__.items(): try: setattr(result, k, copy.deepcopy(v, memodict)) except TypeError: setattr(result, k, copy.copy(v)) return result """ This is the base object for SYNED. It includes the methods of the common interface to allow json file input/output and info mechanism These standard methods are: * keys() * to_dictionary() * to_full_dictionary() * to_json() * to_hex_tring() * from_hex_tring() * info() * set_value_from_key_name() * get_value_from_key_name() """ def _set_support_text(self, text): ordered_support_dict = OrderedDict() for e in text: ordered_support_dict[e[0]] = (e[1], e[2]) self._support_dictionary = ordered_support_dict def _add_support_text(self, text): try: for e in text: self._support_dictionary[e[0]] = (e[1], e[2]) except: self._set_support_text(text) # # this is the common interface to allow json file input/output and info mechanism # # standard methods are: # keys # to_dictionary # to_full_dictionary # to_json # info # set_value_from_key_name # get_value_from_key_name #
[docs] def keys(self): """ Returns the keys of the supporting doctionary. Returns ------- list A list of keys. """ try: return self._support_dictionary.keys() except: return None
[docs] def to_dictionary(self): """ Returns a dictionary with the object fields. Some dictionary keys may contain SYNED instances. Use to_full_dictionary to recurrently expand these objects in their basic ingredients. Returns ------- dict A dictionary with the data. """ dict_to_save = OrderedDict() dict_to_save.update({"CLASS_NAME":self.__class__.__name__}) try: if self.keys() is not None: for key in self.keys(): tmp1 = eval("self._%s" % (key) ) if isinstance(tmp1,SynedObject): dict_to_save[key] = tmp1.to_dictionary() else: dict_to_save[key] = tmp1 except: pass return dict_to_save
[docs] def to_full_dictionary(self): """ Returns a dictionary with the object fields, including other syned objects embedded or list of elements. The "full" means that the SYNED instances found are recurrently expanded in their basic ingredients. Returns ------- dict """ dict_to_save = OrderedDict() dict_to_save.update({"CLASS_NAME":self.__class__.__name__}) try: if self.keys() is not None: for key in self.keys(): tmp1 = eval("self._%s" % (key) ) if isinstance(tmp1, SynedObject): dict_to_save[key] = tmp1.to_full_dictionary() else: mylist = [] mylist.append(tmp1) mylist.append(self._support_dictionary[key]) dict_to_save[key] = mylist # [tmp1,self._support_dictionary[key]] except: print("** Warning: failed to load/write one or multiple items in ", self.keys()) return dict_to_save
[docs] def to_json(self, file_name=None): """ Writes a json file with the SYNED object data. Parameters ---------- file_name : str The file name Returns ------- str JSON formatted str. The result of json.dumps() """ dict1 = OrderedDict() dict1.update(self.to_dictionary()) jsn1 = json_tricks.dumps(dict1, indent=4, separators=(',', ': ')) if file_name != None: f = open(file_name,'w') f.write(jsn1) f.close() print("File written to disk: %s"%(file_name)) return jsn1
[docs] def to_hex_tring(self): return pickle.dumps(self).hex()
[docs] @classmethod def from_hex_tring(cls, hex_string): return pickle.loads(bytes.fromhex(hex_string))
[docs] def info_recurrent(self, fd, prefix=" "): """ Get text info of recurrent SYNED objects. Parameters ---------- fd : dict The dictionary with SYNED data. prefix : str, optional Prefix to indent recursive items. Returns ------- str """ text = "" prefix1 = prefix for key in fd.keys(): if isinstance(fd[key],OrderedDict): text += prefix1 + self.info_recurrent(fd[key], prefix=prefix1) elif isinstance(fd[key],str): text += prefix1 + "-------%s---------\n"%fd[key] elif isinstance(fd[key],list): if isinstance(fd[key][0],OrderedDict): for element in fd[key]: text += self.info_recurrent(element, prefix=prefix1) elif isinstance(fd[key][0],list): for i,element in enumerate(fd[key][0]): try: # text += "****\n" text += prefix1 + element.info() except: text += ("%s%s[%d]: %s\n" %(prefix1, key, i, repr(element))) # used for conic coefficients else: text += prefix1 + prefix1 + '%s: %s %s # %s\n' %(key, repr(fd[key][0]), fd[key][1][1], fd[key][1][0]) else: pass return text
[docs] def info(self): """ Get text info of recurrent SYNED objects. Returns ------- str """ return self.info_recurrent( self.to_full_dictionary() )
[docs] def set_value_from_key_name(self,key,value): """ Sets a value using its key value. Parameters ---------- key : str The key for the value to modify. value The new value """ if key in self.keys(): try: exec("self._%s = value" % (key)) # print("Set variable %s to value: "%key + repr(value)) except: raise ValueError("Cannot set variable %s to value: "%key + repr(value) ) else: raise ValueError("Key %s not accepted by class %s"%(key,self.__class__.__name__))
[docs] def get_value_from_key_name(self, key): """ Gets a value using its key value. Parameters ---------- key : str The key for the value to retrieve. """ try: value = eval("self._%s" % (key)) return value except: raise ValueError("Cannot get variable %s: "%key)
[docs] def duplicate(self): """ Returns a copy of the SYNED object instance. Returns ------- SynedObject instance A copy of the object instance. """ return copy.deepcopy(self)