Change app folder to GitHub_Pulse
This commit is contained in:
@@ -0,0 +1,246 @@
|
||||
"""
|
||||
Configuration Manager
|
||||
Wrapper around SettingsManager for backward compatibility.
|
||||
Now uses config.json + keyring instead of .env files.
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
from typing import Dict, Any, Optional
|
||||
from pathlib import Path
|
||||
from .settings_manager import SettingsManager
|
||||
|
||||
|
||||
class ConfigManager:
|
||||
"""
|
||||
Manages application configuration using the new SettingsManager.
|
||||
|
||||
Provides backward compatibility with old .env-based code while
|
||||
using the modern config.json + keyring system underneath.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize with SettingsManager backend"""
|
||||
# Initialize the modern settings system
|
||||
self._settings = SettingsManager()
|
||||
|
||||
# Check if .env exists and offer migration
|
||||
env_path = Path('.env')
|
||||
if env_path.exists() and not Path('application/config.json').exists():
|
||||
print("\n" + "="*60)
|
||||
print("NOTICE: Legacy .env file detected!")
|
||||
print("="*60)
|
||||
print("Your app now uses a modern settings system with:")
|
||||
print(" ✓ Secure API key storage (Windows Credential Manager)")
|
||||
print(" ✓ Live settings updates (no restart needed)")
|
||||
print(" ✓ Better configuration management")
|
||||
print()
|
||||
print("Migrating settings from .env to new system...")
|
||||
print()
|
||||
|
||||
if self._settings.migrate_from_env(env_path):
|
||||
print("✓ Migration successful!")
|
||||
print(f" - Secrets → System keyring")
|
||||
print(f" - Settings → {self._settings.config_file}")
|
||||
print()
|
||||
print("Your .env file is kept as backup.")
|
||||
print("You can delete it once you verify everything works.")
|
||||
else:
|
||||
print("✗ Migration failed. Using .env as fallback.")
|
||||
print("="*60 + "\n")
|
||||
|
||||
# Load configuration
|
||||
self.config = self._settings.get_all()
|
||||
|
||||
# Auto-default GITHUB_TOKEN to GITHUB_PAT if needed
|
||||
self._apply_token_defaults()
|
||||
|
||||
# Show configuration status
|
||||
self._print_config_status()
|
||||
|
||||
def _apply_token_defaults(self):
|
||||
"""Auto-default GITHUB_TOKEN to GITHUB_PAT if GITHUB_TOKEN is empty"""
|
||||
github_token = self.config.get('GITHUB_TOKEN', '').strip() if self.config.get('GITHUB_TOKEN') else ''
|
||||
github_pat = self.config.get('GITHUB_PAT', '').strip() if self.config.get('GITHUB_PAT') else ''
|
||||
|
||||
if not github_token and github_pat:
|
||||
self.config['GITHUB_TOKEN'] = github_pat
|
||||
self._settings.set('GITHUB_TOKEN', github_pat, save=False)
|
||||
|
||||
def _print_config_status(self):
|
||||
"""Print configuration load status"""
|
||||
loaded_keys = []
|
||||
for key, value in self.config.items():
|
||||
if value and str(value).strip():
|
||||
# Don't show actual secret values
|
||||
if key in SettingsManager.SECRET_KEYS:
|
||||
loaded_keys.append(f"{key}: loaded")
|
||||
else:
|
||||
loaded_keys.append(f"{key}: loaded")
|
||||
|
||||
if loaded_keys:
|
||||
print(f"Configuration status: {', '.join(loaded_keys)}")
|
||||
else:
|
||||
print("No configuration values loaded - using defaults")
|
||||
|
||||
def load_configuration(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Load configuration from new system (config.json + keyring).
|
||||
|
||||
Returns:
|
||||
Dictionary of all settings
|
||||
"""
|
||||
self.config = self._settings.load()
|
||||
self._apply_token_defaults()
|
||||
return self.config
|
||||
|
||||
def save_configuration(self, config_values: Dict[str, Any]) -> bool:
|
||||
"""
|
||||
Save configuration using new system.
|
||||
|
||||
No restart required - changes apply immediately!
|
||||
|
||||
Args:
|
||||
config_values: Settings to save
|
||||
|
||||
Returns:
|
||||
True if successful
|
||||
"""
|
||||
# Save using new system
|
||||
success = self._settings.save(config_values)
|
||||
|
||||
if success:
|
||||
# Reload to get updated values
|
||||
self.config = self._settings.get_all()
|
||||
self._apply_token_defaults()
|
||||
print(f"Configuration saved to {self._settings.config_file}")
|
||||
print("Settings updated (no restart needed!)")
|
||||
else:
|
||||
print("Failed to save configuration")
|
||||
|
||||
return success
|
||||
|
||||
def get_config(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Get current configuration with automatic GITHUB_TOKEN defaulting.
|
||||
|
||||
Returns:
|
||||
Dictionary of all settings
|
||||
"""
|
||||
config = self.config.copy()
|
||||
|
||||
# Auto-default GITHUB_TOKEN to GITHUB_PAT if needed
|
||||
github_token = config.get('GITHUB_TOKEN', '').strip() if config.get('GITHUB_TOKEN') else ''
|
||||
github_pat = config.get('GITHUB_PAT', '').strip() if config.get('GITHUB_PAT') else ''
|
||||
|
||||
if not github_token and github_pat:
|
||||
config['GITHUB_TOKEN'] = github_pat
|
||||
|
||||
return config
|
||||
|
||||
def get_value(self, key: str, default: Any = None) -> Any:
|
||||
"""
|
||||
Get a specific configuration value.
|
||||
|
||||
Args:
|
||||
key: Setting key
|
||||
default: Default value if not found
|
||||
|
||||
Returns:
|
||||
Setting value or default
|
||||
"""
|
||||
return self._settings.get(key, default)
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""
|
||||
Get a specific configuration value (dictionary-like interface).
|
||||
|
||||
Args:
|
||||
key: Setting key
|
||||
default: Default value if not found
|
||||
|
||||
Returns:
|
||||
Setting value or default
|
||||
"""
|
||||
return self._settings.get(key, default)
|
||||
|
||||
def set_value(self, key: str, value: Any) -> None:
|
||||
"""
|
||||
Set a specific configuration value.
|
||||
|
||||
Args:
|
||||
key: Setting key
|
||||
value: New value
|
||||
"""
|
||||
self._settings.set(key, value)
|
||||
self.config[key] = value
|
||||
|
||||
def register_listener(self, callback):
|
||||
"""
|
||||
Register a callback for settings changes (live updates).
|
||||
|
||||
The callback will be called with (key, new_value) when a setting changes.
|
||||
|
||||
Args:
|
||||
callback: Function to call on settings change
|
||||
|
||||
Example:
|
||||
def on_settings_changed(key, value):
|
||||
if key == 'THEME_MODE':
|
||||
# Update theme immediately
|
||||
page.theme_mode = ft.ThemeMode.DARK if value == 'dark' else ft.ThemeMode.LIGHT
|
||||
page.update()
|
||||
|
||||
config_manager.register_listener(on_settings_changed)
|
||||
"""
|
||||
self._settings.register_listener(callback)
|
||||
|
||||
def unregister_listener(self, callback):
|
||||
"""
|
||||
Unregister a settings change callback.
|
||||
|
||||
Args:
|
||||
callback: Function to remove from listeners
|
||||
"""
|
||||
self._settings.unregister_listener(callback)
|
||||
|
||||
# Legacy methods for PR counter (unchanged)
|
||||
|
||||
def get_pr_counter_file(self) -> str:
|
||||
"""Get the path to the PR counter file"""
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
return os.path.join(script_dir, '..', '.pr_counter.json')
|
||||
|
||||
def load_pr_counter(self) -> Dict[str, int]:
|
||||
"""Load the PR counter from file"""
|
||||
counter_file = self.get_pr_counter_file()
|
||||
if os.path.exists(counter_file):
|
||||
try:
|
||||
with open(counter_file, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, FileNotFoundError):
|
||||
pass
|
||||
return {'count': 0}
|
||||
|
||||
def save_pr_counter(self, counter: Dict[str, int]) -> bool:
|
||||
"""Save the PR counter to file"""
|
||||
counter_file = self.get_pr_counter_file()
|
||||
try:
|
||||
with open(counter_file, 'w', encoding='utf-8') as f:
|
||||
json.dump(counter, f, indent=2)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error saving PR counter: {e}")
|
||||
return False
|
||||
|
||||
def increment_pr_counter(self) -> int:
|
||||
"""Increment and return the PR counter"""
|
||||
counter = self.load_pr_counter()
|
||||
counter['count'] = counter.get('count', 0) + 1
|
||||
self.save_pr_counter(counter)
|
||||
return counter['count']
|
||||
|
||||
def get_pr_counter(self) -> int:
|
||||
"""Get the current PR counter value"""
|
||||
counter = self.load_pr_counter()
|
||||
return counter.get('count', 0)
|
||||
Reference in New Issue
Block a user