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 @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 setlst(self, attr, d, name, member, interp=None): val = sg(d, name) if val is not None: lst = [] for x in val: val = sg(x, member) if interp is not None: val = interp(val) lst.append(val) setattr(self, attr, lst) def __setattr__(self, name, value): if name not in ['symbol','store','disable_dirty', 'file_offset'] 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 load(self, d): self.disable_dirty = True self.__dict__.update(d) self.disable_dirty = 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