Skip to content

Fix idom.run uvicorn self.servers exception #943

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Apr 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
83557a4
Fix `idom.run` uvicorn self.servers exception
Archmonger Feb 27, 2023
284bece
Merge branch 'main' into fix-idom-run-uvicorn
Archmonger Mar 1, 2023
ba0c95b
`started` compatibility
Archmonger Mar 1, 2023
e4b0b72
Merge branch 'main' into fix-idom-run-uvicorn
Archmonger Mar 1, 2023
635cd55
Merge branch 'main' into fix-idom-run-uvicorn
rmorshea Mar 2, 2023
c636223
Merge branch 'main' into fix-idom-run-uvicorn
Archmonger Mar 3, 2023
0b47b0f
try fixing tests
Archmonger Mar 3, 2023
4ae0932
Merge branch 'fix-idom-run-uvicorn' of https://github.com/Archmonger/…
Archmonger Mar 3, 2023
0c3a91a
use exception suppression
Archmonger Mar 3, 2023
8f4ac8c
try again
Archmonger Mar 3, 2023
1657b89
try again
Archmonger Mar 3, 2023
74f5298
try alternative shutdown
Archmonger Mar 3, 2023
15a0eae
Revert "try alternative shutdown"
Archmonger Mar 3, 2023
55ecd27
use hasattr
Archmonger Mar 4, 2023
8ffcf8b
remove victorybar tests
Archmonger Mar 4, 2023
f70d99d
add no cov
Archmonger Mar 4, 2023
47913b3
Merge branch 'main' into fix-idom-run-uvicorn
rmorshea Mar 28, 2023
4ed3cae
change pragmas
Archmonger Mar 29, 2023
bb2732c
remove module_from_template
Archmonger Mar 29, 2023
96d28c1
try to fix tests
Archmonger Mar 29, 2023
22126df
remove dead file
Archmonger Mar 29, 2023
2175254
add changelog entry
Archmonger Mar 29, 2023
bdf96f6
add no covers
Archmonger Mar 31, 2023
b18ccaa
move pragmas around
Archmonger Mar 31, 2023
0939200
fix mypy warning
Archmonger Apr 1, 2023
daa90c7
more mypy fixes
Archmonger Apr 1, 2023
89f434f
undo `module_from_template` removal
Archmonger Apr 4, 2023
e4d213a
Merge remote-tracking branch 'upstream/main' into fix-idom-run-uvicorn
Archmonger Apr 4, 2023
14c4da5
fix style
Archmonger Apr 4, 2023
f1b9e37
try to remove some pragmas
Archmonger Apr 4, 2023
ea33932
more logical if statement
Archmonger Apr 4, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions docs/source/about/contributor-guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -140,23 +140,17 @@ followed the `earlier instructions <Development Environment>`_. The suite covers

3. Client-side Javascript code with UVU_

Before running the test suite you'll need to install the required browsers by running:

.. code-block:: bash

playwright install

Once you've installed them you'll be able to run:

.. code-block:: bash

nox -s test
nox -s check-python-tests

You can observe the browser as the tests are running by passing an extra flag:

.. code-block:: bash

nox -s test -- --headed
nox -s check-python-tests -- --headed

To see a full list of available commands (e.g. ``nox -s <your-command>``) run:

Expand Down
19 changes: 12 additions & 7 deletions src/reactpy/backend/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
from pathlib import Path, PurePosixPath
from typing import Any, Awaitable, Sequence, cast

import uvicorn
from asgiref.typing import ASGIApplication
from uvicorn.config import Config as UvicornConfig
from uvicorn.server import Server as UvicornServer

from reactpy import __file__ as _reactpy_file_path
from reactpy import html
Expand All @@ -31,29 +30,35 @@ async def serve_development_asgi(
port: int,
started: asyncio.Event | None,
) -> None:
"""Run a development server for starlette"""
server = UvicornServer(
UvicornConfig(
"""Run a development server for an ASGI application"""
server = uvicorn.Server(
uvicorn.Config(
app,
host=host,
port=port,
loop="asyncio",
reload=True,
)
)

server.config.setup_event_loop()
coros: list[Awaitable[Any]] = [server.serve()]

# If a started event is provided, then use it signal based on `server.started`
if started:
coros.append(_check_if_started(server, started))

try:
await asyncio.gather(*coros)
finally:
# Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
# order of operations. So we need to make sure `shutdown()` always has an initialized
# list of `self.servers` to use.
if not hasattr(server, "servers"): # pragma: no cover
server.servers = []
await asyncio.wait_for(server.shutdown(), timeout=3)


async def _check_if_started(server: UvicornServer, started: asyncio.Event) -> None:
async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> None:
while not server.started:
await asyncio.sleep(0.2)
started.set()
Expand Down
4 changes: 2 additions & 2 deletions src/reactpy/backend/flask.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,8 +129,8 @@ def use_request() -> Request:
def use_connection() -> Connection[_FlaskCarrier]:
"""Get the current :class:`Connection`"""
conn = _use_connection()
if not isinstance(conn.carrier, _FlaskCarrier):
raise TypeError( # pragma: no cover
if not isinstance(conn.carrier, _FlaskCarrier): # pragma: no cover
raise TypeError(
f"Connection has unexpected carrier {conn.carrier}. "
"Are you running with a Flask server?"
)
Expand Down
12 changes: 5 additions & 7 deletions src/reactpy/backend/sanic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import json
import logging
from dataclasses import dataclass
from typing import Any, MutableMapping, Tuple
from typing import Any, Tuple
from urllib import parse as urllib_parse
from uuid import uuid4

Expand Down Expand Up @@ -82,8 +82,8 @@ def use_websocket() -> WebSocketConnection:
def use_connection() -> Connection[_SanicCarrier]:
"""Get the current :class:`Connection`"""
conn = _use_connection()
if not isinstance(conn.carrier, _SanicCarrier):
raise TypeError( # pragma: no cover
if not isinstance(conn.carrier, _SanicCarrier): # pragma: no cover
raise TypeError(
f"Connection has unexpected carrier {conn.carrier}. "
"Are you running with a Sanic server?"
)
Expand Down Expand Up @@ -162,11 +162,9 @@ async def model_stream(
request: request.Request, socket: WebSocketConnection, path: str = ""
) -> None:
asgi_app = getattr(request.app, "_asgi_app", None)
if asgi_app is None: # pragma: no cover
scope = asgi_app.transport.scope if asgi_app else {}
if not scope: # pragma: no cover
logger.warning("No scope. Sanic may not be running with an ASGI server")
scope: MutableMapping[str, Any] = {}
else:
scope = asgi_app.transport.scope

send, recv = _make_send_recv_callbacks(socket)
await serve_layout(
Expand Down
4 changes: 2 additions & 2 deletions src/reactpy/backend/starlette.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ def use_websocket() -> WebSocket:

def use_connection() -> Connection[WebSocket]:
conn = _use_connection()
if not isinstance(conn.carrier, WebSocket):
raise TypeError( # pragma: no cover
if not isinstance(conn.carrier, WebSocket): # pragma: no cover
raise TypeError(
f"Connection has unexpected carrier {conn.carrier}. "
"Are you running with a Flask server?"
)
Expand Down
4 changes: 2 additions & 2 deletions src/reactpy/backend/tornado.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ def use_request() -> HTTPServerRequest:

def use_connection() -> Connection[HTTPServerRequest]:
conn = _use_connection()
if not isinstance(conn.carrier, HTTPServerRequest):
raise TypeError( # pragma: no cover
if not isinstance(conn.carrier, HTTPServerRequest): # pragma: no cover
raise TypeError(
f"Connection has unexpected carrier {conn.carrier}. "
"Are you running with a Flask server?"
)
Expand Down
6 changes: 2 additions & 4 deletions src/reactpy/backend/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,8 @@ def all_implementations() -> Iterator[BackendImplementation[Any]]:
logger.debug(f"Failed to import {name!r}", exc_info=True)
continue

if not isinstance(module, BackendImplementation):
raise TypeError( # pragma: no cover
f"{module.__name__!r} is an invalid implementation"
)
if not isinstance(module, BackendImplementation): # pragma: no cover
raise TypeError(f"{module.__name__!r} is an invalid implementation")

yield module

Expand Down