55# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/api/06_jupyter.ipynb.
66
77# %% auto #0
8- __all__ = ['nb_serve' , 'nb_serve_async' , 'is_port_free' , 'wait_port_free' , 'show ' , 'render_ft ' , 'htmx_config_port' , 'JupyUvi ' ,
9- 'JupyUviAsync' , 'HTMX' , 'ws_client' ]
8+ __all__ = ['nb_serve' , 'nb_serve_async' , 'is_port_free' , 'wait_port_free' , 'wait_port_free_async ' , 'show ' , 'render_ft ' ,
9+ 'htmx_config_port' , 'JupyUvi' , ' JupyUviAsync' , 'HTMX' , 'ws_client' ]
1010
1111# %% ../nbs/api/06_jupyter.ipynb #2c69d9d0
1212import asyncio , socket , time , uvicorn
@@ -38,23 +38,31 @@ async def nb_serve_async(app, log_level="error", port=8000, host='0.0.0.0', **kw
3838
3939# %% ../nbs/api/06_jupyter.ipynb #508917bc
4040def is_port_free (port , host = 'localhost' ):
41- "Check if `port` is free on `host`"
4241 sock = socket .socket (socket .AF_INET , socket .SOCK_STREAM )
42+ sock .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
4343 try :
44- sock .setsockopt (socket .SOL_SOCKET , socket .SO_REUSEADDR , 1 )
4544 sock .bind ((host , port ))
45+ sock .listen (1 )
4646 return True
4747 except OSError : return False
4848 finally : sock .close ()
4949
5050# %% ../nbs/api/06_jupyter.ipynb #1779cb76
51- def wait_port_free (port , host = 'localhost' , max_wait = 3 ):
51+ def wait_port_free (port , host = 'localhost' , max_wait = 20 ):
5252 "Wait for `port` to be free on `host`"
5353 start_time = time .time ()
54- while not is_port_free (port ):
55- if time .time () - start_time > max_wait : return print (f"Timeout " )
54+ while not is_port_free (port , host ):
55+ if time .time () - start_time > max_wait : raise TimeoutError (f"Port { host } : { port } not free after { max_wait } s " )
5656 time .sleep (0.1 )
5757
58+ async def wait_port_free_async (port , host = 'localhost' , max_wait = 20 ):
59+ "Async wait for `port` to be free on `host`"
60+ start_time = time .time ()
61+ while not is_port_free (port , host ):
62+ if time .time () - start_time > max_wait : raise TimeoutError (f"Port { host } :{ port } not free after { max_wait } s" )
63+ await asyncio .sleep (0.1 )
64+
65+
5866# %% ../nbs/api/06_jupyter.ipynb #654b36bb
5967@delegates (_show )
6068def show (* s , ** kwargs ):
@@ -96,12 +104,9 @@ def __init__(self, app, log_level="error", host='0.0.0.0', port=8000, start=True
96104 def start (self ):
97105 self .server = nb_serve (self .app , log_level = self .log_level , host = self .host , port = self .port ,daemon = self .daemon , ** self .kwargs )
98106
99- async def start_async (self ):
100- self .server = await nb_serve_async (self .app , log_level = self .log_level , host = self .host , port = self .port , ** self .kwargs )
101-
102107 def stop (self ):
103108 self .server .should_exit = True
104- wait_port_free (self .port )
109+ wait_port_free (self .port , self . host )
105110
106111 def _setup_live (self , app ):
107112 rt = self .live_rt or '/_lr'
@@ -119,7 +124,7 @@ async def _live_sse(self):
119124 ver = self ._live_ver
120125 yield 'data: reload\n \n '
121126
122- # %% ../nbs/api/06_jupyter.ipynb #9134035e
127+ # %% ../nbs/api/06_jupyter.ipynb #f6316c73
123128class JupyUviAsync (JupyUvi ):
124129 "Start and stop an async Jupyter compatible uvicorn server with ASGI `app` on `port` with `log_level`"
125130 def __init__ (self , app , log_level = "error" , host = '0.0.0.0' , port = 8000 , ** kwargs ):
@@ -128,9 +133,10 @@ def __init__(self, app, log_level="error", host='0.0.0.0', port=8000, **kwargs):
128133 async def start (self ):
129134 self .server = await nb_serve_async (self .app , log_level = self .log_level , host = self .host , port = self .port , ** self .kwargs )
130135
131- def stop (self ):
136+ async def stop (self ):
132137 self .server .should_exit = True
133- wait_port_free (self .port )
138+ await wait_port_free_async (self .port , self .host )
139+
134140
135141# %% ../nbs/api/06_jupyter.ipynb #a448e420
136142from starlette .testclient import TestClient
0 commit comments