|
25 | 25 | from werkzeug.serving import BaseWSGIServer, make_server |
26 | 26 |
|
27 | 27 | import idom |
28 | | -from idom.backend.types import Location |
29 | | -from idom.core.hooks import Context, create_context, use_context |
| 28 | +from idom.backend.hooks import ConnectionContext |
| 29 | +from idom.backend.hooks import use_connection as _use_connection |
| 30 | +from idom.backend.types import Connection, Location |
30 | 31 | from idom.core.layout import LayoutEvent, LayoutUpdate |
31 | 32 | from idom.core.serve import serve_json_patch |
32 | 33 | from idom.core.types import ComponentType, RootComponentConstructor |
|
37 | 38 |
|
38 | 39 | logger = logging.getLogger(__name__) |
39 | 40 |
|
40 | | -ConnectionContext: Context[Connection | None] = create_context(None) |
41 | | - |
42 | 41 |
|
43 | 42 | def configure( |
44 | 43 | app: Flask, component: RootComponentConstructor, options: Options | None = None |
@@ -107,45 +106,25 @@ def run_server() -> None: |
107 | 106 | raise RuntimeError("Failed to shutdown server.") |
108 | 107 |
|
109 | 108 |
|
110 | | -def use_location() -> Location: |
111 | | - """Get the current route as a string""" |
112 | | - conn = use_connection() |
113 | | - search = conn.request.query_string.decode() |
114 | | - return Location(pathname="/" + conn.path, search="?" + search if search else "") |
115 | | - |
116 | | - |
117 | | -def use_scope() -> dict[str, Any]: |
118 | | - """Get the current WSGI environment""" |
119 | | - return use_request().environ |
| 109 | +def use_websocket() -> WebSocket: |
| 110 | + """A handle to the current websocket""" |
| 111 | + return use_connection().carrier.websocket |
120 | 112 |
|
121 | 113 |
|
122 | 114 | def use_request() -> Request: |
123 | 115 | """Get the current ``Request``""" |
124 | | - return use_connection().request |
| 116 | + return use_connection().carrier.request |
125 | 117 |
|
126 | 118 |
|
127 | | -def use_connection() -> Connection: |
| 119 | +def use_connection() -> Connection[_FlaskCarrier]: |
128 | 120 | """Get the current :class:`Connection`""" |
129 | | - connection = use_context(ConnectionContext) |
130 | | - if connection is None: |
131 | | - raise RuntimeError( # pragma: no cover |
132 | | - "No connection. Are you running with a Flask server?" |
| 121 | + conn = _use_connection() |
| 122 | + if not isinstance(conn.carrier, _FlaskCarrier): |
| 123 | + raise TypeError( # pragma: no cover |
| 124 | + f"Connection has unexpected carrier {conn.carrier}. " |
| 125 | + "Are you running with a Flask server?" |
133 | 126 | ) |
134 | | - return connection |
135 | | - |
136 | | - |
137 | | -@dataclass |
138 | | -class Connection: |
139 | | - """A simple wrapper for holding connection information""" |
140 | | - |
141 | | - request: Request |
142 | | - """The current request object""" |
143 | | - |
144 | | - websocket: WebSocket |
145 | | - """A handle to the current websocket""" |
146 | | - |
147 | | - path: str |
148 | | - """The current path being served""" |
| 127 | + return conn |
149 | 128 |
|
150 | 129 |
|
151 | 130 | @dataclass |
@@ -230,11 +209,20 @@ async def recv_coro() -> Any: |
230 | 209 | return await async_recv_queue.get() |
231 | 210 |
|
232 | 211 | async def main() -> None: |
| 212 | + search = request.query_string.decode() |
233 | 213 | await serve_json_patch( |
234 | 214 | idom.Layout( |
235 | 215 | ConnectionContext( |
236 | | - component, value=Connection(request, websocket, path) |
237 | | - ) |
| 216 | + component, |
| 217 | + value=Connection( |
| 218 | + scope=request.environ, |
| 219 | + location=Location( |
| 220 | + pathname=f"/{path}", |
| 221 | + search=f"?{search}" if search else "", |
| 222 | + ), |
| 223 | + carrier=_FlaskCarrier(request, websocket), |
| 224 | + ), |
| 225 | + ), |
238 | 226 | ), |
239 | 227 | send_coro, |
240 | 228 | recv_coro, |
@@ -283,3 +271,14 @@ class _DispatcherThreadInfo(NamedTuple): |
283 | 271 | dispatch_future: "asyncio.Future[Any]" |
284 | 272 | thread_send_queue: "ThreadQueue[LayoutUpdate]" |
285 | 273 | async_recv_queue: "AsyncQueue[LayoutEvent]" |
| 274 | + |
| 275 | + |
| 276 | +@dataclass |
| 277 | +class _FlaskCarrier: |
| 278 | + """A simple wrapper for holding a Flask request and WebSocket""" |
| 279 | + |
| 280 | + request: Request |
| 281 | + """The current request object""" |
| 282 | + |
| 283 | + websocket: WebSocket |
| 284 | + """A handle to the current websocket""" |
0 commit comments