From b862c20a66f241933c037a9268f3d21c690f0f42 Mon Sep 17 00:00:00 2001 From: vagabondHustler Date: Wed, 15 May 2024 03:54:15 +0200 Subject: [PATCH] Refactor update type hints - Added generic `DataClass` class for type hinting --- src/subsearch/core.py | 16 ++++++---------- src/subsearch/globals/__init__.py | 4 ++-- src/subsearch/globals/_logging.py | 15 +++++++-------- src/subsearch/globals/dataclasses.py | 8 ++++++-- src/subsearch/providers/yifysubtitles.py | 2 +- 5 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/subsearch/core.py b/src/subsearch/core.py index 8b734875..325f6c72 100644 --- a/src/subsearch/core.py +++ b/src/subsearch/core.py @@ -8,7 +8,7 @@ from subsearch.globals.dataclasses import Subtitle from subsearch.gui import screen_manager, system_tray from subsearch.gui.screens import download_manager -from subsearch.providers import opensubtitles, yifysubtitles +from subsearch.providers import opensubtitles, yifysubtitles from subsearch.utils import io_file_system, io_toml, string_parser @@ -102,24 +102,20 @@ def _create_threads(self, *tasks) -> None: task_thread.start() task_thread.join() - def start_search(self, provider, flag: str = "") -> None: + def _start_search(self, provider, flag: str) -> None: search_provider = provider(**self.search_kwargs) - if flag: - search_provider.start_search(flag=flag) - else: - search_provider.start_search() + search_provider.start_search(flag=flag) self.accepted_subtitles.extend(search_provider.accepted_subtitles) self.rejected_subtitles.extend(search_provider.rejected_subtitles) @decorators.call_func def opensubtitles(self) -> None: - self.start_search(provider=opensubtitles.OpenSubtitles, flag="hash") - self.start_search(provider=opensubtitles.OpenSubtitles, flag="site") - + self._start_search(provider=opensubtitles.OpenSubtitles, flag="hash") + self._start_search(provider=opensubtitles.OpenSubtitles, flag="site") @decorators.call_func def yifysubtitles(self) -> None: - self.start_search(provider=yifysubtitles.YifiSubtitles) + self._start_search(provider=yifysubtitles.YifiSubtitles, flag="site") @decorators.call_func def download_files(self) -> None: diff --git a/src/subsearch/globals/__init__.py b/src/subsearch/globals/__init__.py index a60c8fc7..d3006f16 100644 --- a/src/subsearch/globals/__init__.py +++ b/src/subsearch/globals/__init__.py @@ -1,3 +1,3 @@ -from ._logging import StdoutHandler +from ._logging import Logger -log = StdoutHandler() +log = Logger() diff --git a/src/subsearch/globals/_logging.py b/src/subsearch/globals/_logging.py index cec5e78f..783bc57f 100644 --- a/src/subsearch/globals/_logging.py +++ b/src/subsearch/globals/_logging.py @@ -3,17 +3,16 @@ import threading from datetime import datetime from pathlib import Path -from typing import Optional, TypeVar +from typing import Callable, Optional import picologging as logging from subsearch.globals import metaclasses from subsearch.globals.constants import APP_PATHS, FILE_PATHS +from subsearch.globals.dataclasses import GenericDataClass -DATACLASS = TypeVar("DATACLASS") - -def capture_call_info(func): +def capture_call_info(func) -> Callable[..., None]: def wrapper(*args, **kwargs): frame = inspect.currentframe().f_back # type: ignore current_time = datetime.now().time() @@ -36,7 +35,7 @@ class ANSIEscapeSequences: UNDERLINE = "\033[4m" -class Logger(metaclass=metaclasses.Singleton): +class _Logging(metaclass=metaclasses.Singleton): def __init__(self, *args, **kwargs) -> None: self.logger_name = kwargs.get("logger_name", "subsearch") if not APP_PATHS.appdata_subsearch.exists(): @@ -98,9 +97,9 @@ def _color_print(self, message: str, hex_color: str, style: str) -> None: print(f"{style_code}{color_code}{message}{self._ansi.RESET}") -class StdoutHandler(metaclass=metaclasses.Singleton): +class Logger(metaclass=metaclasses.Singleton): def __init__(self) -> None: - self._logger = Logger() + self._logger = _Logging() def __call__(self, message: str, **kwargs) -> None: self.log(message, **kwargs) @@ -153,7 +152,7 @@ def file_system_action(self, action_type: str, src: Path, dst: Optional[Path] = self(message, **kwargs) @capture_call_info - def dataclass(self, instance: DATACLASS, **kwargs) -> None: + def dataclass(self, instance: GenericDataClass, **kwargs) -> None: if not dataclasses.is_dataclass(instance): raise ValueError("Input is not a dataclass instance.") instance_name = f"--- [{instance.__class__.__name__}] ---" diff --git a/src/subsearch/globals/dataclasses.py b/src/subsearch/globals/dataclasses.py index cbf8d596..8a5a9449 100644 --- a/src/subsearch/globals/dataclasses.py +++ b/src/subsearch/globals/dataclasses.py @@ -1,6 +1,6 @@ -from dataclasses import dataclass +from dataclasses import Field, dataclass from pathlib import Path -from typing import Any +from typing import Any, ClassVar, Protocol @dataclass(order=True) @@ -112,3 +112,7 @@ class WindowsRegistryPaths: shell: str subsearch: str subsearch_command: str + + +class GenericDataClass(Protocol): + __dataclass_fields__: ClassVar[dict[str, Field[Any]]] diff --git a/src/subsearch/providers/yifysubtitles.py b/src/subsearch/providers/yifysubtitles.py index a1257e2a..72e01bb2 100644 --- a/src/subsearch/providers/yifysubtitles.py +++ b/src/subsearch/providers/yifysubtitles.py @@ -42,7 +42,7 @@ def __init__(self, **kwargs) -> None: YifySubtitlesScraper.__init__(self, **kwargs) self.provider_name = self.__class__.__name__.lower() - def start_search(self) -> list[Subtitle] | None: + def start_search(self, **kwargs) -> list[Subtitle] | None: subtitle_data = self.get_subtitle(self.url_yifysubtitles, self.current_language, self.hi_sub, self.non_hi_sub) if not subtitle_data: