Skip to content

Commit 425c531

Browse files
committed
expose use_scope instead of use_connection
1 parent 1482de1 commit 425c531

File tree

8 files changed

+82
-53
lines changed

8 files changed

+82
-53
lines changed

src/idom/server/_conn.py

-9
This file was deleted.

src/idom/server/default.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ async def serve_development_app(
2828
)
2929

3030

31-
def use_connection() -> Any:
32-
return _default_implementation().use_connection()
31+
def use_scope() -> Any:
32+
return _default_implementation().use_scope()
3333

3434

3535
def _default_implementation() -> ServerImplementation[Any]:

src/idom/server/fastapi.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@
1111
_setup_options,
1212
_setup_single_view_dispatcher_route,
1313
serve_development_app,
14-
use_connection,
14+
use_scope,
1515
)
1616

1717

1818
__all__ = (
1919
"configure",
2020
"serve_development_app",
2121
"create_development_app",
22-
"use_connection",
22+
"use_scope",
2323
)
2424

2525

src/idom/server/flask.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from threading import Thread
1010
from typing import Any, Callable, Dict, NamedTuple, Optional, Union, cast
1111
from urllib.parse import parse_qs as parse_query_string
12+
from wsgiref.types import WSGIEnvironment
1213

1314
from flask import (
1415
Blueprint,
@@ -29,17 +30,18 @@
2930

3031
import idom
3132
from idom.config import IDOM_WEB_MODULES_DIR
32-
from idom.core.hooks import use_context
33+
from idom.core.hooks import Context, create_context, use_context
3334
from idom.core.layout import LayoutEvent, LayoutUpdate
3435
from idom.core.serve import serve_json_patch
3536
from idom.core.types import ComponentType, RootComponentConstructor
3637

37-
from ._conn import Connection
3838
from .utils import CLIENT_BUILD_DIR
3939

4040

4141
logger = logging.getLogger(__name__)
4242

43+
RequestContext: type[Context[Request | None]] = create_context(None, "RequestContext")
44+
4345

4446
def configure(
4547
app: Flask, component: RootComponentConstructor, options: Options | None = None
@@ -105,12 +107,17 @@ def run_server():
105107
raise RuntimeError("Failed to shutdown server.")
106108

107109

108-
def use_connection() -> Request:
110+
def use_request() -> Request:
109111
"""Get the current ``Request``"""
110-
value = use_context(Connection)
111-
if value is None:
112-
raise RuntimeError("No established connection.")
113-
return value
112+
request = use_context(RequestContext)
113+
if request is None:
114+
raise RuntimeError("No request. Are you running with a Flask server?")
115+
return request
116+
117+
118+
def use_scope() -> WSGIEnvironment:
119+
"""Get the current WSGI environment"""
120+
return use_request().environ
114121

115122

116123
class Options(TypedDict, total=False):
@@ -221,7 +228,9 @@ async def recv_coro() -> Any:
221228

222229
async def main() -> None:
223230
await serve_json_patch(
224-
idom.Layout(Connection(component, value=request)), send_coro, recv_coro
231+
idom.Layout(RequestContext(component, value=request)),
232+
send_coro,
233+
recv_coro,
225234
)
226235

227236
main_future = asyncio.ensure_future(main())

src/idom/server/sanic.py

+17-7
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99

1010
from mypy_extensions import TypedDict
1111
from sanic import Blueprint, Sanic, request, response
12+
from sanic.models.asgi import ASGIScope
1213
from sanic_cors import CORS
1314
from websockets.legacy.protocol import WebSocketCommonProtocol
1415

1516
from idom.config import IDOM_WEB_MODULES_DIR
17+
from idom.core.hooks import Context, create_context, use_context
1618
from idom.core.layout import Layout, LayoutEvent
1719
from idom.core.serve import (
1820
RecvCoroutine,
@@ -22,12 +24,15 @@
2224
)
2325
from idom.core.types import RootComponentConstructor
2426

25-
from ._conn import Connection
2627
from .utils import CLIENT_BUILD_DIR
2728

2829

2930
logger = logging.getLogger(__name__)
3031

32+
RequestContext: type[Context[request.Request | None]] = create_context(
33+
None, "RequestContext"
34+
)
35+
3136

3237
def configure(
3338
app: Sanic, component: RootComponentConstructor, options: Options | None = None
@@ -64,12 +69,17 @@ async def serve_development_app(
6469
app.stop()
6570

6671

67-
def use_connection() -> request.Request:
72+
def use_request() -> request.Request:
6873
"""Get the current ``Request``"""
69-
value = use_connection(Connection)
70-
if value is None:
71-
raise RuntimeError("No established connection.")
72-
return value
74+
request = use_context(RequestContext)
75+
if request is None:
76+
raise RuntimeError("No request. Are you running with a Sanic server?")
77+
return request
78+
79+
80+
def use_scope() -> ASGIScope:
81+
"""Get the current ASGI scope"""
82+
return use_request().app._asgi_app.transport.scope
7383

7484

7585
class Options(TypedDict, total=False):
@@ -132,7 +142,7 @@ async def model_stream(
132142
send, recv = _make_send_recv_callbacks(socket)
133143
component_params = {k: request.args.get(k) for k in request.args}
134144
await serve_json_patch(
135-
Layout(Connection(constructor(**component_params), value=request)),
145+
Layout(RequestContext(constructor(**component_params), value=request)),
136146
send,
137147
recv,
138148
)

src/idom/server/starlette.py

+18-12
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import asyncio
44
import json
55
import logging
6-
from asyncio import FIRST_EXCEPTION, CancelledError
76
from typing import Any, Dict, Tuple, Union
87

98
from mypy_extensions import TypedDict
@@ -12,12 +11,11 @@
1211
from starlette.requests import Request
1312
from starlette.responses import RedirectResponse
1413
from starlette.staticfiles import StaticFiles
14+
from starlette.types import Scope
1515
from starlette.websockets import WebSocket, WebSocketDisconnect
16-
from uvicorn.config import Config as UvicornConfig
17-
from uvicorn.server import Server as UvicornServer
1816

1917
from idom.config import IDOM_WEB_MODULES_DIR
20-
from idom.core.hooks import use_context
18+
from idom.core.hooks import Context, create_context, use_context
2119
from idom.core.layout import Layout, LayoutEvent
2220
from idom.core.serve import (
2321
RecvCoroutine,
@@ -28,12 +26,15 @@
2826
from idom.core.types import RootComponentConstructor
2927

3028
from ._asgi import serve_development_asgi
31-
from ._conn import Connection
3229
from .utils import CLIENT_BUILD_DIR
3330

3431

3532
logger = logging.getLogger(__name__)
3633

34+
WebSocketContext: type[Context[WebSocket | None]] = create_context(
35+
None, "WebSocketContext"
36+
)
37+
3738

3839
def configure(
3940
app: Starlette,
@@ -69,12 +70,17 @@ async def serve_development_app(
6970
await serve_development_asgi(app, host, port, started)
7071

7172

72-
def use_connection() -> WebSocket:
73-
"""Get the current ``WebSocket`` connection"""
74-
value = use_context(Connection)
75-
if value is None:
76-
raise RuntimeError("No established connection.")
77-
return value
73+
def use_websocket() -> WebSocket:
74+
"""Get the current WebSocket object"""
75+
websocket = use_context(WebSocketContext)
76+
if websocket is None:
77+
raise RuntimeError("No websocket. Are you running with a Starllette server?")
78+
return websocket
79+
80+
81+
def use_scope() -> Scope:
82+
"""Get the current ASGI scope dictionary"""
83+
return use_websocket().scope
7884

7985

8086
class Options(TypedDict, total=False):
@@ -155,7 +161,7 @@ async def model_stream(socket: WebSocket) -> None:
155161
send, recv = _make_send_recv_callbacks(socket)
156162
try:
157163
await serve_json_patch(
158-
Layout(Connection(constructor(), value=socket)),
164+
Layout(WebSocketContext(constructor(), value=socket)),
159165
send,
160166
recv,
161167
)

src/idom/server/tornado.py

+20-9
Original file line numberDiff line numberDiff line change
@@ -12,18 +12,23 @@
1212
from tornado.platform.asyncio import AsyncIOMainLoop
1313
from tornado.web import Application, RedirectHandler, RequestHandler, StaticFileHandler
1414
from tornado.websocket import WebSocketHandler
15+
from tornado.wsgi import WSGIContainer
1516
from typing_extensions import TypedDict
1617

1718
from idom.config import IDOM_WEB_MODULES_DIR
18-
from idom.core.hooks import use_context
19+
from idom.core.hooks import Context, create_context, use_context
1920
from idom.core.layout import Layout, LayoutEvent
2021
from idom.core.serve import VdomJsonPatch, serve_json_patch
2122
from idom.core.types import ComponentConstructor
2223

23-
from ._conn import Connection
2424
from .utils import CLIENT_BUILD_DIR
2525

2626

27+
RequestContext: type[Context[HTTPServerRequest | None]] = create_context(
28+
None, "RequestContext"
29+
)
30+
31+
2732
def configure(
2833
app: Application,
2934
component: ComponentConstructor,
@@ -72,12 +77,17 @@ async def serve_development_app(
7277
await server.close_all_connections()
7378

7479

75-
def use_connection() -> HTTPServerRequest:
80+
def use_request() -> HTTPServerRequest:
7681
"""Get the current ``HTTPServerRequest``"""
77-
value = use_context(Connection)
78-
if value is None:
79-
raise RuntimeError("No established connection.")
80-
return value
82+
request = use_context(RequestContext)
83+
if request is None:
84+
raise RuntimeError("No request. Are you running with a Tornado server?")
85+
return request
86+
87+
88+
def use_scope() -> dict[str, Any]:
89+
"""Get the current WSGI environment dictionary"""
90+
return WSGIContainer.environ(use_request())
8191

8292

8393
class Options(TypedDict, total=False):
@@ -160,7 +170,6 @@ def initialize(self, component_constructor: ComponentConstructor) -> None:
160170

161171
async def open(self, *args: str, **kwargs: str) -> None:
162172
message_queue: "AsyncQueue[str]" = AsyncQueue()
163-
query_params = {k: v[0].decode() for k, v in self.request.arguments.items()}
164173

165174
async def send(value: VdomJsonPatch) -> None:
166175
await self.write_message(json.dumps(value))
@@ -171,7 +180,9 @@ async def recv() -> LayoutEvent:
171180
self._message_queue = message_queue
172181
self._dispatch_future = asyncio.ensure_future(
173182
serve_json_patch(
174-
Layout(Connection(self._component_constructor(), value=self.request)),
183+
Layout(
184+
RequestContext(self._component_constructor(), value=self.request)
185+
),
175186
send,
176187
recv,
177188
)

src/idom/server/types.py

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
from __future__ import annotations
2+
13
import asyncio
2-
from typing import Any, TypeVar
4+
from typing import Any, MutableMapping, TypeVar
35

46
from typing_extensions import Protocol, runtime_checkable
57

6-
from idom.core.types import RootComponentConstructor
8+
from idom.types import RootComponentConstructor
79

810

911
_App = TypeVar("_App")
@@ -24,5 +26,5 @@ async def serve_development_app(
2426
) -> None:
2527
"""Run an application using a development server"""
2628

27-
def use_connection() -> Any:
28-
"""Get information about a currently active request to the server"""
29+
def use_scope() -> MutableMapping[str, Any]:
30+
"""Get an ASGI scope or WSGI environment dictionary"""

0 commit comments

Comments
 (0)