diff --git a/src/ytdl_sub/main.py b/src/ytdl_sub/main.py index e1fa0e72..dc656cfa 100644 --- a/src/ytdl_sub/main.py +++ b/src/ytdl_sub/main.py @@ -17,8 +17,12 @@ def _download_subscriptions_from_yaml_files(config: ConfigFile, args: argparse.N """ Downloads all subscriptions from one or many subscription yaml files. - :param config: Configuration file - :param args: Arguments from argparse + Parameters + ---------- + config + Configuration file + args + Arguments from argparse """ preset_paths: List[str] = args.subscription_paths presets: List[Preset] = [] @@ -30,15 +34,23 @@ def _download_subscriptions_from_yaml_files(config: ConfigFile, args: argparse.N subscription = Subscription.from_preset(preset=preset, config=config) logger.info("Beginning subscription download for %s", subscription.name) - subscription.download() + subscription.download(dry_run=args.dry_run) -def _download_subscription_from_cli(config: ConfigFile, extra_args: List[str]) -> None: +def _download_subscription_from_cli( + config: ConfigFile, args: argparse.Namespace, extra_args: List[str] +) -> None: """ Downloads a one-off subscription using the CLI - :param config: Configuration file - :param extra_args: Extra arguments from argparse that contain dynamic subscription options + Parameters + ---------- + config + Configuration file + args + Arguments from argparse + extra_args + Extra arguments from argparse that contain dynamic subscription options """ dl_args_parser = DownloadArgsParser( extra_arguments=extra_args, config_options=config.config_options @@ -57,7 +69,7 @@ def _download_subscription_from_cli(config: ConfigFile, extra_args: List[str]) - config=config, ) - subscription.download() + subscription.download(dry_run=args.dry_run) def _main(): @@ -80,7 +92,7 @@ def _main(): # One-off download if args.subparser == "dl": - _download_subscription_from_cli(config=config, extra_args=extra_args) + _download_subscription_from_cli(config=config, args=args, extra_args=extra_args) logger.info("Download complete!") # Ran successfully, so we can delete the debug file diff --git a/src/ytdl_sub/plugins/plugin.py b/src/ytdl_sub/plugins/plugin.py index f28aa1b3..869c950a 100644 --- a/src/ytdl_sub/plugins/plugin.py +++ b/src/ytdl_sub/plugins/plugin.py @@ -7,6 +7,7 @@ from typing import final from ytdl_sub.config.preset_options import Overrides from ytdl_sub.entries.entry import Entry +from ytdl_sub.utils.file_handler import FileMetadata from ytdl_sub.utils.logger import Logger from ytdl_sub.validators.strict_dict_validator import StrictDictValidator from ytdl_sub.ytdl_additions.enhanced_download_archive import EnhancedDownloadArchive @@ -60,7 +61,7 @@ class Plugin(Generic[PluginOptionsT], ABC): file_name=file_name, output_file_name=file_name, entry=entry ) - def post_process_entry(self, entry: Entry): + def post_process_entry(self, entry: Entry) -> Optional[FileMetadata]: """ For each file downloaded, apply post processing to it. @@ -68,6 +69,10 @@ class Plugin(Generic[PluginOptionsT], ABC): ---------- entry: Entry to post process + + Returns + ------- + Optional file metadata for the entry media file. """ def post_process_subscription(self): diff --git a/src/ytdl_sub/utils/file_handler.py b/src/ytdl_sub/utils/file_handler.py index 5b07d654..1e83c208 100644 --- a/src/ytdl_sub/utils/file_handler.py +++ b/src/ytdl_sub/utils/file_handler.py @@ -1,10 +1,50 @@ import os from pathlib import Path from shutil import copyfile +from typing import Dict +from typing import List +from typing import Optional from typing import Set from typing import Union +class FileMetadata: + def __init__(self, metadata: Optional[List[str]] = None): + self.metadata: List[str] = metadata if metadata else [] + + def append(self, other: "FileMetadata") -> "FileMetadata": + self.metadata.extend(other.metadata) + return self + + +class FileHandlerTransactionLog: + """ + Tracks file 'transactions' performed by a FileHandler + """ + + def __init__(self): + self.files_created: Dict[str, FileMetadata] = {} + self.files_removed: Set[str] = set() + + def log_created_file( + self, file_name: str, file_metadata: Optional[FileMetadata] = None + ) -> "FileHandlerTransactionLog": + if not file_metadata: + file_metadata = FileMetadata() + + if file_name in self.files_created: + raise ValueError( + "Adding a file to the file handler transaction log that already exists" + ) + + self.files_created[file_name] = file_metadata + return self + + def log_removed_file(self, file_name: str) -> "FileHandlerTransactionLog": + self.files_removed.add(file_name) + return self + + class FileHandler: """ Performs and tracks all file moving/copying/deleting @@ -14,9 +54,7 @@ class FileHandler: self.dry_run = dry_run self.working_directory = working_directory self.output_directory = output_directory - - self.files_created: Set[str] = set() - self.files_deleted: Set[str] = set() + self._file_handler_transaction_log = FileHandlerTransactionLog() @classmethod def copy(cls, src_file_path: Union[str, Path], dst_file_path: Union[str, Path]): @@ -28,7 +66,7 @@ class FileHandler: os.remove(file_path) def copy_file_to_output_directory(self, file_name: str, output_file_name: str): - self.files_created.add(output_file_name) + self._file_handler_transaction_log.log_created_file(output_file_name) if not self.dry_run: output_file_path = Path(self.output_directory) / output_file_name @@ -43,6 +81,6 @@ class FileHandler: exists = os.path.isfile(file_path) if exists: - self.files_deleted.add(file_name) + self._file_handler_transaction_log.log_removed_file(file_name) if not self.dry_run: self.delete(file_path=file_path)