Advanced Application Framework for Python with a focus on Command Line Interfaces
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The template system provides template rendering framework supporting multiple template engines including Jinja2 and Mustache. It enables consistent template-based output generation for applications.
Base interface for template rendering functionality that defines the contract for template operations.
class TemplateHandler:
"""
Template handler interface for rendering templates with data.
Provides methods for loading template files and rendering them
with data contexts to produce formatted output.
"""
def load(self, template_path: str) -> Any:
"""
Load a template from file path.
Args:
template_path: Path to template file to load
Returns:
Loaded template object
"""
def render(self, content: str, data: Dict[str, Any]) -> str:
"""
Render template content with data context.
Args:
content: Template content string or template object
data: Dictionary of data to render with template
Returns:
Rendered template output string
"""from cement import App, Controller, ex, init_defaults
CONFIG = init_defaults('myapp')
CONFIG['template.jinja2'] = {
'template_dirs': ['./templates']
}
class TemplateController(Controller):
class Meta:
label = 'template'
stacked_on = 'base'
stacked_type = 'nested'
@ex(help='generate report')
def report(self):
"""Generate report using template."""
report_data = {
'title': 'Monthly Report',
'date': '2023-01-15',
'items': [
{'name': 'Sales', 'value': 15000, 'change': '+5%'},
{'name': 'Expenses', 'value': 8000, 'change': '+2%'},
{'name': 'Profit', 'value': 7000, 'change': '+8%'}
],
'summary': 'Overall performance improved this month'
}
# Load and render template
template = self.app.template.load('report.html')
output = self.app.template.render(template, report_data)
print(output)
class BaseController(Controller):
class Meta:
label = 'base'
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
extensions = ['jinja2']
template_handler = 'jinja2'
config_defaults = CONFIG
handlers = [BaseController, TemplateController]
with MyApp() as app:
app.run()
# Usage:
# myapp template reportfrom cement import App, Controller, ex, init_defaults
CONFIG = init_defaults('myapp')
CONFIG['template.jinja2'] = {
'template_dirs': ['./templates', './shared_templates'],
'auto_reload': True,
'cache_size': 50
}
class EmailController(Controller):
class Meta:
label = 'email'
stacked_on = 'base'
stacked_type = 'nested'
@ex(
help='send welcome email',
arguments=[
(['--user'], {'help': 'username', 'required': True}),
(['--email'], {'help': 'email address', 'required': True})
]
)
def welcome(self):
"""Send welcome email using Jinja2 template."""
user_data = {
'username': self.app.pargs.user,
'email': self.app.pargs.email,
'company': 'MyCompany',
'support_email': 'support@mycompany.com',
'features': [
'Dashboard access',
'Real-time notifications',
'Advanced reporting',
'24/7 support'
]
}
# Render email template
template = self.app.template.load('welcome_email.html')
email_html = self.app.template.render(template, user_data)
print(f"Welcome email generated for {user_data['username']}")
print("=" * 50)
print(email_html)
class BaseController(Controller):
class Meta:
label = 'base'
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
extensions = ['jinja2']
template_handler = 'jinja2'
config_defaults = CONFIG
handlers = [BaseController, EmailController]
with MyApp() as app:
app.run()
# Example template: templates/welcome_email.html
"""
<!DOCTYPE html>
<html>
<head>
<title>Welcome to {{ company }}</title>
</head>
<body>
<h1>Welcome, {{ username }}!</h1>
<p>Thank you for joining {{ company }}. Your account ({{ email }}) is now active.</p>
<h2>Available Features:</h2>
<ul>
{% for feature in features %}
<li>{{ feature }}</li>
{% endfor %}
</ul>
<p>Need help? Contact us at {{ support_email }}</p>
<p>Best regards,<br>
The {{ company }} Team</p>
</body>
</html>
"""
# Usage:
# myapp email welcome --user johndoe --email john@example.comfrom cement import App, Controller, ex, init_defaults
CONFIG = init_defaults('myapp')
CONFIG['template.mustache'] = {
'template_dirs': ['./mustache_templates']
}
class ConfigController(Controller):
class Meta:
label = 'config'
stacked_on = 'base'
stacked_type = 'nested'
@ex(help='generate configuration file')
def generate(self):
"""Generate configuration file using Mustache template."""
config_data = {
'app_name': 'MyApplication',
'version': '1.0.0',
'database': {
'host': 'localhost',
'port': 5432,
'name': 'myapp_db'
},
'features': [
{'name': 'authentication', 'enabled': True},
{'name': 'caching', 'enabled': True},
{'name': 'logging', 'enabled': True},
{'name': 'monitoring', 'enabled': False}
],
'debug_mode': False
}
# Render configuration template
template = self.app.template.load('app_config.mustache')
config_output = self.app.template.render(template, config_data)
print("Generated configuration:")
print("=" * 40)
print(config_output)
class BaseController(Controller):
class Meta:
label = 'base'
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
extensions = ['mustache']
template_handler = 'mustache'
config_defaults = CONFIG
handlers = [BaseController, ConfigController]
with MyApp() as app:
app.run()
# Example template: mustache_templates/app_config.mustache
"""
# {{ app_name }} Configuration
# Version: {{ version }}
[application]
name = {{ app_name }}
version = {{ version }}
debug = {{ debug_mode }}
[database]
host = {{ database.host }}
port = {{ database.port }}
name = {{ database.name }}
[features]
{{#features}}
{{name}} = {{enabled}}
{{/features}}
"""
# Usage:
# myapp config generatefrom cement import App, Controller, ex, init_defaults
import datetime
CONFIG = init_defaults('myapp')
CONFIG['template.jinja2'] = {
'template_dirs': ['./templates']
}
def datetime_filter(timestamp, format='%Y-%m-%d %H:%M:%S'):
"""Custom Jinja2 filter for datetime formatting."""
if isinstance(timestamp, str):
dt = datetime.datetime.fromisoformat(timestamp.replace('Z', '+00:00'))
else:
dt = timestamp
return dt.strftime(format)
def currency_filter(amount, symbol='$'):
"""Custom Jinja2 filter for currency formatting."""
return f"{symbol}{amount:,.2f}"
class ReportController(Controller):
class Meta:
label = 'report'
stacked_on = 'base'
stacked_type = 'nested'
@ex(help='generate sales report')
def sales(self):
"""Generate sales report with custom filters."""
sales_data = {
'report_title': 'Q1 Sales Report',
'generated_at': '2023-01-15T10:30:00Z',
'total_sales': 125000.50,
'transactions': [
{
'date': '2023-01-10T14:30:00Z',
'customer': 'Acme Corp',
'amount': 15000.00,
'status': 'completed'
},
{
'date': '2023-01-12T09:15:00Z',
'customer': 'Beta LLC',
'amount': 8500.75,
'status': 'completed'
}
]
}
# Add custom filters to Jinja2 environment
self.app.template.env.filters['datetime'] = datetime_filter
self.app.template.env.filters['currency'] = currency_filter
# Render report
template = self.app.template.load('sales_report.html')
report_html = self.app.template.render(template, sales_data)
print(report_html)
class BaseController(Controller):
class Meta:
label = 'base'
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
extensions = ['jinja2']
template_handler = 'jinja2'
config_defaults = CONFIG
handlers = [BaseController, ReportController]
with MyApp() as app:
app.run()
# Example template using custom filters: templates/sales_report.html
"""
<h1>{{ report_title }}</h1>
<p>Generated: {{ generated_at | datetime('%B %d, %Y at %I:%M %p') }}</p>
<h2>Summary</h2>
<p>Total Sales: {{ total_sales | currency }}</p>
<h2>Transactions</h2>
<table>
<tr>
<th>Date</th>
<th>Customer</th>
<th>Amount</th>
<th>Status</th>
</tr>
{% for transaction in transactions %}
<tr>
<td>{{ transaction.date | datetime('%m/%d/%Y') }}</td>
<td>{{ transaction.customer }}</td>
<td>{{ transaction.amount | currency }}</td>
<td>{{ transaction.status | title }}</td>
</tr>
{% endfor %}
</table>
"""
# Usage:
# myapp report salesfrom cement import App, Controller, ex, init_defaults
CONFIG = init_defaults('myapp')
CONFIG['template.jinja2'] = {
'template_dirs': ['./templates']
}
class PageController(Controller):
class Meta:
label = 'page'
stacked_on = 'base'
stacked_type = 'nested'
@ex(help='generate dashboard page')
def dashboard(self):
"""Generate dashboard page using template inheritance."""
dashboard_data = {
'page_title': 'Dashboard',
'user': {
'name': 'John Doe',
'role': 'Administrator'
},
'stats': [
{'label': 'Total Users', 'value': 1250, 'trend': 'up'},
{'label': 'Active Sessions', 'value': 89, 'trend': 'up'},
{'label': 'System Load', 'value': '65%', 'trend': 'stable'}
],
'recent_activity': [
'User johndoe logged in',
'New user registered: alice',
'System backup completed'
]
}
template = self.app.template.load('dashboard.html')
page_html = self.app.template.render(template, dashboard_data)
print(page_html)
class BaseController(Controller):
class Meta:
label = 'base'
class MyApp(App):
class Meta:
label = 'myapp'
base_controller = 'base'
extensions = ['jinja2']
template_handler = 'jinja2'
config_defaults = CONFIG
handlers = [BaseController, PageController]
with MyApp() as app:
app.run()
# Base template: templates/base.html
"""
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}MyApp{% endblock %}</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
.header { background: #f0f0f0; padding: 10px; }
.content { margin: 20px 0; }
.footer { border-top: 1px solid #ccc; padding: 10px; }
</style>
</head>
<body>
<div class="header">
<h1>{% block header %}MyApp{% endblock %}</h1>
{% block nav %}
<nav>
<a href="/">Home</a> |
<a href="/dashboard">Dashboard</a> |
<a href="/settings">Settings</a>
</nav>
{% endblock %}
</div>
<div class="content">
{% block content %}{% endblock %}
</div>
<div class="footer">
{% block footer %}
<p>© 2023 MyApp. All rights reserved.</p>
{% endblock %}
</div>
</body>
</html>
"""
# Dashboard template: templates/dashboard.html
"""
{% extends "base.html" %}
{% block title %}{{ page_title }} - MyApp{% endblock %}
{% block header %}{{ page_title }}{% endblock %}
{% block content %}
<p>Welcome back, {{ user.name }} ({{ user.role }})</p>
<h2>System Statistics</h2>
<div class="stats">
{% for stat in stats %}
<div class="stat-item">
<strong>{{ stat.label }}:</strong> {{ stat.value }}
<span class="trend-{{ stat.trend }}">{{ stat.trend }}</span>
</div>
{% endfor %}
</div>
<h2>Recent Activity</h2>
<ul>
{% for activity in recent_activity %}
<li>{{ activity }}</li>
{% endfor %}
</ul>
{% endblock %}
"""
# Usage:
# myapp page dashboardInstall with Tessl CLI
npx tessl i tessl/pypi-cement