put settings in dict
This commit is contained in:
parent
c66b021ecc
commit
4bce29d288
@ -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()
|
|
@ -1,5 +0,0 @@
|
|||||||
from .structure import SettingStructure
|
|
||||||
|
|
||||||
settings: SettingStructure = {
|
|
||||||
"bitrate": 125
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
from typing import TypedDict
|
|
||||||
|
|
||||||
class SettingStructure(TypedDict):
|
|
||||||
bitrate: int
|
|
@ -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")
|
||||||
|
@ -1 +1,3 @@
|
|||||||
from .config import config, read_config, write_config
|
from .config import config, read_config, write_config
|
||||||
|
|
||||||
|
from .config.settings import settings
|
||||||
|
@ -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()
|
|
||||||
|
@ -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
|
||||||
|
95
src/music_kraken/utils/config/settings.py
Normal file
95
src/music_kraken/utils/config/settings.py
Normal 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
|
Loading…
Reference in New Issue
Block a user