diff --git a/src/music_kraken/_settings/__init__.py b/src/music_kraken/_settings/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/src/music_kraken/_settings/base_models.py b/src/music_kraken/_settings/base_models.py deleted file mode 100644 index 59b36c2..0000000 --- a/src/music_kraken/_settings/base_models.py +++ /dev/null @@ -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() diff --git a/src/music_kraken/_settings/default.py b/src/music_kraken/_settings/default.py deleted file mode 100644 index 689f9ea..0000000 --- a/src/music_kraken/_settings/default.py +++ /dev/null @@ -1,5 +0,0 @@ -from .structure import SettingStructure - -settings: SettingStructure = { - "bitrate": 125 -} \ No newline at end of file diff --git a/src/music_kraken/_settings/structure.py b/src/music_kraken/_settings/structure.py deleted file mode 100644 index e5e7f2b..0000000 --- a/src/music_kraken/_settings/structure.py +++ /dev/null @@ -1,4 +0,0 @@ -from typing import TypedDict - -class SettingStructure(TypedDict): - bitrate: int diff --git a/src/music_kraken/cli/main_downloader.py b/src/music_kraken/cli/main_downloader.py index ba5ee5f..3018d4f 100644 --- a/src/music_kraken/cli/main_downloader.py +++ b/src/music_kraken/cli/main_downloader.py @@ -6,7 +6,6 @@ from .utils import cli_function from .options.first_config import initial_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.string_processing import fit_to_file_system from ..utils.support_classes import Query, DownloadResult @@ -16,6 +15,8 @@ from ..download.page_attributes import Pages from ..pages import Page from ..objects import Song, Album, Artist, DatabaseObject +from ..utils import settings + """ This is the implementation of the Shell @@ -95,12 +96,12 @@ def get_existing_genre() -> List[str]: existing_genres: List[str] = [] # 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: 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.sort() @@ -133,7 +134,7 @@ def get_genre(): def help_message(): print() - print(HELP_MESSAGE) + print(settings["happy_messages"]) print() @@ -187,17 +188,17 @@ class Downloader: print() def set_current_options(self, current_options: Results): - if ENABLE_RESULT_HISTORY: + if settings["result_history"]: self._result_history.append(current_options) - if HISTORY_LENGTH != -1: - if len(self._result_history) > HISTORY_LENGTH: + if settings["history_length"] != -1: + if len(self._result_history) > settings["history_length"]: self._result_history.pop(0) self.current_results = current_options 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'.") return False @@ -396,7 +397,7 @@ def download( command_list: List[str] = None, process_metadata_anyway: bool = False, ): - if HASNT_YET_STARTED: + if settings["hasnt_yet_started"]: code = initial_config() if code == 0: set_name_to_value("hasnt_yet_started", "false") diff --git a/src/music_kraken/utils/__init__.py b/src/music_kraken/utils/__init__.py index 89186a6..47cac41 100644 --- a/src/music_kraken/utils/__init__.py +++ b/src/music_kraken/utils/__init__.py @@ -1 +1,3 @@ from .config import config, read_config, write_config + +from .config.settings import settings diff --git a/src/music_kraken/utils/config/__init__.py b/src/music_kraken/utils/config/__init__.py index b490e26..1f48b5f 100644 --- a/src/music_kraken/utils/config/__init__.py +++ b/src/music_kraken/utils/config/__init__.py @@ -7,19 +7,7 @@ from .sections.paths import PATHS_SECTION from .sections.paths import LOCATIONS from .config import Config - -config = Config() +from .settings import read_config, write_config, load, 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) - -set_name_to_value = config.set_name_to_value - -read_config() +load() diff --git a/src/music_kraken/utils/config/config.py b/src/music_kraken/utils/config/config.py index 4bac445..1e624c3 100644 --- a/src/music_kraken/utils/config/config.py +++ b/src/music_kraken/utils/config/config.py @@ -42,7 +42,7 @@ class Config: self._length = 0 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: if not isinstance(element, Section): @@ -50,12 +50,12 @@ class Config: self._section_list.append(element) 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: " 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 def set_name_to_value(self, name: str, value: str, silent: bool = True): @@ -65,7 +65,7 @@ class Config: :param value: :return: """ - if name not in self._name_section_map: + if name not in self.name_section_map: if silent: LOGGER.warning(f"The setting \"{name}\" is either deprecated, or doesn't exist.") return @@ -73,7 +73,7 @@ class Config: 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): return self._length diff --git a/src/music_kraken/utils/config/settings.py b/src/music_kraken/utils/config/settings.py new file mode 100644 index 0000000..ba02e75 --- /dev/null +++ b/src/music_kraken/utils/config/settings.py @@ -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