Skip to content

Repository files navigation

AsciiDocstring

Build Status PyPI Version PyPI Downloads Python Versions License Coverage Ruff MyPy Pyodide Compatible

A pure-Python semantic parser, extractor, and translator for Python docstrings written in AsciiDoc. Fully compatible with Python 3.14+ and WASM/Pyodide environments with zero native compiled extensions.

1. Key Features

  • 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.

2. Introduction & Architecture

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:

  1. Render high-fidelity, Sphinx-compatible reStructuredText (reST) using Sphinx-AsciiDoctrine.

  2. Query and extract executable interactive doctest code blocks using AsciiDoctest.

3. Installation

Initialize your project and install the library from PyPI:

pip install asciidocstring

To install optional developer dependencies (testing and linting tools):

pip install "asciidocstring[test,lint]"

4. Usage

4.1. Quick Start

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)

4.2. Translation Comparison (AsciiDoc to reST)

Here is a side-by-side view of how AsciiDoc syntax in a docstring is translated into Sphinx-compatible reStructuredText:

Input AsciiDoc Docstring
= Parse Coordinates

This function processes dynamic coordinate objects.

NOTE: Coordinates must be non-negative integers.

x (int):: The horizontal component
y (int):: The vertical component
Output reStructuredText (reST)
Parse Coordinates
=================

This function processes dynamic coordinate objects.

.. note::

   Coordinates must be non-negative integers.

x (int)
   The horizontal component

y (int)
   The vertical component

4.3. Catching Syntax and Parsing Errors

The 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
^

4.4. Safe Mode Parsing & Warnings

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
      ^

5. API Reference

5.1. Functions

  • parse(docstring: str, safe_mode: bool = False) → AsciiDocStringDocument
    Convenience function to parse a raw Python docstring.

5.2. Classes

  • 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 from ValueError.

    • 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 under safe_mode=True. Inherits from UserWarning.

6. Developer Guide

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]"

6.1. Running Tests

We maintain 100% test coverage standards. To run tests and generate a coverage report:

PYTHONPATH=src pytest --cov=src --cov-report=term-missing

6.2. Static Analysis

Run our linting and type-safety check pipeline:

# Run Ruff code format and quality checks
ruff check src/ tests/

# Run MyPy type-safety validation
mypy src/

7. License

This project is licensed under the Apache License, Version 2.0.

About

Semantic extractor and parser of Python docstrings that are written in AsciiDoc. Also extracts Python source listing blocks from within the docstring.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages