# file_service.py import json import os from typing import List, Dict, Any from calendar_entry import CalendarEntry from config import EventConfig class FileService: """Centralized file operations with error handling""" @staticmethod def save_calendar_to_file(entries: List[CalendarEntry], filename: str) -> bool: """Save calendar entries to a JSON file""" try: # Ensure directory exists os.makedirs(os.path.dirname(filename) if os.path.dirname(filename) else '.', exist_ok=True) # Convert entries to dictionaries data = [entry.to_dict() for entry in entries] # Write to file with open(filename, 'w', encoding='utf-8') as f: json.dump(data, f, indent=4, ensure_ascii=False) return True except Exception as e: print(f"Error saving calendar to file {filename}: {e}") return False @staticmethod def load_calendar_from_file(filename: str) -> List[CalendarEntry]: """Load calendar entries from a JSON file""" try: if not os.path.exists(filename): print(f"File {filename} does not exist") return [] with open(filename, 'r', encoding='utf-8') as f: data = json.load(f) # Convert dictionaries to CalendarEntry objects entries = [] for entry_data in data: try: entry = CalendarEntry.from_dict(entry_data) entries.append(entry) except Exception as e: print(f"Error parsing entry: {e}") continue return entries except (FileNotFoundError, json.JSONDecodeError) as e: print(f"Error loading calendar from file {filename}: {e}") return [] except Exception as e: print(f"Unexpected error loading calendar from file {filename}: {e}") return [] @staticmethod def validate_file_extension(filename: str) -> bool: """Validate that file has correct extension""" if not filename: return False # Add extension if missing if not filename.endswith(EventConfig.DEFAULT_FILE_EXTENSION): filename += EventConfig.DEFAULT_FILE_EXTENSION return True @staticmethod def ensure_json_extension(filename: str) -> str: """Ensure filename has .json extension""" if not filename.endswith(EventConfig.DEFAULT_FILE_EXTENSION): return filename + EventConfig.DEFAULT_FILE_EXTENSION return filename @staticmethod def file_exists(filename: str) -> bool: """Check if file exists""" return os.path.exists(filename) @staticmethod def get_file_size(filename: str) -> int: """Get file size in bytes""" try: return os.path.getsize(filename) except OSError: return 0 @staticmethod def backup_file(filename: str) -> str: """Create a backup of the file""" if not os.path.exists(filename): return filename backup_filename = filename.replace('.json', '_backup.json') try: with open(filename, 'r', encoding='utf-8') as src: with open(backup_filename, 'w', encoding='utf-8') as dst: dst.write(src.read()) return backup_filename except Exception as e: print(f"Error creating backup: {e}") return filename