pydocstring
A zero-dependency Rust parser for Python docstrings (Google / NumPy style).
Produces a unified syntax tree with byte-precise source locations on every token — designed as infrastructure for linters and formatters.
Python bindings are also available as pydocstring-rs.
Features
- Full syntax tree — builds a complete AST, not just extracted fields; traverse it with the built-in
Visitor+walk - Typed nodes per style — style-specific accessors like
GoogleArg,NumPyParameterwith full type safety - Byte-precise source locations — every token carries its exact byte range for pinpoint diagnostics
- Zero dependencies — pure Rust, no external crates, no regex
- Error-resilient — never panics; malformed input still yields a best-effort tree
- Style auto-detection — hand it a docstring, it tells you the convention
Installation
[]
= "0.1.1"
Usage
Parsing
use ;
let input = "Summary.\n\nArgs:\n x (int): The value.\n y (int): Another value.";
let result = parse_google;
let doc = cast.unwrap;
println!;
for section in doc.sections
NumPy style works the same way — use parse_numpy / NumPyDocstring instead.
Style Auto-Detection
use ;
assert_eq!;
assert_eq!;
Source Locations
Every token carries byte offsets for precise diagnostics:
use ;
let result = parse_google;
let doc = cast.unwrap;
for section in doc.sections
Syntax Tree
The parse result is a tree of SyntaxNode (branches) and SyntaxToken (leaves), each tagged with a SyntaxKind. Use pretty_print() to visualize:
use parse_google;
let result = parse_google;
println!;
GOOGLE_DOCSTRING@0..42 {
SUMMARY: "Summary."@0..8
GOOGLE_SECTION@10..42 {
GOOGLE_SECTION_HEADER@10..15 {
NAME: "Args"@10..14
COLON: ":"@14..15
}
GOOGLE_ARG@20..42 {
NAME: "x"@20..21
OPEN_BRACKET: "("@22..23
TYPE: "int"@23..26
CLOSE_BRACKET: ")"@26..27
COLON: ":"@27..28
DESCRIPTION: "The value."@29..39
}
}
}
Visitor Pattern
Walk the tree with the Visitor trait for style-agnostic analysis:
use ;
use parse_google;
let result = parse_google;
let mut collector = NameCollector ;
walk;
assert_eq!;
Style-Independent Model (IR)
Convert any parsed docstring into a style-independent intermediate representation for analysis or transformation:
use ;
let parsed = parse_google;
let doc = to_model.unwrap;
assert_eq!;
for section in &doc.sections
Emitting (Code Generation)
Re-emit a Docstring model in any style — useful for style conversion or formatting:
use ;
use emit_google;
use emit_numpy;
let doc = Docstring ;
let google = emit_google;
assert!;
let numpy = emit_numpy;
assert!;
Combine parsing and emitting to convert between styles:
use ;
use emit_numpy;
let parsed = parse_google;
let doc = to_model.unwrap;
let numpy_text = emit_numpy;
assert!;
Supported Sections
Both styles support the following section categories. Typed accessor methods are available on each style's section node.
| Category | NumPy | |
|---|---|---|
| Parameters | args() → GoogleArg |
parameters() → NumPyParameter |
| Returns / Yields | returns() → GoogleReturns |
returns() → NumPyReturns |
| Raises | exceptions() → GoogleException |
exceptions() → NumPyException |
| Warns | warnings() → GoogleWarning |
warnings() → NumPyWarning |
| See Also | see_also_items() → GoogleSeeAlsoItem |
see_also_items() → NumPySeeAlsoItem |
| Attributes | attributes() → GoogleAttribute |
attributes() → NumPyAttribute |
| Methods | methods() → GoogleMethod |
methods() → NumPyMethod |
| Free text (Notes, Examples, etc.) | body_text() |
body_text() |
Root-level accessors: summary(), extended_summary() (NumPy also has deprecation()).
Development