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