Recount
Python

Tables

Show the data behind a decision as a table in a Python trace, with highlighted rows, summary rows and labelled sections.

The recount.table() builder constructs a single TableData dict. Call .build() to get a value ready to pass directly as span input or output.

Basic usage

recount.add_span("table", "Policy checks", {
    "output": recount.table("Validation Results")
        .from_records([
            {"check": "Policy active", "result": "Pass"},
            {"check": "Cover active at incident", "result": "Pass"},
            {"check": "Comprehensive cover", "result": "Pass"},
        ])
        .highlight_rows(lambda row: "success" if row["result"] == "Pass" else "danger")
        .build(),
})

recount.table(title=None)

Returns a TableBuilder. Chain methods and call .build() to get a TableData dict, ready to use as span input or output.

Data sources

.from_records(data)

Build from a list of dicts. Column names are the dict keys as-is (taken from the first record).

recount.table("Users") \
    .from_records([
        {"name": "Alice", "score": 98.5},
        {"name": "Bob", "score": 72.1},
    ]) \
    .build()

.from_object(data)

Build a key-value table from a plain dict. Renders as two columns: Key and Value.

recount.table("Config") \
    .from_object({"timeout": 5000, "retries": 3, "env": "production"}) \
    .build()

Column selection

.pick(*keys)

Only include the specified columns, in order.

.pick("name", "email", "role")

Labels & formatting

.label(mapping)

Override column display labels.

.label({"usageKwh": "Usage (kWh)", "ratePerKwh": "Rate ($/kWh)"})

.round(decimals)

Round all numeric values to decimals decimal places.

.round(2)

.transform_values(mapping)

Apply a transform function to values in specific columns.

.transform_values({
    "status": lambda v: str(v).upper(),
    "createdAt": lambda v: datetime.fromisoformat(v).strftime("%Y-%m-%d"),
})

Highlighting

.highlight_column(key, highlight)

Apply a highlight color to an entire column header and cells.

.highlight_column("revenue", "success")

.highlight_rows(fn)

Apply a per-row highlight based on the row's data.

def highlight(row):
    if row["errorRate"] > 0.1:
        return "danger"
    if row["errorRate"] > 0.05:
        return "warn"
    return None


.highlight_rows(highlight)

.highlight_cells(key, fn)

Apply a per-cell highlight for a specific column.

def highlight_status(v):
    if v == "error":
        return "danger"
    if v == "ok":
        return "success"
    return None


.highlight_cells("status", highlight_status)

Highlight values: 'danger' | 'warn' | 'success' | 'info' | 'muted'


Column spans

.span_column(key, span)

Make a column header span multiple columns.

.span_column("metrics", 3)

Extra rows

.append_row(cells, highlight=None)

Append a summary row at the bottom of the table.

.append_row(["Total", 450, 890], "info")

Use recount.span_cell(value, span) to create a cell that spans multiple columns:

.append_row([recount.span_cell("Grand total: $1,234", 4)], "success")

.summary(stats)

Define stats shown when this table is collapsed in the dashboard. Each stat has a text string and an optional highlight color.

.summary([
    {"text": "$64.70", "highlight": "info"},
    {"text": "28.8% less", "highlight": "success"},
])

Highlight values: 'danger' | 'warn' | 'success' | 'info' | 'muted'

.build_section()

Returns a TableSection (rows and optional highlights/summary, without column definitions). Used as input to recount.table_sections() when building sectioned tables.

section = recount.table("Active policies") \
    .from_records(active_policies) \
    .highlight_rows(lambda row: "danger" if row["overdue"] else None) \
    .build_section()

recount.table_sections(sections, columns=None, title=None)

Builds a single table with named sections that share the same columns. Use this when you want to group rows under labelled headings within one table span.

recount.add_span("table", "Plan comparison", {
    "output": recount.table_sections(
        [
            recount.table("Medical").from_records([
                {"Benefit": "Hospital", "Current plan": "$500", "Recommended plan": "$250"},
                {"Benefit": "Specialist", "Current plan": "Not covered", "Recommended plan": "$50"},
            ]).highlight_rows(
                lambda row: "warn" if row["Recommended plan"] == "Not covered" else None
            ),
            recount.table("Extras").from_records([
                {"Benefit": "Dental", "Current plan": "Not covered", "Recommended plan": "80%"},
                {"Benefit": "Optical", "Current plan": "50%", "Recommended plan": "80%"},
            ]),
        ],
        title="Coverage breakdown",
        columns=["Benefit", "Current plan", "Recommended plan"],
    ),
})

Parameters

ParameterTypeDescription
sectionslist[TableBuilder | TableSection]At least one section. Pass TableBuilder instances (built via .build_section() internally) or raw TableSection dicts
columnslist[TableColumn]Column definitions shared across all sections. Can be omitted when the first section is a TableBuilder; columns are derived from it automatically
titlestrOptional title for the whole table

sections is required and positional; columns and title are keyword-only in practice. When columns is omitted, the first section must be a TableBuilder instance, not a plain dict.

Raw TableSection dicts

Sections can also be plain dicts instead of builder instances:

recount.table_sections(
    [
        {
            "title": "Q1",
            "rows": [
                ["NSW", 142, "$4,200"],
                ["VIC", 98, "$3,800"],
            ],
        },
        {
            "title": "Q2",
            "rows": [
                ["NSW", 167, "$4,500"],
                ["VIC", 110, "$4,100"],
            ],
        },
    ],
    columns=["Region", "Claims", "Avg settlement"],
)

recount.span_cell(value, span)

Creates a cell that spans span columns. Only useful inside .append_row().

recount.span_cell("Total Cost: $99.00", 3)

Multiple tables

To display multiple tables that share the same columns as labelled sections, use recount.table_sections().

To display distinct tables together, use a group span. Each table is its own span inside the group:

def build_group(g):
    g.span("table", "Summary", {
        "output": recount.table_from_object({
            "claimId": "CLM-2024-03941",
            "decision": "Approved",
            "settlement": "$6,840.00",
        }, title="Summary"),
    })

    g.span("table", "Breakdown", {
        "output": recount.table("Breakdown")
            .from_records([
                {"item": "Vehicle repairs", "amount": 5200},
                {"item": "Rental car", "amount": 840},
                {"item": "Medical", "amount": 800},
            ])
            .round(2)
            .build(),
    })


recount.add_group("Claim report", build_group)

Shorthand exports

For simple cases where you don't need to chain builder methods, two direct exports are available:

recount.table_from_records(data, title=None)

Equivalent to recount.table(title).from_records(data).build(). Returns TableData directly.

recount.add_span("table", "Policy checks", {
    "output": recount.table_from_records(
        [
            {"check": "Policy active", "result": "Pass"},
            {"check": "Cover active at incident", "result": "Pass"},
        ],
        title="Validation Results",
    ),
})

recount.table_from_object(data, title=None)

Equivalent to recount.table(title).from_object(data).build(). Returns TableData directly.

recount.add_span("table", "Claim summary", {
    "output": recount.table_from_object(
        {
            "claimId": "CLM-2024-03941",
            "vehicle": "2019 Toyota Camry",
            "decision": "Approved",
        },
        title="Claim Details",
    ),
})

On this page