from copy import deepcopy from nullptr.util import sg class Reference: def __init__(self, typ, symbol, store): self.typ = typ self.symbol = symbol self.store = store @classmethod def create(cls, obj): o = cls(type(obj), obj.symbol, obj.store) return o def resolve(self): return self.store.get(self.typ, self.symbol) def __repr__(self): return f'*REF*{self.symbol}.{self.typ.ext()}' class Base: identifier = 'symbol' def __init__(self, symbol, store): self._disable_dirty = True self._file_offset = None self.store = store self.symbol = symbol self.define() self._disable_dirty = False def __setstate__(self, d): self.__init__(d['symbol'], d['store']) self.__dict__.update(d) def __getstate__(self): return {k:v for k,v in self.__dict__.items() if not k.startswith('_')} def dirty(self): self.store.dirty(self) @classmethod def ext(cls): raise NotImplementedError('no ext') def define(self): pass def __hash__(self): return hash((str(type(self)), self.symbol)) def __eq__(self, other): return type(self) == type(other) and self.symbol == other.symbol def get_system(self): parts = self.symbol.split('-') system_str = f'{parts[0]}-{parts[1]}' system = self.store.get('System', system_str, create=True) return system def seta(self, attr, d, name=None, interp=None): if name is None: name = attr val = sg(d, name) if val is not None: if interp is not None: val = interp(val) setattr(self, attr, val) def __lt__(self, o): return self.symbol < o.symbol def setlst(self, attr, d, name, member=None, interp=None): val = sg(d, name) if val is not None: lst = [] for x in val: if member is not None: x = sg(x, member) if interp is not None: x = interp(x) lst.append(x) setattr(self, attr, lst) def __setattr__(self, name, value): if not name.startswith('_') and not self._disable_dirty: self.store.dirty(self) if issubclass(type(value), Base): value = Reference.create(value) super().__setattr__(name, value) def __getattribute__(self, nm): val = super().__getattribute__(nm) if type(val) == Reference: val = val.resolve() return val def update(self, d): pass def is_expired(self): return False def type(self): return self.__class__.__name__ def __str__(self): return self.f() def __repr__(self): return self.f() def f(self, detail=1): r = self.symbol if detail > 1: r += '.' + self.ext() return r