Skip to main content

philiprehberger-text-table

Tests PyPI version Last updated

philiprehberger-text-table

Render data as clean ASCII/Unicode tables in the terminal with zero configuration.

Installation

pip install philiprehberger-text-table

Usage

from philiprehberger_text_table import table

headers = ["Name", "Age", "City"]
rows = [
    ["Alice", 30, "New York"],
    ["Bob", 25, "London"],
    ["Charlie", 35, "Tokyo"],
]

print(table(headers, rows))

Output:

┌─────────┬─────┬──────────┐
│ Name    │ Age │ City     │
├─────────┼─────┼──────────┤
│ Alice   │  30 │ New York │
│ Bob     │  25 │ London   │
│ Charlie │  35 │ Tokyo    │
└─────────┴─────┴──────────┘

From dictionaries

from philiprehberger_text_table import from_dicts

data = [
    {"name": "Alice", "score": 95},
    {"name": "Bob", "score": 87},
]

print(from_dicts(data))

From dataclasses

from dataclasses import dataclass

from philiprehberger_text_table import from_dataclasses


@dataclass
class Person:
    name: str
    age: int


print(from_dataclasses([Person("Alice", 30), Person("Bob", 25)]))

Field names become the headers. Passing anything other than dataclass instances raises TypeError; an empty list returns "".

headers = ["Item", "Qty", "Price"]
rows = [["Apple", 3, 1.5], ["Banana", 12, 0.25]]

print(table(headers, rows, title="Fruit Stand", footer=["Total", 15, ""]))

Output:

┌──────────────────────┐
│     Fruit Stand      │
├────────┬─────┬───────┤
│ Item   │ Qty │ Price │
├────────┼─────┼───────┤
│ Apple  │   3 │   1.5 │
│ Banana │  12 │  0.25 │
├────────┼─────┼───────┤
│ Total  │  15 │       │
└────────┴─────┴───────┘

The title is centered across the full table width; if it is wider than the table, the last column widens to fit, and max_width truncates it like any cell. The footer must have one cell per header (ValueError otherwise), counts toward column widths, and uses each column's alignment. In "minimal" and "compact" styles the footer sits below a dashed separator and the title is a centered line. In "markdown" the title is a plain line followed by a blank line, and the footer is the last row with no extra separator (Markdown tables allow only one delimiter row).

From CSV

from philiprehberger_text_table import from_csv

print(from_csv("data.csv"))

Styles

# ASCII style
print(table(headers, rows, style="ascii"))

# Markdown style
print(table(headers, rows, style="markdown"))

# Minimal style (no borders)
print(table(headers, rows, style="minimal"))

# Compact style (no outer borders)
print(table(headers, rows, style="compact"))

# Rounded Unicode corners
print(table(headers, rows, style="rounded"))

# Double-line borders
print(table(headers, rows, style="double"))

Column alignment

# Override auto-detection for all columns
print(table(headers, rows, align="center"))

# Per-column alignment
print(table(headers, rows, align=["left", "center", "right"]))

From CSV string

from philiprehberger_text_table import from_csv_string

csv_data = "Name,Age\nAlice,30\nBob,25"
print(from_csv_string(csv_data))

From JSON

from philiprehberger_text_table import from_json, from_json_string

# List of dicts (keys become headers)
print(from_json_string('[{"name":"Alice","age":30},{"name":"Bob","age":25}]'))

# List of lists (first inner list is the header row)
print(from_json_string('[["Name","Age"],["Alice",30],["Bob",25]]'))

# Read from a file
print(from_json("data.json"))

Truncation

print(table(headers, rows, max_width=10))

Round-tripping CSV

from philiprehberger_text_table import to_csv, from_csv

csv_text = to_csv(
    [["Alice", 30], ["Bob", 25]],
    headers=["Name", "Age"],
    file="people.csv",  # optional — also writes to disk
)
print(csv_text)
# Name,Age
# Alice,30
# Bob,25

# Re-read and render
print(from_csv("people.csv"))

Round-tripping JSON

from philiprehberger_text_table import to_json, from_json_string

json_text = to_json(
    [["Alice", 30], ["Bob", 25]],
    headers=["name", "age"],  # omit for a plain array of arrays
)
print(json_text)
# [
#   {"name": "Alice", "age": 30},
#   {"name": "Bob", "age": 25}
# ]

# Re-render as a table
print(from_json_string(json_text))

Computing column widths

from philiprehberger_text_table import column_widths

widths = column_widths(["name", "count"], [["alice", 100], ["bob", 5]])
# [5, 5]  — max of header and cell str-lengths per column

API

Function / Class Description
table(headers, rows, *, style="unicode", max_width=None, align=None, title=None, footer=None) Render a table from headers and row data, with an optional centered title and summary footer row
from_dicts(data, *, style="unicode", max_width=None, align=None, title=None, footer=None) Render a table from a list of dictionaries
from_dataclasses(items, *, style="unicode", max_width=None, align=None, title=None, footer=None) Render a table from a list of dataclass instances (field names become headers)
from_csv(path, *, style="unicode", max_width=None, align=None, title=None, footer=None) Read a CSV file and render as a table
from_csv_string(text, *, style="unicode", max_width=None, align=None, title=None, footer=None) Render a table from CSV string content
from_json(path, *, style="unicode", max_width=None, align=None, title=None, footer=None) Read a JSON file and render as a table (list of dicts or list of lists)
from_json_string(text, *, style="unicode", max_width=None, align=None, title=None, footer=None) Render a table from a JSON string
to_csv(rows, *, headers=None, file=None) Render rows back to a CSV string (round-trips with from_csv); optionally writes to a file
to_json(rows, *, headers=None, file=None, indent=2) Render rows to a JSON string (round-trips with from_json); optionally writes to a file
column_widths(headers, rows) Return the per-column widths the renderer would compute

Style values

Style Description
"unicode" Box-drawing borders (default)
"rounded" Box-drawing borders with rounded corners
"double" Double-line box-drawing borders
"ascii" +, -, and | borders
"markdown" GitHub-flavored Markdown table
"minimal" No borders, dashed header separator
"compact" Inner separators only, no outer borders

Alignment values

Alignment Description
None Auto-detect (default): numeric columns right-aligned, others left-aligned
"left" Left-align cells
"right" Right-align cells
"center" Center cells

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this project useful:

⭐ Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

Metadata

Release files for philiprehberger-text-table 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for philiprehberger-text-table 0.6.0
File Size Uploaded Provenance Actions
philiprehberger_text_table-0.6.0.tar.gz 199.8 kB Without provenance Details for philiprehberger_text_table-0.6.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for philiprehberger-text-table 0.6.0
File Interpreter ABI Platform Actions
philiprehberger_text_table-0.6.0-py3-none-any.whl Python 3 none any Details for philiprehberger_text_table-0.6.0-py3-none-any.whl

Total release size: 209.9 kB

Release files / philiprehberger_text_table-0.6.0.tar.gz

Download URL philiprehberger_text_table-0.6.0.tar.gz
Size 199.8 kB
Tags Source
SHA-256 checksum
How to use checksums
89c39233a791c51605f78fe5a520220ba6a8bdaab572b72710c23a1ccc068e33
BLAKE2b-256 checksum
How to use checksums
91457fbb068c2ef5dc83a9234aea8f96d3ae9b2d33bb4845243251030f652f50
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Release files / philiprehberger_text_table-0.6.0-py3-none-any.whl

Download URL philiprehberger_text_table-0.6.0-py3-none-any.whl
Size 10.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
434243256dfe17dd8e604a34f8653c81b50c60aa2c18624ca91e2be295adef0c
BLAKE2b-256 checksum
How to use checksums
be6a8c243031adcc283ee573a5fd899791452be13c979f3e737fb1956f25d47e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.15

Security for philiprehberger-text-table 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page