Add shellgen core modules: main, config, history
This commit is contained in:
84
app/shellgen/config.py
Normal file
84
app/shellgen/config.py
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
"""Configuration management for ShellGen."""
|
||||||
|
|
||||||
|
import os
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any, Optional
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
"""Configuration manager that loads from YAML and environment variables."""
|
||||||
|
|
||||||
|
def __init__(self, config_path: Optional[str] = None):
|
||||||
|
self._config: dict = {}
|
||||||
|
self._config_path = config_path or self._find_config_file()
|
||||||
|
|
||||||
|
if self._config_path and Path(self._config_path).exists():
|
||||||
|
self._load_config()
|
||||||
|
|
||||||
|
def _find_config_file(self) -> Optional[str]:
|
||||||
|
"""Find config file in common locations."""
|
||||||
|
candidates = [
|
||||||
|
"config.yaml",
|
||||||
|
os.path.expanduser("~/.shellgen/config.yaml"),
|
||||||
|
"/etc/shellgen/config.yaml",
|
||||||
|
]
|
||||||
|
|
||||||
|
for candidate in candidates:
|
||||||
|
if Path(candidate).exists():
|
||||||
|
return candidate
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _load_config(self) -> None:
|
||||||
|
"""Load configuration from YAML file."""
|
||||||
|
try:
|
||||||
|
config_path = self._config_path or "config.yaml"
|
||||||
|
with open(config_path, "r") as f:
|
||||||
|
self._config = yaml.safe_load(f) or {}
|
||||||
|
except Exception:
|
||||||
|
self._config = {}
|
||||||
|
|
||||||
|
def get(self, key: str, default: Any = None) -> Any:
|
||||||
|
"""Get configuration value from environment or config file."""
|
||||||
|
env_key = key.upper().replace(".", "_")
|
||||||
|
|
||||||
|
env_value = os.environ.get(env_key)
|
||||||
|
if env_value is not None:
|
||||||
|
return env_value
|
||||||
|
|
||||||
|
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 configuration value."""
|
||||||
|
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 save(self, path: Optional[str] = None) -> None:
|
||||||
|
"""Save configuration to file."""
|
||||||
|
save_path = path or self._config_path
|
||||||
|
if not save_path:
|
||||||
|
save_path = "config.yaml"
|
||||||
|
|
||||||
|
with open(save_path, "w") as f:
|
||||||
|
yaml.dump(self._config, f, default_flow_style=False)
|
||||||
Reference in New Issue
Block a user