def filewrapper(file, mode): if type(file) is str: return open(file, mode) elif hasattr(file, "read"): return file else: raise ValueError("need string or file descriptor object") class FileParsingError(SyntaxError): pass class Record: def __init__(self): self.name = None self.data = {} self.children = {} self.parents = {} def __getitem__(self, item): return self.data[item] def __setitem__(self, item, value): self.data[item] = value def __repr__(self): return f"[{self.data}, {len(self.children)}, {len(self.parents)}]" class RecordCollection(): def __init__(self, file): fd = filewrapper(file, "r") self._fromFile(fd) self._parent() def _fromFile(self, fd): lines = [i.rstrip() for i in fd.readlines()] self.objects = {} current = Record() for i in lines: ind = i[0:2] == ' ' if ind: spl = i[2:].split(': ') try: current[spl[0]] = spl[1] except IndexError: raise FileParsingError(f"error parsing '{i}'") else: try: name = i.split(' ')[1][0:-1] except IndexError: current = Record() continue current.name = name self.objects[name] = current def _parent(self): for i in self.objects: current = self.objects[i] try: for j, k in zip( current['inherit'].split(' '), [int(i) for i in current['inherit_order'].split(' ')] ): current.parents[j] = self.objects[j] self.objects[j].children[k] = current except KeyError: pass def findEntrypoints(self): ret = [] for i in self.objects: if not self.objects[i].parents: ret.append(self.objects[i]) return ret def write(self, file): fd = filewrapper(file, "w") lines = [] for i in self.objects: if self.objects[i].children: lines.append(f"cat {self.objects[i].name}:") else: lines.append(f"rec {self.objects[i].name}:") for j in self.objects[i].data: lines.append( f" {j}: {self.objects[i].data[j]}" ) lines.append("") lines.pop() for i in range(len(lines)): lines[i] += "\n" fd.writelines(lines) fd.close()