From 28b84ff3a73760e836279bbdd5a8c91b4ced38cd Mon Sep 17 00:00:00 2001 From: 7000pctAUTO Date: Wed, 4 Feb 2026 12:30:56 +0000 Subject: [PATCH] Add core modules (prompt, template) --- src/promptforge/core/template.py | 59 ++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 src/promptforge/core/template.py diff --git a/src/promptforge/core/template.py b/src/promptforge/core/template.py new file mode 100644 index 0000000..7ab44fe --- /dev/null +++ b/src/promptforge/core/template.py @@ -0,0 +1,59 @@ +from typing import Any, Dict, List, Optional +from jinja2 import Environment, BaseLoader, TemplateSyntaxError, StrictUndefined, UndefinedError +from jinja2.exceptions import TemplateError + +from .prompt import PromptVariable +from .exceptions import MissingVariableError, InvalidPromptError + + +class TemplateEngine: + def __init__(self): + self.env = Environment( + loader=BaseLoader(), + autoescape=True, + trim_blocks=True, + lstrip_blocks=True, + undefined=StrictUndefined, + ) + + def get_variables(self, content: str) -> List[str]: + from jinja2 import meta + ast = self.env.parse(content) + return sorted(meta.find_undeclared_variables(ast)) + + def render( + self, + content: str, + variables: Optional[Dict[str, Any]] = None, + required_variables: Optional[List[PromptVariable]] = None, + ) -> str: + variables = variables.copy() if variables else {} + required_variables = required_variables or [] + + for var in required_variables: + if var.name not in variables and var.default is not None: + variables[var.name] = var.default + + missing = [] + for var in required_variables: + if var.required and var.name not in variables: + missing.append(var.name) + + if missing: + raise MissingVariableError( + f"Missing required variables: {', '.join(missing)}" + ) + + for var in required_variables: + if var.name in variables and var.type.value == "boolean": + val = variables[var.name] + if isinstance(val, str): + variables[var.name] = val.lower() in ("true", "1", "yes") + + try: + template = self.env.from_string(content) + return template.render(**variables) + except TemplateSyntaxError as e: + raise InvalidPromptError(f"Template syntax error: {e.message}") + except (UndefinedError, TemplateError) as e: + raise InvalidPromptError(f"Template rendering error: {e}") \ No newline at end of file