Skip to content

Commit 4cac83b

Browse files
committed
strip down test tooling
only provide the bare minimum
1 parent 9aa5183 commit 4cac83b

File tree

10 files changed

+228
-313
lines changed

10 files changed

+228
-313
lines changed

idom/server/base.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import abc
22
from asyncio import AbstractEventLoop, new_event_loop, set_event_loop, get_event_loop
33
from typing import TypeVar, Dict, Any, Tuple, Type, Optional, Generic, TypeVar
4-
from threading import Thread
4+
from threading import Thread, Event
55

66
from idom.core.element import ElementConstructor
77
from idom.core.layout import Layout, Layout
@@ -33,6 +33,7 @@ class AbstractRenderServer(Generic[_App, _Config]):
3333
_loop: AbstractEventLoop
3434
_dispatcher_type: Type[AbstractDispatcher]
3535
_layout_type: Type[Layout] = Layout
36+
_daemon_server_did_start: Event
3637

3738
def __init__(
3839
self,
@@ -76,6 +77,9 @@ def run_in_thread() -> None:
7677

7778
thread = Thread(target=run_in_thread, daemon=True)
7879
thread.start()
80+
81+
self._wait_until_daemon_server_start()
82+
7983
return thread
8084

8185
def register(self: _Self, app: Optional[_App]) -> _Self:
@@ -141,3 +145,11 @@ def _make_layout(
141145
params: Dict[str, Any],
142146
) -> Layout:
143147
return self._layout_type(self._make_root_element(**params))
148+
149+
def _wait_until_daemon_server_start(self):
150+
try:
151+
self._daemon_server_did_start.wait(timeout=5)
152+
except AttributeError: # pragma: no cover
153+
raise NotImplementedError(
154+
f"Server implementation {self} did not define a server started thread event"
155+
)

idom/server/prefab.py

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,31 @@ def run(
2929
server_type: Optional[Type[_S]] = _find_default_server_type(),
3030
host: str = "127.0.0.1",
3131
port: Optional[int] = None,
32-
server_options: Optional[Any] = None,
33-
run_options: Optional[Dict[str, Any]] = None,
34-
daemon: bool = False,
32+
server_config: Optional[Any] = None,
33+
run_kwargs: Optional[Dict[str, Any]] = None,
3534
app: Optional[Any] = None,
35+
daemon: bool = False,
3636
) -> _S:
3737
"""A utility for quickly running a render server with minimal boilerplate
3838
3939
Parameters:
40-
element: The root of the view.
41-
server_type: What server to run. Defaults to a builtin implementation if available.
42-
host: The host string.
43-
port: The port number. Defaults to a dynamically discovered available port.
44-
server_options: Options passed to configure the server.
45-
run_options: Options passed to the server to run it.
46-
daemon: Whether the server should be run in a daemon thread.
47-
app: Register the server to an existing application and run that.
40+
element:
41+
The root of the view.
42+
server_type:
43+
What server to run. Defaults to a builtin implementation if available.
44+
host:
45+
The host string.
46+
port:
47+
The port number. Defaults to a dynamically discovered available port.
48+
server_config:
49+
Options passed to configure the server.
50+
run_kwargs:
51+
Keyword arguments passed to the :meth:`~AbstractRenderServer.daemon`
52+
or :meth:`~AbstractRenderServer.run` method of the server
53+
app:
54+
Register the server to an existing application and run that.
55+
daemon:
56+
Whether the server should be run in a daemon thread.
4857
4958
Returns:
5059
The server instance. This isn't really useful unless the server is spawned
@@ -55,13 +64,13 @@ def run(
5564
if port is None: # pragma: no cover
5665
port = find_available_port(host)
5766

58-
server = server_type(element, server_options)
67+
server = server_type(element, server_config)
5968

6069
if app is not None:
6170
server.register(app)
6271

6372
run_server = server.run if not daemon else server.daemon
64-
run_server(host, port, **(run_options or {}))
73+
run_server(host, port, **(run_kwargs or {}))
6574

6675
return server
6776

@@ -70,8 +79,8 @@ def multiview_server(
7079
server_type: Type[_S],
7180
host: str = "127.0.0.1",
7281
port: Optional[int] = None,
73-
server_options: Optional[Any] = None,
74-
run_options: Optional[Dict[str, Any]] = None,
82+
server_config: Optional[Any] = None,
83+
run_kwargs: Optional[Dict[str, Any]] = None,
7584
app: Optional[Any] = None,
7685
) -> Tuple[MultiViewMount, _S]:
7786
"""Set up a server where views can be dynamically added.
@@ -84,8 +93,8 @@ def multiview_server(
8493
server: The server type to start up as a daemon
8594
host: The server hostname
8695
port: The server port number
87-
server_options: Value passed to :meth:`AbstractRenderServer.configure`
88-
run_options: Keyword args passed to :meth:`AbstractRenderServer.daemon`
96+
server_config: Value passed to :meth:`AbstractRenderServer.configure`
97+
run_kwargs: Keyword args passed to :meth:`AbstractRenderServer.daemon`
8998
app: Optionally provide a prexisting application to register to
9099
91100
Returns:
@@ -99,8 +108,8 @@ def multiview_server(
99108
server_type,
100109
host,
101110
port,
102-
server_options=server_options,
103-
run_options=run_options,
111+
server_config=server_config,
112+
run_kwargs=run_kwargs,
104113
daemon=True,
105114
app=app,
106115
)
@@ -112,10 +121,10 @@ def hotswap_server(
112121
server_type: Type[_S],
113122
host: str = "127.0.0.1",
114123
port: Optional[int] = None,
115-
server_options: Optional[Any] = None,
116-
run_options: Optional[Dict[str, Any]] = None,
117-
sync_views: bool = True,
124+
server_config: Optional[Any] = None,
125+
run_kwargs: Optional[Dict[str, Any]] = None,
118126
app: Optional[Any] = None,
127+
sync_views: bool = False,
119128
) -> Tuple[MountFunc, _S]:
120129
"""Set up a server where views can be dynamically swapped out.
121130
@@ -127,10 +136,10 @@ def hotswap_server(
127136
server: The server type to start up as a daemon
128137
host: The server hostname
129138
port: The server port number
130-
server_options: Value passed to :meth:`AbstractRenderServer.configure`
131-
run_options: Keyword args passed to :meth:`AbstractRenderServer.daemon`
132-
sync_views: Whether to update all displays with newly mounted elements
139+
server_config: Value passed to :meth:`AbstractRenderServer.configure`
140+
run_kwargs: Keyword args passed to :meth:`AbstractRenderServer.daemon`
133141
app: Optionally provide a prexisting application to register to
142+
sync_views: Whether to update all displays with newly mounted elements
134143
135144
Returns:
136145
The server instance and a function for swapping views.
@@ -143,8 +152,8 @@ def hotswap_server(
143152
server_type,
144153
host,
145154
port,
146-
server_options=server_options,
147-
run_options=run_options,
155+
server_config=server_config,
156+
run_kwargs=run_kwargs,
148157
daemon=True,
149158
app=app,
150159
)

idom/server/sanic.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import asyncio
22
import json
33
import uuid
4+
from threading import Event, Thread
45

56
from typing import Tuple, Any, Dict, Union, cast
67

@@ -31,6 +32,10 @@ class Config(TypedDict, total=False):
3132
class SanicRenderServer(AbstractRenderServer[Sanic, Config]):
3233
"""Base ``sanic`` extension."""
3334

35+
def daemon(self, *args: Any, **kwargs: Any) -> Thread:
36+
self._daemon_server_did_start = Event()
37+
return super().daemon(*args, **kwargs)
38+
3439
def _stop(self) -> None:
3540
self.application.stop()
3641

@@ -59,6 +64,11 @@ def _setup_application(self, app: Sanic, config: Config) -> None:
5964
self._setup_blueprint_routes(bp, config)
6065
app.blueprint(bp)
6166

67+
async def server_did_start(app: Sanic, loop: asyncio.AbstractEventLoop) -> None:
68+
self._daemon_server_did_start.set()
69+
70+
app.register_listener(server_did_start, "after_server_start")
71+
6272
def _setup_blueprint_routes(self, blueprint: Blueprint, config: Config) -> None:
6373
"""Add routes to the application blueprint"""
6474

@@ -84,7 +94,9 @@ async def sock_recv() -> LayoutEvent:
8494

8595
@blueprint.route("/") # type: ignore
8696
def redirect_to_index(request: request.Request) -> response.HTTPResponse:
87-
return response.redirect(f"{blueprint.url_prefix}/client/index.html")
97+
return response.redirect(
98+
f"{blueprint.url_prefix}/client/index.html?{request.query_string}"
99+
)
88100

89101
def _run_application(
90102
self, app: Sanic, config: Config, args: Tuple[Any, ...], kwargs: Dict[str, Any]
@@ -129,8 +141,8 @@ class SharedClientStateServer(SanicRenderServer):
129141
_dispatcher: SharedViewDispatcher
130142

131143
def _setup_application(self, app: Sanic, config: Config) -> None:
132-
app.listener("before_server_start")(self._activate_dispatcher)
133-
app.listener("before_server_stop")(self._deactivate_dispatcher)
144+
app.register_listener(self._activate_dispatcher, "before_server_start")
145+
app.register_listener(self._deactivate_dispatcher, "before_server_stop")
134146
super()._setup_application(app, config)
135147

136148
async def _activate_dispatcher(

0 commit comments

Comments
 (0)