Initial upload: Devtoolbelt v1.0.0 - unified CLI toolkit for developers
This commit is contained in:
144
devtoolbelt/config.py
Normal file
144
devtoolbelt/config.py
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
"""Configuration management for Devtoolbelt."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Dict, Optional
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""Configuration manager for Devtoolbelt."""
|
||||||
|
|
||||||
|
DEFAULT_CONFIG_NAME = ".devtoolbelt.yml"
|
||||||
|
CONFIG_DIR = Path.home() / ".config" / "devtoolbelt"
|
||||||
|
|
||||||
|
def __init__(self, config_path: Optional[Path] = None):
|
||||||
|
"""Initialize configuration.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_path: Optional path to config file. If not provided,
|
||||||
|
uses default locations.
|
||||||
|
"""
|
||||||
|
if config_path:
|
||||||
|
self.config_file = Path(config_path)
|
||||||
|
else:
|
||||||
|
self.config_file = self.CONFIG_DIR / self.DEFAULT_CONFIG_NAME
|
||||||
|
self._config: Dict[str, Any] = {}
|
||||||
|
|
||||||
|
def load(self) -> Dict[str, Any]:
|
||||||
|
"""Load configuration from file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing configuration.
|
||||||
|
"""
|
||||||
|
self._config = self._read_config()
|
||||||
|
return self._config
|
||||||
|
|
||||||
|
def _read_config(self) -> Dict[str, Any]:
|
||||||
|
"""Read configuration file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing config values or empty dict.
|
||||||
|
"""
|
||||||
|
if not self.config_file.exists():
|
||||||
|
return {}
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(self.config_file, 'r') as f:
|
||||||
|
return yaml.safe_load(f) or {}
|
||||||
|
except (yaml.YAMLError, IOError) as e:
|
||||||
|
print(f"Warning: Could not read config file: {e}")
|
||||||
|
return {}
|
||||||
|
|
||||||
|
def save(self, config: Optional[Dict[str, Any]] = None) -> None:
|
||||||
|
"""Save configuration to file.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config: Configuration to save. If None, saves current config.
|
||||||
|
"""
|
||||||
|
if config:
|
||||||
|
self._config = config
|
||||||
|
|
||||||
|
self.CONFIG_DIR.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
with open(self.config_file, 'w') as f:
|
||||||
|
yaml.dump(self._config, f, default_flow_style=False)
|
||||||
|
|
||||||
|
def get(self, key: str, default: Any = None) -> Any:
|
||||||
|
"""Get a configuration value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: Configuration key (supports dot notation).
|
||||||
|
default: Default value if key not found.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Configuration value or default.
|
||||||
|
"""
|
||||||
|
keys = key.split('.')
|
||||||
|
value = self._config
|
||||||
|
|
||||||
|
for k in keys:
|
||||||
|
if isinstance(value, dict):
|
||||||
|
value = value.get(k)
|
||||||
|
else:
|
||||||
|
return default
|
||||||
|
|
||||||
|
if value is None:
|
||||||
|
return default
|
||||||
|
|
||||||
|
return value
|
||||||
|
|
||||||
|
def set(self, key: str, value: Any) -> None:
|
||||||
|
"""Set a configuration value.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
key: Configuration key (supports dot notation).
|
||||||
|
value: Value to set.
|
||||||
|
"""
|
||||||
|
keys = key.split('.')
|
||||||
|
config = self._config
|
||||||
|
|
||||||
|
for k in keys[:-1]:
|
||||||
|
if k not in config:
|
||||||
|
config[k] = {}
|
||||||
|
config = config[k]
|
||||||
|
|
||||||
|
config[keys[-1]] = value
|
||||||
|
|
||||||
|
def get_database_configs(self) -> Dict[str, Dict[str, Any]]:
|
||||||
|
"""Get all database configurations.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary of database configs by name.
|
||||||
|
"""
|
||||||
|
return self.get('databases', {})
|
||||||
|
|
||||||
|
def get_api_endpoints(self) -> Dict[str, str]:
|
||||||
|
"""Get all API endpoints.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary of API endpoints by name.
|
||||||
|
"""
|
||||||
|
return self.get('api_endpoints', {})
|
||||||
|
|
||||||
|
def get_default_db(self) -> Optional[str]:
|
||||||
|
"""Get default database name.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Default database name or None.
|
||||||
|
"""
|
||||||
|
return self.get('default_database')
|
||||||
|
|
||||||
|
|
||||||
|
def get_config(config_path: Optional[str] = None) -> Config:
|
||||||
|
"""Get configuration instance.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
config_path: Optional path to config file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Config instance.
|
||||||
|
"""
|
||||||
|
config = Config(Path(config_path) if config_path else None)
|
||||||
|
config.load()
|
||||||
|
return config
|
||||||
Reference in New Issue
Block a user