Skip to main content

leptris (Python) — lxml-shaped bindings for libleptris

leptris wraps the libleptris C API (XML 1.0 parsing, XPath 1.0) using cffi in ABI mode, with a required C accelerator for Element allocation and the hot accessors (tag, text, attrib, get, indexing, sibling navigation and plain-path XPath evaluation). Wheels ship it compiled; sdist builds require a C compiler.

The pinned libleptris version lives in libleptris-version.txt (lockstep releases); CI builds it from the release tarball. The binding loads the shared library from LEPTRIS_LIB_PATH or the loader path.

Requirements

  • Python 3.9+
  • cffi (installed automatically)
  • libleptris 1.9.3+ as a shared library (1.9.1 has an options-struct ABI break — leptris/leptris#568)
  • libleptris as a shared library (libleptris.dylib / .so / .dll) on the loader path, or pointed to by LEPTRIS_LIB_PATH (which must name the library file — the loader dlopens it verbatim). For a development checkout:
cmake -B build -S /path/to/leptris -DLEPTRIS_BUILD_SHARED=ON
cmake --build build --target leptris_shared
export LEPTRIS_LIB_PATH=/path/to/leptris/build/src/libleptris.dylib

Quick start

from leptris import fromstring, tostring

root = fromstring("<library><book id='1' lang='en'>Ulysses</book></library>")

root.tag                                # "library"
root[0].get("id")                       # "1"
root[0].attrib                          # {"id": "1", "lang": "en"}
root[0].text                            # "Ulysses"

root.xpath("count(//book)")             # 1.0
[b.text for b in root.findall("book")]  # ["Ulysses"]

tostring(root[0], encoding="unicode")   # "<book id=\"1\" lang=\"en\">Ulysses</book>"

Documents own the tree; use the context manager or close():

from leptris import parse

with parse("catalog.xml") as doc:
    doc.xpath("//book[@lang='en']")

Namespaces, variables, canonical XML and streaming:

root.xpath("//x:item", namespaces={"x": "urn:ex"})
root.xpath("//book[@id=$id]", variables={"id": "2"})
c14n(root, exclusive=True)

from leptris import sax
sax.parse(xml, handler)                       # one-shot
with sax.StreamingParser(handler) as parser:  # push, constant memory
    parser.feed(chunk, final=last)

Migrating from lxml

lxml leptris Notes
etree.fromstring / etree.XML fromstring / XML
etree.parse parse paths and file-likes; no URLs
etree.tostring(elem, …) tostring(elem, …) bytes by default, encoding="unicode" for str
elem.tag / .text / .tail same tag uses {uri}local Clark notation; CDATA merges into text (lxml's default parser behavior)
elem.attrib / .get() / .keys() / .items() same attrib is a read-only Mapping
elem.getparent/getnext/getprevious same
elem[i], len(elem), iteration, slices same indexing is child indexing, never attribute lookup
elem.iter() / .iterdescendants() / .itertext() same elements only (ElementTree semantics); lxml's iter() also yields comments/PIs
elem.find/findall/findtext same accepts full XPath 1.0 — a superset of ElementPath — including {uri}local names
elem.xpath(expr, namespaces=…) same plus variables={…} (leptris extension)
etree.c14n / etree.XInclude c14n(…) / doc.process_xinclude()
etree.XMLSyntaxError ParseError XPath failures raise XPathError; both subclass LeptrisError
etree.Element, SubElement, append, set, remove not exposed libleptris has partial mutation upstream (node content setters, set_root, remove_children) — not surfaced here; build trees elsewhere
document-level comments / PIs doc.toplevel_comments() / doc.toplevel_pis() prolog then epilog; requires libleptris 1.9.3+
etree.iterparse leptris.iterparse(source, full_document=False) bounded by the largest subtree; yields ("end", element); elements borrowed until the next yield; tags resolve namespaces (Clark notation, libleptris 1.9.4+). Truncated or malformed input raises ParseError (libleptris 1.9.4 error channel). full_document=True yields every element in completion order — error detection is unreliable in that mode pending leptris/leptris#592. Still ~2× slower than lxml's iterparse (leptris/leptris#563)
smart strings plain str XPath string/attribute results
elem.nsmap absent use elem.namespace / elem.prefix and xpath(namespaces=…)
etree.XPath compiled objects leptris.XPath(expression) compile once, evaluate many; contexts and namespaces supported
parser options (resolve_entities, …) absent libleptris 1.2.0 has no per-parse options
elem.sourceline same requires libleptris 1.3.0+
undeclared XPath prefix raises in lxml evaluates to an empty nodeset here

Layout

  • leptris/_ffi.py — cdef mirror of the public headers + loader (the only place libleptris is declared)
  • leptris/_leptrisaccel.c — the C accelerator (abi3): allocates Elements and runs the hot accessors, subtree iteration, the parse and serialization seams, and the per-document element registry; bound to libleptris by the positional protocol in element.py
  • leptris/element.py, document.py, node.py, xpath.py — the Python surface: queries, walks, documents; node.py exposes the full DOM (comments, CDATA, PIs) beneath the ElementTree shape
  • leptris/api.pyfromstring/parse/tostring/c14n/ iterparse
  • leptris/sax.py — SAX one-shot and streaming
  • tests/ — pytest suite (pytest with LEPTRIS_LIB_PATH set)
  • benchmarks/ — matrix vs lxml/ElementTree/minidom (pip install .[bench], then python -m benchmarks.matrix)

Memory model

The Document owns the whole tree and its pool. Accessor strings are copied into Python str at the boundary, so nothing depends on document lifetime after a call returns. Elements keep a reference to their Document, so the pool cannot be freed while any wrapper is alive. Prefer explicit close() / the context manager; __del__ is a refcounting safety net, not a contract. Using an element after its document is closed raises LeptrisError.

Versioning

libleptris-version.txt pins the library release the binding is built and tested against. From 1.3.0 the package follows its own semver: 1.2.0 shipped an interim bespoke API to no adopters, and 1.3.0 replaces it with the lxml-shaped API (breaking, but pre-adoption). pyproject.toml and leptris/__init__.py must agree at release time.

Publishing

Releases publish to PyPI via .github/workflows/release.yml, using PyPI trusted publishing (no stored credentials). The workflow runs on manual dispatch (ships the version in pyproject.toml) and is called by the libleptris release flow (publish: true), so every libleptris release ships the wheel.

Local development

python3 -m venv .venv
./.venv/bin/pip install --upgrade build pytest cffi
./.venv/bin/pip install -e .[test,bench]
LEPTRIS_LIB_PATH=/path/to/libleptris.dylib ./.venv/bin/python -m pytest tests/ -q

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

leptris-1.17.1.tar.gz (46.7 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

leptris-1.17.1-cp39-abi3-win_amd64.whl (41.8 kB view details)

Uploaded CPython 3.9+Windows x86-64

leptris-1.17.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (93.8 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ ARM64

leptris-1.17.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (90.1 kB view details)

Uploaded CPython 3.9+manylinux: glibc 2.17+ x86-64manylinux: glibc 2.5+ x86-64

leptris-1.17.1-cp39-abi3-macosx_11_0_arm64.whl (40.1 kB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

leptris-1.17.1-cp39-abi3-macosx_10_9_x86_64.whl (39.6 kB view details)

Uploaded CPython 3.9+macOS 10.9+ x86-64

File details

Details for the file leptris-1.17.1.tar.gz.

File metadata

  • Download URL: leptris-1.17.1.tar.gz
  • Upload date:
  • Size: 46.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for leptris-1.17.1.tar.gz
Algorithm Hash digest
SHA256 26728b3ee576a0c8632ad823d1a8c0689ff9b685eb766163b4177fb2f323a935
MD5 2b891cc98a09ce97c403130add49eac4
BLAKE2b-256 ceb2fa5c36220e11563aa5edcfc9ab4c94b76c23135214559a4c6fac7980a23f

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1.tar.gz:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leptris-1.17.1-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: leptris-1.17.1-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 41.8 kB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for leptris-1.17.1-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 61e9ebf524d83295f31ae0568b3bde7a2cba8149cce1b64732810b19dc761d29
MD5 7b48c08fc4b7eaea1caccecc63c7e33b
BLAKE2b-256 ece824144dc21ae7bb24db1a78a94485cd0157e32203fb032e494e25d6e77cc0

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1-cp39-abi3-win_amd64.whl:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leptris-1.17.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for leptris-1.17.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f712a8befe261441b1cda1e26e735f5eb5f66142037afed4b4a03110c6d58701
MD5 dbb457ee4decf41b83c2440dfbe7befa
BLAKE2b-256 1e541507a782af99a39036458aca1bf120900c6383bbfeb9ff9d3ad9f55341fe

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leptris-1.17.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for leptris-1.17.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d30438494c6c8696599d568361401a3e01ebfcc69cb953d29c61d6bafa581abe
MD5 7be5f2c8be0c18e8fa9131ab5f8d92ab
BLAKE2b-256 cbd7119c16b20f74dd0a5bd2355b229bab66570e52b10281a92220a516d733c8

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leptris-1.17.1-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for leptris-1.17.1-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 b43c65672be27a03452c1430afcb940c7c6574592641d3520e7ad96cc2258aa0
MD5 59af614fc7ea3354b2b129f61a74c566
BLAKE2b-256 db95b0e9c71ae5134093e491ba7a51ff5b8551c7d74fa36e46b776290cb8d7bd

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1-cp39-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file leptris-1.17.1-cp39-abi3-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for leptris-1.17.1-cp39-abi3-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 b6c04633f54277fd6d9754b0ed4638591ced575350a6484a33b1861805b96730
MD5 d82ba8afb863d452cb1897802cbbf62b
BLAKE2b-256 1a37a6cae43ab00bdfeca04d500b60713a9d08aadce5921d75672017a97b765e

See more details on using hashes here.

Provenance

The following attestation bundles were made for leptris-1.17.1-cp39-abi3-macosx_10_9_x86_64.whl:

Publisher: release.yml on leptris/leptris-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.27.1

6 files

1.27.0

6 files

1.26.1

6 files

1.26.0

6 files

1.25.4

6 files

1.25.3

6 files

1.25.2

6 files

1.25.1

6 files

1.25.0

6 files

1.24.3

6 files

1.24.2

6 files

1.24.1

6 files

1.24.0

6 files

1.23.3

6 files

1.23.2

6 files

1.23.1

6 files

1.23.0

6 files

1.22.2

6 files

1.22.1

6 files

1.22.0

6 files

1.21.0

6 files

1.20.0

6 files

1.19.0

6 files

1.18.0

6 files

This release

1.17.1 This release

6 files

1.17.0

6 files

1.16.1

6 files

1.16.0

6 files

1.15.1

6 files

1.15.0

6 files

1.14.3

6 files

1.14.2

6 files

1.14.1

6 files

1.14.0

6 files

1.13.3

6 files

1.13.2

6 files

1.13.1

6 files

1.13.0

6 files

1.12.0

6 files

1.11.1

6 files

1.11.0

6 files

1.10.0

6 files

1.9.93.2

6 files

1.9.93.0

6 files

1.9.90.0

6 files

1.9.87.0

6 files

1.9.86.0

6 files

1.9.84.0

6 files

1.9.83.0

6 files

1.9.80.0

6 files

1.9.79.0

6 files

1.9.76.0

6 files

1.9.0

6 files

1.8.0

6 files

1.7.0

6 files

1.6.1

6 files

1.6.0

5 files

1.5.0

2 files

1.4.1

2 files

1.4.0

2 files

1.3.1

2 files

1.3.0

2 files

1.2.0

2 files

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