This commit is contained in:
Artem30801
2019-11-28 08:45:33 +03:00
parent 3dc665bd00
commit fe69c99fb5
5 changed files with 136 additions and 67 deletions

View File

@@ -224,7 +224,7 @@ class Client(object):
@messaging.message_callback("config_write")
def _command_config_write(*args, **kwargs):
options = [ConfigOption(**raw_option) for raw_option in kwargs["options"]]
logger.info("Writing config options: {}".format(options))
logger.info("Writing config_attrs options: {}".format(options))
active_client.write_config(kwargs["reload"], *options)

19
Drone/config/client.ini Normal file
View File

@@ -0,0 +1,19 @@
# This is generated config_attrs with defaults
# Modify to configure
[SERVER]
port = 25000
host = 192.168.1.101
buffer_size = 1024
[BROADCAST]
use = True
port = 8181
[NTP]
use = False
host = ntp1.stratum2.ru
port = 123n
[PRIVATE]
# avialiable options: /hostname ; /default ; /ip ; any string 63 characters lengh
#id = /hostname

View File

@@ -13,4 +13,5 @@ host = string(default=ntp1.stratum2.ru)
port = integer(default=123)
[PRIVATE]
id = string(default=/hostname, max=63)
# avialiable options: /hostname ; /default ; /ip ; any string 63 characters lengh
id = string(default=/hostname, max=63)

View File

@@ -4,10 +4,12 @@ from PyQt5.QtCore import Qt as Qt
class ConfigModelItem:
def __init__(self, label, value="", parent=None):
self.parentItem = parent
def __init__(self, label, value="", is_section=False, parent=None):
self.itemData = [label, value]
self.is_section=is_section
self.childItems = []
self.parentItem = parent
if self.parentItem is not None:
self.parentItem.appendChild(self)
@@ -64,12 +66,6 @@ class ConfigModel(QtCore.QAbstractItemModel):
self.rootItem = ConfigModelItem("Option", "Value")
self.setup(data)
#i = ConfigModelItem("1314", "")
#self.rootItem.appendChild(i)
#i.appendChild(ConfigModelItem("36hhj", "34566"))
#i.appendChild(ConfigModelItem("36hhj", "34566"))
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole and orientation == Qt.Horizontal:
return self.rootItem.data(section)
@@ -143,12 +139,11 @@ class ConfigModel(QtCore.QAbstractItemModel):
def flags(self, index):
if not index.isValid():
return Qt.NoItemFlags
childItem = index.internalPointer()
parentItem = childItem.parent()
item = index.internalPointer()
flags = Qt.ItemIsEnabled | Qt.ItemIsSelectable
if index.column() == 1 and parentItem != self.rootItem:
if index.column() == 1 and not item.is_section:
flags |= Qt.ItemIsEditable
return flags
@@ -168,13 +163,18 @@ class ConfigModel(QtCore.QAbstractItemModel):
self.endRemoveRows()
return True
def setup(self, d: dict):
for section, options in d.items():
section_item = ConfigModelItem(section, parent=self.rootItem)
for option, value in options.items():
section_item.appendChild(ConfigModelItem(option, value))
def setup(self, data: dict, parent=None):
if parent is None:
parent = self.rootItem
def to_dict(self):
for key, value in data.items():
if isinstance(value, dict):
item = ConfigModelItem(key, parent=parent, is_section=True)
self.setup(value, parent=item)
else:
parent.appendChild(ConfigModelItem(key, value))
def to_dict(self): # TODO recursive
d = {}
for section in self.rootItem.childItems:
section_d = {}
@@ -221,8 +221,8 @@ if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
Dialog = QtWidgets.QDialog()
data = {"section 1": {"opt1": "str", "opt2": 123, "opt3": 1.23, "opt4": False, "...": ""},
"section 2": {"opt1": "str", "opt2": 123, "opt3": 1.23, "opt4": False, "...": ""}}
data = {"section 1": {"opt1": "str", "opt2": 123, "opt3": 1.23, "opt4": False, "...": {'subopt': 'bal'}},
"section 2": {"opt1": "str", "opt2": [1.1, 2.3, 34], "opt3": 1.23, "opt4": False, "...": ""}}
ui = ConfigDialog(data)
ui.setupUi(Dialog)
@@ -230,4 +230,8 @@ if __name__ == '__main__':
Dialog.show()
print(app.exec_())
print(Dialog.result())
print(ui.model.to_dict())
sys.exit()

137
config.py
View File

@@ -1,64 +1,109 @@
import collections
import os
from configobj import ConfigObj
from functools import partial
from configobj import ConfigObj, Section
from validate import Validator
ConfigOption = collections.namedtuple("ConfigOption", ["section", "option", "value"])
def modify_filename(path, pattern):
old_path, filename = os.path.split(path)
filename = os.path.splitext(filename)[0]
newfilename = pattern.format(filename)
return os.path.join(old_path, newfilename)
class ConfigManager:
def __init__(self):
self.configs = {}
self.config = ConfigObj()
@staticmethod
def _get_default_path(path):
old_path, filename = os.path.split(path)
filename = os.path.splitext(filename)[0]
newfilename = "default_{}.ini".format(filename)
print(os.path.join(old_path, newfilename))
return os.path.join(old_path, newfilename)
def load_config(self, path):
self.generate_default_config(path)
def load_config(self, path): # todo maybe automatic config path
vdt = Validator()
config = ConfigObj(infile=path, raise_errors=True,
configspec=modify_filename(path, 'spec/configspec_{}.ini'))
test = config.validate(vdt)
print(test)
print(config)
self.config = config
default_config = ConfigObj(
infile=self._get_default_path(path), configspec="Drone/configs/configspec_client.ini")
default_config.validate(vdt)
print(default_config)
default_config.walk(self.transform)
print(default_config.dict())
#default_config = configparser.ConfigParser(co)
#default_config.read(default_path)
def get(self, section, option):
return self.config[section][option]
def set(self, section, option, value, write=False):
self.config[section][option] = value
if write:
self.write()
def create_empty_config(self, path):
with open(path, 'w') as f:
f.write("# Write here any configurations to replace default values \n\n")
@staticmethod
def getvalue(section, key):
try:
return section.as_int(key)
except ValueError:
pass
try:
return section.as_float(key)
except ValueError:
pass
try:
return section.as_bool(key)
except ValueError:
pass
return section.get(key)
def write(self):
self.config.write()
@classmethod
def transform(cls, section, key):
value = cls.getvalue(section, key)
print(value)
section[key] = value
def _get_defaults(cls, item, unchanged_only=False):
if isinstance(item, Section):
default_values = item.default_values.copy()
if unchanged_only:
default_list = item.defaults.copy()
defaults = {key: default_values[key] for key in default_list if key in default_values}
else:
defaults = default_values
for key, value in item.items():
result = cls._get_defaults(value, unchanged_only=unchanged_only)
if result is not None:
defaults[key] = result
return defaults if defaults else None
@property
def default_values(self):
return self._get_defaults(self.config) or {}
@property
def unchanged_defaults(self):
return self._get_defaults(self.config, unchanged_only=True) or {}
@staticmethod
def generate_default_config(path):
if os.path.isfile(path):
return
vdt = Validator()
config = ConfigObj(configspec=modify_filename(path, 'spec/configspec_{}.ini'))
config.filename = path
config.validate(vdt, copy=True)
config.initial_comment = ('This is generated config_attrs with defaults',
'Modify to configure')
config.write()
def __getattr__(self, item):
try:
section, option = item.split('_', 1)
return self.config[section.upper()][option.lower()]
except (ValueError, KeyError):
return self.__dict__[item]
def __setattr__(self, key, value):
try:
section, option = key.split('_', 1)
self.config[section.upper()][option.lower()] = value
except (ValueError, KeyError):
self.__dict__[key] = value
if __name__ == '__main__':
cfg = ConfigManager()
#open('Drone/default_clinet_config.ini')
cfg.load_config('Drone/configs/clinet_config.ini')
cfg.load_config('Drone/config/client.ini')
print(cfg.server_host)
cfg.server_host = '192.168.1.103'
print(cfg.get('SERVER', 'host'))
cfg.set('SERVER', 'host', '192.168.1.103')
print(cfg.config)
print(cfg.default_values)
print(cfg.unchanged_defaults)
#print(cfg.con)