RepoSnowflake (Arctic)Snowflake (Arctic)published Jan 27, 2026seen 5d

Snowflake-Labs/jinjamap

Python

Open original ↗

Captured source

source ↗
published Jan 27, 2026seen 5dcaptured 14hhttp 200method plain

Snowflake-Labs/jinjamap

Language: Python

License: Apache-2.0

Stars: 2

Forks: 0

Open issues: 0

Created: 2026-01-27T06:59:52Z

Pushed: 2026-01-28T16:56:26Z

Default branch: main

Fork: no

Archived: no

README:

jinjamap

Map rendered Jinja2 output lines back to original template lines. Essential for debugging SQL templates and tracking errors to their source in complex template projects.

Install

pip install jinjamap

Or install from source:

pip install -e .

Usage

from jinjamap import render_templates_with_mapping

templates = {
"query.sql": "SELECT * FROM {{ table }} WHERE id = {{ user_id }}"
}

result = render_templates_with_mapping(
templates,
{"table": "users", "user_id": 42}
)

print(result.rendered_files["query.sql"])
# SELECT * FROM users WHERE id = 42

for m in result.source_mappings["query.sql"]:
print(f"Output line {m.output_line} → Template line {m.template_line}")

With Custom Environment

from jinja2 import Environment
from jinjamap import render_templates_with_mapping

env = Environment()
env.filters['upper'] = str.upper
env.globals['limit'] = 100

templates = {
"query.sql": "SELECT * FROM {{ table | upper }} LIMIT {{ limit }}"
}

result = render_templates_with_mapping(templates, {"table": "users"}, environment=env)

Multiple Templates

templates = {
"users.sql": "SELECT * FROM {{ table1 }}",
"orders.sql": "SELECT * FROM {{ table2 }}"
}

result = render_templates_with_mapping(
templates,
{"table1": "users", "table2": "orders"}
)

print(result.rendered_files["users.sql"])
print(result.source_mappings["users.sql"])

API

render_templates_with_mapping(templates, variables, environment=None, flat_mode=True)

Args:

  • templates: dict[str, str] - Dict mapping filenames to template strings
  • variables: dict[str, Any] - Variables to pass to templates
  • environment: Environment | None - Optional Jinja2 Environment
  • flat_mode: bool - If True, omit template_file from mappings (default)

Returns: MultiTemplateResult with:

  • rendered_files: dict[str, str] - Rendered content by filename
  • source_mappings: dict[str, list[SourceMapping]] - Mappings by filename
  • get_template_line(filename, output_line) → int | None
  • get_template_file(filename, output_line) → str | None

SourceMapping

  • output_line: int - Line in rendered output (0-indexed)
  • template_line: int - Line in template (0-indexed)
  • template_file: str | None - Template filename (None when flat_mode=True)

Flat Mode

  • flat_mode=True (default): Omit template_file from mappings
  • flat_mode=False: Include template_file (for templates with includes/imports)

How It Works

The problem: when Jinja2 renders a template, there's no built-in way to know which output line came from which template line. Jinja2 itself doesn't provide source mapping functionality.

Alternative approaches like embedding custom Python functions in templates to track line numbers are too slow for large templates. This marker-based approach is up to 100x faster.

The solution: inject invisible markers before rendering, track them through the render, then remove them.

Process:

1. Analyze: Use Jinja2's lexer to find safe injection points (lines without {{ }} or {% %} blocks) 2. Mark: Insert comment markers with unique IDs at those lines 3. Render: Jinja2 processes the marked template normally 4. Track: Scan rendered output for marker positions 5. Clean: Remove all markers and build the line mappings

Example:

Original template (line 0):
SELECT * FROM {{ table }}

After marking:
-- __MARKER_0_0__query.sql
SELECT * FROM {{ table }}

After render:
-- __MARKER_0_0__query.sql
SELECT * FROM users

After cleanup:
SELECT * FROM users

Mapping: [SourceMapping(output_line=0, template_line=0)]

The markers use a correlation ID to ensure they're unique and don't collide with actual template content.

License

Copyright (c) Snowflake Inc. All rights reserved. Licensed under the Apache 2.0 license.

Notability

notability 1.0/10

Low stars, trivial repo.