Files
wehub-resource-sync adf0d17497
publish / version_or_publish (push) Waiting to run
storybook-build / changes (push) Waiting to run
storybook-build / :storybook-build (push) Blocked by required conditions
Sync Gradio Skills to Hugging Face / sync-skills (push) Waiting to run
functional / changes (push) Waiting to run
functional / build-frontend (push) Blocked by required conditions
functional / functional-test-SSR=false (push) Blocked by required conditions
functional / functional-reload (push) Blocked by required conditions
functional / functional-test-SSR=true (push) Blocked by required conditions
hygiene / hygiene-test (push) Waiting to run
python / changes (push) Waiting to run
python / build (push) Blocked by required conditions
python / test-ubuntu-latest-flaky (push) Blocked by required conditions
python / test-ubuntu-latest-not-flaky (push) Blocked by required conditions
python / test-windows-latest-flaky (push) Blocked by required conditions
python / test-windows-latest-not-flaky (push) Blocked by required conditions
js / changes (push) Waiting to run
js / js-test (push) Blocked by required conditions
docs-build / changes (push) Waiting to run
docs-build / docs-build (push) Blocked by required conditions
docs-build / website-build (push) Blocked by required conditions
chore: import upstream snapshot with attribution
2026-07-13 13:17:32 +08:00

277 lines
8.5 KiB
Python

"""Centralized code snippet generation for Gradio API endpoints. Generates Python, JavaScript, and cURL code snippets from API info dicts."""
import copy
import json
import re
from typing import Any
BLOB_COMPONENTS = {
"Audio",
"DownloadButton",
"File",
"Image",
"ImageSlider",
"Model3D",
"UploadButton",
"Video",
}
def _is_file_data(obj: Any) -> bool:
return (
isinstance(obj, dict)
and "url" in obj
and obj.get("url")
and "meta" in obj
and isinstance(obj.get("meta"), dict)
and obj["meta"].get("_type") == "gradio.FileData"
)
def _has_file_data(obj: Any) -> bool:
if isinstance(obj, dict):
if _is_file_data(obj):
return True
return any(_has_file_data(v) for v in obj.values())
if isinstance(obj, (list, tuple)):
return any(_has_file_data(item) for item in obj)
return False
def _replace_file_data_py(obj: Any) -> Any:
if isinstance(obj, dict) and _is_file_data(obj):
return f"handle_file('{obj['url']}')"
if isinstance(obj, (list, tuple)):
return [_replace_file_data_py(item) for item in obj]
if isinstance(obj, dict):
return {k: _replace_file_data_py(v) for k, v in obj.items()}
return obj
def _simplify_file_data(obj: Any) -> Any:
if isinstance(obj, dict) and _is_file_data(obj):
return {"path": obj["url"], "meta": {"_type": "gradio.FileData"}}
if isinstance(obj, (list, tuple)):
return [_simplify_file_data(item) for item in obj]
if isinstance(obj, dict):
return {k: _simplify_file_data(v) for k, v in obj.items()}
return obj
_UNQUOTED = "UNQUOTED_GRADIO_"
def _stringify_py(obj: Any) -> str:
def _prepare(o: Any) -> Any:
if o is None:
return f"{_UNQUOTED}None"
if isinstance(o, bool):
return f"{_UNQUOTED}True" if o else f"{_UNQUOTED}False"
if isinstance(o, str) and o.startswith("handle_file(") and o.endswith(")"):
return f"{_UNQUOTED}{o}"
if isinstance(o, (list, tuple)):
return [_prepare(item) for item in o]
if isinstance(o, dict):
return {k: _prepare(v) for k, v in o.items()}
return o
prepared = _prepare(obj)
result = json.dumps(prepared, default=str)
result = re.sub(
rf'"{_UNQUOTED}(handle_file\([^)]*\))"',
r"\1",
result,
)
result = result.replace(f'"{_UNQUOTED}None"', "None")
result = result.replace(f'"{_UNQUOTED}True"', "True")
result = result.replace(f'"{_UNQUOTED}False"', "False")
return result
def _represent_value(value: Any, python_type: str | None, lang: str) -> str:
if python_type is None:
return "None" if lang == "py" else "null"
if value is None:
return "None" if lang == "py" else "null"
if python_type in ("string", "str"):
return f'"{value}"'
if python_type == "number":
return str(value)
if python_type in ("boolean", "bool"):
if lang == "py":
return "True" if value else "False"
return str(value).lower() if isinstance(value, bool) else str(value)
if python_type == "List[str]":
return json.dumps(value)
if python_type.startswith("Literal['"):
return f'"{value}"'
if isinstance(value, str):
if value == "":
return "None" if lang == "py" else "null"
return value
value = copy.deepcopy(value)
if lang == "bash":
value = _simplify_file_data(value)
if lang == "py":
value = _replace_file_data_py(value)
return _stringify_py(value)
def _get_param_value(param: dict) -> Any:
if param.get("parameter_has_default"):
return param.get("parameter_default")
return param.get("example_input")
def generate_python_snippet(
api_name: str,
params: list[dict],
src: str,
) -> str:
has_file = any(_has_file_data(p.get("example_input")) for p in params)
imports = "from gradio_client import Client"
if has_file:
imports += ", handle_file"
lines = [imports, ""]
lines.append(f'client = Client("{src}")')
predict_args = []
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "py")
predict_args.append(f"\t{name}={formatted},")
lines.append("result = client.predict(")
lines.extend(predict_args)
lines.append(f'\tapi_name="{api_name}",')
lines.append(")")
lines.append("print(result)")
return "\n".join(lines)
def generate_js_snippet(
api_name: str,
params: list[dict],
src: str,
) -> str:
blob_params = [p for p in params if p.get("component") in BLOB_COMPONENTS]
lines = ['import { Client } from "@gradio/client";', ""]
for i, bp in enumerate(blob_params):
example = bp.get("example_input", {})
url = example.get("url", "") if isinstance(example, dict) else ""
component = bp.get("component", "")
lines.append(f'const response_{i} = await fetch("{url}");')
lines.append(f"const example{component} = await response_{i}.blob();")
if blob_params:
lines.append("")
lines.append(f'const client = await Client.connect("{src}");')
blob_component_names = {bp.get("component") for bp in blob_params}
predict_args = []
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
component = p.get("component", "")
if component in blob_component_names:
predict_args.append(f"\t\t{name}: example{component},")
else:
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "js")
predict_args.append(f"\t\t{name}: {formatted},")
lines.append(f'const result = await client.predict("{api_name}", {{')
lines.extend(predict_args)
lines.append("});")
lines.append("")
lines.append("console.log(result.data);")
return "\n".join(lines)
def generate_bash_snippet(
api_name: str,
params: list[dict],
root: str,
api_prefix: str = "/",
) -> str:
normalised_root = root.rstrip("/")
normalised_prefix = api_prefix if api_prefix else "/"
endpoint_name = api_name.lstrip("/")
has_file = any(_has_file_data(p.get("example_input")) for p in params)
upload_url = f"{normalised_root}{normalised_prefix}upload"
lines: list[str] = []
file_param_names: list[str] = []
if has_file:
for p in params:
if _has_file_data(p.get("example_input")):
name = p.get("parameter_name") or p.get("label", "input")
file_param_names.append(name)
lines.append(
f"FILE_PATH=$(curl -s -X POST {upload_url}"
" -F 'files=@/path/to/your/file'"
" | tr -d '[]\" ')"
)
lines.append("")
data_dict = {}
for p in params:
name = p.get("parameter_name") or p.get("label", "input")
if name in file_param_names:
data_dict[name] = "FILE_PATH_PLACEHOLDER"
else:
value = _get_param_value(p)
ptype = p.get("python_type", {}).get("type")
formatted = _represent_value(value, ptype, "bash")
data_dict[name] = formatted
data_entries = ", ".join(f'"{k}": {v}' for k, v in data_dict.items())
data_str = "{" + data_entries + "}"
for _ in file_param_names:
replacement = '{"path": "\'$FILE_PATH\'", "meta": {"_type": "gradio.FileData"}}'
data_str = data_str.replace("FILE_PATH_PLACEHOLDER", replacement)
base_url = f"{normalised_root}{normalised_prefix}call/v2/{endpoint_name}"
get_url = f"{normalised_root}{normalised_prefix}call/{endpoint_name}"
lines.extend(
[
f'curl -X POST {base_url} -s -H "Content-Type: application/json" \\',
f" -d '{data_str}' \\",
" | awk -F'\"' '{ print $4}' \\",
f" | read EVENT_ID; curl -N {get_url}/$EVENT_ID",
]
)
return "\n".join(lines)
def generate_code_snippets(
api_name: str,
endpoint_info: dict,
root: str,
space_id: str | None = None,
api_prefix: str = "/",
) -> dict[str, str]:
params = endpoint_info.get("parameters", [])
src = space_id or root
return {
"python": generate_python_snippet(api_name, params, src),
"javascript": generate_js_snippet(api_name, params, src),
"bash": generate_bash_snippet(api_name, params, root, api_prefix),
}