Skip to content

Commit 5309ba0

Browse files
committed
add type annotation + update intro notebook
1 parent cbb02b4 commit 5309ba0

File tree

7 files changed

+226
-38
lines changed

7 files changed

+226
-38
lines changed

idom_jupyter/_version.py

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,9 @@
11
# Module version
2-
version_info = (0, 7, 6, "final", 0)
2+
version_info = 0, 7, 6, "final", 0
33

4-
# Module version stage suffix map
5-
_specifier_ = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}
4+
major, minor, patch, stage_name, stage_num = version_info
5+
stage_name = {"alpha": "a", "beta": "b", "candidate": "rc", "final": ""}[stage_name]
6+
stage = f'{stage_name}{stage_num}' if stage_name else ''
67

78
# Module version accessible using idom_jupyter.__version__
8-
__version__ = "%s.%s.%s%s" % (
9-
version_info[0],
10-
version_info[1],
11-
version_info[2],
12-
""
13-
if version_info[3] == "final"
14-
else _specifier_[version_info[3]] + str(version_info[4]),
15-
)
9+
__version__ = f"{major}.{minor}.{patch}{stage}"

idom_jupyter/import_resources.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import logging
24
import socket
35
from uuid import uuid4
@@ -15,7 +17,7 @@
1517
logger = logging.getLogger(__name__)
1618

1719

18-
def setup_import_resources():
20+
def setup_import_resources() -> None:
1921
if _try_to_set_import_source_base_url():
2022
return None
2123

@@ -67,7 +69,7 @@ def _try_to_set_import_source_base_url() -> bool:
6769
return False
6870

6971

70-
def _run_simple_static_file_server(host, port, directory):
72+
def _run_simple_static_file_server(host: str, port: int, directory: str) -> None:
7173
class CORSRequestHandler(SimpleHTTPRequestHandler):
7274
def end_headers(self):
7375
self.send_header("Access-Control-Allow-Origin", "*")

idom_jupyter/ipython_extension.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1+
from __future__ import annotations
2+
13
from functools import partial
24

35
from idom.core.component import ComponentType
46
from IPython import get_ipython
5-
from IPython.core.interactiveshell import InteractiveShell
7+
from IPython.core.interactiveshell import InteractiveShell, ExecutionResult
68
from IPython.display import display
79

810
from .widget import LayoutWidget
@@ -23,14 +25,14 @@ def load_ipython_extension(ipython: InteractiveShell) -> None:
2325
_EXTENSION_LOADED = True
2426

2527

26-
def unload_ipython_extension(ipython):
28+
def unload_ipython_extension(ipython: InteractiveShell) -> None:
2729
global _POST_RUN_CELL_HOOK, _EXTENSION_LOADED
2830
ipython.events.unregister("post_run_cell", _POST_RUN_CELL_HOOK)
2931
_POST_RUN_CELL_HOOK = None
3032
_EXTENSION_LOADED = False
3133

3234

33-
def _post_run_cell(ipython: InteractiveShell, result):
35+
def _post_run_cell(ipython: InteractiveShell, result: ExecutionResult) -> None:
3436
if isinstance(result.result, ComponentType):
3537
display(LayoutWidget(result.result))
3638

idom_jupyter/jupyter_server_extension.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
IDOM_RESOURCE_BASE_PATH = "_idom_web_modules"
2020

2121

22-
def _load_jupyter_server_extension(server_app: ServerApp | NotebookApp):
22+
def _load_jupyter_server_extension(server_app: ServerApp | NotebookApp) -> None:
2323
web_app = server_app.web_app
2424
base_url = web_app.settings["base_url"]
2525
route_pattern = urljoin(base_url, rf"{IDOM_RESOURCE_BASE_PATH}/(.*)")

idom_jupyter/widget.py

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,37 +4,42 @@
44
from functools import wraps
55
from threading import Thread
66
from queue import Queue as SyncQueue
7-
from idom.core.types import ComponentType
7+
from typing import Any, Awaitable, Callable
8+
9+
from typing_extensions import ParamSpec
810

911
import ipywidgets as widgets
10-
from IPython.display import display as ipython_display
12+
from IPython.display import display as ipython_display, DisplayHandle
1113
from traitlets import Unicode
1214
from idom.core.layout import Layout, LayoutEvent, LayoutUpdate
1315
from idom.core.serve import VdomJsonPatch, render_json_patch
14-
16+
from idom.core.types import ComponentType
1517

1618
_IMPORT_SOURCE_BASE_URL = ""
1719

1820

19-
def set_import_source_base_url(base_url):
21+
def set_import_source_base_url(base_url: str) -> None:
2022
"""Fallback URL for import sources, if no Jupyter Server is discovered by the client"""
2123
global _IMPORT_SOURCE_BASE_URL
2224
_IMPORT_SOURCE_BASE_URL = base_url
2325

2426

25-
def run(constructor):
27+
def run(constructor: Callable[[], ComponentType]) -> DisplayHandle | None:
2628
"""Run the given IDOM elemen definition as a Jupyter Widget.
2729
2830
This function is meant to be similarly to ``idom.run``.
2931
"""
3032
return ipython_display(LayoutWidget(constructor()))
3133

3234

33-
def widgetize(constructor):
35+
_P = ParamSpec("_P")
36+
37+
38+
def widgetize(constructor: Callable[_P, ComponentType]) -> Callable[_P, LayoutWidget]:
3439
"""A decorator that turns an IDOM element into a Jupyter Widget constructor"""
3540

3641
@wraps(constructor)
37-
def wrapper(*args, **kwargs):
42+
def wrapper(*args: Any, **kwargs: Any) -> LayoutWidget:
3843
return LayoutWidget(constructor(*args, **kwargs))
3944

4045
return wrapper
@@ -63,15 +68,15 @@ class LayoutWidget(widgets.DOMWidget):
6368

6469
_import_source_base_url = Unicode().tag(sync=True)
6570

66-
def __init__(self, component: ComponentType):
71+
def __init__(self, component: ComponentType) -> None:
6772
super().__init__(_import_source_base_url=_IMPORT_SOURCE_BASE_URL)
6873
self._idom_model = {}
6974
self._idom_views = set()
7075
self._idom_layout = Layout(component)
7176
self._idom_loop = _spawn_threaded_event_loop(self._idom_layout_render_loop())
7277
self.on_msg(lambda _, *args, **kwargs: self._idom_on_msg(*args, **kwargs))
7378

74-
def _idom_on_msg(self, message, buffers):
79+
def _idom_on_msg(self, message: dict[str, Any], buffers: Any):
7580
m_type = message.get("type")
7681
if m_type == "client-ready":
7782
v_id = message["viewID"]
@@ -89,7 +94,7 @@ def _idom_on_msg(self, message, buffers):
8994
if v_id in self._idom_views:
9095
self._idom_views.remove(message["viewID"])
9196

92-
async def _idom_layout_render_loop(self):
97+
async def _idom_layout_render_loop(self) -> None:
9398
async with self._idom_layout:
9499
while True:
95100
diff = await render_json_patch(self._idom_layout)
@@ -101,8 +106,10 @@ def __repr__(self) -> str:
101106
return f"LayoutWidget({self._idom_layout})"
102107

103108

104-
def _spawn_threaded_event_loop(coro):
105-
loop_q = SyncQueue()
109+
def _spawn_threaded_event_loop(
110+
coro: Callable[..., Awaitable[Any]]
111+
) -> asyncio.AbstractEventLoop:
112+
loop_q: SyncQueue[asyncio.AbstractEventLoop] = SyncQueue()
106113

107114
def run_in_thread() -> None:
108115
loop = asyncio.new_event_loop()

0 commit comments

Comments
 (0)