Skip to content

Commit a4ad823

Browse files
committed
avoid importing backend-specific dependencies
1 parent a6eb1dc commit a4ad823

File tree

2 files changed

+42
-36
lines changed

2 files changed

+42
-36
lines changed

Diff for: pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ dependencies = [
2626
[tool.hatch.envs.default.scripts]
2727
publish = "invoke publish {args}"
2828
docs = "invoke docs {args}"
29+
check = ["lint-py", "lint-js", "test-py", "test-js", "test-docs"]
2930

3031
lint-py = "invoke lint-py {args}"
3132
lint-js = "invoke lint-js {args}"

Diff for: src/py/reactpy/reactpy/backend/_common.py

+41-36
Original file line numberDiff line numberDiff line change
@@ -5,57 +5,62 @@
55
from collections.abc import Awaitable, Sequence
66
from dataclasses import dataclass
77
from pathlib import Path, PurePosixPath
8-
from typing import Any, cast
9-
10-
import uvicorn
11-
from asgiref.typing import ASGIApplication
8+
from typing import TYPE_CHECKING, Any, cast
129

1310
from reactpy import __file__ as _reactpy_file_path
1411
from reactpy import html
1512
from reactpy.config import REACTPY_WEB_MODULES_DIR
1613
from reactpy.core.types import VdomDict
1714
from reactpy.utils import vdom_to_html
1815

16+
if TYPE_CHECKING:
17+
from asgiref.typing import ASGIApplication
18+
1919
PATH_PREFIX = PurePosixPath("/_reactpy")
2020
MODULES_PATH = PATH_PREFIX / "modules"
2121
ASSETS_PATH = PATH_PREFIX / "assets"
2222
STREAM_PATH = PATH_PREFIX / "stream"
2323

2424
CLIENT_BUILD_DIR = Path(_reactpy_file_path).parent / "_static" / "app" / "dist"
2525

26-
27-
async def serve_development_asgi(
28-
app: ASGIApplication | Any,
29-
host: str,
30-
port: int,
31-
started: asyncio.Event | None,
32-
) -> None:
33-
"""Run a development server for an ASGI application"""
34-
server = uvicorn.Server(
35-
uvicorn.Config(
36-
app,
37-
host=host,
38-
port=port,
39-
loop="asyncio",
40-
reload=True,
26+
try:
27+
import uvicorn
28+
except ImportError: # nocov
29+
pass
30+
else:
31+
32+
async def serve_development_asgi(
33+
app: ASGIApplication | Any,
34+
host: str,
35+
port: int,
36+
started: asyncio.Event | None,
37+
) -> None:
38+
"""Run a development server for an ASGI application"""
39+
server = uvicorn.Server(
40+
uvicorn.Config(
41+
app,
42+
host=host,
43+
port=port,
44+
loop="asyncio",
45+
reload=True,
46+
)
4147
)
42-
)
43-
server.config.setup_event_loop()
44-
coros: list[Awaitable[Any]] = [server.serve()]
45-
46-
# If a started event is provided, then use it signal based on `server.started`
47-
if started:
48-
coros.append(_check_if_started(server, started))
49-
50-
try:
51-
await asyncio.gather(*coros)
52-
finally:
53-
# Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
54-
# order of operations. So we need to make sure `shutdown()` always has an initialized
55-
# list of `self.servers` to use.
56-
if not hasattr(server, "servers"): # nocov
57-
server.servers = []
58-
await asyncio.wait_for(server.shutdown(), timeout=3)
48+
server.config.setup_event_loop()
49+
coros: list[Awaitable[Any]] = [server.serve()]
50+
51+
# If a started event is provided, then use it signal based on `server.started`
52+
if started:
53+
coros.append(_check_if_started(server, started))
54+
55+
try:
56+
await asyncio.gather(*coros)
57+
finally:
58+
# Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
59+
# order of operations. So we need to make sure `shutdown()` always has an initialized
60+
# list of `self.servers` to use.
61+
if not hasattr(server, "servers"): # nocov
62+
server.servers = []
63+
await asyncio.wait_for(server.shutdown(), timeout=3)
5964

6065

6166
async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> None:

0 commit comments

Comments
 (0)