from typing import Optional, Mapping import os.path import configparser class ObjectDescriptor(object): def __init__(self): self._keys = [] def index_of(self, key, create: bool = False) -> int: try: return self._keys.index(key) except ValueError as e: if not create: raise e self._keys.append(key) return len(self._keys) - 1 @property def keys(self): return self._keys class Object(object): def __init__(self, key, descriptor): self._key = key self._descriptor = descriptor self._data = [] @property def key(self): return self._key def set(self, key: str, value: str): idx = self._descriptor.index_of(key, create=True) self._data.insert(idx, value) def merge(self, kv: Mapping[str, str]): for k, v in kv.items(): self.set(k, v) def get(self, key: str) -> Optional[str]: return self._data[self._descriptor.index_of(key)] class ObjectSet(object): def __init__(self, meta = dict()): self._objects = {} self._meta = meta self._descriptor = ObjectDescriptor() def items(self): return self._objects.values() def create_object(self, key: str): if key in self._objects: raise ValueError("Object already exists: {}".format(key)) o = Object(key, self._descriptor) self._objects[key] = o return o def read(self, path): from pathlib import Path print("Reading objects from {}".format(path)) for p in Path(path).glob("*.ini"): if p.name == "object-set.ini": continue with open(p, "r") as f: ini = configparser.ConfigParser(interpolation = None) ini.read(p) key = ini.get("meta", "key") o = self.create_object(key) o.merge({k:v for k, v in ini.items("values")}) print("Read {} objects".format(len(self._objects))) def write(self, path): print("Writing {} objects".format(len(self._objects))) ini = configparser.ConfigParser(interpolation = None) ini.add_section("object-set") with open(os.path.join(path, "object-set.ini"), "w") as f: ini.write(f) for o in self._objects.values(): ini = configparser.ConfigParser(interpolation = None) ini.add_section("meta") ini.set("meta", "key", o.key) ini.add_section("values") for key in sorted(self._descriptor.keys): value = o.get(key) if value: ini.set("values", key, value) with open(os.path.join(path, "{}.ini".format(o.key)), "w") as f: ini.write(f)