From 1d91c62b489bd94b9a63cbb14cdd973cd3bc3296 Mon Sep 17 00:00:00 2001 From: rchiodo Date: Wed, 3 Jul 2024 18:23:46 +0000 Subject: [PATCH] Add some more typing for the public api --- pyproject.toml | 2 +- src/debugpy/public_api.py | 9 ++++--- src/debugpy/server/cli.py | 51 ++++++++++++++++++++++----------------- 3 files changed, 35 insertions(+), 27 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index cd5f2787..a6906c0d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ exclude = ''' [tool.pyright] pythonVersion = "3.8" include = ["src/**", "tests/**" ] -extraPaths = ["src/debugpy/_vendored/pydevd"] +extraPaths = ["src/debugpy/_vendored/pydevd", "src/debugpy/_vendored/pydevd/pydevd_attach_to_process"] ignore = ["src/debugpy/_vendored/pydevd", "src/debugpy/_version.py"] executionEnvironments = [ { root = "src" }, { root = "." } diff --git a/src/debugpy/public_api.py b/src/debugpy/public_api.py index 9d0f705a..c61a2607 100644 --- a/src/debugpy/public_api.py +++ b/src/debugpy/public_api.py @@ -38,7 +38,7 @@ def _api(cancelable=False): wrapped = getattr(api, f.__name__) return wrapped.cancel(*args, **kwargs) - wrapper.cancel = cancel + wrapper.cancel = cancel # pyright: ignore return wrapper @@ -46,7 +46,7 @@ def _api(cancelable=False): @_api() -def log_to(__path: str) -> None: +def log_to(__path: str | typing.TextIO) -> None: """Generate detailed debugpy logs in the specified directory. The directory must already exist. Several log files are generated, @@ -117,7 +117,7 @@ def listen( adapter that it starts. Use `wait_for_client` to block execution until the client connects. """ - + ... @_api() def connect(__endpoint: Endpoint | int, *, access_token: str | None = None) -> Endpoint: @@ -135,7 +135,7 @@ def connect(__endpoint: Endpoint | int, *, access_token: str | None = None) -> E adapter that it connects to. Use `wait_for_client` to block execution until the client connects. """ - + ... @_api(cancelable=True) def wait_for_client() -> None: @@ -153,6 +153,7 @@ def is_client_connected() -> bool: """True if a client is connected to the debug adapter that is debugging this process. """ + ... @_api() diff --git a/src/debugpy/server/cli.py b/src/debugpy/server/cli.py index ba143479..7ef289e8 100644 --- a/src/debugpy/server/cli.py +++ b/src/debugpy/server/cli.py @@ -7,6 +7,7 @@ import os import re import sys from importlib.util import find_spec +from typing import Any, Optional # debugpy.__main__ should have preloaded pydevd properly before importing this module. # Otherwise, some stdlib modules above might have had imported threading before pydevd @@ -18,6 +19,7 @@ import pydevd from _pydevd_bundle import pydevd_runpy as runpy import debugpy +import debugpy.server from debugpy.common import log from debugpy.server import api @@ -41,13 +43,14 @@ Usage: debugpy --listen | --connect class Options(object): mode = None - address = None + address: "Optional[tuple[str, int]]" = None log_to = None log_to_stderr = False - target = None - target_kind = None + target: "Optional[str]" = None + target_kind: "Optional[str]" = None wait_for_client = False adapter_access_token = None + config: "dict[str, Any]" = {} options = Options() @@ -139,7 +142,7 @@ def set_config(arg, it): options.config[name] = value -def set_target(kind, parser=(lambda x: x), positional=False): +def set_target(kind: str, parser=(lambda x: x), positional=False): def do(arg, it): options.target_kind = kind target = parser(arg if positional else next(it)) @@ -252,9 +255,9 @@ def start_debugging(argv_0): debugpy.configure(options.config) - if options.mode == "listen": + if options.mode == "listen" and options.address is not None: debugpy.listen(options.address) - elif options.mode == "connect": + elif options.mode == "connect" and options.address is not None: debugpy.connect(options.address, access_token=options.adapter_access_token) else: raise AssertionError(repr(options.mode)) @@ -272,7 +275,7 @@ def run_file(): # parent directory to sys.path. Thus, importing other modules from the # same directory is broken unless sys.path is patched here. - if os.path.isfile(target): + if target is not None and os.path.isfile(target): dir = os.path.dirname(target) sys.path.insert(0, dir) else: @@ -293,7 +296,7 @@ def run_module(): # actually invoking it. argv_0 = sys.argv[0] try: - spec = find_spec(options.target) + spec = None if options.target is None else find_spec(options.target) if spec is not None: argv_0 = spec.origin except Exception: @@ -318,16 +321,19 @@ def run_module(): def run_code(): - # Add current directory to path, like Python itself does for -c. - sys.path.insert(0, str("")) - code = compile(options.target, str(""), str("exec")) + if options.target is not None: + # Add current directory to path, like Python itself does for -c. + sys.path.insert(0, str("")) + code = compile(options.target, str(""), str("exec")) - start_debugging(str("-c")) + start_debugging(str("-c")) - log.describe_environment("Pre-launch environment:") - log.info("Running code:\n\n{0}", options.target) + log.describe_environment("Pre-launch environment:") + log.info("Running code:\n\n{0}", options.target) - eval(code, {}) + eval(code, {}) + else: + log.error("No target to run.") def attach_to_pid(): @@ -421,13 +427,14 @@ def main(): ) try: - run = { - "file": run_file, - "module": run_module, - "code": run_code, - "pid": attach_to_pid, - }[options.target_kind] - run() + if options.target_kind is not None: + run = { + "file": run_file, + "module": run_module, + "code": run_code, + "pid": attach_to_pid, + }[options.target_kind] + run() except SystemExit as exc: log.reraise_exception( "Debuggee exited via SystemExit: {0!r}", exc.code, level="debug"