A Python template engine with support for variables, functions, conditionals, loops, and includes
Project description
๐ Python Template Engine
A powerful, lightweight template engine for Python with support for variables, functions, conditionals, loops, and file includes. Built for simplicity and extensibility.
โจ Features
- ๐ค Variable substitution -
{{name}},{{user.email}} - โก Function calls -
{{get_time()}},{{utils.format()}} - ๐ Conditionals -
{{#IF condition}}...{{#ELSE}}...{{/IF}} - ๐ Loops -
{{#EACH items AS item}}...{{/EACH}} - ๐ File includes -
{{#INCLUDE file_path}} - ๐จ Template rendering -
{{#RENDER template_path}} - ๐งช Fully tested - Comprehensive test suite with 54 tests
- ๐ฏ Type hints - Full type annotation support
- ๐๏ธ Extensible - Modular architecture for custom engines
๐ Quick Start
Installation
# Clone the repository
git clone https://github.com/your-username/py-templater.git
cd py-templater
# Create virtual environment (recommended)
python3 -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in development mode
pip install -e .
Basic Usage
from py_template_engine import TemplateEngine
# Simple variable substitution
template = "Hello {{name}}!"
engine = TemplateEngine(template_string=template)
result = engine.render(name="World")
print(result) # Output: Hello World!
๐ Template Syntax
Variables
<!-- Basic variables -->
<h1>{{title}}</h1>
<p>Welcome {{user.name}}!</p>
<!-- Nested object access -->
<span>{{user.profile.email}}</span>
Functions
<!-- Function calls -->
<p>Current time: {{get_time()}}</p>
<p>Formatted date: {{utils.format_date()}}</p>
Conditionals
<!-- IF/ELSE statements -->
{{#IF user_logged_in}}
<p>Welcome back, {{username}}!</p>
{{#ELSE}}
<p>Please log in to continue</p>
{{/IF}}
<!-- Nested conditions -->
{{#IF user}}
{{#IF user.is_premium}}
<span class="premium">Premium User</span>
{{/IF}}
{{/IF}}
Loops
<!-- EACH loops -->
<ul>
{{#EACH items AS item}}
<li>{{item}}</li>
{{/EACH}}
</ul>
<!-- Loop with objects -->
{{#EACH users AS user}}
<div class="user">
<h3>{{user.name}}</h3>
<p>{{user.email}}</p>
</div>
{{/EACH}}
File Operations
<!-- Include raw file content -->
{{#INCLUDE header_file}}
<!-- Render template with full processing -->
{{#RENDER user_template}}
๐ก Advanced Examples
Complete Web Page Template
<!DOCTYPE html>
<html>
<head>
<title>{{page_title}}</title>
</head>
<body>
{{#INCLUDE header.html}}
<main>
{{#IF featured_posts}}
<section class="featured">
<h2>Featured Posts</h2>
{{#EACH featured_posts AS post}}
<article>
<h3>{{post.title}}</h3>
<p>{{post.excerpt}}</p>
<time>{{post.format_date()}}</time>
</article>
{{/EACH}}
</section>
{{/IF}}
{{#RENDER content_template}}
</main>
{{#INCLUDE footer.html}}
</body>
</html>
from py_template_engine import TemplateEngine
engine = TemplateEngine(template_path="page.html")
result = engine.render(
page_title="My Blog",
featured_posts=[
{
"title": "Getting Started",
"excerpt": "Learn the basics...",
"format_date": lambda: "2024-01-15"
}
],
header_file="includes/header.html",
content_template="templates/blog_content.html"
)
Dynamic Dashboard
# Context data
dashboard_data = {
"user": {
"name": "Alice Johnson",
"role": "admin",
"notifications": 5
},
"stats": [
{"label": "Users", "value": 1247},
{"label": "Revenue", "value": "$52,340"},
{"label": "Orders", "value": 89}
],
"is_admin": True,
"get_alert_class": lambda count: "danger" if count > 10 else "info"
}
template = """
<div class="dashboard">
<h1>Welcome {{user.name}}</h1>
{{#IF is_admin}}
<div class="admin-panel">
<h2>Admin Controls</h2>
<p>Notifications: <span class="{{get_alert_class()}}">{{user.notifications}}</span></p>
</div>
{{/IF}}
<div class="stats">
{{#EACH stats AS stat}}
<div class="stat-card">
<h3>{{stat.label}}</h3>
<p class="value">{{stat.value}}</p>
</div>
{{/EACH}}
</div>
</div>
"""
engine = TemplateEngine(template_string=template)
result = engine.render(**dashboard_data)
๐๏ธ API Reference
TemplateEngine
class TemplateEngine:
def __init__(self, template_path: Optional[str] = None,
template_string: Optional[str] = None) -> None:
"""
Initialize template engine with either file path or string.
Args:
template_path: Path to template file
template_string: Template content as string
Raises:
ValueError: If neither template_path nor template_string provided
"""
def render(self, **kwargs) -> str:
"""
Render template with provided context variables.
Args:
**kwargs: Template context variables
Returns:
Rendered template as string
"""
๐งช Testing
Run the comprehensive test suite:
# Activate virtual environment
source .venv/bin/activate
# Run all tests with pytest
pytest tests -v
# Run specific test file
python tests/test_template_engine.py
# Run with coverage
pytest tests --cov=py_template_engine
Test Coverage: 54 tests covering all features:
- Variable substitution (basic + nested)
- Function calls (simple + nested objects)
- Conditional logic (IF/ELSE + nested)
- Loop processing (EACH + complex data)
- File operations (INCLUDE + RENDER)
- Error handling & edge cases
๐ง Development
Project Structure
py-templater/
โโโ py_template_engine/ # Main package
โ โโโ __init__.py
โ โโโ TemplateEngine.py # Main engine
โ โโโ TemplaterInterface.py
โ โโโ sub_engines/ # Individual processors
โ โโโ VariableTemplater.py
โ โโโ FunctionTemplater.py
โ โโโ IfTemplater.py
โ โโโ EachTemplater.py
โ โโโ IncludeTemplater.py
โ โโโ RenderTemplater.py
โโโ tests/ # Test suite
โโโ examples/ # Usage examples
โโโ pyproject.toml # Project configuration
Adding Custom Engines
Create custom template processors by extending TemplaterInterface:
from py_template_engine.TemplaterInterface import TemplaterInterface
import re
class CustomTemplater(TemplaterInterface):
def render(self, template: str, **kwargs) -> str:
return re.sub(
r'{{#CUSTOM (.*?)}}',
lambda m: self.process(m.group(1), **kwargs),
template
)
def process(self, content: str, **kwargs) -> str:
# Custom processing logic
return f"Processed: {content}"
๐ค Contributing
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure all tests pass (
pytest tests) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
Happy templating! ๐
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file py_template_engine-0.1.0.tar.gz.
File metadata
- Download URL: py_template_engine-0.1.0.tar.gz
- Upload date:
- Size: 12.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7d54d5b69653cd3a1d6a442f8e1a8d7373f384c02ccfd114673068b12491f7e9
|
|
| MD5 |
12b618e80bdbbdd7650974e7c46ffd87
|
|
| BLAKE2b-256 |
7296eb2864e0cbbbeea17323c8cee9a15efc596de3c4d81f556db85f94f81310
|
File details
Details for the file py_template_engine-0.1.0-py3-none-any.whl.
File metadata
- Download URL: py_template_engine-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.4
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
662a68ef510189ef2e70a7b71f04da9953d13dbed4907afe841231f32f01deeb
|
|
| MD5 |
4bfa6b9476c59a3025f15c9258ffb5a3
|
|
| BLAKE2b-256 |
5b94c7310a0600b6ff52a85d1095128f3080254016dfca7822f6e5b6f5731864
|