| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- from abc import ABC
- from pathlib import Path
- from typing import Optional, Dict, Any
- import logging
- import yaml
- from typer import Typer, Option, Argument
- from rich.console import Console
- from .exceptions import TemplateNotFoundError
- from .library import LibraryManager
- logger = logging.getLogger('boilerplates')
- console = Console()
- class Module(ABC):
- """Streamlined base module that auto-detects variables from templates."""
-
- # Required class attributes for subclasses
- name = None
- description = None
- files = None
-
- def __init__(self):
- if not all([self.name, self.description, self.files]):
- raise ValueError(
- f"Module {self.__class__.__name__} must define name, description, and files"
- )
-
- self.libraries = LibraryManager()
-
- # Initialize variables if the subclass defines _init_variables method
- if hasattr(self, '_init_variables'):
- self._init_variables()
-
- self.metadata = self._build_metadata()
-
- def _build_metadata(self) -> Dict[str, Any]:
- """Build metadata from class attributes."""
- metadata = {}
-
- # Add categories if defined
- if hasattr(self, 'categories'):
- metadata['categories'] = self.categories
-
- # Add variable metadata if defined
- if hasattr(self, 'variable_metadata'):
- metadata['variables'] = self.variable_metadata
-
- return metadata
- def list(self):
- """List all templates."""
- templates = self.libraries.find(self.name, self.files, sorted=True)
- for template in templates:
- console.print(f"[cyan]{template.id}[/cyan] - {template.name}")
- return templates
- def show(self, id: str = Argument(..., help="Template ID")):
- """Show template details."""
- template = self._get_template(id)
- # Header
- version = f" v{template.version}" if template.version else ""
- console.print(f"[bold magenta]{template.name} ({template.id}{version})[/bold magenta]")
- console.print(f"[dim white]{template.description}[/dim white]\n")
-
- # Metadata (only print if exists)
- metadata = [
- ("Author", template.author),
- ("Date", template.date),
- ("Tags", ', '.join(template.tags) if template.tags else None)
- ]
-
- for label, value in metadata:
- if value:
- console.print(f"{label}: [cyan]{value}[/cyan]")
-
- # Variables
- if template.vars:
- console.print(f"Variables: [cyan]{', '.join(sorted(template.vars))}[/cyan]")
-
- # Content
- if template.content:
- print(f"\n{template.content}")
- def _get_template(self, template_id: str):
- """Get template by ID with unified error handling."""
- template = self.libraries.find_by_id(self.name, self.files, template_id)
-
- if not template:
- raise TemplateNotFoundError(template_id, self.name)
- return template
- def generate(
- self,
- id: str = Argument(..., help="Template ID"),
- out: Optional[Path] = Option(None, "--out", "-o")
- ):
- """Generate from template."""
- template = self._get_template(id)
-
- # Validate template (will raise TemplateValidationError if validation fails)
- module_variable_registry = getattr(self, 'variables', None)
- template.validate(module_variable_registry, id)
-
- print("TEST SUCCESSFUL")
-
- def register_cli(self, app: Typer):
- """Register module commands with the main app."""
- module_app = Typer()
- module_app.command()(self.list)
- module_app.command()(self.show)
- module_app.command()(self.generate)
- app.add_typer(module_app, name=self.name, help=self.description)
|