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 5from __future__ import absolute_import, division, print_function, unicode_literals 6 7"""An implementation of the Debug Adapter Protocol (DAP) for Python. 8 9https://microsoft.github.io/debug-adapter-protocol/ 10""" 11 12# debugpy stable public API consists solely of members of this module that are 13# enumerated below. 14__all__ = [ 15 "__version__", 16 "breakpoint", 17 "configure", 18 "connect", 19 "debug_this_thread", 20 "is_client_connected", 21 "listen", 22 "log_to", 23 "trace_this_thread", 24 "wait_for_client", 25] 26 27import codecs 28import os 29 30from debugpy import _version 31from debugpy.common import compat 32 33 34# Expose debugpy.server API from subpackage, but do not actually import it unless 35# and until a member is invoked - we don't want the server package loaded in the 36# adapter, the tests, or setup.py. 37 38# Docstrings for public API members must be formatted according to PEP 8 - no more 39# than 72 characters per line! - and must be readable when retrieved via help(). 40 41 42def log_to(path): 43 """Generate detailed debugpy logs in the specified directory. 44 45 The directory must already exist. Several log files are generated, 46 one for every process involved in the debug session. 47 """ 48 49 from debugpy.server import api 50 51 return api.log_to(path) 52 53 54def configure(properties=None, **kwargs): 55 """Sets debug configuration properties that cannot be set in the 56 "attach" request, because they must be applied as early as possible 57 in the process being debugged. 58 59 For example, a "launch" configuration with subprocess debugging 60 disabled can be defined entirely in JSON:: 61 62 { 63 "request": "launch", 64 "subProcess": false, 65 ... 66 } 67 68 But the same cannot be done with "attach", because "subProcess" 69 must be known at the point debugpy starts tracing execution. Thus, 70 it is not available in JSON, and must be omitted:: 71 72 { 73 "request": "attach", 74 ... 75 } 76 77 and set from within the debugged process instead:: 78 79 debugpy.configure(subProcess=False) 80 debugpy.listen(...) 81 82 Properties to set can be passed either as a single dict argument, 83 or as separate keyword arguments:: 84 85 debugpy.configure({"subProcess": False}) 86 """ 87 88 from debugpy.server import api 89 90 return api.configure(properties, **kwargs) 91 92 93def listen(address): 94 """Starts a debug adapter debugging this process, that listens for 95 incoming socket connections from clients on the specified address. 96 97 address must be either a (host, port) tuple, as defined by the 98 standard socket module for the AF_INET address family, or a port 99 number. If only the port is specified, host is "127.0.0.1". 100 101 Returns the interface and the port on which the debug adapter is 102 actually listening, in the same format as address. This may be 103 different from address if port was 0 in the latter, in which case 104 the adapter will pick some unused ephemeral port to listen on. 105 106 This function does't wait for a client to connect to the debug 107 adapter that it starts. Use wait_for_client() to block execution 108 until the client connects. 109 """ 110 111 from debugpy.server import api 112 113 return api.listen(address) 114 115 116@compat.kwonly 117def connect(address, access_token=None): 118 """Tells an existing debug adapter instance that is listening on the 119 specified address to debug this process. 120 121 address must be either a (host, port) tuple, as defined by the 122 standard socket module for the AF_INET address family, or a port 123 number. If only the port is specified, host is "127.0.0.1". 124 125 access_token must be the same value that was passed to the adapter 126 via the --server-access-token command-line switch. 127 128 This function does't wait for a client to connect to the debug 129 adapter that it connects to. Use wait_for_client() to block 130 execution until the client connects. 131 """ 132 133 from debugpy.server import api 134 135 return api.connect(address, access_token=access_token) 136 137 138def wait_for_client(): 139 """If there is a client connected to the debug adapter that is 140 debugging this process, returns immediately. Otherwise, blocks 141 until a client connects to the adapter. 142 143 While this function is waiting, it can be canceled by calling 144 wait_for_client.cancel() from another thread. 145 """ 146 147 from debugpy.server import api 148 149 return api.wait_for_client() 150 151 152def is_client_connected(): 153 """True if a client is connected to the debug adapter that is 154 debugging this process. 155 """ 156 157 from debugpy.server import api 158 159 return api.is_client_connected() 160 161 162def breakpoint(): 163 """If a client is connected to the debug adapter that is debugging 164 this process, pauses execution of all threads, and simulates a 165 breakpoint being hit at the line following the call. 166 167 On Python 3.7 and above, this is the same as builtins.breakpoint(). 168 """ 169 170 from debugpy.server import api 171 172 return api.breakpoint() 173 174 175def debug_this_thread(): 176 """Makes the debugger aware of the current thread. 177 178 Must be called on any background thread that is started by means 179 other than the usual Python APIs (i.e. the "threading" module), 180 in order for breakpoints to work on that thread. 181 """ 182 183 from debugpy.server import api 184 185 return api.debug_this_thread() 186 187 188def trace_this_thread(should_trace): 189 """Tells the debug adapter to enable or disable tracing on the 190 current thread. 191 192 When the thread is traced, the debug adapter can detect breakpoints 193 being hit, but execution is slower, especially in functions that 194 have any breakpoints set in them. Disabling tracing when breakpoints 195 are not anticipated to be hit can improve performance. It can also 196 be used to skip breakpoints on a particular thread. 197 198 Tracing is automatically disabled for all threads when there is no 199 client connected to the debug adapter. 200 """ 201 202 from debugpy.server import api 203 204 return api.trace_this_thread(should_trace) 205 206 207__version__ = _version.get_versions()["version"] 208 209# Force absolute path on Python 2. 210__file__ = os.path.abspath(__file__) 211 212# Preload encodings that we're going to use to avoid import deadlocks on Python 2, 213# before importing anything from debugpy. 214map(codecs.lookup, ["ascii", "utf8", "utf-8", "latin1", "latin-1", "idna", "hex"]) 215