Relevant source files
The following files were used as context for generating this wiki page:
- packages/python/fumapy/mksource/document_module.py
- packages/python/fumapy/mksource/simplify_docstring.py
- packages/python/fumapy/mksource/models.py
- packages/python/fumapy/mksource/init.py
- packages/python/fumapy/init.py
- packages/python/fumapy/mksource/utils.py
- packages/content/src/index.ts
- packages/python/src/convert.ts
- packages/python/pyproject.toml
- packages/mdx/src/runtime/server.ts
- packages/core/src/mdx-plugins/remark-structure.ts
- packages/typescript/src/lib/base.ts
- packages/python/src/components/index.tsx
- packages/python/src/generated.ts
- packages/content/src/runtime.ts
- packages/python/package.json
- packages/mdx/src/loaders/mdx/remark-postprocess.ts
- packages/openapi/src/utils/document/load.ts
- packages/asyncapi/src/server/index.tsx
- packages/content-collections/src/configuration.ts
- packages/mdx/src/runtime/types.ts
- packages/sanity/src/index.ts
- packages/twoslash/src/index.ts
- packages/openapi/src/utils/pages/to-static-data.ts
- packages/python/fumapy/mksource/json_encoder.py
- packages/cli/src/commands/file-tree.ts
- packages/doc-gen/package.json
- packages/asyncapi/src/utils/pages/to-static-data.ts
- packages/api-docs/src/i18n.ts
- packages/preview/src/lib/source/storage.ts
Overview
The fumapy Python package provides built-in docgen capabilities for extracting API documentation from Python source code and docstrings, serving as the official Python extension for Fumadocs. It bridges raw Python modules and documentation frontends by inspecting AST structures, simplifying docstring content, and serializing parsed metadata into JSON format for static site generation.
Sources: packages/python/pyproject.toml:4-4, packages/python/package.json:4-4
Command Line and Execution Workflow
CLI Entrypoint and Argument Configuration
The package registers a command-line script named fumapy-generate through pyproject.toml, pointing directly to the generate function within the main package module.
[project.scripts]
fumapy-generate = "fumapy:generate"Sources: packages/python/pyproject.toml:10-11
The generate function builds an argparse.ArgumentParser configured with positional and optional parameters to control target selection and output paths.
| Argument / Flag | Type | Default | Description |
|---|---|---|---|
module | str | (Required) | The target Python module name to generate documentation for. |
--dir, -d | str | "." | The target directory where the resulting JSON documentation file is saved. |
Sources: packages/python/fumapy/init.py:30-41
Execution Lifecycle and Serialization
Once command-line arguments are parsed, the execution workflow initializes griffe with the TypingDocExtension extension. It loads the target module using griffe.load, setting docstring_parser="auto" and store_source=True based on module-level constants DOCSTRING_TYPE and STORE_SOURCE.
extensions = griffe.load_extensions(TypingDocExtension)
pkg = parse_module(
griffe.load(
args.module, docstring_parser="auto", store_source=STORE_SOURCE, extensions=extensions
)
)
api_filename = f"{args.module}.json"
with open(os.path.join(args.dir, api_filename), "w") as file:
json.dump(pkg, file, cls=CustomEncoder, indent=2, full=True)Sources: packages/python/fumapy/init.py:10-12, packages/python/fumapy/init.py:43-52
Note
The generated documentation file is written as {module}.json inside the directory specified by --dir. The serialization process leverages CustomEncoder and enables full=True during json.dump to capture complete AST and docstring metadata.
Sources: packages/python/fumapy/init.py:49-52
Griffe Inspection and AST Traversal
Module AST Parsing
The parse_module function accepts a griffe.Object and verifies that it is an instance of griffe.Module, raising a ValueError otherwise. It processes module docstrings via simplify_docstring and builds a structured Module dictionary containing name, path, filepath, description, remaining docstring, attributes, submodules, classes, and functions while filtering out any aliases (if not value.is_alias).
def parse_module(m: griffe.Object) -> Module:
if not isinstance(m, griffe.Module):
raise ValueError("Module must be a module")
out = simplify_docstring(m.docstring, m)
res: Module = {
"name": m.name,
"path": m.path,
"filepath": m.filepath,
"description": out.description,
"docstring": out.remainder,
"attributes": out.attributes,
"modules": {
name: parse_module(value)
for name, value in m.modules.items()
if not value.is_alias
},
"classes": {
name: parse_class(value)
for name, value in m.classes.items()
if not value.is_alias
},
"functions": {
name: parse_function(value)
for name, value in m.functions.items()
if not value.is_alias
},
}
if m.is_package:
try:
res["version"] = version(m.name)
except AttributeError:
res["version"] = "unknown"
return resSources: packages/python/fumapy/mksource/document_module.py:12-46
Note
When m.is_package evaluates to true, parse_module attempts to dynamically retrieve the package version via importlib.metadata.version(m.name), falling back to "unknown" if an AttributeError occurs.
Sources: packages/python/fumapy/mksource/document_module.py:40-44
Class and Function AST Extraction
The parse_class function processes a griffe.Class object to extract its name, path, description, parameters, attributes, docstring, source code, non-alias functions, and inherited members. It parses inherited members by inspecting c.inherited_members.values(), extracting their canonical paths and kinds, and grouping them by their parent paths.
def parse_class(c: griffe.Class) -> Class:
out = simplify_docstring(c.docstring, c)
res: Class = {
"name": c.name,
"path": c.path,
"description": out.description,
"parameters": out.parameters,
"attributes": out.attributes,
"docstring": out.remainder,
"functions": {
name: parse_function(value)
for name, value in c.functions.items()
if not value.is_alias
},
"source": c.source,
"inherited_members": {},
}
for member in c.inherited_members.values():
parent_path = ".".join(member.canonical_path.split(".")[:-1])
member_info = {"kind": member.kind, "path": member.canonical_path}
if parent_path not in res["inherited_members"]:
res["inherited_members"][parent_path] = []
res["inherited_members"][parent_path].append(member_info)
return resSources: packages/python/fumapy/mksource/document_module.py:49-72
The parse_function function inspects a griffe.Function object, generating its signature via build_signature(f) and extracting its name, path, description, parameters, return annotations, docstring remainder, and source code.
def parse_function(f: griffe.Function) -> Function:
out = simplify_docstring(f.docstring, f)
res: Function = {
"name": f.name,
"path": f.path,
"signature": build_signature(f),
"description": out.description,
"parameters": out.parameters,
"returns": out.returns,
"docstring": out.remainder,
"source": f.source,
}
return resSources: packages/python/fumapy/mksource/document_module.py:75-86
Utility Functions and Helpers
Utility helpers support AST inspection by filtering non-imported objects, stringifying expressions, and building accurate Python callable signatures.
| Function | Parameters | Return Type | Description |
|---|---|---|---|
build_signature | func: griffe.Function | str | Constructs a full function signature string, handling positional-only (/), keyword-only (*), varargs (*args), kwargs (**kwargs), defaults, and return annotations. |
filter_non_imported | d: dict[str, griffe.Object] | dict | Filters a dictionary of Griffe objects to retain only those where not v.is_imported. |
stringify_expr | expr: griffe.Expr | str | str | Converts a Griffe expression into its string path representation or returns the string as-is. |
Sources: packages/python/fumapy/mksource/utils.py:4-49
Docstring Simplification and Signature Normalization
Simplified Docstring Structure and Processing
The docstring transformation pipeline converts raw Griffe docstrings and AST inspection objects into structured dictionaries and named tuples via simplify_docstring. The SimplifiedDocstring named tuple contains five core fields: description, parameters, returns, attributes, and remainder.
class SimplifiedDocstring(t.NamedTuple):
description: str | None
parameters: list[dict[str, str | None]]
returns: dict[str, str | None]
attributes: list[dict[str, str | None]]
remainder: list[griffe.DocstringSection]
Sources: packages/python/fumapy/mksource/simplify_docstring.py:6-12
When processing a module, class, or function, helper routines initialize fields directly from the parent AST signatures before parsing individual docstring sections. Parameter annotations, default values, and attribute visibility filters are established during this initial signature pass.
def get_parameters_from_signature(parent: griffe.Class | griffe.Function):
return [
{
"name": p.name,
"annotation": p.annotation,
"description": None,
"value": p.default,
}
for p in parent.parameters
]
def get_returns_from_signature(parent: griffe.Function):
return {
"name": "",
"annotation": (
parent.returns
if isinstance(parent.returns, (str, type(None)))
else "".join(
elem if isinstance(elem, str) else elem.canonical_path
for elem in parent.returns.iterate(flat=True)
)
),
"description": None,
}
def get_attributes_from_signature(parent: griffe.Module | griffe.Class):
return [
{
"name": attr.name,
"annotation": attr.annotation,
"description": attr.docstring.parsed if attr.docstring else None,
"value": attr.value,
}
for attr in parent.attributes.values()
if (not attr.is_alias and not attr.is_private)
]Sources: packages/python/fumapy/mksource/simplify_docstring.py:17-52
Warning
When iterating over parent attributes in get_attributes_from_signature, both attr.is_alias and attr.is_private items are explicitly excluded from the resulting list to prevent duplicate or private documentation entries.
Sources: packages/python/fumapy/mksource/simplify_docstring.py:50-52
Section Parsing and AST Merging
As simplify_docstring iterates through doc.parsed, it handles specific section kinds (text, parameters, returns, and attributes) while appending unhandled sections to remainder. Text sections appearing at index 0 populate the main description. Parameter and attribute sections merge docstring descriptions with runtime signature data by matching names against dictionaries constructed from parsed docstring section values.
for i, sec in enumerate(doc.parsed):
if sec.kind == "text" and i == 0:
description = sec.value
continue
# Sort the parameters with the real signature
if sec.kind == "parameters":
map = {i.name: i for i in sec.value}
params_list = []
for param in parent.parameters:
if param.name in map:
docstring = map[param.name]
try:
docstring.description = griffe.parse_google(
griffe.Docstring(docstring.description)
)
except AttributeError:
pass
params_list.append(docstring)
else:
params_list.append(
{
"name": param.name,
"annotation": param.annotation,
"description": None,
"value": param.default,
}
)
parameters = params_list
continue
if sec.kind == "returns":
returns: griffe.DocstringReturn = sec.value[0]
returns.annotation = (
returns.annotation.canonical_path
if isinstance(returns.annotation, griffe.Expr)
else returns.annotation
)
continueSources: packages/python/fumapy/mksource/simplify_docstring.py:76-115
Tip
Parameter and attribute descriptions extracted from docstrings are re-parsed using griffe.parse_google(griffe.Docstring(...)) to normalize Google-style formatting within individual item docstrings.
Sources: packages/python/fumapy/mksource/simplify_docstring.py:89-91, packages/python/fumapy/mksource/simplify_docstring.py:135-137
TypedDict definitions in models.py mirror these structures for downstream serialization and documentation rendering, ensuring strict type safety for parameters, attributes, functions, classes, and modules.
| Type Definition | Fields | Description |
|---|---|---|
Parameter | name, annotation, description, value | Represents a single function or method parameter. |
Attribute | name, annotation, description, value | Represents a class or module attribute. |
DocstringSection | kind, value | Represents an unparsed or remaining docstring section. |
Function | name, path, signature, description, parameters, returns, docstring, source | Typed dictionary capturing function metadata. |
Sources: packages/python/fumapy/mksource/models.py:30-60
Serialization Models and JSON Encoding
TypedDict Schema Models
TypedDict schemas define the structure for serialized Python modules, classes, and functions, mapping documentation metadata into strict dictionary types. The Module schema aggregates nested modules, classes, functions, attributes, and docstrings alongside metadata fields. The Class and Function schemas capture signature information, source code strings, parameters, and return mappings.
class Module(t.TypedDict):
name: str
path: str
filepath: str
description: str | None
docstring: Docstring
attributes: list[Attribute]
modules: dict[str, Module]
classes: dict[str, Class]
functions: dict[str, Function]
version: str | None
class Class(t.TypedDict):
name: str
path: str
description: str | None
parameters: list[Parameter]
attributes: list[Attribute]
docstring: Docstring
functions: dict[str, Function]
source: str
class Function(t.TypedDict):
name: str
path: str
signature: str
description: str | None
parameters: list[Parameter]
returns: dict[str, str | None]
docstring: Docstring
source: str
Sources: packages/python/fumapy/mksource/models.py:6-39
Note
Docstring is defined as a list of DocstringSection typed dictionaries, where each section holds a specific kind string and a value containing either plain text or a list of parameters.
Sources: packages/python/fumapy/mksource/models.py:41-46
Custom JSON Encoder
The CustomEncoder class extends griffe.JSONEncoder to serialize Python path objects and expressions during export. A mapping table (_json_encoder_map) directs Path, PosixPath, and WindowsPath instances to str conversion, and Python set objects to sorted lists.
_json_encoder_map: dict[type, t.Callable[[t.Any], t.Any]] = {
Path: str,
PosixPath: str,
WindowsPath: str,
set: sorted,
}Sources: packages/python/fumapy/mksource/json_encoder.py:5-10
Within CustomEncoder.default, objects matching griffe.Expr are converted directly to strings via str(obj), while standard inspected nodes invoke obj.as_dict(full=self.full). Unrecognized types fall back to _json_encoder_map lookups or super().default.
class CustomEncoder(griffe.JSONEncoder):
def default(self, obj: t.Any) -> t.Any:
"""Return a serializable representation of the given object.
Parameters:
obj: The object to serialize.
Returns:
A serializable representation.
"""
try:
if isinstance(obj, griffe.Expr):
return str(obj)
return obj.as_dict(full=self.full)
except AttributeError:
return _json_encoder_map.get(type(obj), super().default)(obj)Sources: packages/python/fumapy/mksource/json_encoder.py:13-29
Caution
If obj.as_dict() raises an AttributeError, the encoder catches the exception and attempts fallback serialization through _json_encoder_map before resorting to the parent encoder.
Sources: packages/python/fumapy/mksource/json_encoder.py:24-29
Frontend Type Mapping and Rendering
MDX Element Conversion and Layout
The convert function processes structured module objects into an array of output files by evaluating descriptions, attributes, nested classes, functions, and submodules. When classes or submodules are present, it dynamically builds layout structures using Tabs and Cards components, mapping entity paths with custom URL builders.
| Function / Utility | Target Element | Purpose |
|---|---|---|
convert | Tabs, Tab, Cards, Card | Assembles module documentation into tabbed layouts and card grids. |
convertClass | Markdown file (.mdx) | Generates standalone class documentation files with attribute and function sections. |
convertFunction | PyFunction | Wraps function definitions, signatures, source code blocks, parameters, and return types. |
convertParameter | PyParameter | Renders parameter entries with type annotations and default values. |
convertAttribute | PyAttribute | Renders module or class attributes with optional annotations and default values. |
Sources: packages/python/src/convert.ts:20-94, packages/python/src/convert.ts:96-126, packages/python/src/convert.ts:128-157, packages/python/src/convert.ts:159-171, packages/python/src/convert.ts:173-183
Warning
Text encoding performed by encodeText explicitly escapes less-than characters and curly braces to prevent syntax collision with MDX expressions during string serialization.
Sources: packages/python/src/convert.ts:249-251
React Documentation Components
The rendering layer defines specialized React components styled with Tailwind CSS and class-variance-authority variants. Badge variants distinguish component categories using color themes for functions, attributes, classes, and primary parameters.
const cardVariants = cva('bg-fd-card rounded-lg text-sm my-6 p-3 border');
const badgeVariants = cva('text-xs font-medium border p-1 rounded-lg not-prose', {
variants: {
color: {
func: 'bg-fdpy-func/10 text-fdpy-func border-fdpy-func/50',
attribute: 'bg-fdpy-attribute/10 text-fdpy-attribute border-fdpy-attribute/50',
class: 'bg-fdpy-class/10 text-fdpy-class border-fdpy-class/50',
primary: 'bg-fd-primary/10 text-fd-primary border-fd-primary/10',
},
},
});Sources: packages/python/src/components/index.tsx:13-23
The PySourceCode component encapsulates function source blocks within collapsible containers that expose toggle triggers with chevron rotation indicators.
export function PySourceCode({ children }: { children: ReactNode }) {
return (
<Collapsible className="my-6">
<CollapsibleTrigger
className={cn(
buttonVariants({
color: 'secondary',
size: 'sm',
className: 'group',
}),
)}
>
Source Code
<ChevronRight className="size-3.5 text-fd-muted-foreground group-data-[state=open]:rotate-90" />
</CollapsibleTrigger>
<CollapsibleContent className="prose-no-margin">{children}</CollapsibleContent>
</Collapsible>
);
}Sources: packages/python/src/components/index.tsx:103-121
Tip
The InlineCode helper leverages syntax highlighting on python code strings, customising pre-formatted spans to render inline type signatures cleanly.
Sources: packages/python/src/components/index.tsx:135-149
Related
On This Page
OverviewCommand Line and Execution WorkflowCLI Entrypoint and Argument ConfigurationExecution Lifecycle and SerializationGriffe Inspection and AST TraversalModule AST ParsingClass and Function AST ExtractionUtility Functions and HelpersDocstring Simplification and Signature NormalizationSimplified Docstring Structure and ProcessingSection Parsing and AST MergingSerialization Models and JSON EncodingTypedDict Schema ModelsCustom JSON EncoderFrontend Type Mapping and RenderingMDX Element Conversion and LayoutReact Documentation ComponentsRelated