put settings in dict

This commit is contained in:
Hellow 2023-08-28 22:31:24 +02:00
parent c66b021ecc
commit 4bce29d288
9 changed files with 115 additions and 165 deletions

View File

@ -1,127 +0,0 @@
from typing import Optional, List, Union, Dict
from collections.abc import Iterable
from pathlib import Path
import toml
def comment_string(uncommented_string: str) -> str:
_fragments = uncommented_string.split("\n")
_fragments = ["# " + frag for frag in _fragments]
return "\n".join(_fragments)
class Comment:
def __init__(self, value: str) -> None:
self.value: str = value
@property
def uncommented(self) -> str:
return self.value
@property
def commented(self) -> str:
return comment_string(self.value)
def __str__(self) -> str:
return self.commented
class Attribute:
def __init__(self, data: dict, comment: Optional[str] = None) -> None:
self.data: dict = data
self.comment: Optional[Comment] = None if comment is None else Comment(
comment)
@property
def toml_string(self) -> str:
_data_string = toml.dumps(self.data)
components: List[str] = [_data_string]
if self.comment is not None:
components.append(self.comment.commented)
return "\n".join(components)
def __setitem__(self, key: str, value):
if key not in self.data:
self.data[key] = value
if isinstance(self.data[key], dict) and isinstance(value, dict):
self.data[key].update(value)
self.data[key] = value
class ConfigFile:
def __init__(self, config_file: Path, data: List[Union[Attribute, Comment]]) -> None:
self.config_file: Path = config_file
self.unknown_attribute: Attribute = Attribute(
{}, "This is the attribute is for all unknown attributes.")
self._data: List[Union[Attribute, Comment]] = data
self._key_attribute_map: Dict[str, Attribute] = {}
for attribute in self._data:
if isinstance(attribute, Comment):
continue
for key in attribute.data:
self._key_attribute_map[key] = attribute
def load(self):
self.update(toml.load(self.config_file.open("r"), encoding="utf-8"))
def dump(self):
with self.config_file.open("w", encoding="utf-8") as config_file:
config_file.write(self.toml_string)
def update(self, data: dict):
for key, value in data.items():
if key not in self._key_attribute_map:
self._key_attribute_map[key] = self.unknown_attribute
self.unknown_attribute[key] = value
continue
self._key_attribute_map[key][key] = value
@property
def toml_string(self) -> str:
components: List[str] = []
for attribute in self._data:
if isinstance(attribute, Attribute):
components.append(attribute.toml_string)
components.append(self.unknown_attribute.toml_string)
return "\n\n".join(components)
def __str__(self) -> str:
return self.toml_string
if __name__ == "__main__":
settings = ConfigFile(Path("/home/lars/.config/music-kraken/music-kraken.toml"), [
Attribute({
"happy_message": [
"Support the artist.",
"Star Me: https://github.com/HeIIow2/music-downloader",
"🏳️‍⚧️🏳️‍⚧️ Trans rights are human rights. 🏳️‍⚧️🏳️‍⚧️",
"🏳️‍⚧️🏳️‍⚧️ Trans women are women, trans men are men, and enbies are enbies. 🏳️‍⚧️🏳️‍⚧️",
"🏴‍☠️🏴‍☠️ Unite under one flag, fck borders. 🏴‍☠️🏴‍☠️",
"Join my Matrix Space: https://matrix.to/#/#music-kraken:matrix.org",
"Gotta love the BPJM ;-;",
"🏳️‍⚧️🏳️‍⚧️ Protect trans youth. 🏳️‍⚧️🏳️‍⚧️",
"Nonstop Progressive Marxism.",
],
"bitrate": 66.6
},
comment="this is a test section"
),
Attribute({
"# hihi": "byebey"
})
])
print(settings)
settings.dump()

View File

@ -1,5 +0,0 @@
from .structure import SettingStructure
settings: SettingStructure = {
"bitrate": 125
}

View File

@ -1,4 +0,0 @@
from typing import TypedDict
class SettingStructure(TypedDict):
bitrate: int

View File

@ -6,7 +6,6 @@ from .utils import cli_function
from .options.first_config import initial_config from .options.first_config import initial_config
from ..utils.config import set_name_to_value, write_config from ..utils.config import set_name_to_value, write_config
from ..utils.shared import MUSIC_DIR, NOT_A_GENRE_REGEX, ENABLE_RESULT_HISTORY, HISTORY_LENGTH, HELP_MESSAGE, HASNT_YET_STARTED
from ..utils.regex import URL_PATTERN from ..utils.regex import URL_PATTERN
from ..utils.string_processing import fit_to_file_system from ..utils.string_processing import fit_to_file_system
from ..utils.support_classes import Query, DownloadResult from ..utils.support_classes import Query, DownloadResult
@ -16,6 +15,8 @@ from ..download.page_attributes import Pages
from ..pages import Page from ..pages import Page
from ..objects import Song, Album, Artist, DatabaseObject from ..objects import Song, Album, Artist, DatabaseObject
from ..utils import settings
""" """
This is the implementation of the Shell This is the implementation of the Shell
@ -95,12 +96,12 @@ def get_existing_genre() -> List[str]:
existing_genres: List[str] = [] existing_genres: List[str] = []
# get all subdirectories of MUSIC_DIR, not the files in the dir. # get all subdirectories of MUSIC_DIR, not the files in the dir.
existing_subdirectories: List[Path] = [f for f in MUSIC_DIR.iterdir() if f.is_dir()] existing_subdirectories: List[Path] = [f for f in settings["music_directory"].iterdir() if f.is_dir()]
for subdirectory in existing_subdirectories: for subdirectory in existing_subdirectories:
name: str = subdirectory.name name: str = subdirectory.name
if not any(re.match(regex_pattern, name) for regex_pattern in NOT_A_GENRE_REGEX): if not any(re.match(regex_pattern, name) for regex_pattern in settings["not_a_genre_regex"]):
existing_genres.append(name) existing_genres.append(name)
existing_genres.sort() existing_genres.sort()
@ -133,7 +134,7 @@ def get_genre():
def help_message(): def help_message():
print() print()
print(HELP_MESSAGE) print(settings["happy_messages"])
print() print()
@ -187,17 +188,17 @@ class Downloader:
print() print()
def set_current_options(self, current_options: Results): def set_current_options(self, current_options: Results):
if ENABLE_RESULT_HISTORY: if settings["result_history"]:
self._result_history.append(current_options) self._result_history.append(current_options)
if HISTORY_LENGTH != -1: if settings["history_length"] != -1:
if len(self._result_history) > HISTORY_LENGTH: if len(self._result_history) > settings["history_length"]:
self._result_history.pop(0) self._result_history.pop(0)
self.current_results = current_options self.current_results = current_options
def previous_option(self) -> bool: def previous_option(self) -> bool:
if not ENABLE_RESULT_HISTORY: if not settings["result_history"]:
print("History is turned of.\nGo to settings, and change the value at 'result_history' to 'true'.") print("History is turned of.\nGo to settings, and change the value at 'result_history' to 'true'.")
return False return False
@ -396,7 +397,7 @@ def download(
command_list: List[str] = None, command_list: List[str] = None,
process_metadata_anyway: bool = False, process_metadata_anyway: bool = False,
): ):
if HASNT_YET_STARTED: if settings["hasnt_yet_started"]:
code = initial_config() code = initial_config()
if code == 0: if code == 0:
set_name_to_value("hasnt_yet_started", "false") set_name_to_value("hasnt_yet_started", "false")

View File

@ -1 +1,3 @@
from .config import config, read_config, write_config from .config import config, read_config, write_config
from .config.settings import settings

View File

@ -7,19 +7,7 @@ from .sections.paths import PATHS_SECTION
from .sections.paths import LOCATIONS from .sections.paths import LOCATIONS
from .config import Config from .config import Config
from .settings import read_config, write_config, load, set_name_to_value
config = Config()
def read_config(): load()
if not LOCATIONS.CONFIG_FILE.is_file():
write_config()
config.read_from_config_file(LOCATIONS.CONFIG_FILE)
def write_config():
config.write_to_config_file(LOCATIONS.CONFIG_FILE)
set_name_to_value = config.set_name_to_value
read_config()

View File

@ -42,7 +42,7 @@ class Config:
self._length = 0 self._length = 0
self._section_list: List[Section] = [] self._section_list: List[Section] = []
self._name_section_map: Dict[str, Section] = dict() self.name_section_map: Dict[str, Section] = dict()
for element in self.config_elements: for element in self.config_elements:
if not isinstance(element, Section): if not isinstance(element, Section):
@ -50,12 +50,12 @@ class Config:
self._section_list.append(element) self._section_list.append(element)
for name in element.name_attribute_map: for name in element.name_attribute_map:
if name in self._name_section_map: if name in self.name_section_map:
raise ValueError(f"Two sections have the same name: " raise ValueError(f"Two sections have the same name: "
f"{name}: " f"{name}: "
f"{element.__class__.__name__} {self._name_section_map[name].__class__.__name__}") f"{element.__class__.__name__} {self.name_section_map[name].__class__.__name__}")
self._name_section_map[name] = element self.name_section_map[name] = element
self._length += 1 self._length += 1
def set_name_to_value(self, name: str, value: str, silent: bool = True): def set_name_to_value(self, name: str, value: str, silent: bool = True):
@ -65,7 +65,7 @@ class Config:
:param value: :param value:
:return: :return:
""" """
if name not in self._name_section_map: if name not in self.name_section_map:
if silent: if silent:
LOGGER.warning(f"The setting \"{name}\" is either deprecated, or doesn't exist.") LOGGER.warning(f"The setting \"{name}\" is either deprecated, or doesn't exist.")
return return
@ -73,7 +73,7 @@ class Config:
LOGGER.debug(f"setting: {name} value: {value}") LOGGER.debug(f"setting: {name} value: {value}")
self._name_section_map[name].modify_setting(setting_name=name, new_value=value) self.name_section_map[name].modify_setting(setting_name=name, new_value=value)
def __len__(self): def __len__(self):
return self._length return self._length

View File

@ -0,0 +1,95 @@
from typing import TypedDict, List
from urllib.parse import ParseResult
from logging import Logger
from pathlib import Path
from .sections.paths import LOCATIONS
from .config import Config
from .base_classes import Section, Attribute
class SettingsStructure(TypedDict):
hasnt_yet_started: bool
result_history: bool
history_length: int
happy_messages: List[str]
modify_gc: bool
id_bits: int
# audio
bitrate: int
audio_format: str
sort_by_date: bool
sort_album_by_type: bool
download_path: str
download_file: str
album_type_blacklist: List[str]
# connection
proxies: List[str]
tor: bool
tor_port: int
chunk_size: int
show_download_errors_threshold: float
# youtube
invidious_instance: ParseResult
piped_instance: ParseResult
sleep_after_youtube_403: float
youtube_music_api_key: str
youtube_music_clean_data: bool
youtube_url: List[ParseResult]
use_sponsor_block: bool
# logging
logging_format: str
log_level: int
download_logger: Logger
tagging_logger: Logger
codex_logger: Logger
object_logger: Logger
database_logger: Logger
musify_logger: Logger
youtube_logger: Logger
youtube_music_logger: Logger
metal_archives_logger: Logger
genius_logger: Logger
# paths
music_directory: Path
temp_directory: Path
log_file: Path
not_a_genre_regex: List[str]
ffmpeg_binary: Path
settings: SettingsStructure = {}
config = Config()
set_name_to_value = config.set_name_to_value
def read_config():
if not LOCATIONS.CONFIG_FILE.is_file():
write_config()
config.read_from_config_file(LOCATIONS.CONFIG_FILE)
def write_config():
config.write_to_config_file(LOCATIONS.CONFIG_FILE)
def load():
read_config()
for section in config.config_elements:
if not isinstance(section, Section):
continue
for attribute in section.attribute_list:
if not isinstance(attribute, Attribute):
continue
settings[attribute.name] = attribute.object_from_value