Python API
The package root intentionally exports only Lumberjack and Document. Import other public components from their dedicated modules.
Orchestration
Lumberjack
Orchestrate the complete document-to-chunks pipeline.
saw
Parse, split, and finalize one raw document into final chunks.
saw_many
Stream per-document outcomes without preloading inputs into memory.
Results preserve input order. Components are reused sequentially; this is
deliberate because optional tokenizer implementations are not thread-safe.
Set fail_fast to re-raise the first document failure.
Models
models
Document
dataclass
Raw document and provenance waiting to be parsed into a structured document.
DocTree
dataclass
Parsed document with a normalized section tree, source, and metadata.
Attributes:
| Name | Type | Description |
|---|---|---|
title |
str
|
Document title. Priority: user-provided |
source |
str
|
Original text for Markdown and HTML inputs. Binary parsers may leave this empty or provide a normalized textual representation. |
root |
SectionNode
|
Root section node of the heading tree. |
source_path |
str | None
|
Original file path or caller-supplied source provenance. |
metadata |
dict[str, Any]
|
Semantic document metadata parsed from the source and merged with caller-provided overrides. |
reference_definitions |
dict[str, dict[str, str]]
|
Link/image reference definitions ( |
topology |
DocumentTopology
|
Structural semantics of the root. |
DocumentBlock
dataclass
Format-neutral block node in the canonical rendered representation.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
BlockKind | str
|
Block type (e.g. |
text |
str
|
Canonical rendered text consumed by splitters. Markdown input is normalized Markdown; HTML and DOCX input is converted to the same Markdown-like representation. It is not guaranteed to be a source slice. |
start_line |
int | None
|
1-based line number where the block begins. |
end_line |
int | None
|
1-based line number where the block ends. |
children |
tuple[DocumentBlock, ...]
|
Nested child blocks for container types ( |
inlines |
tuple[DocumentInline, ...]
|
Normalized inline nodes parsed from the block content.
Populated for |
attrs |
dict[str, Any]
|
Additional attributes (e.g. heading level, list style, code language). |
DocumentInline
dataclass
Format-neutral inline node normalized by an input parser.
Attributes:
| Name | Type | Description |
|---|---|---|
kind |
str
|
Inline node type (e.g. |
text |
str
|
Rendered plain text of this node. |
children |
tuple[DocumentInline, ...]
|
Nested inline children (e.g. emphasis wrapping text). |
attrs |
dict[str, Any]
|
Additional attributes ( |
SectionNode
dataclass
Heading-tree node representing a section and its children.
Attributes:
| Name | Type | Description |
|---|---|---|
level |
int
|
Heading level. |
title |
str
|
Plain-text heading title. |
path |
HeadingPath
|
Tuple of |
blocks |
list[DocumentBlock]
|
Block-level content directly under this section (not in sub-sections). |
children |
list[SectionNode]
|
Child sections (sub-headings nested within this section). |
index |
int
|
Position of this section among its siblings (0-based). |
start_line |
int | None
|
1-based line number where the section heading begins. |
title_inlines |
tuple[DocumentInline, ...]
|
Normalized inline nodes parsed from the heading text. |
ChunkDraft
dataclass
Intermediate split result holding grouped entries and a token estimate.
Args: entries: List of entries to be merged into the chunk, with heading context and body. headings: Full external heading path excluded from the rendered body. own_heading: Optional final heading identifying the chunk itself.
``# H1
H2.1
Content1``, headings=[(1, "H1"), (2, "H2.1")].
``# H1
H2.1
Content1 ## H2.2
Content2``, headings=[(1, "H1")].
headings_token_count: The token count for the chunk's full heading path.
body_token_count: The token count for the chunk body (sum of entry body_token_count plus separator deltas).
token_count: Split-time sum of heading tokens, the external-heading
separator, and body tokens.
split_origin: The split operation that produced this draft, for debugging/analysis.
chunk_type: The draft content type (e.g. "paragraph", "code_block"), used for metadata.
Chunk
dataclass
Final chunk payload with separated heading/body content and token counts.
Attributes:
chunk_id: Unique identifier for this chunk.
chunk_type: Origin block type (e.g. ``"paragraph"``, ``"heading"``,
``"code_fence"``, ``"document"``).
body: Rendered chunk body. Ancestor and own headings are never rendered
here; headings needed to represent merged internal sections remain.
token_count: Sum of heading tokens, ``tokenizer.count("
"), and
body tokens.
estimated_token_count: Split-time running estimate (additive + separator-delta
window).token_countis the authoritative final total. The two
may differ slightly for incremental splitters due to join approximations.
headings_token_count: Token count of the canonical Markdown rendering of
the complete heading path.
body_token_count: Token count ofbody.
ancestor_headings: Tuple of(level, title)pairs representing the
chunk's ancestor heading path.
own_heading: The chunk's own(level, title)heading, orNone``
when the chunk represents multiple merged sibling sections.
section_level: Deepest heading level in this chunk.
``section_level`` is derived from the full section paths covered by
the chunk, not from the ancestor-only ``ancestor_headings`` metadata.
document_title: Title of the source document.
document_path: File path of the source document, if split from a file.
start_line: 1-based line number where this chunk begins in the source.
end_line: 1-based line number where this chunk ends in the source.
SplitResult
dataclass
Document-level result of one complete splitting pipeline run.
Built-in components
parser
Public parsers and automatic parser selection.
AutoParser
Select a built-in parser from document provenance or content.
DelimitedTextParser
Parse CSV or TSV as atomic rows, keeping header schema in row metadata.
DocTreeBuilder
Incrementally construct a validated, format-neutral document tree.
The builder deliberately permits blocks directly on the root. Parsers for flat records (CSV, JSONL, logs) must use that form instead of inventing a heading hierarchy solely to satisfy a section-oriented API.
add_block
Add one canonical rendered block to the current section.
add_field_value
Add one scalar field/value unit without turning its key into a heading.
add_record
Add one ordered, atomic record with explicit record provenance.
add_section
Add a heading section and select it as the current section.
DocxParser
Bases: ParserProtocol
Parse DOCX documents into DocTree.
Maps DOCX structural elements to the same DocTree model used by the Markdown parser, enabling reuse of all existing splitters.
Block kind mapping
- OOXML outline levels → SectionNode hierarchy
- Normal paragraphs →
paragraph - Tables →
table - OOXML numbering →
listwithlist_itemchildren
parse
Parse DOCX binary data into a DocTree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document | bytes
|
A |
required |
document_title
|
str | None
|
Optional override for the document title. |
None
|
metadata_overrides
|
dict[str, object] | None
|
Semantic metadata that overrides DOCX core properties. |
None
|
source_path
|
str | Path | None
|
Optional source provenance stored separately from metadata. |
None
|
HTMLParser
Bases: ParserProtocol
Parse HTML documents into the shared DocTree model.
It mirrors the public parser shape used by Markdown and DOCX:
it exposes block_kinds and returns a heading-tree DocTree so
the existing splitters can operate on HTML input without a separate path.
parse
Parse raw HTML text into a DocTree.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document | str
|
A |
required |
document_title
|
str | None
|
Optional override for the document title. |
None
|
metadata_overrides
|
dict[str, object] | None
|
Semantic metadata that overrides values parsed from HTML metadata tags. |
None
|
source_path
|
str | Path | None
|
Optional source provenance stored separately from metadata. |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the resolved document source is not a |
JSONLinesParser
Parse JSON Lines as one canonical JSON value per atomic record.
JSONParser
Bases: _StructuredDataParser
Parse JSON into scalar records with JSON-path provenance.
LogParser
Parse each non-empty log line as one atomic, ordered record.
MarkdownBlockContext
dataclass
Context passed to custom Markdown block handlers.
MarkdownBlockSpec
dataclass
Declare how MarkdownIt token types map to lumberjack block kinds.
MarkdownItParser
Bases: ParserProtocol
Parse Markdown with markdown-it-py and normalize tokens into lumberjack's document model.
block_kinds
property
Block kinds this parser instance can produce, based on active rules.
find_matching_close
Return the matching close-token index for custom block handlers.
parse
Parse raw Markdown text into a DocTree with section tree and reference definitions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
document
|
Document | str
|
A |
required |
document_title
|
str | None
|
Optional override for the document title. |
None
|
metadata_overrides
|
dict[str, object] | None
|
Semantic metadata that overrides values parsed from front matter. |
None
|
source_path
|
str | Path | None
|
Optional source provenance stored separately from metadata. |
None
|
Raises:
| Type | Description |
|---|---|
TypeError
|
If the resolved document source is not a |
NotebookParser
Parse Jupyter cells as ordered, language-aware atomic records.
SQLParser
Parse semicolon-delimited SQL statements as ordered atomic records.
SQLiteParser
Parse SQLite table rows as atomic records.
Byte inputs are loaded into an in-memory database either through
sqlite3.Connection.deserialize (Python 3.11+) or a temporary-file
extraction (Python 3.10), so every supported runtime accepts the same
SQLite file format.
SourceCodeParser
Parse source files into symbol-aware records without treating code as prose.
When the code-parsing extra is installed, Tree-sitter selects top-level
declarations and retains valid results from malformed source. Otherwise,
Python uses ast and JavaScript/TypeScript use the built-in fallback.
TOMLParser
Bases: _StructuredDataParser
Parse TOML into scalar records with key-path provenance.
TextParser
Parse plain text as root-level paragraph or line blocks.
XMLParser
Parse XML leaf elements as ordered records with element-path provenance.
XlsxParser
Parse each non-empty XLSX row as an atomic, sheet-aware record.
Requires pip install lumberjack-py[spreadsheets].
YAMLParser
Bases: _StructuredDataParser
Parse YAML into scalar records with key-path provenance.
splitter
Public structure-aware splitters.
ExactSectionSplitter
Bases: ExactCountingMixin, SectionTopologyMixin
Per-heading section splitter without subtree-collapse.
Emits one draft per heading section's direct body and recurses into children. This variant:
- Never collapses an entire subtree into a single draft (no
subtree-collapse short-circuit — see :class:
ExactSubtreeSplitterfor that topology). - Merges only adjacent same-heading paragraph tails, bottom-up, according
to
merge_below_ratio. Non-text block drafts remain isolated.
Oversized section bodies are still split by token budget respecting
block_options (standalone isolation, splittable kinds, per-block
budgets). Every budget decision fully recounts the rendered candidate
text.
Publicly exposed as ExactSectionSplitter and selected by the
exact-section CLI/Web integration name. Works with any tokenizer.
ExactSubtreeSplitter
Bases: ExactCountingMixin, SubtreeTopologyMixin
Subtree-first splitter using exact rendered-text budget decisions.
RecordSplitter
Bases: BaseSplitter
Pack complete root-level records while preserving their input order.
A record is atomic: when it alone exceeds the budget, the emitted draft is
marked protected instead of splitting its text or claiming compliance.
Counting is exact but cache-free: like the exact splitters, identical
strings within one split (the emitted body re-counted after packing) are
deduplicated by a per-split memo instead of the tokenizer cache. The
part-sum join bound assumes the join-counting property documented on
TokenizerProtocol.
tokenizer
ApproxByteTokenizer
Bases: TokenizerProtocol
Approximate tokenizer using len(text.encode("utf-8")) // 3 tokens.
Assumes an average of 3 UTF-8 bytes per token, which is a better fit for
mixed ASCII / CJK text than the older chars // 4 heuristic.
TiktokenTokenizer
Bases: TokenizerProtocol
Tokenizer backed by the tiktoken library.
TransformersTokenizer
Bases: TokenizerProtocol
Tokenizer backed by a Hugging Face fast tokenizer.
block
Public block kinds and per-block splitting configuration.
BlockConfig
dataclass
Splitting behavior for one built-in block kind.
BlockKind
Bases: StrEnum
Built-in block kinds emitted by lumberjack parsers.
CustomBlockConfig
dataclass
Sawing behavior for a parser plugin's custom block kind.
HTMLTableConfig
dataclass
Splitting behavior for HTML tables.
MarkdownTableConfig
dataclass
Splitting behavior for Markdown pipe tables.
default_block_config
Return the default config for a built-in or custom block kind.
finalizer
normalizer
TextNormalizer
Conservatively stabilize text without removing document markup.
transformer
PlainTextTransformer
Bases: TextTransformer
Remove common Markdown and HTML surface syntax while retaining readable text.
TextTransformer
Normalize line endings and block spacing while retaining markup.
Extension protocols
protocols
ExtractionParserProtocol
Bases: Protocol
Optional parser capability for exposing an upstream extraction view.
ParserProtocol
Bases: Protocol
Parse a raw document into the shared structured representation.
SplitterProtocol
Bases: Protocol
Split a structured document into unfinished drafts.
TextNormalizerProtocol
Bases: Protocol
Stabilize rendered draft text before transformation.
TextTransformerProtocol
Bases: Protocol
Normalize or simplify text before final chunk creation.
TokenizerProtocol
Bases: Protocol
Measure text units used by splitters and finalizers.
Implementations used with the exact splitters (Exact*Splitter,
RecordSplitter) should satisfy the join-counting property: for the
separators used when rendering chunks ("\n\n" and "\n"),
``count(a + separator + b) >= count(a) + count(b) - 2``
— joining two texts cannot save more than two tokens per join. The built-in tokenizers satisfy this property, and the exact splitters rely on it to skip provably overflowing candidates without encoding them. A custom tokenizer that collapses joined text (for example, one that maps any string containing a blank line to a near-constant count) violates the contract: exact-mode pruning may then reject a join that a full recount would accept, producing smaller chunks than unbounded counting would. Chunk content is never lost either way.