# BackupApp/backup_app/config/settings.py import json import os from pathlib import Path from typing import Dict, Any, List # --- Constants --- CONFIG_FILE_NAME: str = "backup_config.json" # Determine the script directory to locate the config file, similar to original script # If this script is run as part of a frozen application (e.g., PyInstaller), # sys.executable or sys._MEIPASS might be needed. For development, __file__ is fine. # Assuming the config file stays alongside the executable or main script module. try: # This will point to .../BackupApp/backup_app/config/ # We want the config file to be in the root directory of the app (BackupApp/) # or where the executable is. For now, let's assume it's one level up from the package dir. # A common practice for user-specific config is Path.home() or an app data dir. # The original script placed it in the same directory as backupApp.py. # Let's keep that behavior: config file in the *project root* or executable dir. if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'): # Running in a PyInstaller bundle APPLICATION_ROOT_DIR = Path(sys.executable).parent else: # Running as a script, __file__ is .../backup_app/config/settings.py # package_root is .../backup_app/ # project_root is .../ PACKAGE_ROOT_DIR = Path(__file__).resolve().parent.parent APPLICATION_ROOT_DIR = PACKAGE_ROOT_DIR.parent # Assumes BackupApp/backup_app structure except NameError: # sys might not be imported if this is run standalone somehow without main APPLICATION_ROOT_DIR = Path(".") CONFIG_FILE_PATH: Path = APPLICATION_ROOT_DIR / CONFIG_FILE_NAME # --- Configuration Data Structure --- # It's good practice to define what the structure of your config looks like. # (This is more for documentation/type hinting, not strictly enforced without Pydantic etc.) class ProfileConfig: source_dir: str dest_dir: str exclusions: List[str] description: str class AppConfig: source_dir: str # Default source if no profile selected or for general use dest_dir: str # Default dest if no profile selected exclusions: List[str] # Default exclusions description: str # Default description profiles: Dict[str, ProfileConfig] # --- Configuration Management Functions --- def load_application_data() -> Dict[str, Any]: """ Loads the backup application data (profiles, last settings) from the JSON config file. Returns a dictionary with the configuration or default values if not found/error. """ default_config: Dict[str, Any] = { "source_dir": "", "dest_dir": "", "exclusions": [], "description": "", "profiles": {} } if CONFIG_FILE_PATH.exists(): try: with open(CONFIG_FILE_PATH, "r", encoding="utf-8") as f: data = json.load(f) # You might want to validate data against AppConfig structure here return data except json.JSONDecodeError: print(f"Warning: Configuration file {CONFIG_FILE_PATH} is corrupted. Using defaults.") return default_config except IOError: print(f"Warning: Could not read configuration file {CONFIG_FILE_PATH}. Using defaults.") return default_config return default_config def save_application_data(config_data: Dict[str, Any]) -> bool: """ Saves the backup application data to the JSON config file. Args: config_data (Dict[str, Any]): The configuration dictionary to save. Returns: bool: True if saving was successful, False otherwise. """ try: with open(CONFIG_FILE_PATH, "w", encoding="utf-8") as f: json.dump(config_data, f, indent=4) # indent for readability print(f"Info: Configuration saved to {CONFIG_FILE_PATH}") return True except IOError: print(f"Error: Could not write configuration file {CONFIG_FILE_PATH}.") return False