@Generator Decorator
The @Generator decorator registers a class as a code generator in Forge’s global registry.
Location
from core.decorators import Generator
Signature
@Generator(
category: str,
priority: int,
requires: list[str] = None,
enabled_when: callable = None,
description: str = ""
)
Parameters
category (required)
Type: str
The category this generator belongs to. Used for organization and logging.
Common categories:
config- Configuration filesapp_config- Application configuration modulesdatabase- Database connectionmodel- Database modelsschema- Pydantic schemascrud- CRUD operationsservice- Business logicrouter- API routesemail- Email servicetask- Celery taskstest- Test filesdeployment- Docker and deploymentmigration- Database migrations
priority (required)
Type: int
Execution order. Lower numbers execute first.
Recommended ranges:
Range |
Purpose |
|---|---|
1-10 |
Configuration files |
11-20 |
Application configuration |
21-30 |
Database setup |
31-50 |
Models |
51-60 |
Schemas |
61-70 |
CRUD operations |
71-80 |
Services |
81-90 |
Routers |
100-115 |
Tests |
100-110 |
Deployment |
120 |
Migrations |
requires (optional)
Type: list[str]
Default: None (empty list)
List of generator class names that must execute before this generator.
@Generator(
category="router",
priority=80,
requires=["UserModelGenerator", "UserSchemaGenerator", "UserCRUDGenerator"]
)
The orchestrator ensures all required generators complete before executing this one.
enabled_when (optional)
Type: callable(ConfigReader) -> bool
Default: None (always enabled)
A function that receives a ConfigReader instance and returns True if the generator should run.
@Generator(
category="router",
priority=80,
enabled_when=lambda c: c.has_auth()
)
If None, the generator always runs.
description (optional)
Type: str
Default: ""
Human-readable description of what the generator creates.
@Generator(
category="router",
priority=80,
description="Generate authentication router (app/routers/v1/auth.py)"
)
How It Works
When Python imports a module containing a decorated class, the decorator:
Registers the class in
GENERATOR_REGISTRYStores all metadata (category, priority, requires, enabled_when, description)
Returns the original class unchanged
# core/decorators/generator.py
GENERATOR_REGISTRY = {}
def Generator(category, priority, requires=None, enabled_when=None, description=""):
def decorator(cls):
GENERATOR_REGISTRY[cls.__name__] = {
"class": cls,
"category": category,
"priority": priority,
"requires": requires or [],
"enabled_when": enabled_when,
"description": description,
}
return cls
return decorator
Examples
Basic Generator
from core.decorators import Generator
from core.generators.templates.base import BaseTemplateGenerator
@Generator(
category="config",
priority=1,
description="Generate pyproject.toml"
)
class PyprojectGenerator(BaseTemplateGenerator):
def generate(self) -> None:
# Always runs, no dependencies
self.file_ops.create_file("pyproject.toml", content)
Generator with Dependencies
@Generator(
category="crud",
priority=60,
requires=["UserModelGenerator", "UserSchemaGenerator"],
description="Generate user CRUD operations"
)
class UserCRUDGenerator(BaseTemplateGenerator):
def generate(self) -> None:
# Runs after UserModelGenerator and UserSchemaGenerator
pass
Conditional Generator
@Generator(
category="router",
priority=80,
requires=["AuthServiceGenerator"],
enabled_when=lambda c: c.has_auth(),
description="Generate auth router"
)
class AuthRouterGenerator(BaseTemplateGenerator):
def generate(self) -> None:
# Only runs if authentication is enabled
pass
Generator with Complex Condition
@Generator(
category="email",
priority=75,
requires=["ConfigEmailGenerator"],
enabled_when=lambda c: c.get_auth_type() == "complete",
description="Generate email service"
)
class EmailServiceGenerator(BaseTemplateGenerator):
def generate(self) -> None:
# Only runs for complete authentication
pass
Accessing the Registry
from core.decorators import GENERATOR_REGISTRY
# List all registered generators
for name, info in GENERATOR_REGISTRY.items():
print(f"{name}: {info['category']} (priority={info['priority']})")
# Get a specific generator
user_model_info = GENERATOR_REGISTRY.get("UserModelGenerator")
if user_model_info:
generator_class = user_model_info["class"]
Common Patterns
Feature-Specific Generator
@Generator(
category="app",
priority=48,
enabled_when=lambda c: c.has_redis(),
requires=["RedisConfigGenerator"],
description="Generate Redis connection manager"
)
class RedisAppGenerator(BaseTemplateGenerator):
...
Database-Specific Generator
@Generator(
category="database",
priority=31,
requires=["ConfigDatabaseGenerator"],
enabled_when=lambda c: c.get_database_type() == "PostgreSQL",
description="Generate PostgreSQL connection"
)
class PostgreSQLGenerator(BaseTemplateGenerator):
...
Auth-Type-Specific Generator
@Generator(
category="model",
priority=41,
requires=["UserModelGenerator"],
enabled_when=lambda c: c.get_auth_type() == "complete",
description="Generate token models for complete auth"
)
class TokenModelGenerator(BaseTemplateGenerator):
...