feat: layed out commit

This commit is contained in:
Hellow 2023-08-10 23:01:16 +02:00
parent fc83ba3d23
commit aec62903e0
29 changed files with 201 additions and 44 deletions

View File

@ -10,5 +10,9 @@
"test*.py" "test*.py"
], ],
"python.testing.pytestEnabled": false, "python.testing.pytestEnabled": false,
"python.testing.unittestEnabled": true "python.testing.unittestEnabled": true,
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8"
},
"python.formatting.provider": "none"
} }

View File

@ -29,7 +29,8 @@ if __name__ == "__main__":
] ]
youtube_music_test = [ youtube_music_test = [
"s: psychonaut 4" "s: psychonaut 4",
"0"
] ]
music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True) music_kraken.cli.download(genre="test", command_list=youtube_music_test, process_metadata_anyway=True)

View File

@ -3,7 +3,7 @@ import logging
import gc import gc
import musicbrainzngs import musicbrainzngs
from .utils.config import read_config from .utils.old_config import read_config
from .utils.shared import MODIFY_GC from .utils.shared import MODIFY_GC
from . import cli from . import cli

View File

@ -87,7 +87,7 @@ def cli():
logging.getLogger().setLevel(logging.DEBUG) logging.getLogger().setLevel(logging.DEBUG)
from . import cli from . import cli
from .utils.config import read_config from .utils.old_config import read_config
from .utils import shared from .utils import shared
if arguments.r: if arguments.r:

View File

@ -5,7 +5,7 @@ import re
from .utils import cli_function 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.old_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.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

View File

@ -1,6 +1,6 @@
from ..utils import cli_function from ..utils import cli_function
from ...utils.config import config, write_config from ...utils.old_config import config, write_config
from ...utils import exception from ...utils import exception

View File

@ -67,17 +67,6 @@ class YouTube(SuperYouTube):
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
def get_source_type(self, source: Source) -> Optional[Type[DatabaseObject]]:
_url_type = {
YouTubeUrlType.CHANNEL: Artist,
YouTubeUrlType.PLAYLIST: Album,
YouTubeUrlType.VIDEO: Song,
}
parsed = YouTubeUrl(source.url)
if parsed.url_type in _url_type:
return _url_type[parsed.url_type]
def general_search(self, search_query: str) -> List[DatabaseObject]: def general_search(self, search_query: str) -> List[DatabaseObject]:
return self.artist_search(Artist(name=search_query, dynamic=True)) return self.artist_search(Artist(name=search_query, dynamic=True))

View File

@ -50,12 +50,17 @@ class YouTubeUrl:
""" """
def __init__(self, url: str) -> None: def __init__(self, url: str) -> None:
self.SOURCE_TYPE = SourcePages.YOUTUBE
""" """
Raises Index exception for wrong url, and value error for not found enum type Raises Index exception for wrong url, and value error for not found enum type
""" """
self.id = "" self.id = ""
parsed = urlparse(url=url) parsed = urlparse(url=url)
if parsed.netloc == "music.youtube.com":
self.SOURCE_TYPE = SourcePages.YOUTUBE_MUSIC
self.url_type: YouTubeUrlType self.url_type: YouTubeUrlType
type_frag_list = parsed.path.split("/") type_frag_list = parsed.path.split("/")
@ -135,6 +140,19 @@ class SuperYouTube(Page):
_sponsorblock_connection: Connection = Connection(host="https://sponsor.ajay.app/") _sponsorblock_connection: Connection = Connection(host="https://sponsor.ajay.app/")
self.sponsorblock_client = sponsorblock.Client(session=_sponsorblock_connection.session) self.sponsorblock_client = sponsorblock.Client(session=_sponsorblock_connection.session)
def get_source_type(self, source: Source) -> Optional[Type[DatabaseObject]]:
_url_type = {
YouTubeUrlType.CHANNEL: Artist,
YouTubeUrlType.PLAYLIST: Album,
YouTubeUrlType.VIDEO: Song,
}
parsed = YouTubeUrl(source.url)
if parsed.url_type in _url_type:
return _url_type[parsed.url_type]
def download_song_to_target(self, source: Source, target: Target, desc: str = None) -> DownloadResult: def download_song_to_target(self, source: Source, target: Target, desc: str = None) -> DownloadResult:
""" """
1. getting the optimal source 1. getting the optimal source

View File

@ -8,7 +8,7 @@ import re
from ...utils.exception.config import SettingValueError from ...utils.exception.config import SettingValueError
from ...utils.shared import PROXIES_LIST, YOUTUBE_MUSIC_LOGGER, DEBUG from ...utils.shared import PROXIES_LIST, YOUTUBE_MUSIC_LOGGER, DEBUG
from ...utils.config import CONNECTION_SECTION, write_config from ...utils.old_config import CONNECTION_SECTION, write_config
from ...utils.functions import get_current_millis from ...utils.functions import get_current_millis
if DEBUG: if DEBUG:
from ...utils.debug_utils import dump_to_file from ...utils.debug_utils import dump_to_file
@ -279,10 +279,13 @@ class YoutubeMusic(SuperYouTube):
def fetch_song(self, source: Source, stop_at_level: int = 1) -> Song: def fetch_song(self, source: Source, stop_at_level: int = 1) -> Song:
print(source)
return Song() return Song()
def fetch_album(self, source: Source, stop_at_level: int = 1) -> Album: def fetch_album(self, source: Source, stop_at_level: int = 1) -> Album:
return Album() return Album()
def fetch_artist(self, source: Source, stop_at_level: int = 1) -> Artist: def fetch_artist(self, source: Source, stop_at_level: int = 1) -> Artist:
print("fuck you")
print(source)
return Artist() return Artist()

View File

@ -1 +1 @@
from .config import config, read_config, write_config from .old_config import config, read_config, write_config

View File

@ -0,0 +1,17 @@
from dynaconf import Dynaconf
from .path_manager import LOCATIONS
"""
https://www.dynaconf.com/settings_files/
This file is there to load the settings.
How I will structure this programm exactly is in the stars.
The concept is that I package a config file, with this programm, and then load it.
Then I check if there is a config file at the LOCATIONS.CONFIG_FILE, and if yes they get merged
"""
settings = Dynaconf(
settings_files=[str(LOCATIONS.CONFIG_FILE)],
)

View File

@ -1,10 +1,10 @@
from .logging import LOGGING_SECTION from .sections.logging import LOGGING_SECTION
from .audio import AUDIO_SECTION from .sections.audio import AUDIO_SECTION
from .connection import CONNECTION_SECTION from .sections.connection import CONNECTION_SECTION
from .misc import MISC_SECTION from .sections.misc import MISC_SECTION
from .paths import PATHS_SECTION from .sections.paths import PATHS_SECTION
from .paths import LOCATIONS from .sections.paths import LOCATIONS
from .config import Config from .config import Config

View File

@ -0,0 +1,60 @@
import re
from ...exception.config import SettingValueError
from ..utils import comment
class Description:
def __init__(self, string: str) -> None:
self.string = string
@property
def config_string(self) -> str:
return comment(self.string)
class Attribute:
pattern: str = r'^.*a$'
rule: str = "This is a default string, it has no rule."
string_value: str = ""
def __init__(self, name: str, description: str, pattern: str = None, rule: str = None) -> None:
if pattern is not None:
self.pattern = pattern
if rule is not None:
self.rule = rule
self.name = name
self.description = description
def validate(self, input_string: str) -> bool:
return re.match(self.REGEX, input_string) is None
def output_parse(self):
return self.string_value.strip()
def input_parse(self, input_string: str) -> str:
match_result = re.match(self.pattern, input_string)
if match_result is None:
raise SettingValueError(
setting_name=self.name,
setting_value=input_string,
rule=self.rule
)
return match_result.string
@property
def value(self) -> str:
raise NotImplementedError()
@property
def config_string(self) -> str:
return NotImplementedError()
attr = Attribute(name="hello world", description="fuck you", value="defaulte")
attr.input_parse("fafda")
attr.input_parse("eeee")

View File

@ -0,0 +1,34 @@
from typing import List
from .attribute import Attribute
from ..utils import comment
class ListAttribute(Attribute):
def __init__(self, name: str, description: str, value: List[str], pattern: str = None, rule: str = None) -> None:
super().__init__(name, description, pattern, rule)
self.string_value_list = []
self.set_to_list(value)
def set_to_list(self, input_value_list: List[str]):
self.string_value_list = []
for input_value in input_value_list:
self.string_value_list.append(input_value)
def append(self, input_value: str):
self.string_value_list.append(self.input_parse(input_value))
@property
def value(self) -> str:
return [self.output_parse(element) for element in self.string_value_list]
@property
def config_string(self) -> str:
NEWLINE = "\n"
return f"[{self.name}.start]" \
f"{comment(self.description)}\n" \
f"{NEWLINE.join(self.name+'='+v for v in self.string_value_list)}\n" \
f"{comment('RULE: ' + self.rule)}\n" \
f"[{self.name}.end]"

View File

@ -0,0 +1,18 @@
from ..utils import comment
from .attribute import Attribute
class SingleAttribute(Attribute):
def __init__(self, name: str, description: str, value: str, pattern: str = None, rule: str = None) -> None:
super().__init__(name, description, pattern, rule)
self.string_value = self.input_parse(value)
@property
def value(self) -> str:
return self.output_parse(self.string_value)
@property
def config_string(self) -> str:
return f"{comment(self.description)}\n" \
f"{self.name}={self.value}\n" \
f"{comment('RULE: ' + self.rule)}" \

View File

@ -6,11 +6,11 @@ import os
from ..exception.config import SettingNotFound, SettingValueError from ..exception.config import SettingNotFound, SettingValueError
from ..path_manager import LOCATIONS from ..path_manager import LOCATIONS
from .base_classes import Description, Attribute, Section, EmptyLine, COMMENT_PREFIX from .base_classes import Description, Attribute, Section, EmptyLine, COMMENT_PREFIX
from .audio import AUDIO_SECTION from .sections.audio import AUDIO_SECTION
from .logging import LOGGING_SECTION from .sections.logging import LOGGING_SECTION
from .connection import CONNECTION_SECTION from .sections.connection import CONNECTION_SECTION
from .misc import MISC_SECTION from .sections.misc import MISC_SECTION
from .paths import PATHS_SECTION from .sections.paths import PATHS_SECTION
LOGGER = logging.getLogger("config") LOGGER = logging.getLogger("config")

View File

@ -1,6 +1,6 @@
import logging import logging
from .base_classes import ( from ..base_classes import (
SingleAttribute, SingleAttribute,
FloatAttribute, FloatAttribute,
StringAttribute, StringAttribute,
@ -10,8 +10,8 @@ from .base_classes import (
BoolAttribute, BoolAttribute,
ListAttribute ListAttribute
) )
from ...utils.enums.album import AlbumType from ...enums.album import AlbumType
from ...utils.exception.config import SettingValueError from ...exception.config import SettingValueError
# Only the formats with id3 metadata can be used # Only the formats with id3 metadata can be used
# https://www.audioranger.com/audio-formats.php # https://www.audioranger.com/audio-formats.php

View File

@ -1,9 +1,9 @@
from urllib.parse import urlparse, ParseResult from urllib.parse import urlparse, ParseResult
import re import re
from .base_classes import Section, FloatAttribute, IntAttribute, BoolAttribute, ListAttribute, StringAttribute from ..base_classes import Section, FloatAttribute, IntAttribute, BoolAttribute, ListAttribute, StringAttribute
from ..regex import URL_PATTERN from ...regex import URL_PATTERN
from ..exception.config import SettingValueError from ...exception.config import SettingValueError
class ProxAttribute(ListAttribute): class ProxAttribute(ListAttribute):

View File

@ -1,7 +1,7 @@
import logging import logging
from typing import Callable from typing import Callable
from .base_classes import SingleAttribute, StringAttribute, Section, Description, EmptyLine from ..base_classes import SingleAttribute, StringAttribute, Section, Description, EmptyLine
LOG_LEVELS = { LOG_LEVELS = {
"CRITICAL": 50, "CRITICAL": 50,

View File

@ -1,4 +1,4 @@
from .base_classes import Section, IntAttribute, ListAttribute, BoolAttribute from ..base_classes import Section, IntAttribute, ListAttribute, BoolAttribute
class MiscSection(Section): class MiscSection(Section):

View File

@ -1,7 +1,7 @@
from pathlib import Path from pathlib import Path
from ..path_manager import LOCATIONS from ...path_manager import LOCATIONS
from .base_classes import Section, StringAttribute, ListAttribute from ..base_classes import Section, StringAttribute, ListAttribute
class PathAttribute(StringAttribute): class PathAttribute(StringAttribute):

View File

@ -0,0 +1,4 @@
def comment(uncommented_string: str) -> str:
_fragments = uncommented_string.split("\n")
_fragments = ["# " + frag for frag in _fragments]
return "\n".join(_fragments)

View File

@ -19,7 +19,8 @@ class Locations:
self.CONFIG_DIRECTORY = get_config_directory(str(application_name)) self.CONFIG_DIRECTORY = get_config_directory(str(application_name))
self.CONFIG_DIRECTORY.mkdir(exist_ok=True, parents=True) self.CONFIG_DIRECTORY.mkdir(exist_ok=True, parents=True)
self.CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.conf") self.CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.toml")
self.LEGACY_CONFIG_FILE = Path(self.CONFIG_DIRECTORY, f"{application_name}.conf")
self.FFMPEG_BIN = Path(FFmpeg(enable_log=False).get_ffmpeg_bin()) self.FFMPEG_BIN = Path(FFmpeg(enable_log=False).get_ffmpeg_bin())

View File

@ -1,2 +1,3 @@
URL_PATTERN = 'https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+' URL_PATTERN = r"https?://(?:[-\w.]|(?:%[\da-fA-F]{2}))+"
INT_PATTERN = r"^\d*$"
FLOAT_PATTERN = r"^[\d|\,|\.]*$"

View File

@ -5,7 +5,7 @@ from typing import List, Tuple, Set, Dict
from urllib.parse import ParseResult from urllib.parse import ParseResult
from .path_manager import LOCATIONS from .path_manager import LOCATIONS
from .config import LOGGING_SECTION, AUDIO_SECTION, CONNECTION_SECTION, MISC_SECTION, PATHS_SECTION from .old_config import LOGGING_SECTION, AUDIO_SECTION, CONNECTION_SECTION, MISC_SECTION, PATHS_SECTION
from .enums.album import AlbumType from .enums.album import AlbumType
CONFIG_FILE = LOCATIONS.CONFIG_FILE CONFIG_FILE = LOCATIONS.CONFIG_FILE

View File

@ -33,3 +33,10 @@ def fit_to_file_system(string: str) -> str:
string = sanitize_filename(string) string = sanitize_filename(string)
return string return string
def comment(uncommented_string: str) -> str:
_fragments = uncommented_string.split("\n")
_fragments = ["# " + frag for frag in _fragments]
return "\n".join(_fragments)