mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-23 10:11:53 +00:00
100 lines
3.0 KiB
Python
100 lines
3.0 KiB
Python
from datetime import datetime
|
|
from weakref import WeakKeyDictionary
|
|
|
|
import itertools
|
|
|
|
class ConfigObject:
|
|
def __init__(self, comment=None):
|
|
self.symbols = {}
|
|
self.config = WeakKeyDictionary()
|
|
self.comment = comment
|
|
|
|
def isp(self, indent):
|
|
return " " * indent
|
|
|
|
def append(self):
|
|
return "" if self.comment is None else f" # {self.comment}"
|
|
|
|
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__(comment=f"{comment} at {datetime.now()}")
|
|
|
|
class BlockOption(ConfigObject):
|
|
def __init__(self, config_text, _type, value, **kwargs):
|
|
super().__init__(**kwargs)
|
|
|
|
if not isinstance(value, _type):
|
|
raise Exception("BlockOption value doesn't match declared type")
|
|
|
|
self.config_text = config_text
|
|
self._type = _type
|
|
self.value = 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, **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(ConfigBlock):
|
|
options = {
|
|
"disabled": BlockOption("disabled", bool, False),
|
|
}
|
|
|
|
def __init__(self, name=None, template=None, **kwargs):
|
|
super().__init__(**kwargs)
|
|
self.name = name
|
|
|
|
if template is not None:
|
|
raise NotImplementedError()
|
|
|
|
def block_header(self):
|
|
return f"protocol {self.protocol_type}{'' if self.name is None else ' ' + self.name }"
|
|
|
|
class DeviceProtocolConfig(ProtocolConfig):
|
|
name_prefix = "device"
|
|
protocol_type = "device"
|
|
|
|
options = ProtocolConfig.options | {
|
|
"scan_time": BlockOption("scan time", int, 60),
|
|
}
|