from datetime import datetime
from weakref import WeakKeyDictionary
+import itertools
+
class ConfigObject:
- def __init__(self):
+ def __init__(self, comment=None):
self.symbols = {}
self.config = WeakKeyDictionary()
- self.comment = None
+ self.comment = comment
+
+ def isp(self, indent):
+ return " " * indent
+
+ def append(self):
+ return "" if self.comment is None else f" # {self.comment}"
- def __str__(self):
- return "" if self.comment is None else f"# {self.comment}\n"
+ def lines(self, indent):
+ return [] if self.comment is None else [ f"{self.isp(indent)}# {self.comment}" ]
+
+ def writelines(self, f):
+ f.writelines([ x + "\n" for x in self.lines(0) ])
class Timestamp(ConfigObject):
def __init__(self, comment):
- super().__init__()
- self.comment = f"{comment} at {datetime.now()}"
+ super().__init__(comment=f"{comment} at {datetime.now()}")
+
+class BlockOption(ConfigObject):
+ def __init__(self, config_text, _type, value, **kwargs):
+ super().__init__(**kwargs)
-class BlockOption:
- def __init__(self, config_text, _type, value):
if not isinstance(value, _type):
raise Exception("BlockOption value doesn't match declared type")
self._type = _type
self.value = value
- def set(self, value):
- if value == self.value:
+ def set(self, value, **kwargs):
+ if value == self.value and len(kwargs) == 0:
return self
else:
- return type(self)(self.config_text, self._type, value)
+ return type(self)(self.config_text, self._type, value, **kwargs)
+
+ def lines(self, indent):
+ return [ f"{self.isp(indent)}{self.config_text} {self.value};{self.append()}" ]
+
+class ConfigBlock(ConfigObject):
+ def __init__(self, **kwargs):
+ super().__init__(**{ k:v for k,v in kwargs.items() if k not in self.options })
+
+ self.options_set = {}
+ for k,v in kwargs.items():
+ if k in self.options:
+ self.options_set[k] = self.options[k].set(v)
+
+ def set(self, arg, val, **kwargs):
+ if arg not in self.options:
+ raise NotImplementedError
+
+ self.options_set[arg] = self.options[arg].set(val, **kwargs)
+
+ def lines(self, indent):
+ inside = [
+ (opt.lines(indent+1))
+ for k,opt in self.options_set.items()
+ if opt != self.options[k]
+ ]
+
+ header = self.block_header()
+ isp = " " * indent
+
+ if len(inside) == 0:
+ return [ header + " {}" + self.append() ]
+ else:
+ return [ *super().lines(indent), isp + header + " {", *itertools.chain(*inside), isp + "}" ]
-class ProtocolConfig(ConfigObject):
+class ProtocolConfig(ConfigBlock):
options = {
"disabled": BlockOption("disabled", bool, False),
}
def __init__(self, name=None, template=None, **kwargs):
- super().__init__()
+ super().__init__(**kwargs)
self.name = name
if template is not None:
raise NotImplementedError()
- self.options_set = {}
- for k in kwargs:
- if k not in self.options:
- raise NotImplementedError()
-
- self.options_set[k] = self.options[k].set(kwargs[k])
-
- def block_inside(self, indent):
- if len(self.options_set) == 0:
- return None
-
- return ("\n" + " " * indent).join([""] + [
- f"{opt.config_text} {opt.value};" for k,opt in self.options_set.items() if opt != self.options[k]
- ])
-
- def __str__(self):
- inside = self.block_inside(1)
- header = f"protocol {self.protocol_type}{'' if self.name is None else ' ' + self.name }"
-
- if inside is None:
- return header + " {}\n"
- else:
- return header + " {" + inside + "\n}\n"
+ def block_header(self):
+ return f"protocol {self.protocol_type}{'' if self.name is None else ' ' + self.name }"
class DeviceProtocolConfig(ProtocolConfig):
name_prefix = "device"