Skip to content

A fast Rust parser for Python docstrings (NumPy and Google styles)

License

Notifications You must be signed in to change notification settings

qraqras/pydocstring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pydocstring

A fast, zero-dependency Rust parser for Python docstrings with full AST and source location tracking.

Features

  • Zero external dependencies — pure Rust implementation
  • Docstring styles:
    • Google style — fully supported
    • NumPy style — fully supported
  • Accurate source spans (byte offsets) on every AST node
  • Diagnostic-based error reporting — partial results + diagnostics, never panics
  • Style auto-detection — automatically identifies NumPy or Google style
  • Comprehensive test coverage (140+ tests)

Installation

Add to your Cargo.toml:

[dependencies]
pydocstring = "0.1.0"

Quick Start

NumPy Style

use pydocstring::numpy::parse_numpy;

let docstring = r#"
Calculate the area of a rectangle.

This function takes the width and height of a rectangle
and returns its area.

Parameters
----------
width : float
    The width of the rectangle.
height : float
    The height of the rectangle.

Returns
-------
float
    The area of the rectangle.

Raises
------
ValueError
    If width or height is negative.
"#;

let result = parse_numpy(docstring);

println!("Summary: {}", result.summary.source_text(&result.source));
for item in &result.items {
    if let pydocstring::NumPyDocstringItem::Section(s) = item {
        if let pydocstring::NumPySectionBody::Parameters(params) = &s.body {
            for param in params {
                let names: Vec<&str> = param.names.iter()
                    .map(|n| n.source_text(&result.source)).collect();
                println!("  {:?}: {:?}", names,
                    param.r#type.as_ref().map(|t| t.source_text(&result.source)));
            }
        }
    }
}

Google Style

use pydocstring::google::parse_google;

let docstring = r#"
Calculate the area of a rectangle.

This function takes the width and height of a rectangle
and returns its area.

Args:
    width (float): The width of the rectangle.
    height (float): The height of the rectangle.

Returns:
    float: The area of the rectangle.

Raises:
    ValueError: If width or height is negative.
"#;

let result = parse_google(docstring);

println!("Summary: {}", result.summary.source_text(&result.source));
for item in &result.items {
    if let pydocstring::GoogleDocstringItem::Section(s) = item {
        if let pydocstring::GoogleSectionBody::Args(args) = &s.body {
            for arg in args {
                println!("  {} ({:?}): {}", arg.name.source_text(&result.source),
                    arg.r#type.as_ref().map(|t| t.source_text(&result.source)),
                    arg.description.source_text(&result.source));
            }
        }
    }
}

Style Auto-Detection

use pydocstring::{detect_style, Style};

let numpy_doc = "Summary.\n\nParameters\n----------\nx : int\n    Desc.";
assert_eq!(detect_style(numpy_doc), Style::NumPy);

let google_doc = "Summary.\n\nArgs:\n    x: Desc.";
assert_eq!(detect_style(google_doc), Style::Google);

Diagnostic-Based Error Handling

Parsers always return a result — even for malformed input. Diagnostics are collected alongside the best-effort AST:

use pydocstring::google::parse_google;

let result = parse_google("Summary.\n\nArgs:\n    : missing name");

if result.has_errors() {
    for diag in result.errors() {
        eprintln!("{}", diag); // e.g. "error at 14..28: ..."
    }
}

// The AST is still available
println!("Summary: {}", result.summary.source_text(&result.source));

Source Locations

Every AST node carries a TextRange (byte offsets) so linters can report precise positions:

use pydocstring::numpy::parse_numpy;
use pydocstring::LineIndex;

let docstring = "Summary.\n\nParameters\n----------\nx : int\n    Desc.";
let result = parse_numpy(docstring);

for item in &result.items {
    if let pydocstring::NumPyDocstringItem::Section(s) = item {
        if let pydocstring::NumPySectionBody::Parameters(params) = &s.body {
            if let Some(param) = params.first() {
                let name_range = &param.names[0];
                println!("Parameter '{}' at byte {}..{}",
                    name_range.source_text(&result.source),
                    name_range.start(), name_range.end());

                // Convert to line/column if needed
                let index = LineIndex::from_source(docstring);
                let (line, col) = index.line_col(name_range.start());
                println!("  line {}, col {}", line, col);
            }
        }
    }
}

Supported Sections

NumPy Style

Section Method Return Type
Parameters parameters() Vec<&NumPyParameter>
Other Parameters other_parameters() Vec<&NumPyParameter>
Returns returns() Vec<&NumPyReturns>
Yields yields() Vec<&NumPyReturns>
Receives receives() Vec<&NumPyParameter>
Raises raises() Vec<&NumPyException>
Warns warns() Vec<&NumPyWarning>
Warnings warnings() Option<&TextRange>
See Also see_also() Vec<&SeeAlsoItem>
Notes notes() Option<&TextRange>
References references() Vec<&NumPyReference>
Examples examples() Option<&TextRange>
Attributes attributes() Vec<&NumPyAttribute>
Methods methods() Vec<&NumPyMethod>

Additionally, NumPyDocstring has fields: summary, deprecation, extended_summary.

Google Style

Section Method Return Type
Args args() Vec<&GoogleArgument>
Keyword Args keyword_args() Vec<&GoogleArgument>
Other Parameters other_parameters() Vec<&GoogleArgument>
Returns returns() Vec<&GoogleReturns>
Yields yields() Vec<&GoogleReturns>
Receives receives() Vec<&GoogleArgument>
Raises raises() Vec<&GoogleException>
Warns warns() Vec<&GoogleWarning>
Warnings warnings() Option<&TextRange>
See Also see_also() Vec<&GoogleSeeAlsoItem>
Notes notes() Option<&TextRange>
References references() Option<&TextRange>
Examples examples() Option<&TextRange>
Attributes attributes() Vec<&GoogleAttribute>
Methods methods() Vec<&GoogleMethod>
Todo todo() Option<&TextRange>

Additionally, GoogleDocstring has fields: summary, description, and admonition sections (Attention, Caution, Danger, etc.).

Development

# Build
cargo build

# Run tests
cargo test

# Run examples
cargo run --example parse_numpy
cargo run --example parse_google

License

MIT

About

A fast Rust parser for Python docstrings (NumPy and Google styles)

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors