Spaces:
Running
Running
| from fastapi import Query | |
| from typing import Dict, Literal | |
| import httpx | |
| import os | |
| def extract_type(p): | |
| schema = p.get("schema", {}) | |
| if "$ref" in schema: | |
| return str # fallback | |
| if "enum" in schema: | |
| return Literal[tuple(schema["enum"])] | |
| return openapi_type_to_python(schema.get("type", "string")) | |
| def get_param_metadata(p): | |
| schema = p.get("schema", {}) | |
| return { | |
| "name": p["name"], | |
| "type": extract_type(p), | |
| "required": p.get("required", False), | |
| "description": p.get("description", ""), | |
| "default": schema.get("default", ...), # `...` => required if undefined | |
| "enum": schema.get("enum", None), | |
| } | |
| async def get_remote_params(base_url: str, | |
| endpoint: str, | |
| method: str = 'get') -> Dict: | |
| async with httpx.AsyncClient() as client: | |
| headers = {} | |
| if TENNIS_ML_API_KEY := os.getenv('TENNIS_ML_API_KEY'): | |
| headers["Authorization"] = TENNIS_ML_API_KEY | |
| response = await client.get(f"{base_url}openapi.json", headers=headers) | |
| spec = response.json() | |
| # Extraction of the parameters from the OpenAPI spec | |
| path_def = spec["paths"].get(f'/{endpoint}', {}) | |
| method_def = path_def.get(method, {}) | |
| params = method_def.get("parameters", []) | |
| return { | |
| "found": bool(path_def), | |
| "general": { | |
| "description": method_def.get("description", ""), | |
| "summary": method_def.get("summary", ""), | |
| "tags": method_def.get("tags", []), | |
| }, | |
| "params": [ | |
| get_param_metadata(p) | |
| for p in params if p["in"] == "query" | |
| ] | |
| } | |
| def openapi_type_to_python(t: str): | |
| return { | |
| "string": str, | |
| "integer": int, | |
| "number": float, | |
| "boolean": bool, | |
| "array": list, | |
| }.get(t, str) # fallback = str | |
| def create_forward_endpoint(base_url: str, _endpoint: str, param_defs: Dict): | |
| # Dynamic endpoint creation | |
| def endpoint_factory(): | |
| async def endpoint(**kwargs): | |
| headers = {} | |
| if TENNIS_ML_API_KEY := os.getenv('TENNIS_ML_API_KEY'): | |
| headers["Authorization"] = TENNIS_ML_API_KEY | |
| async with httpx.AsyncClient() as client: | |
| response = await client.get( | |
| f"{base_url}{_endpoint}", | |
| params=kwargs, | |
| headers=headers, | |
| ) | |
| response.raise_for_status() | |
| return response.json() | |
| return endpoint | |
| endpoint = endpoint_factory() | |
| # Add the parameters to the endpoint | |
| endpoint.__annotations__ = { | |
| p["name"]: openapi_type_to_python(p["type"]) for p in param_defs | |
| } | |
| # Add dependencies to the endpoint | |
| from inspect import Parameter, Signature | |
| parameters = [] | |
| for p in param_defs: | |
| annotation = p["type"] | |
| default = p.get("default", ...) if p.get("required", False) else p.get("default", None) | |
| query = Query( | |
| default=default, | |
| description=p.get("description", "") | |
| ) | |
| param = Parameter( | |
| name=p["name"], | |
| kind=Parameter.KEYWORD_ONLY, | |
| default=query, | |
| annotation=annotation | |
| ) | |
| parameters.append(param) | |
| endpoint.__signature__ = Signature(parameters) | |
| return endpoint | |