diff --git a/itch_dl/cli.py b/itch_dl/cli.py index 3df36c0..273d0d8 100644 --- a/itch_dl/cli.py +++ b/itch_dl/cli.py @@ -22,7 +22,7 @@ def parse_args() -> argparse.Namespace: help="configuration profile to load") # These args must match config.py -> Settings class. Make sure all defaults here - # evaluate to False, or apply_args_on_settings will override profile settings. + # evaluate to False, or load_config will override profile settings. parser.add_argument("--api-key", metavar="key", default=None, help="itch.io API key - https://itch.io/user/settings/api-keys") parser.add_argument("--user-agent", metavar="agent", default=None, diff --git a/itch_dl/config.py b/itch_dl/config.py index d8ec1af..1f0df61 100644 --- a/itch_dl/config.py +++ b/itch_dl/config.py @@ -3,27 +3,16 @@ import json import logging import platform import argparse -from typing import Optional +from dataclasses import dataclass, fields +from typing import Optional, Any, get_type_hints import requests -from pydantic import BaseModel from . import __version__ -OVERRIDABLE_SETTINGS = ( - "api_key", - "user_agent", - "download_to", - "mirror_web", - "urls_only", - "parallel", - "filter_files_glob", - "filter_files_regex", - "verbose", -) - -class Settings(BaseModel): +@dataclass +class Settings: """Available settings for itch-dl. Make sure all of them have default values, as the config file may not exist.""" @@ -57,6 +46,33 @@ def create_and_get_config_path() -> str: return os.path.join(base_path, "itch-dl") +def clean_config(config_data: dict[str, Any]) -> dict[str, Any]: + cleaned_config = {} + settings_invalid = False + type_hints = get_type_hints(Settings) + + # Complain about invalid types, if any: + for key, value in config_data.items(): + if not (expected_type := type_hints.get(key)): + logging.warning("Settings contain an unknown item, ignoring: '%s'", key) + continue + + if not isinstance(value, expected_type): + logging.fatal("Settings.%s has invalid type '%s', expected '%s'", key, type(value), expected_type) + + # Keep iterating to look up all the bad keys: + settings_invalid = True + continue + + cleaned_config[key] = value + + if settings_invalid: + logging.fatal("Settings invalid, bailing out!") + exit(1) + + return cleaned_config + + def load_config(args: argparse.Namespace, profile: Optional[str] = None) -> Settings: """Loads the configuration from the file system if it exists, the returns a Settings object.""" @@ -79,12 +95,12 @@ def load_config(args: argparse.Namespace, profile: Optional[str] = None) -> Sett config_data.update(profile_data) # All settings from the base file: - settings = Settings(**config_data) + settings = Settings(**clean_config(config_data)) - # Apply overrides from CLI args: - for key in OVERRIDABLE_SETTINGS: - value = getattr(args, key) - if value: + # Apply overrides from CLI args on each field in Settings: + for field in fields(Settings): + key = field.name + if value := getattr(args, key): setattr(settings, key, value) return settings diff --git a/pyproject.toml b/pyproject.toml index d5b4a30..ab01414 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -26,12 +26,11 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.8" -tqdm = "^4.67.0" +tqdm = "^4.67.1" urllib3 = "^1.26.20" requests = "^2.32.3" -beautifulsoup4 = "^4.12.3" -lxml = "^5.3.0" -pydantic = "^1.10.19" +beautifulsoup4 = "^4.13.3" +lxml = "^5.3.1" [tool.poetry.scripts] itch-dl = "itch_dl.cli:run"