# config.py -- Pamhyr configuration manager # Copyright (C) 2023-2024 INRAE # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # -*- coding: utf-8 -*- import os import pickle import logging from platformdirs import user_cache_dir from SQL import SQL from Model.Stricklers.Stricklers import Stricklers from Model.Stricklers.StricklersList import StricklersList from Solver.Solvers import solver_type_list config_dir = user_cache_dir("pamhyr") config_file = "config.sqlite3" logger = logging.getLogger() class Config(SQL): def __init__(self): self._version = '0.0.5' self.filename = Config.filename() self.set_default_value() logging.info(f"Configuration file : {self.filename}") super(Config, self).__init__(filename=self.filename) def _create(self): # Info (meta data) self.execute( "CREATE TABLE info(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)") self.execute(f"INSERT INTO info VALUES ('version', '{self._version}')") # Key / Value (data) self.execute( "CREATE TABLE data(key TEXT NOT NULL UNIQUE, value TEXT NOT NULL)") # Solver self.execute(""" CREATE TABLE solver( type TEXT NOT NULL, name TEXT NOT NULL UNIQUE, description TEXT NOT NULL, path_input TEXT NOT NULL, path_solver TEXT NOT NULL, path_output TEXT NOT NULL, cmd_input TEXT NOT NULL, cmd_solver TEXT NOT NULL, cmd_output TEXT NOT NULL ) """) # Stricklers self.execute(""" CREATE TABLE stricklers( name TEXT NOT NULL UNIQUE, comment TEXT NOT NULL, minor REAL NOT NULL, medium REAL NOT NULL ) """) self.commit() def _update(self): version = self.execute( f"SELECT value FROM info WHERE key='version'")[0] if version != self._version: logger.info( "Configuration file update from " + f"{version} to {self._version}..." ) major, minor, release = version.strip().split(".") if major == minor == "0": if int(release) < 2: # Add default solver posix = os.name == 'posix' ext = "" if posix else ".exe" self.execute(f""" INSERT INTO solver VALUES ( 'mage8', 'default-mage', 'Default Pamhyr2 mage 8 version', '', '', '', '', '@install_dir/mage/mage{ext} @args @input', '' ) """) if int(release) < 3: self.execute( "INSERT OR IGNORE INTO data " + "VALUES ('last_study', '')" ) self.execute( "INSERT OR IGNORE INTO data " + "VALUES ('close_correctly', 'True')" ) if int(release) < 4: self.execute( "INSERT OR IGNORE INTO data " + "VALUES ('last_solver_name', '')" ) if int(release) < 5: posix = os.name == 'posix' ext = "" if posix else ".exe" self.execute( "UPDATE solver SET cmd_solver=" + f"'@install_dir/mage8/mage{ext} @args @input' " "WHERE name='default-mage'" ) self.execute(f""" INSERT INTO solver VALUES ( 'mage_fake7', 'default-mage-fake-7', 'Default Pamhyr2 mage fake version 7', '', '', '', '', '@install_dir/mage8/mage_as7{ext} @args @input', '' ) """) self.execute( f"UPDATE info SET value='{self._version}' " + "WHERE key='version'" ) self.commit() def _load_solver(self): self._solvers = [] compatible_types = ', '.join( map(lambda t: f"'{t}'", solver_type_list) ) solvers = self.execute( "SELECT * FROM solver " + f"WHERE type IN ({compatible_types})", fetch_one=False ) for solver in solvers: solver_type = solver[0] ctor = solver_type_list[solver_type] new = ctor(solver[1]) new._description = solver[2] new._path_input = solver[3] new._path_solver = solver[4] new._path_output = solver[5] new._cmd_input = solver[6] new._cmd_solver = solver[7] new._cmd_output = solver[8] self._solvers.append(new) def _load_stricklers(self): self.stricklers = StricklersList() id = 0 stricklers = self.execute( "SELECT * FROM stricklers", fetch_one=False ) for strickler in stricklers: new = Stricklers() new._name = strickler[0] new._comment = strickler[1] new._minor = float(strickler[2]) new._medium = float(strickler[3]) self.stricklers.insert(id, new) id += 1 def _load(self): # Backup v = self.execute("SELECT value FROM data WHERE key='backup_enable'") self.backup_enable = v[0] == "True" # v = self.execute("SELECT value FROM data WHERE key='backup_path'") # self.backup_path = v[0] v = self.execute("SELECT value FROM data WHERE key='backup_frequence'") self.backup_frequence = v[0] # v = self.execute("SELECT value FROM data WHERE key='backup_max'") # self.backup_max = int(v[0]) # Editor v = self.execute("SELECT value FROM data WHERE key='editor'") self.editor = v[0] # Languages v = self.execute("SELECT value FROM data WHERE key='lang'") self.lang = v[0] # Last study v = self.execute("SELECT value FROM data WHERE key='last_study'") self.last_study = v[0] v = self.execute("SELECT value FROM data WHERE key='close_correctly'") self.close_correctly = v[0] == "True" # Last Solver v = self.execute("SELECT value FROM data WHERE key='last_solver_name'") self.last_solver_name = v[0] # Debug v = self.execute("SELECT value FROM data WHERE key='debug'") self.debug = v[0] == "True" self._load_solver() self._load_stricklers() def _save_solver(self): self.execute(f"DELETE FROM solver") for solver in self.solvers: self.execute(f""" INSERT INTO solver VALUES ( '{solver._type}', '{self._db_format(solver._name)}', '{self._db_format(solver._description)}', '{self._db_format(solver._path_input)}', '{self._db_format(solver._path_solver)}', '{self._db_format(solver._path_output)}', '{self._db_format(solver._cmd_input)}', '{self._db_format(solver._cmd_solver)}', '{self._db_format(solver._cmd_output)}' ) """, commit=True) def _save_stricklers(self): self.execute(f"DELETE FROM stricklers") for stricklers in self.stricklers.stricklers: self.execute(f""" INSERT INTO stricklers VALUES ( '{self._db_format(stricklers._name)}', '{self._db_format(stricklers._comment)}', '{stricklers._minor}', '{stricklers._medium}' ) """) self.commit() def _save(self): data = { "backup_enable": self.backup_enable, # "backup_path": self.backup_path, "backup_frequence": self.backup_frequence, # "backup_max": self.backup_max, "editor": self.editor, "lang": self.lang, "last_study": self.last_study, "close_correctly": self.close_correctly, "debug": self.debug, "last_solver_name": self.last_solver_name, } for key in data: self.execute( f"INSERT OR IGNORE INTO data VALUES " + f" ('{key}', '{self._db_format(data[key])}')" ) self.execute( f"UPDATE data SET " + f"value='{self._db_format(data[key])}' " + f"WHERE key='{key}'" ) self.commit() self._save_solver() self._save_stricklers() def set_default_value(self): # Solvers self._solvers = [] posix = os.name == 'posix' ext = "" if posix else ".exe" # Mage8 ctor = solver_type_list["mage8"] new = ctor("default-mage") new._description = "Default Pamhyr2 mage 8 version" new._cmd_solver = f""""@install_dir/mage8/mage{ext}" @args @input""" self._solvers.append(new) # Mage fake 7 # ctor = solver_type_list["mage_fake7"] # new = ctor("default-mage-fake-7") # new._description = "Default Pamhyr2 mage fake version 7" # new._cmd_solver = f"""\ # "@install_dir/mage8/mage_as7{ext}" @args @input""" # self._solvers.append(new) # Backup self.backup_enable = True # self.backup_path = "" self.backup_frequence = "00:15:00" # self.backup_max = 10 # Editor self.editor = "editor @file" # Languages self.lang = "" # Stricklers self.stricklers = StricklersList() # Last study self.last_study = "" self.close_correctly = False # Last Solver self.last_solver_name = "" # Debug self.debug = False def set_close_correctly(self): self.close_correctly = True self.execute( f"UPDATE data SET value='True' WHERE key='close_correctly'") self.commit() def set_last_study(self, filename): if filename is None: return self.last_study = filename self.close_correctly = False self.execute( "UPDATE data SET " + f"value='{self._db_format(self.last_study)}' " + "WHERE key='last_study'" ) self.execute( f"UPDATE data SET value='{self.close_correctly}' " + "WHERE key='close_correctly'" ) self.commit() def update_last_solver_used(self, solver_name): self.last_solver_name = solver_name self.execute( "UPDATE data SET " + f"value='{self._db_format(self.last_solver_name)}' " + "WHERE key='last_solver_name'" ) @classmethod def filename(cls): file = "" if os.name == 'posix': ndir = config_dir else: ndir = config_dir ndir = ndir.replace("/", "\\") os.makedirs(ndir, exist_ok=True) file = os.path.join(ndir, config_file) return file @classmethod def languages(cls): return { "System": "", "English": "en", "French": "fr", } @property def solvers(self): return self._solvers.copy() @solvers.setter def solvers(self, solvers): self._solvers = solvers def save(self): self._save() @classmethod def load(cls): return cls()