diff --git a/pyproject.toml b/pyproject.toml index 859c49a87..b58a8723a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ test = [ lint = [ "black==24.4.2", "isort==5.13.2", - "pylint==2.13.5", + "pylint==3.1.0", ] docs = [ "sphinx~=7.0", diff --git a/src/ytdl_sub/config/plugin/plugin.py b/src/ytdl_sub/config/plugin/plugin.py index 33e98a1b3..e3c6d1d80 100644 --- a/src/ytdl_sub/config/plugin/plugin.py +++ b/src/ytdl_sub/config/plugin/plugin.py @@ -9,27 +9,27 @@ from typing import Type from ytdl_sub.config.overrides import Overrides +from ytdl_sub.config.validators.options import OptionsValidatorT from ytdl_sub.config.validators.options import ToggleableOptionsDictValidator -from ytdl_sub.config.validators.options import TOptionsValidator from ytdl_sub.entries.entry import Entry from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.script import ScriptUtils from ytdl_sub.ytdl_additions.enhanced_download_archive import DownloadArchiver from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -# pylint: disable=no-self-use,unused-argument +# pylint: disable=unused-argument -class BasePlugin(DownloadArchiver, Generic[TOptionsValidator], ABC): +class BasePlugin(DownloadArchiver, Generic[OptionsValidatorT], ABC): """ Shared code amongst all SourcePlugins (downloaders) and Plugins (post-download modification) """ - plugin_options_type: Type[TOptionsValidator] + plugin_options_type: Type[OptionsValidatorT] def __init__( self, - options: TOptionsValidator, + options: OptionsValidatorT, overrides: Overrides, enhanced_download_archive: EnhancedDownloadArchive, ): @@ -38,7 +38,7 @@ def __init__( self.overrides = overrides -class Plugin(BasePlugin[TOptionsValidator], Generic[TOptionsValidator], ABC): +class Plugin(BasePlugin[OptionsValidatorT], Generic[OptionsValidatorT], ABC): """ Class to define the new plugin functionality """ @@ -121,7 +121,7 @@ def post_process_subscription(self): """ -class SplitPlugin(Plugin[TOptionsValidator], Generic[TOptionsValidator], ABC): +class SplitPlugin(Plugin[OptionsValidatorT], Generic[OptionsValidatorT], ABC): """ Plugin that splits entries into zero or more entries """ diff --git a/src/ytdl_sub/config/plugin/preset_plugins.py b/src/ytdl_sub/config/plugin/preset_plugins.py index 2a86af6ad..7eda8a9d5 100644 --- a/src/ytdl_sub/config/plugin/preset_plugins.py +++ b/src/ytdl_sub/config/plugin/preset_plugins.py @@ -5,7 +5,7 @@ from ytdl_sub.config.plugin.plugin import Plugin from ytdl_sub.config.validators.options import OptionsValidator -from ytdl_sub.config.validators.options import TOptionsValidator +from ytdl_sub.config.validators.options import OptionsValidatorT class PresetPlugins: @@ -29,7 +29,7 @@ def zipped(self) -> List[Tuple[Type[Plugin], OptionsValidator]]: """ return list(zip(self.plugin_types, self.plugin_options)) - def get(self, plugin_type: Type[TOptionsValidator]) -> Optional[TOptionsValidator]: + def get(self, plugin_type: Type[OptionsValidatorT]) -> Optional[OptionsValidatorT]: """ Parameters ---------- diff --git a/src/ytdl_sub/config/validators/options.py b/src/ytdl_sub/config/validators/options.py index 324b39e1b..76b6d3adf 100644 --- a/src/ytdl_sub/config/validators/options.py +++ b/src/ytdl_sub/config/validators/options.py @@ -9,7 +9,6 @@ from ytdl_sub.validators.string_formatter_validators import OverridesBooleanFormatterValidator from ytdl_sub.validators.validators import Validator -# pylint: disable=no-self-use # pylint: disable=unused-argument @@ -53,7 +52,7 @@ def added_variables( return {} -TOptionsValidator = TypeVar("TOptionsValidator", bound=OptionsValidator) +OptionsValidatorT = TypeVar("OptionsValidatorT", bound=OptionsValidator) class OptionsDictValidator(StrictDictValidator, OptionsValidator, ABC): diff --git a/src/ytdl_sub/downloaders/source_plugin.py b/src/ytdl_sub/downloaders/source_plugin.py index f5357fa58..70127c636 100644 --- a/src/ytdl_sub/downloaders/source_plugin.py +++ b/src/ytdl_sub/downloaders/source_plugin.py @@ -11,13 +11,13 @@ from ytdl_sub.config.overrides import Overrides from ytdl_sub.config.plugin.plugin import BasePlugin from ytdl_sub.config.plugin.plugin import Plugin -from ytdl_sub.config.validators.options import TOptionsValidator +from ytdl_sub.config.validators.options import OptionsValidatorT from ytdl_sub.downloaders.ytdl_options_builder import YTDLOptionsBuilder from ytdl_sub.entries.entry import Entry from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive -class SourcePluginExtension(Plugin[TOptionsValidator], Generic[TOptionsValidator], ABC): +class SourcePluginExtension(Plugin[OptionsValidatorT], Generic[OptionsValidatorT], ABC): """ Plugins that get added automatically by using a downloader. Downloader options are the plugin options. @@ -32,12 +32,12 @@ def ytdl_options(self) -> Optional[Dict]: return None -class SourcePlugin(BasePlugin[TOptionsValidator], Generic[TOptionsValidator], ABC): +class SourcePlugin(BasePlugin[OptionsValidatorT], Generic[OptionsValidatorT], ABC): plugin_extensions: List[Type[SourcePluginExtension]] = [] def __init__( self, - options: TOptionsValidator, + options: OptionsValidatorT, enhanced_download_archive: EnhancedDownloadArchive, download_ytdl_options: YTDLOptionsBuilder, metadata_ytdl_options: YTDLOptionsBuilder, diff --git a/src/ytdl_sub/downloaders/url/downloader.py b/src/ytdl_sub/downloaders/url/downloader.py index 2b8d92ca3..81f310a71 100644 --- a/src/ytdl_sub/downloaders/url/downloader.py +++ b/src/ytdl_sub/downloaders/url/downloader.py @@ -397,17 +397,15 @@ def _iterate_child_entries( def _iterate_parent_entry( self, parent: EntryParent, download_reversed: bool ) -> Iterator[Entry]: - for entry_child in self._iterate_child_entries( + yield from self._iterate_child_entries( entries=parent.entry_children(), download_reversed=download_reversed - ): - yield entry_child + ) # Recursion the parent's parent entries for parent_child in reversed(parent.parent_children()): - for entry_child in self._iterate_parent_entry( + yield from self._iterate_parent_entry( parent=parent_child, download_reversed=download_reversed - ): - yield entry_child + ) def _download_url_metadata( self, url: str, include_sibling_metadata: bool, ytdl_options_overrides: Dict @@ -449,15 +447,13 @@ def _iterate_entries( # Delete info json files afterwards so other collection URLs do not use them with self._separate_download_archives(clear_info_json_files=True): for parent in parents: - for entry_child in self._iterate_parent_entry( + yield from self._iterate_parent_entry( parent=parent, download_reversed=download_reversed - ): - yield entry_child + ) - for orphan in self._iterate_child_entries( + yield from self._iterate_child_entries( entries=orphans, download_reversed=download_reversed - ): - yield orphan + ) def _download_metadata(self, url: str, validator: UrlValidator) -> Iterable[Entry]: metadata_ytdl_options = self.metadata_ytdl_options( @@ -479,12 +475,11 @@ def _download_metadata(self, url: str, validator: UrlValidator) -> Iterable[Entr ) download_logger.info("Beginning downloads for %s", url) - for entry in self._iterate_entries( + yield from self._iterate_entries( parents=parents, orphans=orphan_entries, download_reversed=download_reversed, - ): - yield entry + ) def download_metadata(self) -> Iterable[Entry]: """The function to perform the download of all media entries""" diff --git a/src/ytdl_sub/entries/base_entry.py b/src/ytdl_sub/entries/base_entry.py index d863bc427..c83217744 100644 --- a/src/ytdl_sub/entries/base_entry.py +++ b/src/ytdl_sub/entries/base_entry.py @@ -16,7 +16,7 @@ v: VariableDefinitions = VARIABLES -TBaseEntry = TypeVar("TBaseEntry", bound="BaseEntry") +BaseEntryT = TypeVar("BaseEntryT", bound="BaseEntry") class BaseEntry(ABC): @@ -140,7 +140,7 @@ def get_download_info_json_path(self) -> str: return str(Path(self.working_directory()) / self.get_download_info_json_name()) @final - def to_type(self, entry_type: Type[TBaseEntry]) -> TBaseEntry: + def to_type(self, entry_type: Type[BaseEntryT]) -> BaseEntryT: """ Returns ------- @@ -149,7 +149,7 @@ def to_type(self, entry_type: Type[TBaseEntry]) -> TBaseEntry: return entry_type(entry_dict=self._kwargs, working_directory=self._working_directory) @classmethod - def is_entry_parent(cls, entry_dict: Dict | TBaseEntry): + def is_entry_parent(cls, entry_dict: Dict | BaseEntryT): """ Returns ------- @@ -164,7 +164,7 @@ def is_entry_parent(cls, entry_dict: Dict | TBaseEntry): return entry_type == "playlist" @classmethod - def is_entry(cls, entry_dict: Dict | TBaseEntry): + def is_entry(cls, entry_dict: Dict | BaseEntryT): """ Returns ------- diff --git a/src/ytdl_sub/entries/entry_parent.py b/src/ytdl_sub/entries/entry_parent.py index 797c4d629..ae32bcc46 100644 --- a/src/ytdl_sub/entries/entry_parent.py +++ b/src/ytdl_sub/entries/entry_parent.py @@ -7,7 +7,7 @@ from urllib.parse import urlparse from ytdl_sub.entries.base_entry import BaseEntry -from ytdl_sub.entries.base_entry import TBaseEntry +from ytdl_sub.entries.base_entry import BaseEntryT from ytdl_sub.entries.entry import Entry from ytdl_sub.entries.script.variable_definitions import VARIABLES from ytdl_sub.entries.script.variable_definitions import VariableDefinitions @@ -21,7 +21,7 @@ class EntryParent(BaseEntry): @classmethod - def _sort_entries(cls, entries: List[TBaseEntry]) -> List[TBaseEntry]: + def _sort_entries(cls, entries: List[BaseEntryT]) -> List[BaseEntryT]: """Try sorting by playlist_id first, then fall back to uid""" return sorted( entries, diff --git a/src/ytdl_sub/entries/script/variable_definitions.py b/src/ytdl_sub/entries/script/variable_definitions.py index 4fc9e29e7..5526780a8 100644 --- a/src/ytdl_sub/entries/script/variable_definitions.py +++ b/src/ytdl_sub/entries/script/variable_definitions.py @@ -21,6 +21,7 @@ # pylint: disable=no-member # pylint: disable=too-many-public-methods # pylint: disable=too-many-lines +# pylint: disable=method-cache-max-size-none class MetadataVariableDefinitions(ABC): diff --git a/src/ytdl_sub/entries/script/variable_types.py b/src/ytdl_sub/entries/script/variable_types.py index 214d8a7c9..f406baf64 100644 --- a/src/ytdl_sub/entries/script/variable_types.py +++ b/src/ytdl_sub/entries/script/variable_types.py @@ -17,8 +17,8 @@ PLAYLIST_METADATA_VARIABLE_NAME = "playlist_metadata" SOURCE_METADATA_VARIABLE_NAME = "source_metadata" -TMetadataVariable = TypeVar("TMetadataVariable", bound="MetadataVariable") -TVariable = TypeVar("TVariable", bound="Variable") +MetadataVariableT = TypeVar("MetadataVariableT", bound="MetadataVariable") +VariableT = TypeVar("VariableT", bound="Variable") def _get( @@ -26,9 +26,9 @@ def _get( metadata_variable_name: str, metadata_key: str, variable_name: Optional[str], - default: Optional[TVariable | str | int | Dict | List], - as_type: Type[TMetadataVariable], -) -> TMetadataVariable: + default: Optional[VariableT | str | int | Dict | List], + as_type: Type[MetadataVariableT], +) -> MetadataVariableT: if default is None: # TODO: assert with good error message if key DNE out = f"%map_get({metadata_variable_name}, '{metadata_key}')" diff --git a/src/ytdl_sub/script/parser.py b/src/ytdl_sub/script/parser.py index a6109f4de..c6a781369 100644 --- a/src/ytdl_sub/script/parser.py +++ b/src/ytdl_sub/script/parser.py @@ -247,7 +247,7 @@ def _parse_numeric(self) -> Integer | Float: if self._read(increment_pos=False) == "-": numeric_string += "-" self._pos += 1 - if has_decimal := (self._read(increment_pos=False) == "."): + if has_decimal := self._read(increment_pos=False) == ".": numeric_string += "." self._pos += 1 @@ -504,7 +504,9 @@ def _parse_map(self) -> UnresolvedMap: output[key] = value_args[0] key = None else: - raise UNREACHABLE + break + + raise UNREACHABLE def _parse_main_loop(self, ch: str) -> bool: if ch == "\\" and self._read(increment_pos=False) in {"{", "}"}: diff --git a/src/ytdl_sub/script/utils/exception_formatters.py b/src/ytdl_sub/script/utils/exception_formatters.py index 6e14354e5..b2cab76d1 100644 --- a/src/ytdl_sub/script/utils/exception_formatters.py +++ b/src/ytdl_sub/script/utils/exception_formatters.py @@ -8,11 +8,11 @@ from ytdl_sub.script.utils.type_checking import FunctionSpec from ytdl_sub.script.utils.type_checking import is_union -TUserException = TypeVar("TUserException", bound=UserException) +UserExceptionT = TypeVar("UserExceptionT", bound=UserException) class ParserExceptionFormatter: - def __init__(self, text: str, start: int, end: int, exception: TUserException): + def __init__(self, text: str, start: int, end: int, exception: UserExceptionT): self._text = text self._start = start self._end = end @@ -78,7 +78,7 @@ def _exception_text_lines(self, border_lines: int = 0) -> str: return "\n" + "\n".join(to_return) - def highlight(self) -> TUserException: + def highlight(self) -> UserExceptionT: """ Returns ------- diff --git a/src/ytdl_sub/script/utils/type_checking.py b/src/ytdl_sub/script/utils/type_checking.py index 2170c3e04..4fa22ffc2 100644 --- a/src/ytdl_sub/script/utils/type_checking.py +++ b/src/ytdl_sub/script/utils/type_checking.py @@ -23,7 +23,7 @@ from ytdl_sub.script.types.variable import Variable from ytdl_sub.script.utils.exceptions import UNREACHABLE -TLambda = TypeVar("TLambda", bound=Lambda) +LambdaT = TypeVar("LambdaT", bound=Lambda) def is_union(arg_type: Type) -> bool: @@ -212,7 +212,7 @@ def is_lambda_function(self) -> Optional[Type[Lambda | LambdaTwo | LambdaThree]] return None @property - def is_lambda_like(self) -> Optional[Type[TLambda]]: + def is_lambda_like(self) -> Optional[Type[LambdaT]]: """ Returns ------- diff --git a/src/ytdl_sub/subscriptions/subscription_download.py b/src/ytdl_sub/subscriptions/subscription_download.py index b017d0056..1655a6333 100644 --- a/src/ytdl_sub/subscriptions/subscription_download.py +++ b/src/ytdl_sub/subscriptions/subscription_download.py @@ -126,8 +126,8 @@ def _prepare_working_directory(self): except Exception as exc: self._delete_working_directory(is_error=True) raise exc - else: - self._delete_working_directory() + + self._delete_working_directory() @contextlib.contextmanager def _maintain_archive_file(self): diff --git a/src/ytdl_sub/validators/string_formatter_validators.py b/src/ytdl_sub/validators/string_formatter_validators.py index c561e47e8..15e76e706 100644 --- a/src/ytdl_sub/validators/string_formatter_validators.py +++ b/src/ytdl_sub/validators/string_formatter_validators.py @@ -63,8 +63,6 @@ def format_string(self) -> str: """ return self._value - # pylint: disable=no-self-use - def post_process(self, resolved: str) -> str: """ Returns @@ -73,8 +71,6 @@ def post_process(self, resolved: str) -> str: """ return resolved - # pylint: enable=no-self-use - # pylint: disable=line-too-long class OverridesStringFormatterValidator(StringFormatterValidator): diff --git a/src/ytdl_sub/validators/validators.py b/src/ytdl_sub/validators/validators.py index 5bd4dbaae..fbb13c957 100644 --- a/src/ytdl_sub/validators/validators.py +++ b/src/ytdl_sub/validators/validators.py @@ -169,6 +169,7 @@ class ListValidator(Validator, ABC, Generic[ValidatorT]): Validates a list of objects to validate """ + # pylint: disable=used-before-assignment _expected_value_type = list _expected_value_type_name = "list"