mirror of
https://codeberg.org/vlw/3rd.git
synced 2026-01-11 22:36:01 +01:00
This PR refactors the config file structure into a simpler format, as well as making it more capable at the same time. Config values are now accessed as properties instead of referenced on the parsed config JSON list directly. Config files are also loaded with the `-i` argument which can take any compatible JSON file, this replaces the previous `-a` (autorun) argument. Reviewed-on: https://codeberg.org/vlw/3rd/pulls/1 Co-authored-by: vlw <victor@vlw.se> Co-committed-by: vlw <victor@vlw.se>
174 lines
4.2 KiB
Python
174 lines
4.2 KiB
Python
import json
|
|
import tempfile
|
|
from pathlib import Path
|
|
from typing import Self, Union
|
|
|
|
from .Enums import ConfigKeys
|
|
|
|
class Config():
|
|
pathnames = set()
|
|
|
|
@staticmethod
|
|
def for_each(items: list) -> Self:
|
|
"""
|
|
Returns a generator which iterates over each item in a list of item configs
|
|
|
|
Args:
|
|
items (list): The list to iterate over
|
|
|
|
Returns:
|
|
Self: Instance of the Config class
|
|
|
|
Yields:
|
|
Iterator[Self]: Config class for the current item
|
|
"""
|
|
|
|
for item in items:
|
|
yield Config(item)
|
|
|
|
@staticmethod
|
|
def from_json_file(pathname: str) -> Self:
|
|
"""
|
|
Load item configs from a JSON file
|
|
|
|
Args:
|
|
pathname (str): _description_
|
|
|
|
Returns:
|
|
Self: _description_
|
|
"""
|
|
|
|
with open(pathname, "r") as f:
|
|
json = json.load(f)
|
|
|
|
for item in json:
|
|
Config.pathnames.add(item[ConfigKeys.ABSPATH_TARGET.value])
|
|
|
|
Config.for_each(json)
|
|
|
|
@staticmethod
|
|
def __throw_missing_key(key: ConfigKeys) -> None:
|
|
"""
|
|
Raises a KeyError for an item config key if it does not exist
|
|
|
|
Args:
|
|
key (ConfigKeys): The key to raise an error for
|
|
|
|
Raises:
|
|
KeyError: Raised from an item config key
|
|
"""
|
|
|
|
raise KeyError(f"Expected required item config key '{key.value}' but it was not found")
|
|
|
|
@staticmethod
|
|
def __throw_value_error(key: ConfigKeys, expected_type: str) -> None:
|
|
"""
|
|
Raise a ValueError for a key with an expected type
|
|
|
|
Args:
|
|
key (ConfigKeys): The item config key to raise an error for
|
|
expected_type (str): The expected type
|
|
|
|
Raises:
|
|
ValueError: Raised from an item config key and expected value type
|
|
"""
|
|
|
|
raise ValueError(f"Item config key '{key.value}' expects a value of type {expected_type}")
|
|
|
|
def __init__(self, item: dict):
|
|
"""
|
|
Create a new Config instance
|
|
"""
|
|
|
|
self.__item = item
|
|
|
|
@property
|
|
def password(self) -> str|False:
|
|
"""
|
|
Returns the password for this item, or None if unset
|
|
|
|
Returns:
|
|
str|False: Password or None if no password is set
|
|
"""
|
|
|
|
if not self.__key_exists(ConfigKeys.PASSWORD.value):
|
|
return False
|
|
|
|
return self.__item[ConfigKeys.PASSWORD.value] if isinstance(self.__item[ConfigKeys.PASSWORD.value], str) else None
|
|
|
|
@property
|
|
def compression(self) -> int:
|
|
"""
|
|
Returns the compression level for this item, or false if STORE mode should be used
|
|
|
|
Returns:
|
|
str|False: Compression level for this item, false if compression is disabled
|
|
"""
|
|
|
|
if not self.__key_exists(ConfigKeys.COMPRESSION.value):
|
|
return 0
|
|
|
|
if not isinstance(self.__item[ConfigKeys.COMPRESSION.value], int) or self.__item[ConfigKeys.COMPRESSION.value] == 0:
|
|
return 0
|
|
|
|
return max(1, min(self.__item[ConfigKeys.COMPRESSION.value], 10))
|
|
|
|
@property
|
|
def abspath_temp(self) -> str:
|
|
"""
|
|
Returns the path to the directory where the created archive will be stored until it's uploaded
|
|
|
|
Returns:
|
|
str: Absolute path to the destination directory
|
|
"""
|
|
|
|
if not self.__key_exists(ConfigKeys.ABSPATH_TEMP.value):
|
|
return tempfile.gettempdir()
|
|
|
|
return self.__item[ConfigKeys.ABSPATH_TEMP.value] if isinstance(self.__item[ConfigKeys.ABSPATH_TEMP.value], str) else tempfile.gettempdir()
|
|
|
|
@property
|
|
def abspath_target(self) -> str:
|
|
"""
|
|
Returns an absolute path to the target to be archived
|
|
|
|
Returns:
|
|
str: Absolute path to the target
|
|
"""
|
|
|
|
if not self.__key_exists(ConfigKeys.ABSPATH_TARGET.value):
|
|
return Config.__throw_missing_key(ConfigKeys.ABSPATH_TARGET)
|
|
|
|
if not isinstance(self.__item[ConfigKeys.ABSPATH_TARGET.value], str):
|
|
return Config.__throw_value_error(ConfigKeys.ABSPATH_TARGET, str)
|
|
|
|
return self.__item[ConfigKeys.ABSPATH_TARGET.value]
|
|
|
|
@property
|
|
def abspath_destination(self) -> str:
|
|
"""
|
|
Returns an absolute path to the target to be archived
|
|
|
|
Returns:
|
|
str: Absolute path to the target
|
|
"""
|
|
|
|
if not self.__key_exists(ConfigKeys.ASBPATH_DESTINATION.value):
|
|
return Config.__throw_missing_key(ConfigKeys.ASBPATH_DESTINATION)
|
|
|
|
if not isinstance(self.__item[ConfigKeys.ASBPATH_DESTINATION.value], str):
|
|
return Config.__throw_value_error(ConfigKeys.ASBPATH_DESTINATION, str)
|
|
|
|
return self.__item[ConfigKeys.ASBPATH_DESTINATION.value]
|
|
|
|
def __key_exists(self, key: str) -> bool:
|
|
"""
|
|
Returns true if a property key is defined for the current item
|
|
|
|
Args:
|
|
key (str): The key to test
|
|
|
|
Returns:
|
|
bool: True if key exists
|
|
"""
|
|
return key in self.__item
|