itch-dl/itch_dl/config.py
Ryszard Knop 1cb57d0be4 Sync settings and CLI arguments
Most CLI arguments can be now saved into the configuration profile JSON.
This also cleans up passing around some, but not all args, into various
classes and methods, instead of just passing all of settings.
2025-01-31 22:35:37 +01:00

91 lines
2.6 KiB
Python

import os
import json
import logging
import platform
import argparse
from typing import Optional
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):
"""Available settings for itch-dl. Make sure all of them
have default values, as the config file may not exist."""
api_key: Optional[str] = None
user_agent: str = f"python-requests/{requests.__version__} itch-dl/{__version__}"
download_to: Optional[str] = None
mirror_web: bool = False
urls_only: bool = False
parallel: int = 1
filter_files_glob: Optional[str] = None
filter_files_regex: Optional[str] = None
verbose: bool = False
def create_and_get_config_path() -> str:
"""Returns the configuration directory in the appropriate
location for the current OS. The directory may not exist."""
system = platform.system()
if system == "Linux":
base_path = os.environ.get("XDG_CONFIG_HOME") or os.path.expanduser("~/.config/")
elif system == "Darwin":
base_path = os.path.expanduser("~/Library/Application Support/")
elif system == "Windows":
base_path = os.environ.get("APPDATA") or os.path.expanduser("~/AppData/Roaming/")
else:
raise NotImplementedError(f"Unknown platform: {system}")
return os.path.join(base_path, "itch-dl")
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."""
config_path = create_and_get_config_path()
config_file_path = os.path.join(config_path, "config.json")
profile_file_path = os.path.join(config_path, "profiles", profile or "")
if os.path.isfile(config_file_path):
logging.debug(f"Found config file: {config_file_path}")
with open(config_file_path) as f:
config_data = json.load(f)
else:
config_data = {}
if os.path.isfile(profile_file_path):
logging.debug(f"Found profile: {profile_file_path}")
with open(config_file_path) as f:
profile_data = json.load(f)
config_data.update(profile_data)
# All settings from the base file:
settings = Settings(**config_data)
# Apply overrides from CLI args:
for key in OVERRIDABLE_SETTINGS:
value = getattr(args, key)
if value:
setattr(settings, key, value)
return settings