3 Commits

View File

@@ -1,270 +1,536 @@
""" """
Renderer-agnostic Python documentation compiler that converts docstrings into Renderer-agnostic Python documentation compiler that converts Python docstrings
structured documentation for both humans (MkDocs) and machines (MCP / AI agents). into structured documentation for both humans (MkDocs) and machines (MCP / AI agents).
`doc-forge` statically analyzes source code, builds a semantic model of modules,
classes, functions, and attributes, and renders that model into documentation
outputs without executing user code.
`doc-forge` statically analyzes your source code, builds a semantic model of
modules and objects, and renders that model into documentation outputs without
executing your code.
--- ---
# Core Philosophy ## Installation
Install using pip:
pip install doc-forge
---
## Quick start
Generate a MkDocs site from a Python package:
doc-forge build --mkdocs --module my_package
Generate MCP JSON documentation:
doc-forge build --mcp --module my_package
Serve documentation locally:
doc-forge serve --mkdocs --module my_package
---
## Core concepts
**Loader**
Extracts symbols, signatures, and docstrings using static analysis.
**Semantic model**
Structured, renderer-agnostic representation of the API.
**Renderer**
Converts the semantic model into output formats such as MkDocs or MCP JSON.
**Symbol**
Any documentable object:
- module
- class
- function
- method
- property
- attribute
---
## Architecture
`doc-forge` follows a compiler architecture: `doc-forge` follows a compiler architecture:
1. **Front-end (Introspection)** Front-end:
Static analysis of modules, classes, functions, signatures, and docstrings.
2. **Middle-end (Semantic Model)** Static analysis of modules, classes, functions, type hints, and docstrings.
Renderer-neutral structured representation of your API.
3. **Back-end (Renderers)** Middle-end:
Builds a semantic model describing symbols and relationships.
Back-end:
Renders documentation using interchangeable renderers.
This architecture ensures deterministic documentation generation.
* MkDocs → human documentation
* MCP JSON → AI-readable documentation
--- ---
# Docstring Writing Standard ## Rendering pipeline
Docstrings are the single source of truth. `doc-forge` does not generate content. Typical flow:
It compiles and renders what you write.
Python package
Loader (static analysis)
Semantic model
Renderer
MkDocs site or MCP JSON
Documentation follows the Python import hierarchy.
--- ---
# Package docstring (`package/__init__.py`) — Full user guide ## CLI usage
This is the landing page. A developer must be able to install and use the Build MkDocs documentation:
package after reading only this docstring.
## Example: doc-forge build --mkdocs --module my_package
Build MCP documentation:
doc-forge build --mcp --module my_package
Serve MkDocs locally:
doc-forge serve --module my_package
---
## Public API
Loaders:
GriffeLoader
discover_module_paths
Renderers:
MkDocsRenderer
MCPRenderer
CLI:
main
Models:
models
---
# Google-Styled Doc-Forge Convention (GSDFC)
GSDFC defines how docstrings must be written so they render correctly in MkDocs and remain machine-parsable by doc-forge and AI tooling.
- Docstrings are the single source of truth.
- doc-forge compiles docstrings but does not generate documentation content.
- Documentation follows the Python import hierarchy.
- Every public symbol should have a complete and accurate docstring.
---
## General rules
- Use **Markdown headings** at package and module level.
- Use **Google-style structured sections** at class, function, and method level.
- Indent section contents using four spaces.
- Use type hints in signatures instead of duplicating types in prose.
- Write summaries in imperative form.
- Sections are separated by ```---```
---
## Package docstrings
- Package docstrings act as the documentation home page.
Recommended sections:
## Summary
## Installation
## Quick start
## Core concepts
## Architecture
## Rendering pipeline
## CLI usage
## Public API
## Examples
## Notes
Example:
Package Doc String:
''' '''
Short description of what this package provides. Foo-bar processing framework.
Provides tools for defining Foo objects and executing Bar pipelines.
---
# Installation # Installation
```bash pip install foo-bar
pip install my-package
``` ---
# Quick start # Quick start
```python from foobar import Foo, BarEngine
from my_package.foo import Bar
bar = Bar() foo = Foo("example")
result = bar.process("example") engine = BarEngine([foo])
```
---
# Core concepts result = engine.run()
## Bar
- Primary object exposed by the package.
## foo module
- Provides core functionality.
---
# Typical workflow
1. Import public objects
2. Initialize objects
3. Call methods
--- ---
# Public API # Public API
foo.Bar Foo
foo.helper_function Bar
BarEngine
--- ---
''' '''
--- ---
# Submodule docstring (`package/foo/__init__.py`) — Subsystem guide ## Module docstrings
Explains a specific subsystem. - Module docstrings describe a subsystem.
## Example: Recommended sections:
## Summary
## Examples
## Notes
## Public API
Example:
Module Doc String:
''' '''
Provides core functionality. Foo execution subsystem.
# Usage Provides utilities for executing Foo objects through Bar stages.
```python
from my_package.foo import Bar
bar = Bar()
bar.process("example")
```
---
'''
---
# Class docstring — Object contract
Defines responsibility and behavior.
## Example:
```python
class Bar:
'''
Performs processing on input data.
Instances may be reused across multiple calls.
---
'''
```
Include:
* Responsibility
* Lifecycle expectations
* Thread safety (if relevant)
* Performance characteristics (if relevant)
---
# Function and method docstrings — API specification
## Example:
```python
def process(
self,
value1: str,
value2: str | None = "default value",
value3: str | None = None,
) -> str:
'''
Process an input value.
--- ---
Parameters
----------
value1 : str
required: True
value to be processed
Example: Example:
'string'
value2 : str from foobar.engine import BarEngine
required: False from foobar.foo import Foo
default: "default value"
value to be processed foo = Foo("example")
engine = BarEngine([foo])
engine.run()
---
'''
---
## Class docstrings
- Class docstrings define object responsibility, lifecycle, and attributes.
Recommended sections:
Attributes:
Notes:
Example: Example:
'string' Raises:
Example:
Simple Foo:
class Foo:
'''
Represents a unit of work.
Attributes:
name (str):
Identifier of the foo instance.
value (int):
Numeric value associated with foo.
Notes:
Guarantees:
- instances are immutable after creation
Lifecycle:
- create instance
- pass to processing engine
value3 : str
required: False
value to be processed
Example: Example:
'string' Create and inspect a Foo:
---
Returns foo = Foo("example", value=42)
------- print(foo.name)
processed value : str '''
result after processing value
--- Complex Bar:
Behavior class BarEngine:
-------- '''
- behaviour 1 Executes Foo objects through Bar stages.
- behaviour 2
--- Attributes:
''' foos (tuple[Foo, ...]):
``` Foo instances managed by the engine.
---
Notes:
# Attribute docstrings (optional) Guarantees:
## Example: - deterministic execution order
```python Example:
class Class Run engine:
'''
attribute1 : str foo1 = Foo("a")
required: True foo2 = Foo("b")
default: "default value"
attribute description engine = BarEngine([foo1, foo2])
engine.run()
attribute2 : str
required: False
attribute description
attribute2 : str
required: False
default: "default value"
attribute description
''' '''
attribute1: str = "default value"
attribute2: str | None = None
attribute3: str | None = "default value"
```
--- ---
# Writing Rules ## Function and method docstrings
**Heading hierarchy** - Function docstrings define API contracts.
Module docstring Recommended sections:
- Examples Args:
- Usage Returns:
- Core concepts Raises:
- Public API Yields:
Notes:
Example:
Class docstring Example:
Simple process method:
- Attributes def process(foo: Foo, multiplier: int) -> int:
- Execution contract '''
- Lifecycle Process a Foo instance.
- Thread safety
- Notes
Method docstring Args:
foo (Foo):
Foo instance to process.
- Parameters multiplier (int):
- Returns Value used to scale foo.
- Raises
- Yields
- Behavior
**Required** Returns:
int:
Processed result.
* Use Markdown headings Raises:
* Use Markdown line separator `---` ValueError:
* Line separator should be followed by a blank line If multiplier is negative.
* Provide real import examples
* Document all public APIs
* Keep descriptions precise and factual
**Avoid** Notes:
Guarantees:
- foo is not modified
Example:
Process foo:
foo = Foo("example", value=10)
result = process(foo, multiplier=2)
print(result)
'''
Multiple Examples:
def combine(foo_a: Foo, foo_b: Foo) -> Foo:
'''
Combine two Foo instances.
Args:
foo_a (Foo):
First foo.
foo_b (Foo):
Second foo.
Returns:
Foo:
Combined foo.
Example:
Basic usage:
foo1 = Foo("a")
foo2 = Foo("b")
combined = combine(foo1, foo2)
Pipeline usage:
engine = BarEngine([foo1, foo2])
engine.run()
'''
* Plain-text separators like `====`
* Duplicate external documentation
* Informal or conversational language
--- ---
# How doc-forge uses these docstrings ## Property docstrings
## Build MkDocs site: - Properties must document return values.
```bash Example:
doc-forge build --mkdocs --module my_package Property Doc String:
```
## Build MCP documentation: @property
def foos(self) -> tuple[Foo, ...]:
'''
Return contained Foo instances.
```bash Returns:
doc-forge build --mcp --module my_package tuple[Foo, ...]:
``` Stored foo objects.
Example:
container = FooContainer()
foos = container.foos
'''
Both outputs are generated directly from docstrings.
--- ---
## Attribute documentation
- Document attributes in class docstrings using Attributes:.
Example:
Attribute Doc String:
'''
Represents a processing stage.
Attributes:
id (str):
Unique identifier.
enabled (bool):
Whether the stage is active.
'''
---
## Notes subsection grouping
- Group related information using labeled subsections.
Example:
Notes Example:
Notes:
**Guarantees:**
- deterministic behavior
**Lifecycle:**
- created during initialization
- reused across executions
**Thread safety:**
- safe for concurrent reads
---
## Example formatting
- Use indentation for examples.
Example:
Single example:
Example:
foo = Foo("example")
process(foo, multiplier=2)
Multiple examples:
Example:
Create foo:
foo = Foo("example")
Run engine:
engine = BarEngine([foo])
engine.run()
Avoid fenced code blocks inside structured sections.
---
## Separator rules
Use horizontal separators only at docstring root level to separate sections:
---
Allowed locations:
- package docstrings
- module docstrings
- major documentation sections
Do not use separators inside code sections.
---
## Parsing guarantees
GSDFC ensures doc-forge can deterministically extract:
- symbol kind (module, class, function, property, attribute)
- symbol name
- parameters
- return values
- attributes
- examples
- structured Notes subsections
This enables:
- reliable MkDocs rendering
- deterministic MCP export
- accurate AI semantic interpretation
---
Notes:
- doc-forge never executes analyzed modules.
- Documentation is generated entirely through static analysis.
""" """
from .loaders import GriffeLoader, discover_module_paths from .loaders import GriffeLoader, discover_module_paths