Skip to content

Commit

Permalink
avoid sanic import
Browse files Browse the repository at this point in the history
Sanic was accidentally imported when not explicitely requested.
This means `pip install idom[sanic]` is currently required.
To avoid this we add a find_builtin_server_type() function to
help in testing and internal utilities.
  • Loading branch information
rmorshea committed Jan 19, 2021
1 parent f6196f1 commit 6fd73fd
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 29 deletions.
2 changes: 1 addition & 1 deletion idom/server/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from .base import AbstractRenderServer
from .prefab import run, multiview_server, hotswap_server
from . import default


__all__ = [
"default",
Expand Down
4 changes: 0 additions & 4 deletions idom/server/default.py

This file was deleted.

20 changes: 3 additions & 17 deletions idom/server/prefab.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
from importlib import import_module
from typing import Any, Dict, Optional, Tuple, Type, TypeVar, cast
from typing import Any, Dict, Optional, Tuple, Type, TypeVar

from idom.core.element import ElementConstructor
from idom.widgets.utils import multiview, hotswap, MultiViewMount, MountFunc

from .base import AbstractRenderServer
from .utils import find_available_port
from .utils import find_available_port, find_builtin_server_type


_S = TypeVar("_S", bound=AbstractRenderServer[Any, Any])


def _find_default_server_type() -> Optional[Type[_S]]:
for name in ["sanic.PerClientStateServer"]:
module_name, server_name = name.split(".")
try:
module = import_module(f"idom.server.{module_name}")
except ImportError: # pragma: no cover
pass
else:
return cast(Type[_S], getattr(module, server_name))
else: # pragma: no cover
return None


def run(
element: ElementConstructor,
server_type: Optional[Type[_S]] = _find_default_server_type(),
server_type: Optional[Type[_S]] = find_builtin_server_type("PerClientStateServer"),
host: str = "127.0.0.1",
port: Optional[int] = None,
server_config: Optional[Any] = None,
Expand Down
34 changes: 33 additions & 1 deletion idom/server/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,37 @@
from socket import socket
from typing import cast
from types import ModuleType
from typing import Type, Any, List, cast
from importlib import import_module


def find_builtin_server_type(type_name: str) -> Type[Any]:
"""Find first installed server implementation"""
builtin_module_names = ["sanic", "flask", "tornado"]

installed_builtin_modules: List[ModuleType] = []
for module_name in builtin_module_names:
try:
installed_builtin_modules.append(
import_module(f"idom.server.{module_name}")
)
except ImportError: # pragma: no cover
pass

if not installed_builtin_modules: # pragma: no cover
raise RuntimeError(
f"Found none of the following builtin server implementations {builtin_module_names}"
)

for builtin_module in installed_builtin_modules:
try:
return getattr(builtin_module, type_name)
except AttributeError: # pragma: no cover
pass
else: # pragma: no cover
installed_names = [m.__name__ for m in installed_builtin_modules]
raise ImportError(
f"No server type {type_name!r} found in installed implementations {installed_names}"
)


def find_available_port(host: str) -> int:
Expand Down
4 changes: 2 additions & 2 deletions idom/testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from selenium.webdriver.remote.webdriver import WebDriver
from selenium.webdriver import Chrome

from idom import server
from idom.server.utils import find_builtin_server_type
from idom.server.base import AbstractRenderServer
from idom.server.prefab import hotswap_server
from idom.server.utils import find_available_port
Expand Down Expand Up @@ -59,7 +59,7 @@ class ServerMountPoint(Generic[_Mount, _Server]):

def __init__(
self,
server_type: Type[_Server] = server.default.PerClientStateServer,
server_type: Type[_Server] = find_builtin_server_type("PerClientStateServer"),
host: str = "127.0.0.1",
port: Optional[int] = None,
server_config: Optional[Any] = None,
Expand Down
4 changes: 2 additions & 2 deletions tests/test_server/test_base.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import pytest

import idom
from idom.server.default import PerClientStateServer
from idom.server.utils import find_builtin_server_type


def test_no_application_until_running():
@idom.element
def AnyElement():
pass

server = PerClientStateServer(AnyElement)
server = find_builtin_server_type("PerClientStateServer")(AnyElement)

with pytest.raises(RuntimeError, match="No application"):
server.application
5 changes: 3 additions & 2 deletions tests/test_server/test_prefab.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import pytest

import idom
from idom.server.default import PerClientStateServer
from idom.server.utils import find_builtin_server_type
from idom.server.prefab import multiview_server
from idom.testing import ServerMountPoint

Expand All @@ -11,7 +11,8 @@
@pytest.fixture
def server_mount_point():
return ServerMountPoint(
PerClientStateServer, mount_and_server_constructor=multiview_server
find_builtin_server_type("PerClientStateServer"),
mount_and_server_constructor=multiview_server,
)


Expand Down

0 comments on commit 6fd73fd

Please sign in to comment.