Source code for pdpy_lib.memory.data

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# **************************************************************************** #
# This file is part of the pdpy project: https://github.com/pdpy-org
# Copyright (C) 2021 Fede Camara Halac
# **************************************************************************** #
""" Data Class Definition """

from . import types
from ..core.base import Base
from ..utilities.utils import splitByEscapedChar, log, splitByNone

__all__ = [ 'Data' ]

[docs]class Data(Base): """ A Data base class """ def __init__(self, data=None, head=None, template=None, json=None, xml=None): self.__pdpy__ = self.__class__.__name__ super().__init__(pdtype='A', cls=head or '0') if json is not None: super().__populate__(self, json) elif xml is not None: self.parseXml(xml) else: if head is not None: # 'set' or 'saved' for symbols, otherwise '0' for arrays of floats self.__cls__ = str(head) self.header = self.__cls__ if self.__isnum__(self.header): self.data = list(map(lambda x: float(x), data)) elif 'saved' == self.header: self.data = list(map(lambda x: str(x), data)) elif 'set' == self.header: self.data = splitByEscapedChar(data, char=';') if self.data: # check if the data exists # check for name in first element (scalar define) if not self.__isnum__(self.data[0].split()[0]): self.data = self.data[0].split() setattr(self, 'name', self.data.pop(0)) else: log(1,"Unknown data type" + str(head) + " for:\n" + self.__json__()) else: if template is not None: self.template = template.name self.data = self.fill(template, splitByEscapedChar(data, char=';')) elif data is not None: self.header = 0 self.data = super().__setdata__(self, data) else: raise ValueError("Struct and Data must be present.")
[docs] def add(self, attr, value): """ Adds a value to the data list in attr """ if not hasattr(self, attr): setattr(self, attr, []) getattr(self, attr).append(value)
[docs] def parseXml(self, xml): """ Parses the xml string into a pd object """ if 'header' in xml.attrib: self.header = xml.attrib.get('header') self.__cls__ = str(self.header) data = xml.findall('datum') if len(data): if self.__isnum__(self.header): self.data = [self.__num__(d.text) for d in data] elif self.header in ('set', 'saved'): self.data = [str(d.text) for d in data] else: for x in xml.findall('float'): self.add('float', types.Float(xml=x)) for x in xml.findall('symbol'): self.add('symbol', types.Symbol(xml=x)) for x in xml.findall('list'): self.add('array', types.List(xml=x))
[docs] def fill(self, template, data): """ Fills the data with a template """ if len(data) == 0: return None # log(1,"DATAA", data) # log(1,"TEMPLATE", template.__json__()) def fill_element(target, template, data, attrib='float', cls=types.Float): # for k,v in zip(getattr(template, 'float', []), flt): # super().__setdata__(self, Float(v, name=k), 'float') if hasattr(template, attrib): # log(1,'Filling '+str(attrib).upper(),data) for k,v in zip(getattr(template, attrib, []), data): super(Data, self).__setdata__(target, cls(v, name=k), attrib) def fill_array(target, template, data): # log(1,'TEMPLATE',template.name) # log(1,'ARRAY',data) arrays = getattr(template, 'array', []) data = splitByNone(data) for e, d in zip(arrays, data): _, _template = template.__p__.getTemplate(e.template) if _template is None: log(1,"Did not find a template array candidate for: " + template) continue # log(1, 'Filling array', d) # log(1, 'Template:', _template.__json__()) pdlist = types.List(name=e.template) attributes = [ { 'attr':a, 'keys':getattr(_template, a) } for a in _template.order ] # log(1, 'Attributes:', attributes) # log(1, 'Length:', len(attributes)) # log(1, 'Lengths:', lengths) for v in d: # log(1, 'Filling:', v) if len(attributes) == 1: attr = attributes[0]['attr'] keys = attributes[0]['keys'] # log(1, 'Attr:', attr, 'Keys:', keys) for key, val in zip(keys, v): # log(1, f"add {attr} element", key, val) pdlist.addelement(attr, key, val) else: for idx, att in enumerate(attributes): attr = att['attr'] keys = att['keys'] # log(1, 'Keys:', keys, 'Attr:', attr) for key in keys: # log(1, f"add {attr} element", key, v) pdlist.addelement(attr, key, v[idx]) # TODO: Array recursion ?? # if hasattr(_template, 'array'): # log(1,'RECURSE ON ARRAY', v) # log(1,'RECURSE ON TEMPLATE', _template.name) # k = getattr(_template, 'array') # # log(1, 'array: keys, values:', k, v) # for key,val in zip(k,v): # # log(1, 'add array element', key, val) # target.addelement('array', key, str(val)) # fill_array(target.array, _template, v) # recursion ?????? super(Data, self).__setdata__(target, pdlist, 'array') fs = data[0].split(' ') if hasattr(template, 'float') and hasattr(template, 'symbol'): flt = fs[:len(template.float)] sym = fs[len(template.float):] elif hasattr(template, 'float'): flt = fs[:len(template.float):] sym = None elif hasattr(template, 'symbol'): flt = None sym = fs[:len(template.symbol):] else: log(1, "Template " + template.name + " has no float attribute") log(1, "Template", template.__json__()) log(1,'FS',fs) if flt is not None: # log(1,'FILL FLOAT',flt) fill_element(self, template, flt, attrib='float', cls=types.Float) if sym is not None: # log(1,'FILL SYMBOL',sym) fill_element(self, template, flt, attrib='symbol', cls=types.Symbol) arr = data[1:] if len(data) >= 2 else [] if hasattr(template, 'array') and arr is not []: # log(1,'FILL ARRAY',arr) # log(1, 'Template', template.__json__()) fill_array(self, template, arr) # fill the array
def __pd__(self, template=None): """ Parses the pd object into a string """ if hasattr(self, 'data'): if hasattr(self, 'header'): if self.__isnum__(self.header): s = ' '.join(list(map(lambda x:str(self.__num__(x)), self.data))) return super().__pd__(s) # return super().__pd__('0 '+s) if self.header == 'set' or self.header == 'saved': self.__cls__ = self.header s = '' for d in self.data: if type(d) in (int, float, str): s += str(d) else: s += ' ' + ' '.join(list(map(lambda x:str(x), d))) s += ' \\;' return super().__pd__(s) # FIXME: this is a hack to get the 'obj' class working as float arrays elif self.header == 'obj': self.__cls__ = '0' s = ' '.join(list(map(lambda x:str(x), self.data))) return super().__pd__(s) else: raise ValueError("Unknown type " + str(self.header) + " for:\n" + self.__dumps__()) else: s = '' # call the pd method on every float (PdFLoat) element if (hasattr(self, 'float') or hasattr(self, 'floats')) and hasattr(template, 'float'): for x in getattr(self, 'float', getattr(self, 'floats', [])): s += ' ' + x.__pd__() # call the pd method on every symbol (Symbol) element if (hasattr(self, 'symbol') or hasattr(self, 'symbols')) and hasattr(template, 'symbol'): for x in getattr(self, 'symbol', getattr(self, 'symbols', [])): s += ' ' + x.__pd__() if s != '': s += self.__semi__ # call the pd method on the array (List) element if (hasattr(self, 'array') or hasattr(self, 'arrays')) and hasattr(template, 'array'): for x, t in zip(getattr(self, 'array', getattr(self, 'arrays', [])), template.array): _, _template = template.__p__.getTemplate(t.template) s += ' ' + x.__pd__(_template) return s # return an empty string if nothing else happened return '' def __xml__(self, template=None): """ Returns the XML Element for this object """ x = super().__element__(scope=self) if hasattr(self, 'data'): if hasattr(self, 'header'): super().__update_attrib__(x, 'header', self.header) if self.__d__.xml['data_as_text']: x.text = ' '.join(list(map(lambda x:str(x),self.data))) else: for d in self.data: if isinstance(d, list): for dd in d: super().__subelement__(x, 'datum', text=str(dd)) else: super().__subelement__(x, 'datum', text=d) else: # call the xml method on every float (PdFLoat) element if hasattr(self, 'float') and hasattr(template, 'float'): # flt = super().__element__(tag='floats') for e in getattr(self, 'float', []): super().__subelement__(x, e.__xml__()) # super().__subelement__(flt, e.__xml__()) # super().__subelement__(x, flt) # call the xml method on every symbol (Symbol) element if hasattr(self, 'symbol') and hasattr(template, 'symbol'): # sym = super().__element__(tag='symbols') for e in getattr(self, 'symbol', []): super().__subelement__(x, e.__xml__()) # super().__subelement__(sym, e.__xml__()) # super().__subelement__(x, sym) # call the xml method on the array (List) element if hasattr(self, 'array') and hasattr(template, 'array'): # arr = super().__element__(tag='arrays') for e, t in zip(getattr(self, 'array', []), template.array): _, _template = template.__p__.getTemplate(t.template) super().__subelement__(x, e.__xml__(_template)) # super().__subelement__(arr, e.__xml__(_template)) # super().__subelement__(x, arr) return x