From 0008bf3acafb76353d5e4ea0b6ca62609859d7d9 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Fri, 15 Sep 2023 12:35:34 -0700 Subject: [PATCH] [FEATURE] More verbose error logs when using ytdl-sub commands (#717) Add a more informative error message when the config file is missing, and when no command is supplied (i.e. sub, dl, view) --- src/ytdl_sub/cli/main.py | 2 ++ src/ytdl_sub/config/config_file.py | 15 ++++++++++++++- src/ytdl_sub/utils/logger.py | 2 +- tests/unit/main/test_main.py | 31 ++++++++++++++++++++++++++++-- 4 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/ytdl_sub/cli/main.py b/src/ytdl_sub/cli/main.py index acb615ae..fbace307 100644 --- a/src/ytdl_sub/cli/main.py +++ b/src/ytdl_sub/cli/main.py @@ -341,6 +341,8 @@ def main() -> List[Tuple[Subscription, FileHandlerTransactionLog]]: transaction_logs.append( _view_url_from_cli(config=config, url=args.url, split_chapters=args.split_chapters) ) + else: + raise ValidationException("Must provide one of the commands: sub, dl, view") if not args.suppress_transaction_log: _output_transaction_log( diff --git a/src/ytdl_sub/config/config_file.py b/src/ytdl_sub/config/config_file.py index 6d6bcc66..b5981e51 100644 --- a/src/ytdl_sub/config/config_file.py +++ b/src/ytdl_sub/config/config_file.py @@ -4,6 +4,7 @@ from typing import Dict from ytdl_sub.config.config_validator import ConfigValidator from ytdl_sub.config.preset import Preset +from ytdl_sub.utils.exceptions import FileNotFoundException from ytdl_sub.utils.ffmpeg import FFMPEG from ytdl_sub.utils.yaml import load_yaml from ytdl_sub.validators.file_path_validators import FilePathValidatorMixin @@ -68,8 +69,20 @@ class ConfigFile(ConfigValidator): Returns ------- Config file validator + + Raises + ------ + FileNotFoundException + Not found """ - config_dict = load_yaml(file_path=config_path) + try: + config_dict = load_yaml(file_path=config_path) + except FileNotFoundException as exc: + raise FileNotFoundException( + f"The config file '{config_path}' could not be found. " + f"Did you set --config correctly?" + ) from exc + return ConfigFile.from_dict(config_dict) def as_dict(self) -> Dict[str, Any]: diff --git a/src/ytdl_sub/utils/logger.py b/src/ytdl_sub/utils/logger.py index 058c57f2..0b70082f 100644 --- a/src/ytdl_sub/utils/logger.py +++ b/src/ytdl_sub/utils/logger.py @@ -220,7 +220,7 @@ class Logger: # Log validation exceptions as-is if isinstance(exception, ValidationException): - logger.error(exception) + logger.error(str(exception)) # For other uncaught errors, log as bug: else: logger.exception("An uncaught error occurred:") diff --git a/tests/unit/main/test_main.py b/tests/unit/main/test_main.py index 368d2def..eea87a49 100644 --- a/tests/unit/main/test_main.py +++ b/tests/unit/main/test_main.py @@ -41,14 +41,14 @@ def test_main_success(mock_sys_exit): def test_main_validation_error(capsys, mock_sys_exit): - validation_exception = ValidationException("test") + validation_exception = ValidationException("test exc") with mock_sys_exit(expected_exit_code=1), patch( "src.ytdl_sub.main._main", side_effect=validation_exception ), patch.object(logging.Logger, "error") as mock_logger: main() assert mock_logger.call_count == 1 - assert mock_logger.call_args.args[0] == validation_exception + assert mock_logger.call_args.args[0] == "test exc" def test_main_uncaught_error(capsys, mock_sys_exit, expected_uncaught_error_message): @@ -80,3 +80,30 @@ def test_args_after_sub_work(mock_sys_exit): assert mock_sub.call_count == 1 assert mock_sub.call_args.kwargs["subscription_paths"] == ["subscriptions.yaml"] assert Logger._LOGGER_LEVEL == LoggerLevels.VERBOSE + + +def test_no_positional_arg_command(mock_sys_exit): + with mock_sys_exit(expected_exit_code=1), patch.object( + sys, + "argv", + ["ytdl-sub", "-c", "examples/tv_show_config.yaml", "--log-level", "verbose"], + ), patch.object(logging.Logger, "error") as mock_error: + main() + + assert mock_error.call_count == 1 + assert mock_error.call_args.args[0] == "Must provide one of the commands: sub, dl, view" + + +def test_bad_config_path(mock_sys_exit): + with mock_sys_exit(expected_exit_code=1), patch.object( + sys, + "argv", + ["ytdl-sub", "-c", "does_not_exist.yaml", "sub", "--log-level", "verbose"], + ), patch.object(logging.Logger, "error") as mock_error: + main() + + assert mock_error.call_count == 1 + assert mock_error.call_args.args[0] == ( + "The config file 'does_not_exist.yaml' could not be found. " + "Did you set --config correctly?" + )