Skip to content

Latest commit

 

History

History
37 lines (26 loc) · 1.55 KB

File metadata and controls

37 lines (26 loc) · 1.55 KB

pydantic-handlebars

Handlebars template engine for composing LLM prompts, built on Pydantic.

Quick Reference

  • make all — format, lint, typecheck, test with coverage
  • make test — run tests (parallel with pytest-xdist)
  • make lint — ruff format check + ruff check
  • make typecheck — pyright strict mode

Code Rules

  • Only runtime dependency is pydantic (2.0+)
  • 100% test coverage required
  • All implementation modules are private (_tokenizer.py, etc.)
  • Public API is exported from __init__.py
  • Tests are ported from the Handlebars.js spec suite — maintain 1:1 correspondence
  • Single quotes for code, double quotes for docstrings
  • Google-style docstrings
  • Python 3.10+ (use X | Y union syntax in annotations, but isinstance(x, (X, Y)) in runtime checks)
  • No except Exception — catch specific types
  • No imports inside functions

Architecture

  1. Tokenizer (_tokenizer.py) → Token stream
  2. Parser (_parser.py) → AST (_ast_nodes.py)
  3. Compiler (_compiler.py) → Output string

Security

Templates may be untrusted. All context data is serialized to JSON-safe types via pydantic_core.to_jsonable_python before rendering — the template engine only sees dicts, lists, strings, numbers, bools, and None. Enforce depth limits for nesting.

Testing

Tests are ported from https://github.com/handlebars-lang/handlebars.js/tree/master/spec. When adding new features, find the corresponding JS spec tests and port them. Use assert render(template, context) == expected pattern. No test classes — standalone functions only.