diff --git a/app/shellgen/config.py b/app/shellgen/config.py new file mode 100644 index 0000000..6919974 --- /dev/null +++ b/app/shellgen/config.py @@ -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)