1 # Copyright (c) Microsoft Corporation. All rights reserved. 2 # Licensed under the MIT License. See LICENSE in the project root 3 # for license information. 4 5 from __future__ import annotations 6 7 import functools 8 import typing 9 10 from debugpy import _version 11 12 13 # Expose debugpy.server API from subpackage, but do not actually import it unless 14 # and until a member is invoked - we don't want the server package loaded in the 15 # adapter, the tests, or setup.py. 16 17 # Docstrings for public API members must be formatted according to PEP 8 - no more 18 # than 72 characters per line! - and must be readable when retrieved via help(). 19 20 21 Endpoint = typing.Tuple[str, int] 22 23 24 def _api(cancelable=False): 25 def apply(f): 26 @functools.wraps(f) 27 def wrapper(*args, **kwargs): 28 from debugpy.server import api 29 30 wrapped = getattr(api, f.__name__) 31 return wrapped(*args, **kwargs) 32 33 if cancelable: 34 35 def cancel(*args, **kwargs): 36 from debugpy.server import api 37 38 wrapped = getattr(api, f.__name__) 39 return wrapped.cancel(*args, **kwargs) 40 41 wrapper.cancel = cancel # pyright: ignore 42 43 return wrapper 44 45 return apply 46 47 48 @_api() 49 def log_to(__path: str | typing.TextIO) -> None: 50 """Generate detailed debugpy logs in the specified directory. 51 52 The directory must already exist. Several log files are generated, 53 one for every process involved in the debug session. 54 """ 55 56 57 @_api() 58 def configure(__properties: dict[str, typing.Any] | None = None, **kwargs) -> None: 59 """Sets debug configuration properties that cannot be set in the 60 "attach" request, because they must be applied as early as possible 61 in the process being debugged. 62 63 For example, a "launch" configuration with subprocess debugging 64 disabled can be defined entirely in JSON:: 65 66 { 67 "request": "launch", 68 "subProcess": false, 69 ... 70 } 71 72 But the same cannot be done with "attach", because "subProcess" 73 must be known at the point debugpy starts tracing execution. Thus, 74 it is not available in JSON, and must be omitted:: 75 76 { 77 "request": "attach", 78 ... 79 } 80 81 and set from within the debugged process instead:: 82 83 debugpy.configure(subProcess=False) 84 debugpy.listen(...) 85 86 Properties to set can be passed either as a single dict argument, 87 or as separate keyword arguments:: 88 89 debugpy.configure({"subProcess": False}) 90 """ 91 92 93 @_api() 94 def listen( 95 __endpoint: Endpoint | int, *, in_process_debug_adapter: bool = False 96 ) -> Endpoint: 97 """Starts a debug adapter debugging this process, that listens for 98 incoming socket connections from clients on the specified address. 99 100 `__endpoint` must be either a (host, port) tuple as defined by the 101 standard `socket` module for the `AF_INET` address family, or a port 102 number. If only the port is specified, host is "127.0.0.1". 103 104 `in_process_debug_adapter`: by default a separate python process is 105 spawned and used to communicate with the client as the debug adapter. 106 By setting the value of `in_process_debug_adapter` to True a new 107 python process is not spawned. Note: the con of setting 108 `in_process_debug_adapter` to True is that subprocesses won't be 109 automatically debugged. 110 111 Returns the interface and the port on which the debug adapter is 112 actually listening, in the same format as `__endpoint`. This may be 113 different from address if port was 0 in the latter, in which case 114 the adapter will pick some unused ephemeral port to listen on. 115 116 This function does't wait for a client to connect to the debug 117 adapter that it starts. Use `wait_for_client` to block execution 118 until the client connects. 119 """ 120 ... 121 122 @_api() 123 def connect(__endpoint: Endpoint | int, *, access_token: str | None = None) -> Endpoint: 124 """Tells an existing debug adapter instance that is listening on the 125 specified address to debug this process. 126 127 `__endpoint` must be either a (host, port) tuple as defined by the 128 standard `socket` module for the `AF_INET` address family, or a port 129 number. If only the port is specified, host is "127.0.0.1". 130 131 `access_token` must be the same value that was passed to the adapter 132 via the `--server-access-token` command-line switch. 133 134 This function does't wait for a client to connect to the debug 135 adapter that it connects to. Use `wait_for_client` to block 136 execution until the client connects. 137 """ 138 ... 139 140 @_api(cancelable=True) 141 def wait_for_client() -> None: 142 """If there is a client connected to the debug adapter that is 143 debugging this process, returns immediately. Otherwise, blocks 144 until a client connects to the adapter. 145 146 While this function is waiting, it can be canceled by calling 147 `wait_for_client.cancel()` from another thread. 148 """ 149 150 151 @_api() 152 def is_client_connected() -> bool: 153 """True if a client is connected to the debug adapter that is 154 debugging this process. 155 """ 156 ... 157 158 159 @_api() 160 def breakpoint() -> None: 161 """If a client is connected to the debug adapter that is debugging 162 this process, pauses execution of all threads, and simulates a 163 breakpoint being hit at the line following the call. 164 165 It is also registered as the default handler for builtins.breakpoint(). 166 """ 167 168 169 @_api() 170 def debug_this_thread() -> None: 171 """Makes the debugger aware of the current thread. 172 173 Must be called on any background thread that is started by means 174 other than the usual Python APIs (i.e. the "threading" module), 175 in order for breakpoints to work on that thread. 176 """ 177 178 179 @_api() 180 def trace_this_thread(__should_trace: bool): 181 """Tells the debug adapter to enable or disable tracing on the 182 current thread. 183 184 When the thread is traced, the debug adapter can detect breakpoints 185 being hit, but execution is slower, especially in functions that 186 have any breakpoints set in them. Disabling tracing when breakpoints 187 are not anticipated to be hit can improve performance. It can also 188 be used to skip breakpoints on a particular thread. 189 190 Tracing is automatically disabled for all threads when there is no 191 client connected to the debug adapter. 192 """ 193 194 195 __version__: str = _version.get_versions()["version"] 196