cleaned up download

This commit is contained in:
Hellow2 2023-04-03 09:43:45 +02:00
parent 37854e30e0
commit bdf05adcb1
3 changed files with 146 additions and 130 deletions

View File

@ -72,7 +72,7 @@ def cli():
print("The given url couldn't be downloaded") print("The given url couldn't be downloaded")
return return
page = search.get_page_from_query(parsed) page = search._get_page_from_query(parsed)
if page is not None: if page is not None:
search.choose_page(page) search.choose_page(page)
return return

View File

@ -0,0 +1,100 @@
from collections import defaultdict
from typing import Tuple, List, Dict, Type
from . import page_attributes
from ..abstract import Page
from ...objects import Options, DatabaseObject, Source
class MultiPageOptions:
def __init__(
self,
max_displayed_options: int = 10,
option_digits: int = 3,
derived_from: DatabaseObject = None
) -> None:
self.max_displayed_options = max_displayed_options
self.option_digits: int = option_digits
self._length = 0
self._current_option_dict: Dict[Type[Page], Options] = defaultdict(lambda: Options())
self._derive_from = derived_from
def __getitem__(self, key: Type[Page]):
return self._current_option_dict[key]
def __setitem__(self, key: Type[Page], value: Options):
self._current_option_dict[key] = value
self._length = 0
for key in self._current_option_dict:
self._length += 1
def __len__(self) -> int:
return self._length
def get_page_str(self, page: Type[Page]) -> str:
page_name_fill = "-"
max_page_len = 21
return f"({page_attributes.PAGE_NAME_MAP[page]}) ------------------------{page.__name__:{page_name_fill}<{max_page_len}}------------"
def string_from_all_pages(self) -> str:
if self._length == 1:
for key in self._current_option_dict:
return self.string_from_single_page(key)
lines: List[str] = []
j = 0
for page, options in self._current_option_dict.items():
lines.append(self.get_page_str(page))
i = -1
option_obj: DatabaseObject
for i, option_obj in enumerate(options):
if i >= self.max_displayed_options:
lines.append("...")
break
lines.append(f"{j + i:0{self.option_digits}} {option_obj.option_string}")
j += i + 1
return "\n".join(lines)
def choose_from_all_pages(self, index: int) -> Tuple[DatabaseObject, Type[Page]]:
if self._length == 1:
for key in self._current_option_dict:
return self.choose_from_single_page(key, index), key
sum_of_length = 0
for page, options in self._current_option_dict.items():
option_len = min((len(options), self.max_displayed_options))
index_of_list = index - sum_of_length
if index_of_list < option_len:
return options[index_of_list], page
sum_of_length += option_len
raise IndexError("index is out of range")
def string_from_single_page(self, page: Type[Page]) -> str:
lines: List[str] = [self.get_page_str(page)]
option_obj: DatabaseObject
for i, option_obj in enumerate(self._current_option_dict[page]):
lines.append(f"{i:0{self.option_digits}} {option_obj.option_string}")
return "\n".join(lines)
def choose_from_single_page(self, page: Type[Page], index: int) -> DatabaseObject:
return self._current_option_dict[page][index]
def __repr__(self) -> str:
return self.string_from_all_pages()

View File

@ -3,117 +3,10 @@ from typing import Tuple, List, Set, Dict, Type, Union, Optional
from . import page_attributes from . import page_attributes
from .download import Download from .download import Download
from .multiple_options import MultiPageOptions
from ..abstract import Page from ..abstract import Page
from ...objects import Options, DatabaseObject, Source from ...objects import Options, DatabaseObject, Source
from ...utils.shared import DOWNLOAD_LOGGER as LOGGER
class MultiPageOptions:
def __init__(
self,
max_displayed_options: int = 10,
option_digits: int = 3,
database_object: DatabaseObject = None,
page: Type[Page] = None
) -> None:
self.max_displayed_options = max_displayed_options
self.option_digits: int = option_digits
self._length = 0
self._current_option_dict: Dict[Type[Page], Options] = defaultdict(lambda: Options())
self.database_object = database_object
self.page = page
if database_object is not None and page is not None:
self[page] = database_object.options
def __getitem__(self, key: Type[Page]):
return self._current_option_dict[key]
def __setitem__(self, key: Type[Page], value: Options):
self._current_option_dict[key] = value
self._length = 0
for key in self._current_option_dict:
self._length += 1
def __len__(self) -> int:
return self._length
def get_page_str(self, page: Type[Page]) -> str:
page_name_fill = "-"
max_page_len = 21
return f"({page_attributes.PAGE_NAME_MAP[page]}) ------------------------{page.__name__:{page_name_fill}<{max_page_len}}------------"
def string_from_all_pages(self) -> str:
if self._length == 1:
for key in self._current_option_dict:
return self.string_from_single_page(key)
lines: List[str] = []
j = 0
for page, options in self._current_option_dict.items():
lines.append(self.get_page_str(page))
i = -1
option_obj: DatabaseObject
for i, option_obj in enumerate(options):
if i >= self.max_displayed_options:
lines.append("...")
break
lines.append(f"{j + i:0{self.option_digits}} {option_obj.option_string}")
j += i + 1
return "\n".join(lines)
def choose_from_all_pages(self, index: int) -> Tuple[DatabaseObject, Type[Page]]:
if self._length == 1:
for key in self._current_option_dict:
return self.choose_from_single_page(key, index), key
sum_of_length = 0
for page, options in self._current_option_dict.items():
option_len = min((len(options), self.max_displayed_options))
index_of_list = index - sum_of_length
if index_of_list < option_len:
return options[index_of_list], page
sum_of_length += option_len
raise IndexError("index is out of range")
def string_from_single_page(self, page: Type[Page]) -> str:
lines: List[str] = [self.get_page_str(page)]
option_obj: DatabaseObject
for i, option_obj in enumerate(self._current_option_dict[page]):
lines.append(f"{i:0{self.option_digits}} {option_obj.option_string}")
return "\n".join(lines)
def choose_from_single_page(self, page: Type[Page], index: int) -> DatabaseObject:
return self._current_option_dict[page][index]
def __repr__(self) -> str:
return self.string_from_all_pages()
def download(self) -> bool:
if self._length != 1:
return False
if self.database_object is None or self.page is None:
return False
self.page.download(self.database_object)
return True
class Search(Download): class Search(Download):
@ -141,32 +34,23 @@ class Search(Download):
def __repr__(self): def __repr__(self):
return self._current_option.__repr__() return self._current_option.__repr__()
@property
def next_options(self) -> MultiPageOptions:
mpo = MultiPageOptions(
max_displayed_options=self.max_displayed_options,
option_digits=self.option_digits
)
self._option_history.append(mpo)
self._current_option = mpo
return mpo
def next_options_from_music_obj(self, database_obj: DatabaseObject, page: Type[Page]) -> MultiPageOptions: def next_options(self, derive_from: DatabaseObject = None) -> MultiPageOptions:
mpo = MultiPageOptions( mpo = MultiPageOptions(
max_displayed_options=self.max_displayed_options, max_displayed_options=self.max_displayed_options,
option_digits=self.option_digits, option_digits=self.option_digits,
database_object=database_obj, derived_from=derive_from
page=page
) )
self._option_history.append(mpo) self._option_history.append(mpo)
self._current_option = mpo self._current_option = mpo
return mpo return mpo
@property
def _previous_options(self) -> MultiPageOptions: def _previous_options(self) -> MultiPageOptions:
self._option_history.pop() self._option_history.pop()
self._current_option = self._option_history[-1] self._current_option = self._option_history[-1]
return self._option_history[-1] return self._option_history[-1]
def search(self, query: str): def search(self, query: str):
@ -177,40 +61,62 @@ class Search(Download):
the letter behind it defines the *type* of parameter, the letter behind it defines the *type* of parameter,
followed by a space "#a Psychonaut 4 #r Tired, Numb and #t Drop by Drop" followed by a space "#a Psychonaut 4 #r Tired, Numb and #t Drop by Drop"
if no # is in the query it gets treated as "unspecified query" if no # is in the query it gets treated as "unspecified query"
doesn't set derived_from thus,
can't download right after
""" """
for page in self.pages: for page in self.pages:
self._current_option[page] = page.search_by_query(query=query) self._current_option[page] = page.search_by_query(query=query)
def choose_page(self, page: Type[Page]): def choose_page(self, page: Type[Page]):
"""
doesn't set derived_from thus,
can't download right after
"""
if page not in page_attributes.ALL_PAGES: if page not in page_attributes.ALL_PAGES:
raise ValueError(f"Page \"{page.__name__}\" does not exist in page_attributes.ALL_PAGES") raise ValueError(f"Page \"{page.__name__}\" does not exist in page_attributes.ALL_PAGES")
prev_mpo = self._current_option prev_mpo = self._current_option
mpo = self.next_options mpo = self.next_options()
mpo[page] = prev_mpo[page] mpo[page] = prev_mpo[page]
def get_page_from_query(self, query: str) -> Optional[Type[Page]]: def _get_page_from_query(self, query: str) -> Optional[Type[Page]]:
"""
query can be for example:
"a" or "EncyclopaediaMetallum" to choose a page
"""
page = page_attributes.NAME_PAGE_MAP.get(query.lower().strip()) page = page_attributes.NAME_PAGE_MAP.get(query.lower().strip())
if page in self.pages: if page in self.pages:
return page return page
def _get_page_from_source(self, source: Source) -> Optional[Type[Page]]:
return page_attributes.SOURCE_PAGE_MAP.get(source.page_enum)
def choose_index(self, index: int): def choose_index(self, index: int):
db_object, page = self._current_option.choose_from_all_pages(index=index) db_object, page = self._current_option.choose_from_all_pages(index=index)
music_object = self.fetch_details(db_object) music_object = self.fetch_details(db_object)
mpo = self.next_options_from_music_obj(music_object, page) mpo = self.next_options_from_music_obj(music_object, page)
mpo[page] = music_object.options
def goto_previous(self): def goto_previous(self):
try: try:
self._current_option = self._previous_options self._previous_options()
except IndexError: except IndexError:
pass pass
def search_url(self, url: str) -> bool: def search_url(self, url: str) -> bool:
"""
sets derived_from, thus
can download directly after
"""
source = Source.match_url(url=url) source = Source.match_url(url=url)
if source is None: if source is None:
return False return False
@ -220,10 +126,20 @@ class Search(Download):
return False return False
page = page_attributes.SOURCE_PAGE_MAP[source.page_enum] page = page_attributes.SOURCE_PAGE_MAP[source.page_enum]
mpo = self.next_options mpo = self.next_options(derive_from=new_object)
mpo[page] = new_object.options mpo[page] = new_object.options
return True return True
def download_chosen(self) -> bool: def download_chosen(self) -> bool:
return self._current_option.download() if self._current_option._derive_from is None:
LOGGER.warning(f"can't download from an non choosen stuff")
return False
source: Source
for source in self._current_option._derive_from.source_collection:
page = self._get_page_from_source(source=source)
if page in self.audio_pages:
return page.download(music_object=self._current_option._derive_from)