ProvenPin Install

tabulate Markdown and grid reports from dict rows: working versions (tested 2026-10-16)

Turn lists of dicts into GitHub Markdown or grid tables with tabulate, controlling column order, labels, missing values and numeric alignment.

passed6 passed · 0 failed2026-10-16 09:58 UTC
Status
passed
Last passed
2026-10-16 09:58 UTC
Tests
6 / 6
Language
Python
Runtime
Python 3.13.16
pinned versions2
tabulate@0.10.0pytest@9.1.1
run it
uv venv -q .venv && uv pip install -q --python .venv/bin/python -r requirements.txt
.venv/bin/python -m pytest -q
test environment
Python 3.13.16
linux 6.17.0-1022-azure
x64
runner: github-actions 38883899161

The code

Exactly the files that passed. Your agent can pull them with get_recipe("tabulate-markdown-report") (install), or see them on GitHub.

requirements.txt
tabulate==0.10.0
pytest==9.1.1
report.py
from tabulate import tabulate


def render(rows, columns=None, tablefmt="github", **kwargs):
    if columns is None:
        return tabulate(rows, headers="keys", tablefmt=tablefmt, **kwargs)
    headers = [label for _, label in columns]
    data = [[row.get(key) for key, _ in columns] for row in rows]
    return tabulate(data, headers=headers, tablefmt=tablefmt, **kwargs)


def markdown_report(rows, columns=None, **kwargs):
    return render(rows, columns, tablefmt="github", **kwargs)


def grid_report(rows, columns=None, **kwargs):
    return render(rows, columns, tablefmt="grid", **kwargs)
tests/test_report.py
from report import grid_report, markdown_report, render

COLUMNS = [("name", "Repo"), ("stars", "Stars"), ("lang", "Lang")]
ROWS = [
    {"name": "alpha", "stars": 12, "lang": "py"},
    {"name": "beta", "stars": 3},
]


def test_markdown_projects_dict_rows_in_declared_order():
    out = markdown_report(ROWS, COLUMNS, missingval="-")
    assert out.splitlines() == [
        "| Repo   |   Stars | Lang   |",
        "|--------|---------|--------|",
        "| alpha  |      12 | py     |",
        "| beta   |       3 | -      |",
    ]


def test_grid_uses_box_drawing():
    out = grid_report(ROWS, [("name", "Repo")], missingval="-")
    assert out.splitlines()[0] == "+--------+"
    assert "| alpha  |" in out
    assert "| beta   |" in out


def test_columns_not_supplied_falls_back_to_keys_union():
    out = render([{"b": 1}, {"a": 2}, {"c": 3}])
    assert out.splitlines()[0] == "|   b |   a |   c |"
    assert out.splitlines()[2] == "|   1 |     |     |"


def test_ragged_rows_get_missingval():
    out = markdown_report(ROWS, COLUMNS, missingval="n/a")
    assert "| beta   |       3 | n/a    |" in out


def test_disable_numparse_changes_alignment_of_numeric_strings():
    parsed = markdown_report([{"id": "007"}], [("id", "ID")]).splitlines()
    raw = markdown_report([{"id": "007"}], [("id", "ID")], disable_numparse=True).splitlines()
    assert parsed[0] == "|   ID |" and parsed[2] == "|  007 |"
    assert raw[0] == "| ID   |" and raw[2] == "| 007  |"


def test_floatfmt_rounds_numeric_cells():
    out = markdown_report([{"ratio": 3.14159}], [("ratio", "Ratio")], floatfmt=".2f")
    assert out.splitlines()[2] == "|    3.14 |"
pytest.ini
[pytest]
pythonpath = .

Connect to ProvenPin

Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.

terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.