Skip to main content

ltem (Python)

Reference Python implementation of LTEM: Markdown pipe tables with merged cells and multi-row headers. It follows the LTEM specification, version 1.0.

Status: version 0.1.1, for LTEM 1.0. The API may change before version 1.0.0.

Install

pip install ltem-core              # no dependencies
pip install "ltem-core[markdown]"  # also renders inline Markdown in cells (uses markdown-it-py)

Use

import ltem

result = ltem.parse_table("""\
| Region | Revenue | <<  |
| ^^     | Q1      | Q2  |
|--------|---------|-----|
| Asia   | 100     | 120 |""")

table = result.table            # the table model (see ast/ in the LTEM repository)
table.to_dict()                 # JSON-ready dict
ltem.render_html(table)         # <table> with colspan and rowspan
ltem.write(table)               # canonical LTEM
result.problems                 # validation problems, if any

for item in ltem.from_html(html):   # HTML tables -> table models
    print(ltem.write(item.table), item.warnings)

text, sources = ltem.write_with_sources(table)   # canonical LTEM and where each cell is

Where cells are

ParseResult.sources and write_with_sources give, for each cell of the table and in the same order, a CellSource(row, col, rowspan, colspan, line, start, end):

  • line counts lines from 0: lines of the parsed text for parse_table and find_tables, lines of the table for write_with_sources.
  • start and end index that line in Python string units (code points). They cover the cell's source without the spaces and tabs around it, including any span attribute and escapes.
  • For an empty cell, start equals end, at the end of its space between the pipes. A cell added because its row was short (rule V14) has start == end == the length of its line.

Without markdown-it-py, cell text is HTML-escaped and backslash escapes are applied, but emphasis, links and code are shown as written.

ltem.find_tables(markdown) finds every LTEM table in a Markdown document. It is a light scan that skips code blocks. It is not a full Markdown parser.

Command line

ltem parse    [FILE]          # table models as JSON
ltem render   [FILE]          # HTML of each table
ltem validate [FILE] [--json] # validation problems; exit status 1 if any
ltem fmt      [FILE]          # rewrite every table in canonical form
ltem from-html [FILE] [--header-rows N] [--plain]  # convert HTML tables to LTEM

from_html(html, header_rows=None, inline="markdown") options:

  • header_rows: the number of header rows. By default it is the <thead> rows; without <thead>, the leading rows made only of <th> cells; and if there are none, the first row (with a warning). With 0, the table has no header: it gets one header row of empty cells and every HTML row becomes a body row (spec Section 11).
  • inline: "markdown" keeps emphasis, code, links and images as Markdown; "plain" keeps text only. Either way, text is escaped so that it reads literally.

<th> cells below the header rows become ordinary cells, since LTEM 1.0 has no row headers; the converter reports this once per table in warnings.

from_html forms the grid as browsers do: cells take the next free position, rowspan="0" reaches the end of its row group, and spans stop at the edge of <thead>, <tbody> or <tfoot>. The header rows are the <thead> rows; without <thead>, the leading rows made only of <th> cells; and if there are none, the first row. Cell content becomes inline Markdown: <br> and block elements become line breaks, and <strong>, <em>, <code>, <a>, <img>, lists, <sup> and <sub> are kept. A table inside a cell is flattened to text with a warning, since LTEM 1.0 has no nested tables.

Development

From ltem-lib/python:

uv sync --all-packages
uv run --directory ltem pytest

The tests run the conformance cases in conformance/.

Metadata

Release files for ltem-core 0.1.1

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

Source distribution (sdist)

Source distribution for ltem-core 0.1.1
File Size Uploaded Provenance
ltem_core-0.1.1.tar.gz 27.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for ltem-core 0.1.1
File Interpreter ABI Platform
ltem_core-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 51.7 kB

Release files / ltem_core-0.1.1.tar.gz

Download URL ltem_core-0.1.1.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
0c2ea5dce584dcfa98f3fc5edb3afc6b45f47c3b0e9e1d24620a8dd30b70674e
BLAKE2b-256 checksum
How to use checksums
1d8001fe5f4004cd6ad88f7083b67df117efd526bceff669dbfbbf4742db41a0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / ltem_core-0.1.1-py3-none-any.whl

Download URL ltem_core-0.1.1-py3-none-any.whl
Size 24.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
5146b6223fe543ed1b3a4f9aac1fc07f5d45ddaeba2b0ac8d2522b8e0d8ffee5
BLAKE2b-256 checksum
How to use checksums
2795613b4d4ca2e755dd6c4b47b2d6fddc54adbaa750604c2ca24d14b9c5f574
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Security for ltem-core 0.1.1

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.

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files No provenance

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