Initial commit with Python .gitignore
This commit is contained in:
114
scientific_surfing/storage.py
Normal file
114
scientific_surfing/storage.py
Normal file
@ -0,0 +1,114 @@
|
||||
"""
|
||||
Cross-platform data storage for scientific-surfing.
|
||||
Handles configuration and subscription data storage using YAML format.
|
||||
"""
|
||||
|
||||
import os
|
||||
import platform
|
||||
import yaml
|
||||
from pathlib import Path
|
||||
from typing import Optional, Dict
|
||||
|
||||
from scientific_surfing.models import SubscriptionsData
|
||||
|
||||
|
||||
class StorageManager:
|
||||
"""Manages cross-platform data storage for subscriptions and configuration."""
|
||||
|
||||
def __init__(self):
|
||||
self.config_dir = self._get_config_dir()
|
||||
self.config_file = self.config_dir / "config.yaml"
|
||||
self.subscriptions_file = self.config_dir / "subscriptions.yaml"
|
||||
self._ensure_config_dir()
|
||||
|
||||
def _get_config_dir(self) -> Path:
|
||||
"""Get the appropriate configuration directory for the current platform."""
|
||||
system = platform.system().lower()
|
||||
|
||||
if system == "windows":
|
||||
# Windows: %APPDATA%/scientific_surfing
|
||||
app_data = os.environ.get("APPDATA")
|
||||
if app_data:
|
||||
return Path(app_data) / "scientific_surfing"
|
||||
else:
|
||||
return Path.home() / "AppData" / "Roaming" / "scientific_surfing"
|
||||
|
||||
elif system == "darwin":
|
||||
# macOS: ~/Library/Application Support/scientific_surfing
|
||||
return Path.home() / "Library" / "Application Support" / "scientific_surfing"
|
||||
|
||||
else:
|
||||
# Linux and other Unix-like systems: ~/.config/scientific_surfing
|
||||
xdg_config_home = os.environ.get("XDG_CONFIG_HOME")
|
||||
if xdg_config_home:
|
||||
return Path(xdg_config_home) / "scientific_surfing"
|
||||
else:
|
||||
return Path.home() / ".config" / "scientific_surfing"
|
||||
|
||||
def _ensure_config_dir(self) -> None:
|
||||
"""Ensure the configuration directory exists."""
|
||||
self.config_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
def load_subscriptions(self) -> SubscriptionsData:
|
||||
"""Load subscriptions from YAML file."""
|
||||
if not self.subscriptions_file.exists():
|
||||
return SubscriptionsData()
|
||||
|
||||
try:
|
||||
with open(self.subscriptions_file, 'r', encoding='utf-8') as f:
|
||||
data = yaml.safe_load(f)
|
||||
if isinstance(data, dict):
|
||||
return SubscriptionsData(**data)
|
||||
return SubscriptionsData()
|
||||
except (yaml.YAMLError, IOError) as e:
|
||||
print(f"Warning: Failed to load subscriptions: {e}")
|
||||
return SubscriptionsData()
|
||||
|
||||
def save_subscriptions(self, subscriptions: SubscriptionsData) -> bool:
|
||||
"""Save subscriptions to YAML file."""
|
||||
try:
|
||||
with open(self.subscriptions_file, 'w', encoding='utf-8') as f:
|
||||
# Convert Pydantic model to dict for YAML serialization
|
||||
data = subscriptions.dict()
|
||||
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
|
||||
return True
|
||||
except (yaml.YAMLError, IOError, ValueError) as e:
|
||||
print(f"Error: Failed to save subscriptions: {e}")
|
||||
return False
|
||||
|
||||
def load_config(self) -> dict:
|
||||
"""Load configuration from YAML file."""
|
||||
if not self.config_file.exists():
|
||||
return {}
|
||||
|
||||
try:
|
||||
with open(self.config_file, 'r', encoding='utf-8') as f:
|
||||
data = yaml.safe_load(f)
|
||||
if isinstance(data, dict):
|
||||
return data
|
||||
return {}
|
||||
except (yaml.YAMLError, IOError) as e:
|
||||
print(f"Warning: Failed to load config: {e}")
|
||||
return {}
|
||||
|
||||
def save_config(self, config: dict) -> bool:
|
||||
"""Save configuration to YAML file."""
|
||||
try:
|
||||
with open(self.config_file, 'w', encoding='utf-8') as f:
|
||||
# Convert Pydantic model to dict for YAML serialization
|
||||
data = config
|
||||
yaml.dump(data, f, default_flow_style=False, allow_unicode=True)
|
||||
return True
|
||||
except (yaml.YAMLError, IOError, ValueError) as e:
|
||||
print(f"Error: Failed to save config: {e}")
|
||||
return False
|
||||
|
||||
def get_storage_info(self) -> Dict[str, str]:
|
||||
"""Get information about the storage location."""
|
||||
return {
|
||||
'config_dir': str(self.config_dir),
|
||||
'config_file': str(self.config_file),
|
||||
'subscriptions_file': str(self.subscriptions_file),
|
||||
'platform': platform.system(),
|
||||
'exists': str(self.config_dir.exists())
|
||||
}
|
||||
Reference in New Issue
Block a user