Channels config file now has version information and set up basis for converting to newer versions
This commit is contained in:
parent
927a96d8b0
commit
3c7dd2e8a0
|
|
@ -1,19 +1,37 @@
|
||||||
from pathlib import Path
|
|
||||||
from typing import Union, Dict, List
|
|
||||||
import logging
|
|
||||||
import json
|
|
||||||
import atexit
|
import atexit
|
||||||
|
import json
|
||||||
|
import logging
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Union, Dict, List, Callable, Tuple
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
import utils
|
import utils
|
||||||
|
from . import vNoneTov1_0
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# Functions used to convert between configuration versions, in a dictionary of: old_version -> converter
|
||||||
|
# Each converter takes the old configuration and returns the converted configuration and the new version
|
||||||
|
config_version_converters: Dict[Union[None, str], Callable[[Dict], Tuple[Dict, str]]] = {
|
||||||
|
None: vNoneTov1_0.convert
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ChannelsConfigFile:
|
class ChannelsConfigFile:
|
||||||
"""
|
"""
|
||||||
Wrapper for the channels configuration file, telling which channels to watch and which channels were created by the bot.
|
Wrapper for the channels configuration file, telling which channels to watch and which channels were created by the bot.
|
||||||
"""
|
"""
|
||||||
|
version = "1.0"
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def empty_config() -> Dict:
|
||||||
|
"""
|
||||||
|
:return: An empty configuration, used to initialise the configuration file
|
||||||
|
"""
|
||||||
|
return {
|
||||||
|
"__version__": ChannelsConfigFile.version,
|
||||||
|
}
|
||||||
|
|
||||||
def __init__(self, config_file_path: Union[str, Path]):
|
def __init__(self, config_file_path: Union[str, Path]):
|
||||||
self.config_file = None # File descriptor to the on-disk config file
|
self.config_file = None # File descriptor to the on-disk config file
|
||||||
|
|
@ -30,13 +48,15 @@ class ChannelsConfigFile:
|
||||||
|
|
||||||
if config_file_path.stat().st_size == 0: # Config file is empty
|
if config_file_path.stat().st_size == 0: # Config file is empty
|
||||||
logger.warning(f"Config file {config_file_path} is empty, using empty config")
|
logger.warning(f"Config file {config_file_path} is empty, using empty config")
|
||||||
self.config = {}
|
self.config = self.empty_config()
|
||||||
self.save_to_file() # So that the file is proper json
|
self.save_to_file() # So that the file is proper json
|
||||||
else: # Config file is not empty
|
else: # Config file is not empty
|
||||||
self.reload_from_disk()
|
has_been_converted = self.reload_from_disk()
|
||||||
|
if has_been_converted:
|
||||||
|
self.save_to_file()
|
||||||
else: # Config file does not exist
|
else: # Config file does not exist
|
||||||
self.config_file = config_file_path.open("w+")
|
self.config_file = config_file_path.open("w+")
|
||||||
self.config = {}
|
self.config = self.empty_config()
|
||||||
self.save_to_file() # So that the file is proper json
|
self.save_to_file() # So that the file is proper json
|
||||||
|
|
||||||
# Verifying that attributes have been initialised properly
|
# Verifying that attributes have been initialised properly
|
||||||
|
|
@ -45,9 +65,13 @@ class ChannelsConfigFile:
|
||||||
|
|
||||||
atexit.register(self.save_to_file)
|
atexit.register(self.save_to_file)
|
||||||
|
|
||||||
def reload_from_disk(self) -> None:
|
def reload_from_disk(self) -> bool:
|
||||||
"""
|
"""
|
||||||
Reload the configuration from the on-disk file
|
Reload the configuration from the on-disk file
|
||||||
|
|
||||||
|
:return: Whether the configuration had to be converted to a more recent version because the on-file was an earlier version
|
||||||
|
:except json.JSONDecodeError: if the file is not valid json
|
||||||
|
:except ValueError: if the version of the configuration in the file is not known or can not be converted to a more recent one
|
||||||
"""
|
"""
|
||||||
logger.debug("Loading channels configuration file from disk")
|
logger.debug("Loading channels configuration file from disk")
|
||||||
self.config_file.seek(0) # Moving to beginning of file
|
self.config_file.seek(0) # Moving to beginning of file
|
||||||
|
|
@ -56,7 +80,27 @@ class ChannelsConfigFile:
|
||||||
except json.JSONDecodeError as e:
|
except json.JSONDecodeError as e:
|
||||||
logger.critical(f"JSON Error when parsing channels config file: {e}")
|
logger.critical(f"JSON Error when parsing channels config file: {e}")
|
||||||
raise e
|
raise e
|
||||||
|
# Checking configuration version and converting if needed
|
||||||
|
config_version = self.config["__version__"] if "__version__" in self.config else None
|
||||||
|
has_been_converted = False
|
||||||
|
if config_version != self.version:
|
||||||
|
logger.info(f"Channels configuration file is an older version, converting (on-file: {config_version}, current: {self.version})...")
|
||||||
|
|
||||||
|
# Performing the conversion
|
||||||
|
while config_version != self.version:
|
||||||
|
if config_version in config_version_converters:
|
||||||
|
logger.debug(f"Converting from {config_version}")
|
||||||
|
self.config, config_version = config_version_converters[config_version](self.config)
|
||||||
|
logger.debug(f"Converted to {config_version}")
|
||||||
|
else:
|
||||||
|
logger.critical(f"Impossible to find converter to convert from {config_version}")
|
||||||
|
raise ValueError(f"Configuration loading: impossible to convert on-file config to current version")
|
||||||
|
has_been_converted = True
|
||||||
|
|
||||||
|
assert self.config["__version__"] == self.version
|
||||||
|
|
||||||
logger.debug("Loaded channels configuration file from disk")
|
logger.debug("Loaded channels configuration file from disk")
|
||||||
|
return has_been_converted
|
||||||
|
|
||||||
def save_to_file(self, indent = 2) -> None:
|
def save_to_file(self, indent = 2) -> None:
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
"""
|
||||||
|
Converter for converting ChannelsConfigFile from version "Versions weren't a thing back then" to version 1.0
|
||||||
|
"""
|
||||||
|
|
||||||
|
from typing import Dict, Tuple
|
||||||
|
|
||||||
|
|
||||||
|
def convert(config: Dict) -> Tuple[Dict, str]:
|
||||||
|
assert "__version__" not in config
|
||||||
|
# This first simple converter only adds version information to the config
|
||||||
|
# this poses the basis for version conversion
|
||||||
|
config["__version__"] = "1.0"
|
||||||
|
return config, "1.0"
|
||||||
Loading…
Reference in New Issue