Skip to main content

fast5ever

fast5ever parses HTML into a mutable DOM for Python programs. You can inspect and edit nodes, construct elements, and serialize the result as HTML. It uses Servo's html5ever for WHATWG-compliant parsing and serialization.

html5ever implements the specification's algorithms and requires a separate tree implementation. fast5ever supplies an arena-based DOM and Python bindings. Parsing, error recovery, and serialization follow the same algorithms and produce the same results as a browser's innerHTML.

from fast5ever import parse, parse_fragment

frag = parse_fragment('<p>one<p>two')
frag.to_html()                        # '<p>one</p><p>two</p>'
[c.name for c in frag.children]       # ['p', 'p']
frag.children[0].attrs['class'] = 'lead'   # attrs is live: writes go straight to the tree

from fast5ever import Span
frag.children[0].replace(Span('replacement', cls='lead'))

doc = parse('<!DOCTYPE html><title>t</title>hello')
doc.to_html()                         # '<!DOCTYPE html><html><head><title>t'...

API

parse(html) parses a complete document. parse_fragment(html, context='body') parses a fragment in a context element. For example, use context='tbody' to parse table rows. Both functions return a Document node.

Nodes and attributes

Every node is a Document, Element, Text, Comment, or Doctype. These classes inherit from Node. Use isinstance(c, Text) to check a node's type.

All nodes provide .name, .children, .parent, to_html(), and to_text(). An element's .name is its tag name. Other node names are #document, #text, #comment, and #doctype. Assigning el.name = 'details' renames an element in place and preserves its attributes and children.

For element queries:

  • .element_children returns direct element children in order, including SVG/MathML elements but excluding text and comments. It does not enter template contents; use template.content.element_children for those.
  • el.is_tag('a') matches an HTML anchor, not an SVG anchor. Pass a namespace URL explicitly for foreign elements: el.is_tag('a', namespace='http://www.w3.org/2000/svg'). Names are case-sensitive; .name remains the local name regardless of namespace.
  • el.has_class('lead') checks a complete, case-sensitive class token, separated by HTML's ASCII whitespace. Non-elements return False for both predicates.

An undefined Python property reads the corresponding HTML attribute, with underscores converted to hyphens. For example, el.data_op reads data-op. An absent attribute raises AttributeError. Write attributes through .attrs.

el.attrs is a live mapping in source order. It supports the following operations:

  • Read, set, and delete entries with attrs['k'], attrs['k'] = v, and del attrs['k'].
  • Use in, len, and iteration as with a dictionary.
  • Call get, keys, values, items, update, and pop.
  • Compare with any mapping using ==, or take a snapshot with dict(attrs).

On non-element nodes, .attrs reads as an empty mapping and rejects writes.

.text contains a text or comment node's own content. Assign to it with t.text = 'new'. template.content returns a <template> element's contents as a Document.

Constructing elements

Element(name, attrs=None), Text(text), and Comment(text) construct detached nodes for insertion.

Undefined capitalized module attributes create element factories using fastcore.xml naming conventions. For example, from fast5ever import CustomTag provides a factory for <custom-tag>. Calling CustomTag('text', cls='x', data_kind='demo') constructs <custom-tag class="x" data-kind="demo">text</custom-tag>.

Positional strings become escaped Text nodes. Positional nodes remain nodes. fastcore.xml.Safe and fastcore.basics.NotStr values contain trusted markup. The constructor parses these as fragments in the new element's context, including the context required for table children.

Changing the tree

Use these methods to insert, replace, or remove nodes:

  • append_child(child) appends a child.
  • insert_before(child, reference) inserts a child before a reference node.
  • replace_child(new, old) replaces a child.
  • old.replace(new) is shorthand for old.parent.replace_child(new, old).
  • el.unwrap() replaces an element with its contents.
  • detach() removes a node from its parent.

Inserting a Document inserts its children, following DocumentFragment semantics. For example, old.replace(parse_fragment(markup)) replaces old with the parsed markup. Inserting a node from another tree deep-copies it. Node handles stay valid across all mutations.

The API uses WHATWG DOM terminology. Its Python node classes, live attribute mapping, to_html(), and to_text() are modeled on Emil Stenström's JustHTML.

Serialization and nesting

fast5ever uses html5ever's implementation of the WHATWG serialization algorithm. Its output matches Chrome's innerHTML byte for byte. The output conventions include:

  • Boolean attributes have empty values, such as open="".
  • Attribute values use double quotes.
  • Void elements have no closing /.
  • Text inside script and style remains unescaped.

fast5ever provides no serialization formatting options or compatibility shims for other serializers.

Parsing flattens element nesting beyond 512 levels, matching Chromium's limit. This keeps parsing linear-time for deeply nested input. html5ever's tree builder alone takes quadratic time for that input.

The Rust API

The Python API binds to the fast5ever Rust crate. Add the crate as a dependency with fast5ever = { git = "https://github.com/AnswerDotAI/fast5ever" }.

Both APIs provide the same tree operations. In Rust, you hold a Dom containing a Vec-indexed arena and address its nodes by NodeId. There are no separate node objects. Node 0 (DOCUMENT) is always the document. Every id stays valid for the life of the Dom, including after tree mutations.

use fast5ever::{parse_fragment, DOCUMENT};

let mut dom = parse_fragment("<p>one<p>two", "body");
let p = dom.children(DOCUMENT)[0];
dom.set_attr(p, "class", "lead").unwrap();
let extra = parse_fragment("<b>!</b>", "body");
let extra = dom.import(&extra, DOCUMENT);   // cross-tree moves go through an explicit import
dom.append_child(p, extra).unwrap();        // a document node splices its children, as in Python
assert_eq!(dom.to_html(DOCUMENT), r#"<p class="lead">one<b>!</b></p><p>two</p>"#);

Read methods use the Python names: children, parent, attr, to_html, and to_text. Mutation methods return Result where Python raises an exception. These include set_attr, set_text, append_child, insert_before, replace_child, and detach.

Element queries are dom.element_children(id), dom.tag(id) (the local name, or None for non-elements), dom.is_tag(id, "a", None) (None selects HTML; Some(url) selects another namespace), and dom.has_class(id, "lead").

Construct nodes with create_element, create_text, and create_comment, corresponding to Python's Element, Text, and Comment. Rust also provides NodeData matching for direct tree inspection.

Development

pip install -e .[dev]
cargo develop && pytest -q

All tests use pytest. cargo check and cargo clippy run without warnings and do not need Python. The python feature enables pyo3.

Release

ship-release pushes a tag for CI to publish, then bumps the version.

cargo develop && pytest -q
ship-release

The GitHub workflow builds wheels on tags matching v* and publishes them to GitHub Releases and PyPI.

Metadata

Release files for fast5ever 0.1.7

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

Source distribution (sdist)

Source distribution for fast5ever 0.1.7
File Size Uploaded
fast5ever-0.1.7.tar.gz 33.2 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for fast5ever 0.1.7
File
fast5ever-0.1.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.7-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
fast5ever-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.7-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
fast5ever-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.7-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
fast5ever-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.17+ x86-64 Details
fast5ever-0.1.7-cp310-cp310-macosx_11_0_arm64.whl CPython 3.10 CPython 3.10 macOS 11.0+ ARM64 Details

Total release size: 4.2 MB

Release files / fast5ever-0.1.7.tar.gz

Download URL fast5ever-0.1.7.tar.gz
Size 33.2 kB
Tags Source
SHA-256 checksum
How to use checksums
9565dc69dcb0a9773251aa5fbf2df0a09ffd0c0b610b44ac06c3b3089874f187
BLAKE2b-256 checksum
How to use checksums
0a402b2579bb7281f5e78e2e44a2673e3fe213ff4b4917f09bf8c75fc690e857
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 544.4 kB
Tags CPython 3.13 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
f4517b08089ae7bbf790acb23ed6a479400cecc2739574a5fbcf14ff5103f31d
BLAKE2b-256 checksum
How to use checksums
ff6e108f1d22e5ba6398a9b065f33e4812756c91313e8ca062625a7ec01458cc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp313-cp313-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.7-cp313-cp313-macosx_11_0_arm64.whl
Size 497.3 kB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9f17c54f1fc5ee8baa94989bc9d07ccb4969f2f35d516da92dd1532f720b058e
BLAKE2b-256 checksum
How to use checksums
6e126abe18cb3129fa65c38dd1298db3a140b43b32e71ebb9b8b08da4b5ce460
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 544.1 kB
Tags CPython 3.12 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
d031c3a4bbb17f667250139e465fe2709e3e1d1071323e660f00929fd121b183
BLAKE2b-256 checksum
How to use checksums
aa173ad0e9e7a411024d1300ae02aeca71c5bdf21f7c7ddd18adac5e44c851ea
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp312-cp312-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.7-cp312-cp312-macosx_11_0_arm64.whl
Size 497.3 kB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
4df7685f6c704ed7c2baff170d2eb31cc6ab4ec7190adc55163c8ea999eb9cf5
BLAKE2b-256 checksum
How to use checksums
104e118126151ab45df79d8300220e710a1fded69d8576390403d0239d4e9bb5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 544.6 kB
Tags CPython 3.11 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
b19b4833a46090a5b072ee4997ca3c2e86174d96c4d9845c4412ee69a2953331
BLAKE2b-256 checksum
How to use checksums
4280c552324c3f7b8594633e8cde7107b2f93bf79d5e659d37b651681a22875f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp311-cp311-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.7-cp311-cp311-macosx_11_0_arm64.whl
Size 499.6 kB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
fb1330aa2a32b4fe5d6cc1e8a16cb580c988be6cfca8686d93de29b4461d1755
BLAKE2b-256 checksum
How to use checksums
a06c31c2a761274ab607574abdb84a7b5fd671301b46daede5865b21bdb71a79
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL fast5ever-0.1.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 544.8 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64
SHA-256 checksum
How to use checksums
928fe04fb23051b559ed889c98aedb679e24563902c8b2875ab8bb3ab8922dc9
BLAKE2b-256 checksum
How to use checksums
5d9dc8c0d5a7dca70367ddd6517aeeafd1d98206b3a33b8ab2d9dae4b2995e26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release files / fast5ever-0.1.7-cp310-cp310-macosx_11_0_arm64.whl

Download URL fast5ever-0.1.7-cp310-cp310-macosx_11_0_arm64.whl
Size 499.7 kB
Tags CPython 3.10 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
f823df4a40581ac56fde637728a040bbc938668d8924b06a258a422d1a4fd4a3
BLAKE2b-256 checksum
How to use checksums
a03140cf8f812bc577c11ad57615a7db06cc902bf950ade43cdd71b61e63a986
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 5, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.7 This release

9 release files

0.1.6

9 release files

0.1.5

9 release files

0.1.4

9 release files

0.1.3

9 release files

0.1.2

9 release files

0.1.1

9 release files

0.1.0

9 release 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