-
Pure Python & WASM/Pyodide Ready: Zero C-extensions or native binary dependencies.
-
Sphinx Integration: Converts AsciiDoc docstrings into Sphinx-compatible reStructuredText (reST).
-
Doctest Extraction: Queries and extracts executable code blocks and interactive prompts (
>>>). -
Safe Mode & Graceful Fallbacks: Emits non-blocking warnings (
AsciiDocStringWarning) with visual error carets during Sphinx builds instead of crashing. -
Detailed Diagnostics: Rich exception reporting with precise line, column, and caret context previews on syntax errors.
asciidocstring is built on top of the pure-Python AsciiDoctrine parser. It is designed to cleanly process Python docstrings written in AsciiDoc, resolve indentation, and parse them into a lossless Abstract Semantic Graph (ASG).
┌─────────────────────────┐
│ Raw AsciiDoc Docstring │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ asciidocstring.parse() │
└────────────┬────────────┘
│
▼
┌─────────────────────────┐
│ Abstract Semantic Graph │
└────────────┬────────────┘
│
┌─────────────────┴─────────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ doc.to_rest() │ │ doc.extract_tests() │
└─────────────┬─────────────┘ └─────────────┬─────────────┘
│ │
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ Sphinx-Compatible reST │ │ Executable Doctest Blocks │
└───────────────────────────┘ └───────────────────────────┘This parsed semantic representation can be used by downstream libraries to:
-
Render high-fidelity, Sphinx-compatible reStructuredText (reST) using Sphinx-AsciiDoctrine.
-
Query and extract executable interactive doctest code blocks using AsciiDoctest.
Initialize your project and install the library from PyPI:
pip install asciidocstringTo install optional developer dependencies (testing and linting tools):
pip install "asciidocstring[test,lint]"import asciidocstring
docstring = """
= Parse Coordinates
This function processes dynamic coordinate objects.
[source,python,test]
----
assert parse_coords(10, 20) == (10, 20)
----
x (int):: The horizontal component
y (int):: The vertical component
"""
# Parse the raw docstring (automatically cleans leading docstring indentation)
doc = asciidocstring.parse(docstring)
# Translate the docstring into reStructuredText (reST) for Sphinx
rest_text = doc.to_rest()
print(rest_text)
# Extract code blocks tagged for doctesting
test_blocks = doc.extract_tests(language="python")
for block in test_blocks:
print(f"Test Code ({block.language}):")
print(block.content)Here is a side-by-side view of how AsciiDoc syntax in a docstring is translated into Sphinx-compatible reStructuredText:
= Parse Coordinates
This function processes dynamic coordinate objects.
NOTE: Coordinates must be non-negative integers.
x (int):: The horizontal component
y (int):: The vertical componentParse Coordinates
=================
This function processes dynamic coordinate objects.
.. note::
Coordinates must be non-negative integers.
x (int)
The horizontal component
y (int)
The vertical componentThe library includes robust, structured syntax error handling. When parsing syntactically invalid AsciiDoc, an AsciiDocStringParseError is raised, detailing the exact location and a visual caret context.
import asciidocstring
invalid_docstring = """
= Sample Header
:: invalid-syntax
"""
try:
asciidocstring.parse(invalid_docstring)
except asciidocstring.AsciiDocStringParseError as e:
print(f"Error Message: {e}")
print(f"Error Location: Line {e.line}, Column {e.column}")
print("Caret Preview:")
print(e.context)Expected output:
Error Message: AsciiDoc Parse Error: Syntax error at line 3, column 1.
:: invalid-syntax
^
Error Location: Line 3, Column 1
Caret Preview:
:: invalid-syntax
^By default, syntax violations raise an exception and halt Sphinx builds. To allow documentation to compile successfully even if a docstring contains syntax errors, you can enable safe_mode:
import asciidocstring
invalid_docstring = """
= Sample Header
:: invalid-syntax
"""
# Parse in safe mode (emits a non-blocking AsciiDocStringWarning)
doc = asciidocstring.parse(invalid_docstring, safe_mode=True)
# Generates a standard warning admonition containing the error and careted source
print(doc.to_rest())Output:
.. warning::
Failed to parse AsciiDoc docstring: AsciiDoc Parse Error: Syntax error at line 3, column 1.
.. code-block:: asciidoc
= Sample Header
:: invalid-syntax
^-
parse(docstring: str, safe_mode: bool = False) → AsciiDocStringDocument
Convenience function to parse a raw Python docstring.
-
AsciiDocStringDocument
The main interface representing a parsed docstring document.-
init(raw_source: str, safe_mode: bool = False): Cleans and parses the given docstring. -
to_rest() → str: Renders the parsed document as standard Sphinx-compatible reStructuredText. -
extract_tests(language: str = "python", requires_test_marker: bool = False) → list[TestBlock]: Extracts executable code blocks.
-
-
TestBlock
Represents an extracted code block designed for execution or testing.-
content(str): The raw code contents of the block. -
language(str): The code block language (e.g.python). -
line_number(int): The 1-based starting line number of the block in the docstring. -
is_interactive(bool): True if the block contains python-interactive prompts (`>>> `). -
attributes(dict): A dictionary of raw block attributes parsed from the AsciiDoc metadata.
-
-
AsciiDocStringParseError
Raised when parsing an AsciiDoc docstring fails. Inherits fromValueError.-
line(int | None): The line number of the parsing error. -
column(int | None): The column number of the parsing error. -
context(str | None): A visual text block indicating the line of code and a caret highlighting the syntax error position.
-
-
AsciiDocStringWarning
Warning raised when parsing fails undersafe_mode=True. Inherits fromUserWarning.
Ensure you have your environment set up and dependencies installed:
# Set up a virtual environment
python3 -m venv venv
source venv/bin/activate
# Install the package in editable mode with development dependencies
pip install -e ".[test,lint]"We maintain 100% test coverage standards. To run tests and generate a coverage report:
PYTHONPATH=src pytest --cov=src --cov-report=term-missing