forked from chrism0dwk/PyTado
-
Notifications
You must be signed in to change notification settings - Fork 56
Expand file tree
/
Copy pathgenerate_api_docs.py
More file actions
119 lines (93 loc) · 3.71 KB
/
generate_api_docs.py
File metadata and controls
119 lines (93 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import importlib
import inspect
import os
OUTPUT_FILE = "docs/content/api.md"
MODULES_TO_SCAN = [
"PyTado.interface.api", # Main API classes
"PyTado.interface", # Central interface
"PyTado.zone", # Zone management
]
def format_signature(method):
"""Returns the method signature as a readable string."""
try:
signature = inspect.signature(method)
except ValueError:
return "()"
param_list = []
for param_name, param in signature.parameters.items():
param_type = f": {param.annotation}" if param.annotation != inspect.Parameter.empty else ""
param_list.append(f"**{param_name}**{param_type}")
return f"({', '.join(param_list)})"
def get_method_doc(method):
"""Generates formatted Markdown documentation for a method with parameter details."""
doc = f"### {method.__name__}{format_signature(method)}\n\n"
docstring = inspect.getdoc(method) or "No description available."
doc += f"{docstring}\n\n"
try:
signature = inspect.signature(method)
params = signature.parameters
if params:
doc += "**Parameters:**\n\n"
for name, param in params.items():
param_type = f"`{param.annotation}`" if param.annotation != inspect.Parameter.empty else "Unknown" # noqa: E501
default_value = param.default if param.default != inspect.Parameter.empty else "Required" # noqa: E501
doc += f"- **{name}** ({param_type}): {default_value}\n"
doc += "\n"
except ValueError:
pass # If no signature can be extracted
return doc
def get_class_doc(cls):
"""
Generates formatted Markdown documentation for a class
with methods and attributes.
"""
doc = f"## {cls.__name__}\n\n"
doc += f"{inspect.getdoc(cls) or 'No documentation available.'}\n\n"
# Collect attributes (no methods or private elements)
attributes = {name: value for name, value in vars(
cls).items() if not callable(value) and not name.startswith("_")}
if attributes:
doc += "**Attributes:**\n\n"
for attr_name, attr_value in attributes.items():
attr_type = type(attr_value).__name__
doc += f"- **{attr_name}** (`{attr_type}`): `{attr_value}`\n"
doc += "\n"
# Document public methods
methods = inspect.getmembers(cls, predicate=inspect.isfunction)
for _, method in methods:
if method.__name__.startswith("_"): # Skip private methods
continue
doc += get_method_doc(method)
return doc
def add_frontmatter(content, key="API", order=3):
"""Adds frontmatter for 11ty navigation."""
frontmatter = f"""---
eleventyNavigation:
key: "{key}"
order: {order}
---
"""
return frontmatter + content
def generate_markdown():
"""Generates a Markdown file with all relevant classes."""
os.makedirs(os.path.dirname(OUTPUT_FILE), exist_ok=True)
doc = "# API Documentation for `PyTado`\n\n"
for module_name in MODULES_TO_SCAN:
try:
module = importlib.import_module(module_name)
classes = [
cls for _,
cls in inspect.getmembers(
module,
predicate=inspect.isclass) if cls.__module__.startswith(module_name)]
if classes:
doc += f"## Module `{module_name}`\n\n"
for cls in classes:
doc += get_class_doc(cls)
except Exception as e:
print(f"Error loading {module_name}: {e}")
with open(OUTPUT_FILE, "w", encoding="utf-8") as f:
f.write(add_frontmatter(doc))
print(f"API documentation generated: {OUTPUT_FILE}")
if __name__ == "__main__":
generate_markdown()