Format: text/x-python
⬇ Download File (6.4 KB)
   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