mirror of
https://github.com/modelscope/FunASR.git
synced 2026-10-12 02:19:18 +00:00
docs: preserve API signatures and discover AutoModelVLLM
Signed-off-by: zhifu gao <[email protected]>
This commit is contained in:
+82
-20
@@ -26,7 +26,10 @@ STYLESHEET = REPO_ROOT / "gh-pages-output" / "api-reference.css"
|
||||
os.chdir(REPO_ROOT)
|
||||
|
||||
tree_structure = {
|
||||
"funasr.auto": {"auto_model": "funasr/auto/auto_model.py"},
|
||||
"funasr.auto": {
|
||||
"auto_model": "funasr/auto/auto_model.py",
|
||||
"auto_model_vllm": "funasr/auto/auto_model_vllm.py",
|
||||
},
|
||||
"funasr.register": {"register": "funasr/register.py"},
|
||||
"funasr.models": {},
|
||||
"funasr.frontends": {},
|
||||
@@ -115,6 +118,43 @@ def get_source_lines(filepath, node):
|
||||
def github_url(filepath, lineno):
|
||||
return f"{REPO_URL}/blob/{BRANCH}/{filepath}#L{lineno}"
|
||||
|
||||
def callable_signature(node, source, bound=False, constructor=False):
|
||||
"""Render source expressions without importing code or evaluating defaults."""
|
||||
def expression(value):
|
||||
return ast.get_source_segment(source, value).strip()
|
||||
|
||||
def argument(value, default=None, prefix=""):
|
||||
result = prefix + value.arg
|
||||
if value.annotation is not None:
|
||||
result += ": " + expression(value.annotation)
|
||||
if default is not None:
|
||||
result += (" = " if value.annotation is not None else "=") + expression(default)
|
||||
return result
|
||||
|
||||
args = node.args
|
||||
positional = args.posonlyargs + args.args
|
||||
defaults = [None] * (len(positional) - len(args.defaults)) + list(args.defaults)
|
||||
static = any(isinstance(d, ast.Name) and d.id == "staticmethod"
|
||||
for d in node.decorator_list)
|
||||
start = 1 if bound and not static and positional else 0
|
||||
parts = []
|
||||
for index in range(start, len(positional)):
|
||||
parts.append(argument(positional[index], defaults[index]))
|
||||
if index + 1 == len(args.posonlyargs):
|
||||
parts.append("/")
|
||||
if args.vararg is not None:
|
||||
parts.append(argument(args.vararg, prefix="*"))
|
||||
elif args.kwonlyargs:
|
||||
parts.append("*")
|
||||
parts.extend(argument(value, default) for value, default
|
||||
in zip(args.kwonlyargs, args.kw_defaults))
|
||||
if args.kwarg is not None:
|
||||
parts.append(argument(args.kwarg, prefix="**"))
|
||||
signature = "(" + ", ".join(parts) + ")"
|
||||
if node.returns is not None and not constructor:
|
||||
signature += " -> " + expression(node.returns)
|
||||
return signature
|
||||
|
||||
# Extract all data
|
||||
all_data = {}
|
||||
for top_level, sub_modules in tree_structure.items():
|
||||
@@ -136,27 +176,30 @@ for top_level, sub_modules in tree_structure.items():
|
||||
class_doc = ast.get_docstring(node) or ""
|
||||
src, lineno, trunc = get_source_lines(filepath, node)
|
||||
methods = []
|
||||
constructor = None
|
||||
for item in node.body:
|
||||
if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)):
|
||||
if item.name == "__init__":
|
||||
constructor = {
|
||||
"signature": callable_signature(item, source, bound=True, constructor=True),
|
||||
"doc": ast.get_docstring(item) or "",
|
||||
"lineno": item.lineno,
|
||||
}
|
||||
if item.name.startswith("_"):
|
||||
continue
|
||||
mdoc = ast.get_docstring(item) or ""
|
||||
args = [a.arg for a in item.args.args if a.arg != "self"]
|
||||
if item.args.vararg: args.append("*" + item.args.vararg.arg)
|
||||
if item.args.kwarg: args.append("**" + item.args.kwarg.arg)
|
||||
msrc, mline, mtrunc = get_source_lines(filepath, item)
|
||||
methods.append({"name": item.name, "args": args, "doc": mdoc,
|
||||
methods.append({"name": item.name,
|
||||
"signature": callable_signature(item, source, bound=True), "doc": mdoc,
|
||||
"source": msrc, "lineno": mline, "truncated": mtrunc})
|
||||
entries.append({"type": "class", "name": node.name, "doc": class_doc,
|
||||
"methods": methods, "source": src, "lineno": lineno,
|
||||
"methods": methods, "constructor": constructor, "source": src, "lineno": lineno,
|
||||
"truncated": trunc, "filepath": filepath})
|
||||
elif isinstance(node, ast.FunctionDef) and not node.name.startswith("_"):
|
||||
fdoc = ast.get_docstring(node) or ""
|
||||
args = [a.arg for a in node.args.args]
|
||||
if node.args.vararg: args.append("*" + node.args.vararg.arg)
|
||||
if node.args.kwarg: args.append("**" + node.args.kwarg.arg)
|
||||
fsrc, fline, ftrunc = get_source_lines(filepath, node)
|
||||
entries.append({"type": "function", "name": node.name, "args": args,
|
||||
entries.append({"type": "function", "name": node.name,
|
||||
"signature": callable_signature(node, source),
|
||||
"doc": fdoc, "source": fsrc, "lineno": fline,
|
||||
"truncated": ftrunc, "filepath": filepath})
|
||||
if entries:
|
||||
@@ -169,7 +212,20 @@ print(f"Extracted: {len(all_data)} modules, {total_entries} entries")
|
||||
sidebar = ""
|
||||
content = ""
|
||||
overview_links = ""
|
||||
# Allocate newly documented vLLM entries after legacy entries, even though their
|
||||
# navigation belongs beside AutoModel. Existing numeric deep links stay stable.
|
||||
new_module = "funasr.auto.auto_model_vllm"
|
||||
anchor_modules = [key for key in all_data if key != new_module]
|
||||
if new_module in all_data:
|
||||
anchor_modules.append(new_module)
|
||||
eid = 0
|
||||
for key in anchor_modules:
|
||||
for entry in all_data[key]:
|
||||
eid += 1
|
||||
entry["anchor"] = f"e{eid}"
|
||||
for method in entry.get("methods", []):
|
||||
eid += 1
|
||||
method["anchor"] = f"e{eid}"
|
||||
|
||||
for group_index, top_level in enumerate(tree_structure):
|
||||
sub_modules = tree_structure[top_level]
|
||||
@@ -182,23 +238,30 @@ for group_index, top_level in enumerate(tree_structure):
|
||||
module_id = f"{group_id}-module-{module_index}"
|
||||
sidebar += f'<div class="l2"><button type="button" class="l2-title" aria-expanded="true" aria-controls="{module_id}"><span>{esc(sub_name)}</span><span class="arr" aria-hidden="true">▸</span></button><div class="l2-children" id="{module_id}">\n'
|
||||
for entry in all_data[key]:
|
||||
eid += 1
|
||||
eid_str = f"e{eid}"
|
||||
eid_str = entry["anchor"]
|
||||
filepath = entry.get("filepath", "")
|
||||
if entry["type"] == "class":
|
||||
if entry["name"] in {"AutoModel", "RegisterTables"}:
|
||||
if entry["name"] in {"AutoModel", "AutoModelVLLM", "RegisterTables"}:
|
||||
overview_links += f'<a href="#{eid_str}" class="entry-link">{esc(entry["name"])} <span aria-hidden="true">→</span></a> '
|
||||
sidebar += f'<a class="l3-item" href="#{eid_str}" data-target="{eid_str}"><span class="mb badge-c" aria-hidden="true">C</span><span>{esc(entry["name"])}</span></a>\n'
|
||||
gh_link = github_url(filepath, entry["lineno"])
|
||||
content += f'<div class="api-detail" id="{eid_str}"><span class="dtag badge-c">class</span><h2>{esc(entry["name"])}</h2><div class="dmod">{key} · <a href="{gh_link}" target="_blank">View on GitHub ↗</a></div><div class="ddoc">{format_doc(entry["doc"])}</div>'
|
||||
title = esc(entry["name"])
|
||||
if entry["constructor"] is not None:
|
||||
title = '<code>' + esc(entry["name"] + entry["constructor"]["signature"]) + '</code>'
|
||||
content += f'<div class="api-detail" id="{eid_str}"><span class="dtag badge-c">class</span><h2>{title}</h2><div class="dmod">{key} · <a href="{gh_link}" target="_blank">View on GitHub ↗</a></div><div class="ddoc">{format_doc(entry["doc"])}</div>'
|
||||
content += f'<details class="src-block"><summary>📄 Source code</summary><pre><code>{esc(entry["source"])}</code></pre>'
|
||||
if entry["truncated"]:
|
||||
content += f'<a href="{gh_link}" target="_blank" class="src-more">View full source on GitHub →</a>'
|
||||
content += '</details>'
|
||||
if entry["constructor"] is not None:
|
||||
constructor = entry["constructor"]
|
||||
constructor_url = github_url(filepath, constructor["lineno"])
|
||||
content += f'<h3 class="mt">Constructor</h3><div class="mblk"><a href="{constructor_url}" class="gh-link">L{constructor["lineno"]}</a>'
|
||||
content += format_doc(constructor["doc"]) + '</div>'
|
||||
if entry["methods"]:
|
||||
content += '<h3 class="mt">Methods</h3>'
|
||||
for m in entry["methods"]:
|
||||
sig = f'.{m["name"]}({", ".join(m["args"])})'
|
||||
sig = f'.{m["name"]}{m["signature"]}'
|
||||
mgh = github_url(filepath, m["lineno"])
|
||||
content += f'<div class="mblk"><code>{esc(sig)}</code> <a href="{mgh}" target="_blank" class="gh-link">L{m["lineno"]}</a><div class="mdoc">{format_doc(m["doc"])}</div>'
|
||||
content += f'<details class="src-block"><summary>📄 Source</summary><pre><code>{esc(m["source"])}</code></pre>'
|
||||
@@ -207,10 +270,9 @@ for group_index, top_level in enumerate(tree_structure):
|
||||
content += '</details></div>'
|
||||
content += '</div>\n'
|
||||
for m in entry["methods"]:
|
||||
eid += 1
|
||||
mid = f"e{eid}"
|
||||
mid = m["anchor"]
|
||||
sidebar += f'<a class="l3-item l3m" href="#{mid}" data-target="{mid}"><span class="mb badge-m" aria-hidden="true">M</span><span>.{esc(m["name"])}()</span></a>\n'
|
||||
sig = f'{entry["name"]}.{m["name"]}({", ".join(m["args"])})'
|
||||
sig = f'{entry["name"]}.{m["name"]}{m["signature"]}'
|
||||
mgh = github_url(filepath, m["lineno"])
|
||||
content += f'<div class="api-detail" id="{mid}"><span class="dtag badge-m">method</span><h2><code>{esc(sig)}</code></h2><div class="dmod">{key}.{entry["name"]} · <a href="{mgh}" target="_blank">View on GitHub ↗</a></div><div class="ddoc">{format_doc(m["doc"])}</div>'
|
||||
content += f'<details class="src-block"><summary>📄 Source code</summary><pre><code>{esc(m["source"])}</code></pre>'
|
||||
@@ -218,10 +280,10 @@ for group_index, top_level in enumerate(tree_structure):
|
||||
content += f'<a href="{mgh}" target="_blank" class="src-more">View full source on GitHub →</a>'
|
||||
content += '</details></div>\n'
|
||||
else:
|
||||
args_str = ", ".join(entry.get("args", []))
|
||||
signature = entry["name"] + entry["signature"]
|
||||
gh_link = github_url(filepath, entry["lineno"])
|
||||
sidebar += f'<a class="l3-item" href="#{eid_str}" data-target="{eid_str}"><span class="mb badge-f" aria-hidden="true">F</span><span>{esc(entry["name"])}</span></a>\n'
|
||||
content += f'<div class="api-detail" id="{eid_str}"><span class="dtag badge-f">function</span><h2><code>{esc(entry["name"])}({esc(args_str)})</code></h2><div class="dmod">{key} · <a href="{gh_link}" target="_blank">View on GitHub ↗</a></div><div class="ddoc">{format_doc(entry["doc"])}</div>'
|
||||
content += f'<div class="api-detail" id="{eid_str}"><span class="dtag badge-f">function</span><h2><code>{esc(signature)}</code></h2><div class="dmod">{key} · <a href="{gh_link}" target="_blank">View on GitHub ↗</a></div><div class="ddoc">{format_doc(entry["doc"])}</div>'
|
||||
content += f'<details class="src-block"><summary>📄 Source code</summary><pre><code>{esc(entry["source"])}</code></pre>'
|
||||
if entry["truncated"]:
|
||||
content += f'<a href="{gh_link}" target="_blank" class="src-more">View full source on GitHub →</a>'
|
||||
|
||||
Reference in New Issue
Block a user