11import argparse
22import asyncio
3+ import functools
34import logging
45import logging .config
56import os
67import sys
78import threading
89from logging .handlers import RotatingFileHandler
910from pathlib import Path
10- from typing import TYPE_CHECKING , Any , List , Optional , Sequence , Union , cast
11+ from typing import TYPE_CHECKING , Any , Callable , List , Optional , Sequence , Union , cast
1112
1213__file__ = os .path .abspath (__file__ )
1314if __file__ .endswith ((".pyc" , ".pyo" )):
@@ -65,27 +66,33 @@ async def wait() -> None:
6566
6667
6768@_logger .call
68- async def _debug_adapter_server_ (host : str , port : int ) -> None :
69+ async def _debug_adapter_server_ (
70+ host : str , port : int , on_config_done_callback : Optional [Callable [["DebugAdapterServer" ], None ]]
71+ ) -> None :
6972 from ..jsonrpc2 .server import TcpParams
7073 from .server import DebugAdapterServer
7174
72- async with DebugAdapterServer (tcp_params = TcpParams (host , port )) as server :
73- set_server (cast (DebugAdapterServer , server ))
75+ async with DebugAdapterServer (tcp_params = TcpParams (host , port )) as s :
76+ server = cast (DebugAdapterServer , s )
77+ if on_config_done_callback is not None :
78+ server .protocol .received_configuration_done_callback = functools .partial (on_config_done_callback , server )
79+ set_server (server )
7480 await server .serve ()
7581
7682
7783DEFAULT_TIMEOUT = 10.0
7884
7985
86+ config_done_callback : Optional [Callable [["DebugAdapterServer" ], None ]] = None
87+
88+
8089@_logger .call
8190async def start_debugpy_async (
82- server : "DebugAdapterServer" ,
8391 debugpy_port : int = 5678 ,
8492 addresses : Union [Sequence [str ], str , None ] = None ,
8593 wait_for_debugpy_client : bool = False ,
8694 wait_for_client_timeout : float = DEFAULT_TIMEOUT ,
8795) -> None :
88- from ..utils .async_tools import run_coroutine_from_thread_async
8996 from ..utils .debugpy import enable_debugpy , wait_for_debugpy_connected
9097 from ..utils .net import find_free_port
9198 from .dap_types import Event
@@ -94,19 +101,17 @@ async def start_debugpy_async(
94101 if port != debugpy_port :
95102 _logger .warning (f"start debugpy session on port { port } " )
96103
97- if enable_debugpy (port , addresses ) and await run_coroutine_from_thread_async (
98- server .protocol .wait_for_client , wait_for_client_timeout , loop = server .loop
99- ):
100- await asyncio .wrap_future (
101- asyncio .run_coroutine_threadsafe (
102- server .protocol .send_event_async (
103- Event (event = "debugpyStarted" , body = {"port" : port , "addresses" : addresses })
104- ),
105- loop = server .loop ,
106- )
107- )
108- if wait_for_debugpy_client :
109- wait_for_debugpy_connected ()
104+ if enable_debugpy (port , addresses ):
105+ global config_done_callback
106+
107+ def connect_debugpy (server : "DebugAdapterServer" ) -> None :
108+
109+ server .protocol .send_event (Event (event = "debugpyStarted" , body = {"port" : port , "addresses" : addresses }))
110+
111+ if wait_for_debugpy_client :
112+ wait_for_debugpy_connected ()
113+
114+ config_done_callback = connect_debugpy
110115
111116
112117@_logger .call
@@ -132,14 +137,17 @@ async def run_robot(
132137 run_coroutine_from_thread_async ,
133138 run_coroutine_in_thread ,
134139 )
135- from ..utils .debugpy import is_debugpy_installed
140+ from ..utils .debugpy import is_debugpy_installed , wait_for_debugpy_connected
136141 from .dap_types import Event
137142 from .debugger import Debugger
138143
139144 if debugpy and not is_debugpy_installed ():
140145 print ("debugpy not installed." )
141146
142- server_future = run_coroutine_in_thread (_debug_adapter_server_ , addresses , port )
147+ if debugpy :
148+ await start_debugpy_async (debugpy_port , addresses , wait_for_debugpy_client , wait_for_client_timeout )
149+
150+ server_future = run_coroutine_in_thread (_debug_adapter_server_ , addresses , port , config_done_callback )
143151
144152 server = await wait_for_server ()
145153
@@ -166,8 +174,8 @@ async def run_robot(
166174 except asyncio .TimeoutError as e :
167175 raise ConnectionError ("Timeout to get configuration from client." ) from e
168176
169- if debugpy :
170- await start_debugpy_async ( server , debugpy_port , addresses , wait_for_debugpy_client , wait_for_client_timeout )
177+ if debugpy and wait_for_debugpy_client :
178+ wait_for_debugpy_connected ( )
171179
172180 args = [
173181 "--listener" ,
@@ -210,6 +218,8 @@ async def run_robot(
210218 return exit_code
211219 except asyncio .CancelledError :
212220 pass
221+ except ConnectionError as e :
222+ print (e , file = sys .stderr )
213223 finally :
214224 if server .protocol .connected :
215225 await run_coroutine_from_thread_async (server .protocol .terminate , loop = server .loop )
0 commit comments