From e54da824a0b46d9cc503160ca5e0153d462a02c1 Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Thu, 5 Feb 2026 11:01:16 +0000 Subject: [PATCH] Initial upload: Project Scaffold CLI with multi-language templates and CI/CD --- project_scaffold_cli/config.py | 154 +++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 project_scaffold_cli/config.py diff --git a/project_scaffold_cli/config.py b/project_scaffold_cli/config.py new file mode 100644 index 0000000..e284d95 --- /dev/null +++ b/project_scaffold_cli/config.py @@ -0,0 +1,154 @@ +"""Configuration handling for Project Scaffold CLI.""" + +import os +from pathlib import Path +from typing import Any, Dict, List, Optional + +import yaml + + +class Config: + """Configuration management for project scaffold CLI.""" + + def __init__( + self, + author: Optional[str] = None, + email: Optional[str] = None, + license: Optional[str] = None, + description: Optional[str] = None, + default_language: Optional[str] = None, + default_ci: Optional[str] = None, + default_template: Optional[str] = None, + template_vars: Optional[Dict[str, Any]] = None, + custom_templates_dir: Optional[str] = None, + config_path: Optional[str] = None, + ): + self.author = author + self.email = email + self.license = license + self.description = description + self.default_language = default_language + self.default_ci = default_ci + self.default_template = default_template + self.template_vars = template_vars or {} + self.custom_templates_dir = custom_templates_dir + self.config_path = config_path + + @classmethod + def load(cls, config_path: Optional[str] = None) -> "Config": + """Load configuration from file.""" + if config_path: + config_file = Path(config_path) + if config_file.exists(): + return cls._from_file(config_file) + + search_paths = [ + Path("project.yaml"), + Path(".project-scaffoldrc"), + Path.cwd() / "project.yaml", + Path.cwd() / ".project-scaffoldrc", + ] + + for path in search_paths: + if path.exists(): + return cls._from_file(path) + + home_config = Path.home() / ".config" / "project-scaffold" / "config.yaml" + if home_config.exists(): + return cls._from_file(home_config) + + return cls() + + @classmethod + def _from_file(cls, path: Path) -> "Config": + """Load configuration from a YAML file.""" + try: + with open(path, "r", encoding="utf-8") as f: + data = yaml.safe_load(f) or {} + except yaml.YAMLError as e: + raise ValueError(f"Invalid YAML in {path}: {e}") + + project_config = data.get("project", {}) + defaults = data.get("defaults", {}) + template_vars = data.get("template_vars", {}) + template_paths = data.get("template_paths", []) + custom_templates_dir = data.get("custom_templates_dir") + + return cls( + author=project_config.get("author"), + email=project_config.get("email"), + license=project_config.get("license"), + description=project_config.get("description"), + default_language=defaults.get("language"), + default_ci=defaults.get("ci"), + default_template=defaults.get("template"), + template_vars=template_vars, + custom_templates_dir=custom_templates_dir, + config_path=str(path), + ) + + def save(self, path: Path) -> None: + """Save configuration to a YAML file.""" + data = { + "project": { + "author": self.author, + "email": self.email, + "license": self.license, + "description": self.description, + }, + "defaults": { + "language": self.default_language, + "ci": self.default_ci, + "template": self.default_template, + }, + "template_vars": self.template_vars, + } + + if self.custom_templates_dir: + data["custom_templates_dir"] = self.custom_templates_dir + + with open(path, "w", encoding="utf-8") as f: + yaml.dump(data, f, default_flow_style=False, sort_keys=False) + + def get_template_dirs(self) -> List[str]: + """Get list of template directories to search.""" + dirs = [] + + if self.custom_templates_dir: + dirs.append(self.custom_templates_dir) + + home_templates = ( + Path.home() + / ".local" + / "share" + / "project-scaffold" + / "templates" + ) + dirs.append(str(home_templates)) + + return dirs + + def get_custom_templates_dir(self) -> str: + """Get the directory for custom templates.""" + if self.custom_templates_dir: + return self.custom_templates_dir + + custom_dir = ( + Path.home() / ".config" / "project-scaffold" / "templates" + ) + custom_dir.mkdir(parents=True, exist_ok=True) + return str(custom_dir) + + def get_template_vars(self, language: str) -> Dict[str, Any]: + """Get template variables for a specific language.""" + return self.template_vars.get(language, {}) + + @property + def ci(self) -> Optional[str]: + """Get default CI provider.""" + return self.default_ci + + @property + def template(self) -> Optional[str]: + """Get default template.""" + return self.default_template