[BACKEND] Error if arg after positional arg

This commit is contained in:
Jesse Bannon 2023-03-02 22:45:18 -08:00
parent 896a9e2073
commit 6eabd55043
4 changed files with 77 additions and 15 deletions

View file

@ -7,7 +7,7 @@ from typing import Tuple
from mergedeep import mergedeep
from ytdl_sub.cli.main_args_parser import MainArgs
from ytdl_sub.cli.main_args_parser import MainArguments
from ytdl_sub.config.config_validator import ConfigOptions
from ytdl_sub.utils.exceptions import InvalidDlArguments
@ -41,7 +41,7 @@ class DownloadArgsParser:
self._config_options = config_options
for arg in extra_arguments:
if arg in MainArgs.all():
if arg in MainArguments.all():
raise InvalidDlArguments(
f"'{arg}' is a ytdl-sub argument and must placed behind 'dl'"
)

View file

@ -5,9 +5,11 @@ from typing import List
from typing import Tuple
from ytdl_sub.cli.download_args_parser import DownloadArgsParser
from ytdl_sub.cli.main_args_parser import MainArguments
from ytdl_sub.cli.main_args_parser import parser
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.utils.exceptions import ValidationException
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.file_lock import working_directory_lock
from ytdl_sub.utils.logger import Logger
@ -35,11 +37,19 @@ def _download_subscriptions_from_yaml_files(
Returns
-------
List of (subscription, transaction_log)
Raises
------
Validation exception if main arg is specified as a subscription path
"""
subscription_paths: List[str] = args.subscription_paths
subscriptions: List[Subscription] = []
output: List[Tuple[Subscription, FileHandlerTransactionLog]] = []
# Make sure no main args are passed as a subscription path
if main_argument := MainArguments.get_argument_if_exists(subscription_paths) is not None:
raise ValidationException(f"The argument '{main_argument}' must be passed before 'sub'")
# Load all the subscriptions first to perform all validation before downloading
for path in subscription_paths:
subscriptions += Subscription.from_file_path(config=config, subscription_path=path)

View file

@ -1,23 +1,73 @@
import argparse
import dataclasses
from enum import Enum
from typing import List
from typing import Optional
from ytdl_sub.utils.logger import LoggerLevels
class MainArgs(Enum):
CONFIG = "--config"
DRY_RUN = "--dry-run"
LOG_LEVEL = "--log-level"
@dataclasses.dataclass
class MainArgument:
short: str
long: str
is_positional: bool = False
class MainArguments:
CONFIG = MainArgument(
short="-c",
long="--config",
)
DRY_RUN = MainArgument(
short="-d",
long="--dry-run",
is_positional=True,
)
LOG_LEVEL = MainArgument(
short="-l",
long="--log-level",
is_positional=True,
)
@classmethod
def all(cls) -> List[str]:
def all(cls) -> List[MainArgument]:
"""
Returns
-------
List of all args used in main CLI
List of MainArgument classes
"""
return list(map(lambda arg: arg.value, cls))
return [cls.CONFIG, cls.DRY_RUN, cls.LOG_LEVEL]
@classmethod
def all_arguments(cls) -> List[str]:
"""
Returns
-------
List of all string args that can be used in the CLI
"""
all_args = []
for arg in cls.all():
all_args.extend([arg.short, arg.long])
return all_args
@classmethod
def get_argument_if_exists(cls, input_args: List[str]) -> Optional[str]:
"""
Parameters
----------
input_args
List of arguments
Returns
-------
True if a Main argument is in the input arguments. False otherwise.
"""
for input_arg in input_args:
for main_arg in cls.all_arguments():
if input_arg == main_arg:
return input_arg
return None
###################################################################################################
@ -26,21 +76,23 @@ parser = argparse.ArgumentParser(
description="ytdl-sub: Automate download and adding metadata with YoutubeDL"
)
parser.add_argument(
"-c",
MainArgs.CONFIG.value,
MainArguments.CONFIG.short,
MainArguments.CONFIG.long,
metavar="CONFIGPATH",
type=str,
help="path to the config yaml, uses config.yaml if not provided",
default="config.yaml",
)
parser.add_argument(
MainArgs.DRY_RUN.value,
MainArguments.DRY_RUN.short,
MainArguments.DRY_RUN.long,
action="store_true",
help="preview what a download would output, "
"does not perform any video downloads or writes to output directories",
)
parser.add_argument(
MainArgs.LOG_LEVEL.value,
MainArguments.LOG_LEVEL.short,
MainArguments.LOG_LEVEL.long,
metavar="|".join(LoggerLevels.names()),
type=str,
help="level of logs to print to console, defaults to info",

View file

@ -7,7 +7,7 @@ from typing import Optional
import pytest
from ytdl_sub.cli.download_args_parser import DownloadArgsParser
from ytdl_sub.cli.main_args_parser import MainArgs
from ytdl_sub.cli.main_args_parser import MainArguments
from ytdl_sub.cli.main_args_parser import parser
from ytdl_sub.config.config_validator import ConfigOptions
from ytdl_sub.utils.exceptions import InvalidDlArguments
@ -151,7 +151,7 @@ class TestDownloadArgsParser:
extra_arguments=extra_args, config_options=config_options
).to_subscription_dict()
@pytest.mark.parametrize("main_argument", MainArgs.all())
@pytest.mark.parametrize("main_argument", MainArguments.all())
def test_error_uses_main_args(self, main_argument, config_options_generator):
config_options = config_options_generator()
extra_args = _get_extra_arguments(cmd_string=f"dl {main_argument}")