Claude Code for Mako: Python Template Engine — Claude Skills 360 Blog
Blog / AI / Claude Code for Mako: Python Template Engine
AI

Claude Code for Mako: Python Template Engine

Published: April 22, 2028
Read time: 5 min read
By: Claude Skills 360

Mako is a high-performance Python template engine with full Python syntax inside templates. pip install mako. Render string: from mako.template import Template; t = Template("Hello, ${name}!"); t.render(name="World"). Variables: ${expr} → HTML-escaped. ${expr | n} → no escape. Filters: ${val | h} HTML, ${val | u} URL, ${val | n} none. Control: % if cond: / % elif: / % else: / % endif. Loop: % for item in items: / % endfor. Def: <%def name="my_fn(x)"> ... </%def>. Call: ${my_fn(42)}. Lookup: from mako.lookup import TemplateLookup; lookup = TemplateLookup(directories=["templates"]); t = lookup.get_template("page.html"). Inherit: child → <%inherit file="base.html"/>. Block: <%block name="content"> ... </%block>. Include: <%include file="header.html"/>. Namespace: from ns import fn with <%namespace file="helpers.html" import="*"/>. Comments: ## comment (single line), <%doc> ... </%doc> (block). Text block: <%text> raw text, no parsing </%text>. Module-level: <%! import datetime %> — module-level Python. Code block: <% x = 1 %> — inline Python. Render: t.render_unicode() → str. t.render() → bytes. Context: from mako.runtime import Context. Claude Code generates Mako HTML templates, email templates, and code generation pipelines.

CLAUDE.md for Mako

## Mako Stack
- Version: mako >= 1.3 | pip install mako
- Render: Template("text ${var}").render(var="val") → bytes
- Unicode: Template("...").render_unicode() → str
- Lookup: TemplateLookup(directories=["tmpl"]).get_template("page.html")
- Escape: ${val} → auto HTML-escape | ${val | n} → raw | ${val | u} → URL
- Control: % if / % for / % while — full Python indented with %
- Def: <%def name="fn(x)"> ... </%def> | ${fn(arg)}

Mako Template Pipeline

# app/templates.py — mako rendering, lookup, inheritance, and code-gen helpers
from __future__ import annotations

import os
import textwrap
from pathlib import Path
from typing import Any

from mako.lookup import TemplateLookup
from mako.template import Template


# ─────────────────────────────────────────────────────────────────────────────
# 1. Inline template rendering
# ─────────────────────────────────────────────────────────────────────────────

def render(tmpl_str: str, **context: Any) -> str:
    """
    Render a Mako template string with the given context variables.
    Returns the rendered Unicode string.

    Example:
        render("Hello, ${name}!", name="Alice") → "Hello, Alice!"
    """
    return Template(tmpl_str).render_unicode(**context)


def render_bytes(tmpl_str: str, encoding: str = "utf-8", **context: Any) -> bytes:
    """Render template to bytes."""
    return Template(tmpl_str, output_encoding=encoding).render(**context)


def render_file(path: str | Path, **context: Any) -> str:
    """Render a .html/.txt template file from the given path."""
    text = Path(path).read_text(encoding="utf-8")
    return Template(text, filename=str(path)).render_unicode(**context)


# ─────────────────────────────────────────────────────────────────────────────
# 2. TemplateLookup — filesystem-based templates
# ─────────────────────────────────────────────────────────────────────────────

def make_lookup(
    directories: list[str | Path],
    module_directory: str | None = None,
    input_encoding: str = "utf-8",
    strict_undefined: bool = True,
    filesystem_checks: bool = True,
) -> TemplateLookup:
    """
    Create a TemplateLookup for directory-based template resolution.
    module_directory: path to cache compiled .py modules for speed.

    Usage:
        lookup = make_lookup(["templates"])
        html = lookup.get_template("emails/welcome.html").render_unicode(**ctx)
    """
    kw: dict[str, Any] = {
        "directories": [str(d) for d in directories],
        "input_encoding": input_encoding,
        "filesystem_checks": filesystem_checks,
    }
    if module_directory:
        kw["module_directory"] = module_directory
    if strict_undefined:
        kw["strict_undefined"] = True
    return TemplateLookup(**kw)


def render_template(
    lookup: TemplateLookup,
    name: str,
    **context: Any,
) -> str:
    """
    Render a named template from a TemplateLookup.
    name: relative template path, e.g. "emails/welcome.html"
    """
    return lookup.get_template(name).render_unicode(**context)


# ─────────────────────────────────────────────────────────────────────────────
# 3. Email template helpers
# ─────────────────────────────────────────────────────────────────────────────

_WELCOME_EMAIL_TMPL = """\
Subject: Welcome to ${app_name}, ${user_name}!

Hello ${user_name},

Thank you for joining ${app_name}. Your account is ready.

## Your Details
- Email:    ${email}
- Plan:     ${plan}
- Joined:   ${joined_date}

% if features:
## Your Plan Includes
% for feature in features:
  - ${feature}
% endfor
% endif

To get started, visit: ${login_url}

If you have any questions, reply to this email.

Best regards,
The ${app_name} Team
"""


_HTML_EMAIL_TMPL = """\
<!DOCTYPE html>
<html>
<body style="font-family: sans-serif; max-width: 600px; margin: 0 auto;">
  <h1>Welcome, ${user_name | h}!</h1>
  <p>Thank you for joining <strong>${app_name | h}</strong>.</p>
  <table>
    <tr><td><b>Email:</b></td><td>${email | h}</td></tr>
    <tr><td><b>Plan:</b></td><td>${plan | h}</td></tr>
  </table>
  % if features:
  <h2>Your Plan Includes</h2>
  <ul>
    % for feature in features:
    <li>${feature | h}</li>
    % endfor
  </ul>
  % endif
  <p><a href="${login_url | h}">Log in now</a></p>
</body>
</html>
"""


def render_welcome_email(
    user_name: str,
    email: str,
    app_name: str,
    plan: str,
    login_url: str,
    features: list[str] | None = None,
    html: bool = False,
    joined_date: str = "",
) -> str:
    """
    Render a welcome email as plain text or HTML.
    """
    ctx = {
        "user_name":   user_name,
        "email":       email,
        "app_name":    app_name,
        "plan":        plan,
        "login_url":   login_url,
        "features":    features or [],
        "joined_date": joined_date,
    }
    tmpl = _HTML_EMAIL_TMPL if html else _WELCOME_EMAIL_TMPL
    return render(tmpl, **ctx)


# ─────────────────────────────────────────────────────────────────────────────
# 4. Code generation helpers
# ─────────────────────────────────────────────────────────────────────────────

_PYTHON_MODULE_TMPL = """\
<%! from datetime import date %>
# Generated by ${generator} on ${date.today().isoformat()}
# DO NOT EDIT — regenerate with: ${regen_cmd}
from __future__ import annotations

% for imp in imports:
${imp}
% endfor

% for cls in classes:
class ${cls.name}(${cls.base}):
    """${cls.docstring}"""
    % for field in cls.fields:
    ${field.name}: ${field.type_}${' = ' + repr(field.default) if field.default is not None else ''}
    % endfor

% endfor
% for func in functions:
def ${func.name}(${func.signature}) -> ${func.return_type}:
    """${func.docstring}"""
    ${func.body | n}


% endfor
"""

_SQL_SCHEMA_TMPL = """\
-- Generated by ${generator}
-- Tables: ${", ".join(t.name for t in tables)}

% for table in tables:
CREATE TABLE IF NOT EXISTS ${table.name} (
    % for i, col in enumerate(table.columns):
    ${col.name} ${col.type_}${' NOT NULL' if col.not_null else ''}${' PRIMARY KEY' if col.primary_key else ''}${' DEFAULT ' + str(col.default) if col.default is not None else ''}${',' if i < len(table.columns) - 1 else ''}
    % endfor
);

% endfor
"""


def render_python_module(
    classes: list[Any],
    functions: list[Any],
    imports: list[str] | None = None,
    generator: str = "mako codegen",
    regen_cmd: str = "python generate.py",
) -> str:
    """Render a Python module from structured class/function definitions."""
    return render(
        _PYTHON_MODULE_TMPL,
        classes=classes,
        functions=functions,
        imports=imports or [],
        generator=generator,
        regen_cmd=regen_cmd,
    )


def render_sql_schema(tables: list[Any], generator: str = "mako codegen") -> str:
    """Render a SQL CREATE TABLE schema from table definitions."""
    return render(_SQL_SCHEMA_TMPL, tables=tables, generator=generator)


# ─────────────────────────────────────────────────────────────────────────────
# 5. HTML report helpers
# ─────────────────────────────────────────────────────────────────────────────

_HTML_TABLE_TMPL = """\
<table class="${table_class | h}">
  <thead>
    <tr>
      % for col in columns:
      <th>${col | h}</th>
      % endfor
    </tr>
  </thead>
  <tbody>
    % for row in rows:
    <tr class="${loop.index % 2 == 0 and 'even' or 'odd'}">
      % for cell in row:
      <td>${cell | h}</td>
      % endfor
    </tr>
    % endfor
  </tbody>
</table>
"""


def render_html_table(
    columns: list[str],
    rows: list[list[Any]],
    table_class: str = "data-table",
) -> str:
    """Render an HTML table from column names and row data."""
    return render(
        _HTML_TABLE_TMPL,
        columns=columns,
        rows=[[str(cell) for cell in row] for row in rows],
        table_class=table_class,
    )


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    print("=== Basic render ===")
    out = render(
        "Hello, ${name | h}! You have ${count} message${'s' if count != 1 else ''}.",
        name="Alice & Bob",
        count=3,
    )
    print(out)

    print("\n=== For loop + if ===")
    tmpl = """\
Items:
% for i, item in enumerate(items, 1):
  ${i}. ${item | h}${'  ← first!' if i == 1 else ''}
% endfor
% if not items:
  (none)
% endif
"""
    print(render(tmpl, items=["Python", "Mako", "<Templates>"]))
    print(render(tmpl, items=[]))

    print("\n=== Def (reusable component) ===")
    tmpl2 = """\
<%def name="badge(label, color='blue')"><span class="badge badge-${color | h}">${label | h}</span></%def>
Roles: ${badge('admin', 'red')} ${badge('user')} ${badge('guest', 'gray')}
"""
    print(render(tmpl2))

    print("\n=== Welcome email (plain text) ===")
    email = render_welcome_email(
        user_name="Alice",
        email="[email protected]",
        app_name="MyApp",
        plan="Pro",
        login_url="https://myapp.com/login",
        features=["Unlimited projects", "Priority support", "API access"],
        joined_date="2028-04-22",
    )
    print(email[:400])

    print("\n=== HTML table ===")
    html = render_html_table(
        columns=["Name", "Role", "Score"],
        rows=[["Alice", "admin", 95], ["Bob", "user", 72], ["Carol", "mod", 88]],
    )
    print(html[:300])

For the Jinja2 alternative — Jinja2 is the most popular Python template engine with sandboxed execution, a large ecosystem (Flask, FastAPI, Ansible), and strict separation of logic from templates; Mako allows full Python expressions (% for, % if, <% code %>) making it more powerful for code generation and technical templates where Python logic is intentional — Mako is notably used by Pyramid and SQLAlchemy’s migration tool Alembic. For the string.Template stdlib alternative — Python’s string.Template only supports $var substitution with no control flow, no loops, no filters; Mako supports full Python syntax, template inheritance, namespace imports, and auto-escaping, making it suitable for generating complex HTML, SQL, or source code. The Claude Skills 360 bundle includes Mako skill sets covering render()/render_bytes()/render_file(), make_lookup()/render_template() filesystem templates, ${expr}/% if/% for/<%def> syntax examples, render_welcome_email() plain text + HTML, render_python_module() code generation, render_sql_schema() DDL generation, render_html_table(), and h/u/n escape filter examples. Start with the free tier to try Mako template code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free