Expand description
§pydocstring
A fast, zero-dependency Rust parser for Python docstrings with full AST and source location tracking. Supports NumPy and Google styles, and reads anything else as a plain summary/extended-summary docstring.
One parse result, Parsed, is read through three lenses:
the style-independent Document view (semantic), the
raw CST (faithful — it keeps byte positions and the parser’s zero-length
placeholders), and Parsed::to_model (the
normalized IR that feeds emit). Nothing downstream branches on style.
§Quick Start
Parse with auto-detection and traverse the style-independent typed views
(Document → Section →
Entry) — one code path for every docstring style:
use pydocstring::model::SectionKind;
use pydocstring::parse::{parse, Document, Style};
let docstring = "\
Brief description.
Parameters
----------
x : int
The first parameter.
";
let parsed = parse(docstring);
assert_eq!(parsed.style(), Style::NumPy);
let doc = Document::new(&parsed);
assert_eq!(doc.summary().unwrap().text(), "Brief description.");
let section = doc.sections().next().unwrap();
assert_eq!(section.kind(), SectionKind::Parameters);
let entry = section.entries().next().unwrap();
assert_eq!(entry.name().unwrap().text(), "x");
assert_eq!(entry.type_annotation().unwrap().text(), "int");§The Raw CST
The unified view is a semantic lens: it answers “is there a type?” and
folds away punctuation and the parser’s zero-length placeholders. For the
tree exactly as parsed, go down to the CST with syntax():
use pydocstring::parse::{parse, Document};
use pydocstring::syntax::SyntaxKind;
let parsed = parse("Summary.\n\nArgs:\n x (): The value.\n");
let entry = Document::new(&parsed).sections().next().unwrap().entries().next().unwrap();
// The semantic lens says "no type" …
assert!(entry.type_annotation().is_none());
// … the CST says *why*: an empty type between brackets, whose zero-length
// range is the anchor to write one at.
let placeholder = entry.syntax().find_missing(SyntaxKind::TYPE).unwrap();
assert!(placeholder.is_missing());§Style Auto-Detection
use pydocstring::parse::{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);§Features
- Zero external dependencies — pure Rust
- Accurate source spans (byte offsets) on every AST node
- NumPy style: fully supported
- Google style: fully supported
- Anchored splice edits (
Parsed::edit, seeedit): everything an edit does not touch is preserved byte-for-byte - Pattern fragments with
$X/$$$Xmetavariables (Pattern, seepattern) — the input side of the match/rewrite engine - Anchor-based structural matching
(
Pattern::matches/Pattern::matches_in, seematcher): trivia-skipping, indentation-relative unification whose captures expose the original target bytes - Pattern-based rewriting
(
Parsed::replace/Parsed::replace_in, seerewrite): splices a template rendered with byte-exact captured content, preserving everything outside the rewritten regions by construction - Emit to Google, NumPy, and Sphinx (reStructuredText) styles (Sphinx is
emit-only; see
emit::sphinx)
Modules§
- edit
- Anchored splice edits over a parsed docstring.
- emit
- Emit (code generation) from the style-independent document model.
- matcher
- The matching engine (#46): anchor-based structural matching of
Patterns against parsed docstrings. - model
- Style-independent document model (IR) for docstrings.
- parse
- Parsing: source text in,
Parsedout. - pattern
- Pattern fragments with
$X/$$$Xmetavariables (the input side of the match/rewrite engine — parsing and introspection only; matching is #46 and rewriting is #47). - rewrite
- Pattern-based rewriting (#47): the capstone of the edit API (RFC #48).
- syntax
- Unified syntax tree types.
- text
- Source location types (offset-only).