"""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), }