Files
toolbox/generate_readme.py

126 lines
3.5 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动生成 README.md扫描当前目录下的 Python 脚本和可执行包,
提取其 docstring 并更新到 README 中。
"""
import os
import ast
import sys
from pathlib import Path
# 当前脚本所在目录
SCRIPT_DIR = Path(__file__).parent.resolve()
# 输出 README 路径
README_PATH = SCRIPT_DIR / "README.md"
# 模板路径(可选)
TEMPLATE_PATH = SCRIPT_DIR / "README.template.md"
def extract_docstring_from_file(file_path: Path) -> str:
"""从 Python 文件中提取模块级 docstring。"""
try:
with open(file_path, "r", encoding="utf-8") as f:
node = ast.parse(f.read())
return ast.get_docstring(node) or "(无文档说明)"
except Exception as e:
return f"(解析失败: {e}"
def collect_items():
"""收集当前目录下所有 .py 文件和含 __main__.py 的子目录。"""
items = []
for item in SCRIPT_DIR.iterdir():
if item.name == Path(__file__).name:
continue # 跳过本脚本
if item.name.startswith("."):
continue # 跳过隐藏文件/目录
if item.is_file() and item.suffix == ".py":
name = item.stem
doc = extract_docstring_from_file(item)
items.append({"type": "script", "name": name, "doc": doc, "path": item.name})
elif item.is_dir():
main_py = item / "__main__.py"
if main_py.exists():
name = item.name
doc = extract_docstring_from_file(main_py)
items.append({"type": "package", "name": name, "doc": doc, "path": str(item.name) + "/__main__.py"})
# 按名称排序
items.sort(key=lambda x: x["name"].lower())
return items
def load_template() -> str:
"""加载模板:优先用 README.template.md否则用内置模板。"""
if TEMPLATE_PATH.exists():
with open(TEMPLATE_PATH, "r", encoding="utf-8") as f:
return f.read()
else:
# 内置默认模板
return """# 工具集
本目录包含以下可执行脚本与工具包:
{content}
---
> 自动由 `{script_name}` 生成
"""
def generate_content(items):
"""根据 items 生成 Markdown 内容。"""
if not items:
return "> 暂无 Python 脚本或可执行包。\n"
lines = []
for item in items:
title = f"`{item['name']}`"
if item["type"] == "package":
title += " (包)"
lines.append(f"## {title}")
lines.append("")
# 渲染 docstring保留原始换行但缩进处理
doc = item["doc"].strip()
if doc:
# 如果 docstring 是多行,用引用块或直接段落
if "\n" in doc:
lines.append("```text")
lines.append(doc)
lines.append("```")
else:
lines.append(doc)
else:
lines.append("(无文档说明)")
lines.append("")
lines.append(f"> 文件路径: `{item['path']}`")
lines.append("")
return "\n".join(lines)
def main():
items = collect_items()
template = load_template()
content = generate_content(items)
readme_text = template.format(
content=content,
script_name=Path(__file__).name
)
with open(README_PATH, "w", encoding="utf-8") as f:
f.write(readme_text)
print(f"✅ README.md 已更新,共收录 {len(items)} 个项目。")
if __name__ == "__main__":
main()