256 lines
8.2 KiB
Python
256 lines
8.2 KiB
Python
"""
|
|
Model Generator
|
|
|
|
Generates Pydantic models from framework configuration.
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from typing import List
|
|
from .config_loader import ConfigLoader
|
|
|
|
|
|
class ModelGenerator:
|
|
"""Generates Pydantic model files from configuration"""
|
|
|
|
def __init__(self, config: ConfigLoader, output_dir: Path):
|
|
self.config = config
|
|
self.output_dir = Path(output_dir)
|
|
|
|
def generate(self):
|
|
"""Generate all model files"""
|
|
models_dir = self.output_dir / "models" / "pydantic"
|
|
models_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
# Generate __init__.py with all models
|
|
self._generate_models_file(models_dir / "__init__.py")
|
|
|
|
print(f"Generated models in {models_dir}")
|
|
|
|
def _generate_models_file(self, output_path: Path):
|
|
"""Generate the main models file"""
|
|
|
|
# Get component names from config
|
|
config_comp = self.config.get_shared_component('config')
|
|
data_comp = self.config.get_shared_component('data')
|
|
|
|
data_flow_sys = self.config.get_system('data_flow')
|
|
doc_sys = self.config.get_system('documentation')
|
|
exec_sys = self.config.get_system('execution')
|
|
|
|
connector_comp = self.config.get_component('data_flow', 'connector')
|
|
pulse_comp = self.config.get_component('data_flow', 'composed')
|
|
|
|
pattern_comp = self.config.get_component('documentation', 'pattern')
|
|
maps_comp = self.config.get_component('documentation', 'library')
|
|
doc_composed = self.config.get_component('documentation', 'composed')
|
|
|
|
tool_comp = self.config.get_component('execution', 'utility')
|
|
monitor_comp = self.config.get_component('execution', 'watcher')
|
|
cabinet_comp = self.config.get_component('execution', 'container')
|
|
exec_composed = self.config.get_component('execution', 'composed')
|
|
|
|
# Build the template
|
|
content = f'''"""
|
|
Pydantic models - Generated from {self.config.framework.name}.config.json
|
|
|
|
DO NOT EDIT MANUALLY - Regenerate from config
|
|
"""
|
|
|
|
from enum import Enum
|
|
from typing import Optional, List, Literal
|
|
from pydantic import BaseModel, Field
|
|
|
|
|
|
class Status(str, Enum):
|
|
PENDING = "pending"
|
|
PLANNED = "planned"
|
|
BUILDING = "building"
|
|
DEV = "dev"
|
|
LIVE = "live"
|
|
READY = "ready"
|
|
|
|
|
|
class System(str, Enum):
|
|
{data_flow_sys.name.upper()} = "{data_flow_sys.name}"
|
|
{doc_sys.name.upper()} = "{doc_sys.name}"
|
|
{exec_sys.name.upper()} = "{exec_sys.name}"
|
|
|
|
|
|
class ToolType(str, Enum):
|
|
APP = "app"
|
|
CLI = "cli"
|
|
|
|
|
|
# === Shared Components ===
|
|
|
|
class {config_comp.title}(BaseModel):
|
|
"""{config_comp.description}. Shared across {data_flow_sys.name}, {exec_sys.name}."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
config_path: Optional[str] = None
|
|
|
|
|
|
class {data_comp.title}(BaseModel):
|
|
"""{data_comp.description}. Shared across all systems."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
source_template: Optional[str] = None
|
|
data_path: Optional[str] = None
|
|
|
|
|
|
# === System-Specific Components ===
|
|
|
|
class {connector_comp.title}(BaseModel):
|
|
"""{connector_comp.description} ({data_flow_sys.name})."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
system: Literal["{data_flow_sys.name}"] = "{data_flow_sys.name}"
|
|
mock: Optional[bool] = None
|
|
description: Optional[str] = None
|
|
|
|
|
|
class {pattern_comp.title}(BaseModel):
|
|
"""{pattern_comp.description} ({doc_sys.name})."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
template_path: Optional[str] = None
|
|
system: Literal["{doc_sys.name}"] = "{doc_sys.name}"
|
|
|
|
|
|
class {tool_comp.title}(BaseModel):
|
|
"""{tool_comp.description} ({exec_sys.name})."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
system: Literal["{exec_sys.name}"] = "{exec_sys.name}"
|
|
type: Optional[ToolType] = None
|
|
description: Optional[str] = None
|
|
path: Optional[str] = None
|
|
url: Optional[str] = None
|
|
cli: Optional[str] = None
|
|
|
|
|
|
class {monitor_comp.title}(BaseModel):
|
|
"""{monitor_comp.description} ({exec_sys.name})."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
system: Literal["{exec_sys.name}"] = "{exec_sys.name}"
|
|
|
|
|
|
class {cabinet_comp.title}(BaseModel):
|
|
"""{cabinet_comp.description} ({exec_sys.name})."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
tools: List[{tool_comp.title}] = Field(default_factory=list)
|
|
system: Literal["{exec_sys.name}"] = "{exec_sys.name}"
|
|
|
|
|
|
# === Composed Types ===
|
|
|
|
class {pulse_comp.title}(BaseModel):
|
|
"""{pulse_comp.description} ({data_flow_sys.name}). Formula: {pulse_comp.formula}."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
{connector_comp.name}: Optional[{connector_comp.title}] = None
|
|
{config_comp.name}: Optional[{config_comp.title}] = None
|
|
{data_comp.name}: Optional[{data_comp.title}] = None
|
|
system: Literal["{data_flow_sys.name}"] = "{data_flow_sys.name}"
|
|
|
|
|
|
class {doc_composed.title}(BaseModel):
|
|
"""{doc_composed.description} ({doc_sys.name}). Formula: {doc_composed.formula}."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
template: Optional[{pattern_comp.title}] = None
|
|
{data_comp.name}: Optional[{data_comp.title}] = None
|
|
output_{data_comp.name}: Optional[{data_comp.title}] = None
|
|
system: Literal["{doc_sys.name}"] = "{doc_sys.name}"
|
|
|
|
|
|
class {exec_composed.title}(BaseModel):
|
|
"""{exec_composed.description} ({exec_sys.name}). Formula: {exec_composed.formula}."""
|
|
name: str # Unique identifier
|
|
slug: str # URL-friendly identifier
|
|
title: str # Display title for UI
|
|
status: Optional[Status] = None
|
|
cabinet: Optional[{cabinet_comp.title}] = None
|
|
{config_comp.name}: Optional[{config_comp.title}] = None
|
|
{data_comp.plural}: List[{data_comp.title}] = Field(default_factory=list)
|
|
system: Literal["{exec_sys.name}"] = "{exec_sys.name}"
|
|
|
|
|
|
# === Collection wrappers for JSON files ===
|
|
|
|
class {config_comp.title}Collection(BaseModel):
|
|
items: List[{config_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {data_comp.title}Collection(BaseModel):
|
|
items: List[{data_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {connector_comp.title}Collection(BaseModel):
|
|
items: List[{connector_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {pattern_comp.title}Collection(BaseModel):
|
|
items: List[{pattern_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {tool_comp.title}Collection(BaseModel):
|
|
items: List[{tool_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {monitor_comp.title}Collection(BaseModel):
|
|
items: List[{monitor_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {cabinet_comp.title}Collection(BaseModel):
|
|
items: List[{cabinet_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {pulse_comp.title}Collection(BaseModel):
|
|
items: List[{pulse_comp.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {doc_composed.title}Collection(BaseModel):
|
|
items: List[{doc_composed.title}] = Field(default_factory=list)
|
|
|
|
|
|
class {exec_composed.title}Collection(BaseModel):
|
|
items: List[{exec_composed.title}] = Field(default_factory=list)
|
|
'''
|
|
|
|
output_path.write_text(content)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
from .config_loader import load_config
|
|
|
|
# Test with soleprint config
|
|
config_path = Path(__file__).parent.parent / "soleprint.config.json"
|
|
config = load_config(config_path)
|
|
|
|
output_dir = Path(__file__).parent.parent / "soleprint-room"
|
|
generator = ModelGenerator(config, output_dir)
|
|
generator.generate()
|
|
|
|
print("Models generated successfully!")
|