draft: improved searching one page only

This commit is contained in:
Hazel 2024-05-27 16:37:55 +02:00
parent a0e42fc6ee
commit 999299c32a
2 changed files with 54 additions and 33 deletions

View File

@ -1,7 +1,7 @@
import random import random
import re import re
from pathlib import Path from pathlib import Path
from typing import Dict, Generator, List, Set, Type from typing import Dict, Generator, List, Set, Type, Union
from .. import console from .. import console
from ..download import Downloader, Page, components from ..download import Downloader, Page, components
@ -112,8 +112,8 @@ class CliDownloader:
print() print()
def set_current_options(self, current_options: Generator[DatabaseObject, None, None]): def set_current_options(self, current_options: Union[Generator[DatabaseObject, None, None], components.Select]):
current_options = components.DataObjectSelect(current_options) current_options = current_options if isinstance(current_options, components.Select) else components.DataObjectSelect(current_options)
if main_settings["result_history"]: if main_settings["result_history"]:
self._result_history.append(current_options) self._result_history.append(current_options)
@ -221,12 +221,14 @@ class CliDownloader:
self.set_current_options(self.downloader.search(parsed_query)) self.set_current_options(self.downloader.search(parsed_query))
self.print_current_options() self.print_current_options()
def goto(self, data_object: DatabaseObject): def goto(self, data_object: Union[DatabaseObject, components.Select]):
page: Type[Page] page: Type[Page]
self.downloader.fetch_details(data_object, stop_at_level=1) if isinstance(data_object, components.Select):
self.set_current_options(data_object)
self.set_current_options(GoToResults(data_object.options, max_items_per_page=self.max_displayed_options)) else:
self.downloader.fetch_details(data_object, stop_at_level=1)
self.set_current_options(data_object.options)
self.print_current_options() self.print_current_options()
@ -293,24 +295,15 @@ class CliDownloader:
indices = [] indices = []
for possible_index in q.split(","): for possible_index in q.split(","):
possible_index = possible_index.strip()
if possible_index == "": if possible_index == "":
continue continue
if possible_index not in self.current_results:
raise MKInvalidInputException(message=f"The index \"{possible_index}\" is not in the current options.")
i = 0 yield self.current_results[possible_index]
try:
i = int(possible_index)
except ValueError:
raise MKInvalidInputException(message=f"The index \"{possible_index}\" is not a number.")
if i < 0 or i >= len(self.current_results): selected_objects = list(get_selected_objects(query))
raise MKInvalidInputException(message=f"The index \"{i}\" is not within the bounds of 0-{len(self.current_results) - 1}.")
indices.append(i)
return [self.current_results[i] for i in indices]
selected_objects = get_selected_objects(query)
if do_merge: if do_merge:
old_selected_objects = selected_objects old_selected_objects = selected_objects
@ -337,7 +330,7 @@ class CliDownloader:
if len(selected_objects) != 1: if len(selected_objects) != 1:
raise MKInvalidInputException(message="You can only go to one object at a time without merging.") raise MKInvalidInputException(message="You can only go to one object at a time without merging.")
self.goto(selected_objects[0]) self.goto(selected_objects[0].value)
return False return False
except MKInvalidInputException as e: except MKInvalidInputException as e:
output("\n" + e.message + "\n", color=BColors.FAIL) output("\n" + e.message + "\n", color=BColors.FAIL)

View File

@ -125,7 +125,11 @@ class Select:
return self._parse_option_key(key) in self._key_to_option return self._parse_option_key(key) in self._key_to_option
def __getitem__(self, key: Any) -> Option: def __getitem__(self, key: Any) -> Option:
return self._key_to_option[self._parse_option_key(key)] r = self._key_to_option[self._parse_option_key(key)]
# check if is callable
if callable(r.value):
r.value = r.value()
return r
def create_option(self, key: Any, **kwargs) -> Option: def create_option(self, key: Any, **kwargs) -> Option:
if not self.can_create_options: if not self.can_create_options:
@ -186,20 +190,36 @@ class GenreSelect(StringSelect):
super().__init__(sort=True, raw_options=(genre.name for genre in filter(self.is_valid_genre, main_settings["music_directory"].iterdir()))) super().__init__(sort=True, raw_options=(genre.name for genre in filter(self.is_valid_genre, main_settings["music_directory"].iterdir())))
class SourceTypeToOption(dict):
def __init__(self, callback):
super().__init__()
self.callback = callback
def __missing__(self, key):
self[key] = self.callback(key)
return self[key]
class DataObjectSelect(Select): class DataObjectSelect(Select):
def __init__(self, data_objects: Generator[DataObject]): def __init__(self, data_objects: Generator[DataObject]):
self._source_type_to_data_objects: Dict[SourceType, List[Option]] = defaultdict(list) self._source_type_to_data_objects: Dict[SourceType, List[Option]] = defaultdict(list)
self._source_type_to_option: Dict[SourceType, Option] = SourceTypeToOption(self.option_from_source_type)
self._data_object_index: int = 0 self._data_object_index: int = 0
self._source_type_index: int = 0 self._source_type_index: int = 0
super().__init__() super().__init__(
parse_option_key=lambda x: unify(str(x)),
)
self.extend(data_objects) self.extend(data_objects)
def option_from_data_object(self, data_object: DataObject) -> Option: def option_from_data_object(self, data_object: DataObject) -> Option:
index = self._data_object_index index = self._data_object_index
self._data_object_index += 1 self._data_object_index += 1
return Option( return Option(
value=data_object, value=data_object,
keys=[index, data_object.option_string, data_object.title_string], keys=[index, data_object.option_string, data_object.title_string],
@ -210,12 +230,16 @@ class DataObjectSelect(Select):
index = ALPHABET[self._source_type_index % len(ALPHABET)] index = ALPHABET[self._source_type_index % len(ALPHABET)]
self._source_type_index += 1 self._source_type_index += 1
return Option( o = Option(
value=self._source_type_to_data_objects[source_type], value=lambda: DataObjectSelect(self._source_type_to_data_objects[source_type]),
keys=[index, source_type], keys=[index, source_type],
text=f"{BColors.HEADER.value}({index}) --------------------------------{source_type.name:{'-'}<{21}}--------------------{BColors.ENDC.value}", text=f"{BColors.HEADER.value}({index}) --------------------------------{source_type.name:{'-'}<{21}}--------------------{BColors.ENDC.value}",
) )
super().append(o)
return o
def append(self, option: Union[Option, DataObject]): def append(self, option: Union[Option, DataObject]):
if isinstance(option, DataObject): if isinstance(option, DataObject):
data_object = option data_object = option
@ -224,15 +248,19 @@ class DataObjectSelect(Select):
data_object = option.value data_object = option.value
for source_type in data_object.source_collection.source_types(only_with_page=True): for source_type in data_object.source_collection.source_types(only_with_page=True):
if source_type not in self._source_type_to_data_objects:
st_option = self.option_from_source_type(source_type)
self._source_type_to_data_objects[source_type].append(st_option)
super().append(st_option)
self._source_type_to_data_objects[source_type].append(option) self._source_type_to_data_objects[source_type].append(option)
super().append(option) super().append(option)
def __iter__(self): def __iter__(self):
for options in self._source_type_to_data_objects.values(): source_types = list(sorted(self._source_type_to_data_objects.keys(), key=lambda x: x.name))
yield from options has_limit = len(source_types) > 1
for st in source_types:
if has_limit:
yield self._source_type_to_option[st]
limit = min(15, len(self._source_type_to_data_objects[st])) if has_limit else len(self._source_type_to_data_objects[st])
for i in range(limit):
yield self._source_type_to_data_objects[st][i]