Skip to main content

A Python library for converting Atlassian Document Format (ADF) to Markdown

Reason this release was yanked:

broken Linux x86_64 wheels, use 0.4.1

Project description

pyadf

A high-performance Python library for converting Atlassian Document Format (ADF) to Markdown, powered by a Rust core.

Features

  • Rust-powered — parsing and rendering run in native code via PyO3
  • Streaming JSONL API for ETL pipelines processing millions of documents
  • Same Document class API — drop-in upgrade for most users (see changelog for breaking changes)
  • Flexible input — accepts JSON strings, dictionaries, or any ADF node type
  • Comprehensive node support:
    • Text formatting (bold, italic, links)
    • Headings (h1-h6)
    • Lists (bullet, ordered, task lists)
    • Tables with headers and column spans
    • Code blocks with syntax highlighting
    • Blockquotes and panels
    • Status badges, inline cards, emoji, mentions
  • Type-safe with comprehensive type hints and Python 3.11+ support
  • Eager validation — ADF structure errors surface at construction time, not render time
  • Robust error handling with detailed, context-aware error messages

Installation

pip install pyadf

Prebuilt wheels are available for Linux and macOS (x86_64 and aarch64) and Windows (x86_64).

Usage

Basic Usage

from pyadf import Document

adf_data = {
    "type": "doc",
    "content": [
        {
            "type": "paragraph",
            "content": [
                {"type": "text", "text": "Hello, "},
                {"type": "text", "text": "world!", "marks": [{"type": "strong"}]}
            ]
        }
    ]
}

doc = Document(adf_data)
print(doc.to_markdown())
# Output: Hello, **world!**

Converting from JSON String

from pyadf import Document

adf_json = '{"type": "doc", "content": [...]}'
doc = Document(adf_json)
markdown = doc.to_markdown()

Converting Individual Nodes

from pyadf import Document

node = {
    "type": "heading",
    "attrs": {"level": 2},
    "content": [{"type": "text", "text": "My Heading"}]
}

doc = Document(node)
print(doc.to_markdown())
# Output: ## My Heading

Batch JSONL Processing

For ETL pipelines processing large volumes of ADF documents:

from pyadf import convert_jsonl, MarkdownConfig

# From a JSONL file (one ADF document per line)
for result in convert_jsonl("export.jsonl"):
    print(result)

# From bytes with custom config
config = MarkdownConfig(bullet_marker="*", show_links=True)
for result in convert_jsonl(jsonl_bytes, config=config, batch_size=10_000):
    print(result)

# Error handling modes
from pyadf import ConversionError

for result in convert_jsonl(data, on_error="include"):
    if isinstance(result, ConversionError):
        print(f"Line {result.line_number}: {result.error}")
    else:
        print(result)

convert_jsonl accepts:

  • source: file path (str), raw bytes, or a binary file-like object
  • config: optional MarkdownConfig
  • on_error: "include" (default, yields ConversionError), "skip", or "raise"
  • batch_size: lines per Rust batch (default 10,000)

Error Handling

from pyadf import Document, InvalidJSONError, UnsupportedNodeTypeError

try:
    doc = Document('invalid json')
except InvalidJSONError as e:
    print(f"Invalid JSON: {e}")

try:
    doc = Document({"type": "unsupported_type"})
except UnsupportedNodeTypeError as e:
    print(f"Unsupported node: {e}")

Customizing Markdown Output

from pyadf import Document, MarkdownConfig

doc = Document(adf_data)

# Default bullet marker is +
doc.to_markdown()  # "+ Item 1\n+ Item 2"

# Use * for bullet lists
config = MarkdownConfig(bullet_marker="*")
doc.to_markdown(config)  # "* Item 1\n* Item 2"

# Show links with both display text and underlying href
config = MarkdownConfig(show_links=True)
doc.to_markdown(config)  # [Link text](http://example.com)
Option Values Default Description
bullet_marker +, -, * + Character used for bullet list items
show_links True, False False Show underlying links in markdown

Supported ADF Node Types

ADF Node Type Markdown Output Notes
doc Document root Top-level container
paragraph Plain text with newlines
text Text with optional formatting Supports bold, italic, links
heading # Heading (levels 1-6)
bulletList + Item
orderedList 1. Item
taskList - [ ] Task Checkbox tasks
codeBlock ```language\ncode\n``` Optional language syntax
blockquote > Quote
panel > Panel content Info/warning/error boxes
table Markdown table Supports headers and colspan
status **[STATUS]** Status badges
inlineCard [link] or code block Link previews
emoji Unicode emoji
hardBreak Line break
mention @DisplayName Jira user mentions

Exception Types

  • PyADFError — Base exception for all pyadf errors
  • InvalidJSONError — Raised when JSON parsing fails
  • InvalidInputError — Raised when input type is incorrect
  • InvalidADFError — Raised when ADF structure is invalid
  • MissingFieldError — Raised when required fields are missing
  • InvalidFieldError — Raised when field values are invalid
  • UnsupportedNodeTypeError — Raised when encountering unsupported node types
  • NodeCreationError — Raised when node creation fails

All exceptions include detailed context about the error location in the ADF tree.

Performance

Benchmarked against pyadf v0.3.1 (pure Python) on realistic ADF documents:

Mode v0.3.1 v0.4.0 Speedup
Single doc (Document class) 34K docs/s 177K docs/s 5.2x
JSONL batch (convert_jsonl) 34K docs/s 797K docs/s 23.7x

Run python -m benchmarks to reproduce.

Development

Prerequisites

  • Python 3.11+
  • Rust toolchain (stable)
  • maturin (uv tool install maturin)

Setup

git clone https://github.com/YoungseokCh/pyadf.git
cd pyadf
uv sync
uv run maturin develop

Testing

cargo test              # Rust unit tests
uv run pytest tests/ -v # Python tests

Linting

# Rust
cargo fmt --check
cargo clippy -- -D warnings

# Python
ruff check src/ tests/ benchmarks/
ruff format --check src/ tests/ benchmarks/

Benchmarks

uv run maturin develop --release
uv run python -m benchmarks

License

MIT License — see LICENSE file for details.

Changelog

0.4.0 (Current)

  • Rust core via PyO3 — 5x faster single-doc, 24x faster batch processing
  • New convert_jsonl() streaming API for batch JSONL processing
  • New ConversionError dataclass for structured batch error handling
  • Build system switched from setuptools to maturin
  • abi3 stable ABI wheels for Linux, macOS (x86_64 + aarch64) and Windows (x86_64)

Breaking changes:

  • Removed set_debug_mode() and _logger module (will be replaced with Rust-native tracing in a future release)
  • nodes and _types modules removed (internal implementation replaced by Rust)

0.3.2

  • Added support for showing href links in markdown output

0.3.1

  • Added mention node support

0.3.0

  • Added emoji node support
  • Added configurable bullet markers via MarkdownConfig

0.1.0

  • Class-based API with Document class
  • Support for common ADF node types
  • Type-safe architecture with comprehensive type hints (Python 3.11+)
  • Flexible input handling (JSON strings, dictionaries, individual nodes)

Project details


Download files

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

Source Distribution

pyadf-0.4.0.tar.gz (42.7 kB view details)

Uploaded Source

Built Distributions

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

pyadf-0.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (324.0 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pyadf-0.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (324.4 kB view details)

Uploaded PyPymanylinux: glibc 2.17+ ARM64

pyadf-0.4.0-cp311-abi3-win_amd64.whl (249.9 kB view details)

Uploaded CPython 3.11+Windows x86-64

pyadf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (322.5 kB view details)

Uploaded CPython 3.11+manylinux: glibc 2.17+ ARM64

pyadf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl (302.2 kB view details)

Uploaded CPython 3.11+macOS 11.0+ ARM64

pyadf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl (322.4 kB view details)

Uploaded CPython 3.11+macOS 10.12+ x86-64

pyadf-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (343.4 kB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

File details

Details for the file pyadf-0.4.0.tar.gz.

File metadata

  • Download URL: pyadf-0.4.0.tar.gz
  • Upload date:
  • Size: 42.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyadf-0.4.0.tar.gz
Algorithm Hash digest
SHA256 6b270f0773923024e7902bc9b9fe0ca7e5ec4bd3fc540dcfe5c1b409254cbc16
MD5 edc7938425d9aa6bb5c6c6dcbb7c58b0
BLAKE2b-256 d485950e4d662a2cb42a6152a5f0a73938d82e01e79603fb5416109777bcdeb7

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0.tar.gz:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyadf-0.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a9330598a7d0b7ee36187518ffe7b525d49165260f823a05a17f98e640741a88
MD5 ac0413093cb7be51e65a48394ea3ca10
BLAKE2b-256 b5e40bc8df1a58b30c88092b242aaaba87fa6184e5fdb19d85b72202292957ef

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyadf-0.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 ed72f9377702347cb4d512c478c9c53a548ca65cd5856664a31d04fd397afa56
MD5 b7cc3d9d3dac7454e7100c9dd40a0e97
BLAKE2b-256 be50946b89cbf1fae9b2a309b1ffd438683ad8f8d3e9c58f05ae000920e78413

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-cp311-abi3-win_amd64.whl.

File metadata

  • Download URL: pyadf-0.4.0-cp311-abi3-win_amd64.whl
  • Upload date:
  • Size: 249.9 kB
  • Tags: CPython 3.11+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyadf-0.4.0-cp311-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 135052cf5b28efb2f14ce1a71a649604b51e7d9f2c38b119eb96fd4eee5dc11e
MD5 9f71e9056e7de256d9b21304a47ff8c7
BLAKE2b-256 dae6ab4be6174725e5ce65d50a8c56f10d1a5b2da2390c13a0eaa01a4e31b33a

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-cp311-abi3-win_amd64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for pyadf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 31ce8877d927c5afd9ac1729445f6e585d2b4f1eaf1927463e61003b9af0d304
MD5 c4f1c4d1f37c8fc44c61a0c715bd8789
BLAKE2b-256 4790453a69efde5148da3e00d8bbf0e5ed949eff7005fa37e58c80212420dd23

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: pyadf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 302.2 kB
  • Tags: CPython 3.11+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for pyadf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 82f72d8fde016049a2b7544bd77ccaab8c455a51fb197a049532551dbbad1f48
MD5 72f2c85461a35b6a6f5094e52154a247
BLAKE2b-256 a50606df79e53fb7bb697456a90a3502672a7fe227e1e5e8b9a650603472f72b

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-cp311-abi3-macosx_11_0_arm64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for pyadf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 df5c9e72fa5f52931bfc4bd78c887d599c1888220246c2a9e21e376a696a3e52
MD5 67408acb7072edbfacc02f5c6fd276ba
BLAKE2b-256 36c1546fcd7860fe6a56e9a6e9e4bc771f9741e01d5c169bc9b126461c6dee40

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-cp311-abi3-macosx_10_12_x86_64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

File details

Details for the file pyadf-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for pyadf-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d1b022b22fdd21e2eacb251904ca25a71fddcb66cd27ee3226a84853a8005485
MD5 daef00b2c92cf81e4a82513f8235befa
BLAKE2b-256 e5af2a532813f5217a894bcd975d13a01901a35ec26b389ad71e42448f4eeb90

See more details on using hashes here.

Provenance

The following attestation bundles were made for pyadf-0.4.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: publish.yml on YoungseokCh/pyadf

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page