File size: 2,841 Bytes
c4e3b10 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
"""Minimal FastAPI shim for tests in this workspace.
This provides a tiny subset of the FastAPI API used by the tests: FastAPI, APIRouter,
Depends and TestClient. It's intended only for local test runs where fastapi isn't
installed. It does not implement full ASGI features.
"""
from typing import Callable, Any, Optional
class FastAPI:
def __init__(self):
self._routes = []
def on_event(self, event_name: str):
def decorator(fn: Callable):
# store but don't execute; tests only expect startup handler to exist
setattr(self, f"_on_event_{event_name}", fn)
return fn
return decorator
def get(self, path: str):
def decorator(fn: Callable):
self._routes.append(("GET", path, fn))
return fn
return decorator
def include_router(self, router: Any):
# assume router has routes attribute
routes = getattr(router, 'routes', [])
self._routes.extend(routes)
class APIRouter:
def __init__(self, prefix: str = "", tags: Optional[list] = None, **kwargs):
# store basic router metadata and route list
self.prefix = prefix or ""
self.tags = tags or []
self.routes = []
def get(self, path: str, **kwargs):
def decorator(fn: Callable):
full_path = f"{self.prefix}{path}"
self.routes.append(("GET", full_path, fn))
return fn
return decorator
def post(self, path: str, **kwargs):
def decorator(fn: Callable):
full_path = f"{self.prefix}{path}"
self.routes.append(("POST", full_path, fn))
return fn
return decorator
def Depends(dep: Any):
return dep
class TestClient:
def __init__(self, app: FastAPI):
self.app = app
def get(self, path: str):
# find matching route and call handler
for method, route_path, fn in self.app._routes:
if method == 'GET' and route_path == path:
result = fn()
class Resp:
status_code = 200
def json(self):
return result
return Resp()
class Resp404:
status_code = 404
def json(self):
return {"detail": "Not Found"}
return Resp404()
class HTTPException(Exception):
def __init__(self, status_code: int = 500, detail: Any = None):
self.status_code = status_code
self.detail = detail
super().__init__(f"HTTP {status_code}: {detail}")
# Minimal status codes used in tests
class _status:
HTTP_401_UNAUTHORIZED = 401
HTTP_403_FORBIDDEN = 403
HTTP_400_BAD_REQUEST = 400
status = _status()
|