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()