33import time
44import contextlib
55import socket
6+ import os
7+ import sys
68from contextlib import closing
7-
8- from typing import Optional , Tuple , Union , Sequence , cast , Callable , TypeVar , Dict , Any
9+ from typing import Optional , cast , Any , Dict
910
1011def find_free_port (start : Optional [int ] = None , end : Optional [int ] = None ) -> int :
1112 port = start
@@ -32,38 +33,113 @@ def find_free_port(start: Optional[int] = None, end: Optional[int] = None) -> in
3233 return find_free_port (None )
3334 raise
3435
35-
3636def is_debugpy_installed () -> bool :
3737 try :
3838 __import__ ("debugpy" )
39+ return True
3940 except ImportError :
4041 return False
41- return True
4242
43+ def _get_python_interpreter_path (install_dir : Optional [str ]) -> Optional [str ]:
44+ """Get the path to the Python interpreter."""
45+ if not install_dir :
46+ return None
47+
48+ python_exe = 'irispython.exe' if sys .platform == 'win32' else 'irispython'
49+ python_path = os .path .join (install_dir , 'bin' , python_exe )
50+
51+ return python_path if os .path .exists (python_path ) else None
52+
53+ def _get_debugpy_config (python_path : str ) -> Dict [str , str ]:
54+ """Get the debugpy configuration."""
55+ return {"python" : python_path }
56+
57+ def configure_debugpy (self , python_path : Optional [str ] = None ) -> bool :
58+ """Configure debugpy with the appropriate Python interpreter."""
59+ import debugpy
60+
61+ if not python_path :
62+ install_dir = os .environ .get ('IRISINSTALLDIR' ) or os .environ .get ('ISC_PACKAGE_INSTALLDIR' )
63+ python_path = _get_python_interpreter_path (install_dir )
64+
65+ if not python_path :
66+ self .log_alert ("Could not determine Python interpreter path" )
67+ return False
68+
69+ try :
70+ debugpy .configure (_get_debugpy_config (python_path ))
71+ self .log_info (f"Debugpy configured with Python interpreter: { python_path } " )
72+ return True
73+ except Exception as e :
74+ self .log_alert (f"Failed to configure debugpy: { e } " )
75+ return False
4376
44- def wait_for_debugpy_connected (timeout : float = 30 ,port = 0 ) -> bool :
45- import debugpy # noqa: T100
77+ def wait_for_debugpy_connected (timeout : float = 30 , port : int = 0 ) -> bool :
78+ """Wait for debugpy client to connect."""
79+ import debugpy
4680
4781 if not is_debugpy_installed ():
4882 return False
4983
50- class T (threading .Thread ):
51- daemon = True
52- def run (self ):
53- time .sleep (timeout )
54- debugpy .wait_for_client .cancel ()
55- T ().start ()
56- debugpy .wait_for_client ()
57- if debugpy .is_client_connected ():
58- return True
84+ def timeout_handler ():
85+ time .sleep (timeout )
86+ debugpy .wait_for_client .cancel ()
87+
88+ threading .Thread (target = timeout_handler , daemon = True ).start ()
89+
90+ try :
91+ debugpy .wait_for_client ()
92+ return debugpy .is_client_connected ()
93+ except Exception :
94+ import pydevd # type: ignore
95+ pydevd .stoptrace ()
96+ return False
5997
60- return False
98+ def enable_debugpy (port : int , address : str = "0.0.0.0" ) -> None :
99+ """Enable debugpy server on specified port and address."""
100+ import debugpy
101+ debugpy .listen ((address , port ))
61102
62- def enable_debugpy (port : int , address = None ) -> bool :
103+ def debugpython (self , host_object : Any ) -> None :
104+ """Enable and configure debugpy for debugging purposes."""
105+ # hack to set __file__ for os module in debugpy
106+ # This is a workaround for the issue where debugpy cannot find the __file__ attribute of the os module.
107+ if not hasattr (os , '__file__' ):
108+ setattr (os , '__file__' , __file__ )
63109
64- import debugpy # noqa: T100
65110
66- if address is None :
67- address = "0.0.0.0"
111+ if host_object is None :
112+ self .log_alert ("No host object found, cannot enable debugpy." )
113+ return
68114
69- debugpy .listen ((address , port ))
115+ if host_object .enable != 1 :
116+ self .log_info ("Debugpy is not enabled." )
117+ return
118+
119+ if not is_debugpy_installed ():
120+ self .log_alert ("Debugpy is not installed." )
121+ return
122+
123+ # Configure Python interpreter
124+ if host_object .PythonInterpreterPath != '' :
125+ success = configure_debugpy (self , host_object .PythonInterpreterPath )
126+ else :
127+ success = configure_debugpy (self )
128+
129+ if not success :
130+ return
131+
132+ # Setup debugging server
133+ port = host_object .port if host_object .port and host_object .port > 0 else find_free_port ()
134+
135+ try :
136+ enable_debugpy (port = port )
137+ self .log_info (f"Debugpy enabled on port { port } " )
138+
139+ self .trace (f"Waiting { host_object .timeout } seconds for debugpy connection..." )
140+ if wait_for_debugpy_connected (timeout = host_object .timeout , port = port ):
141+ self .log_info ("Debugpy connected successfully" )
142+ else :
143+ self .log_alert (f"Debugpy connection timed out after { host_object .timeout } seconds" )
144+ except Exception as e :
145+ self .log_alert (f"Error enabling debugpy: { e } " )
0 commit comments