diff --git a/src/debugpy/adapter/clients.py b/src/debugpy/adapter/clients.py index 03a14db8..84084dd1 100644 --- a/src/debugpy/adapter/clients.py +++ b/src/debugpy/adapter/clients.py @@ -219,9 +219,9 @@ class Client(components.Component): if self.session.no_debug: servers.dont_wait_for_first_connection() - request("debugOptions", json.array(str)) + request_options = request("debugOptions", json.array(str)) self.session.debug_options = debug_options = set( - + request_options ) f(self, request) @@ -656,7 +656,7 @@ class Client(components.Component): result = {"debugpy": {"version": debugpy.__version__}} if self.server: try: - pydevd_info: messaging.AssociatableMessageDict = self.server.channel.request("pydevdSystemInfo") + pydevd_info: messaging.MessageDict = self.server.channel.request("pydevdSystemInfo") except Exception: # If the server has already disconnected, or couldn't handle it, # report what we've got. @@ -777,7 +777,7 @@ class Client(components.Component): def serve(host, port): global listener - listener = sockets.serve("Client", Client, host, port) # type: ignore + listener = sockets.serve("Client", Client, host, port) sessions.report_sockets() return listener.getsockname() diff --git a/src/debugpy/adapter/servers.py b/src/debugpy/adapter/servers.py index 77575f01..219a85a6 100644 --- a/src/debugpy/adapter/servers.py +++ b/src/debugpy/adapter/servers.py @@ -399,7 +399,7 @@ class Server(components.Component): def serve(host="127.0.0.1", port=0): global listener - listener = sockets.serve("Server", Connection, host, port) # type: ignore + listener = sockets.serve("Server", Connection, host, port) sessions.report_sockets() return listener.getsockname() diff --git a/src/debugpy/common/messaging.py b/src/debugpy/common/messaging.py index fa9bfe7b..39e46ddf 100644 --- a/src/debugpy/common/messaging.py +++ b/src/debugpy/common/messaging.py @@ -408,7 +408,7 @@ class MessageDict(collections.OrderedDict): raise message.isnt_valid("{0}{1}", json.repr(key), err) return value - def _invalid_if_no_key(func: Callable[..., Any]): # type: ignore + def _invalid_if_no_key(func: Callable[..., Any]): # pyright: ignore[reportSelfClsParameterName] def wrap(self, key, *args, **kwargs): try: return func(self, key, *args, **kwargs) @@ -425,11 +425,11 @@ class MessageDict(collections.OrderedDict): del _invalid_if_no_key -class AssociatableMessageDict(MessageDict): +class AssociableMessageDict(MessageDict): def associate_with(self, message: Message): self.message = message -def is_associatable(obj) -> TypeIs[AssociatableMessageDict]: +def is_associable(obj) -> TypeIs[AssociableMessageDict]: return isinstance(obj, MessageDict) and hasattr(obj, "associate_with") def _payload(value): @@ -446,7 +446,7 @@ def _payload(value): # Missing payload. Construct a dummy MessageDict, and make it look like it was # deserialized. See JsonMessageChannel._parse_incoming_message for why it needs # to have associate_with(). - value = AssociatableMessageDict(None) + value = AssociableMessageDict(None) return value @@ -471,7 +471,7 @@ class Message(object): """ def __str__(self): - return json.repr(self.json).__str__() if self.json is not None else repr(self) + return str(json.repr(self.json)) if self.json is not None else repr(self) def describe(self): """A brief description of the message that is enough to identify it. @@ -483,14 +483,17 @@ class Message(object): raise NotImplementedError @property - def payload(self) -> MessageDict: + def payload(self) -> MessageDict | Exception: """Payload of the message - self.body or self.arguments, depending on the message type. """ raise NotImplementedError - def __call__(self, *args, **kwargs): + def __call__(self, *args, **kwargs) -> MessageDict | Any | int | float: """Same as self.payload(...).""" + assert not isinstance(self.payload, Exception) + if args.count == 0 and kwargs == {}: + return self.payload return self.payload(*args, **kwargs) def __contains__(self, key): @@ -573,12 +576,12 @@ class Event(Message): the appropriate exception type that applies_to() the Event object. """ - def __init__(self, channel, seq, event, body, json=None): + def __init__(self, channel, seq, event, body: MessageDict, json=None): super().__init__(channel, seq, json) self.event = event - if is_associatable(body): + if is_associable(body): body.associate_with(self) self.body = body @@ -667,12 +670,12 @@ class Request(Message): the appropriate exception type that applies_to() the Request object. """ - def __init__(self, channel, seq, command, arguments, json=None): + def __init__(self, channel, seq, command, arguments: MessageDict, json=None): super().__init__(channel, seq, json) self.command = command - if is_associatable(arguments): + if is_associable(arguments): arguments.associate_with(self) self.arguments = arguments @@ -787,7 +790,7 @@ class OutgoingRequest(Request): def describe(self): return f"{self.seq} request {json.repr(self.command)} to {self.channel}" - def wait_for_response(self, raise_if_failed=True)-> AssociatableMessageDict | Exception: + def wait_for_response(self, raise_if_failed=True)-> MessageDict: """Waits until a response is received for this request, records the Response object for it in self.response, and returns response.body. @@ -804,6 +807,8 @@ class OutgoingRequest(Request): if raise_if_failed and not self.response.success and isinstance( self.response.body, BaseException): raise self.response.body + + assert not isinstance(self.response.body, Exception) return self.response.body def on_response(self, response_handler): @@ -889,13 +894,13 @@ class Response(Message): the appropriate exception type that applies_to() the Response object. """ - def __init__(self, channel, seq, request, body, json=None): + def __init__(self, channel, seq, request, body: MessageDict | Exception, json=None): super().__init__(channel, seq, json) self.request = request """The request to which this is the response.""" - if is_associatable(body): + if is_associable(body): body.associate_with(self) self.body = body """Body of the response if the request was successful, or an instance @@ -1366,7 +1371,7 @@ class JsonMessageChannel(object): # for all JSON objects, and track them so that they can be later wired up to # the Message they belong to, once it is instantiated. def object_hook(d): - d = AssociatableMessageDict(None, d) + d = AssociableMessageDict(None, d) if "seq" in d: self._prettify(d) setattr(d, "associate_with", associate_with) diff --git a/src/debugpy/common/singleton.py b/src/debugpy/common/singleton.py index f8da9ec3..f3f9abf8 100644 --- a/src/debugpy/common/singleton.py +++ b/src/debugpy/common/singleton.py @@ -141,9 +141,9 @@ class ThreadSafeSingleton(Singleton): # with @threadsafe_method. Such methods should perform the necessary locking to # ensure thread safety for the callers. - @staticmethod - def assert_locked(self): # type: ignore + def assert_locked(self): lock = type(self)._lock + assert lock is not None assert lock.acquire(blocking=False), ( "ThreadSafeSingleton accessed without locking. Either use with-statement, " "or if it is a method or property, mark it as @threadsafe_method or with " diff --git a/src/debugpy/common/sockets.py b/src/debugpy/common/sockets.py index 7b26026a..202bbbe7 100644 --- a/src/debugpy/common/sockets.py +++ b/src/debugpy/common/sockets.py @@ -5,7 +5,7 @@ import socket import sys import threading -from typing import Callable, Union +from typing import Any, Callable, Union from debugpy.common import log from debugpy.common.util import hide_thread_from_debugger @@ -89,7 +89,7 @@ def close_socket(sock): sock.close() -def serve(name: str, handler: Callable[[socket.socket], None], host: str, port: int=0, backlog=socket.SOMAXCONN, timeout: Union[int, None]=None): +def serve(name: str, handler: Callable[[socket.socket], Any], host: str, port: int=0, backlog=socket.SOMAXCONN, timeout: Union[int, None]=None): """Accepts TCP connections on the specified host and port, and invokes the provided handler function for every new connection. diff --git a/src/debugpy/launcher/debuggee.py b/src/debugpy/launcher/debuggee.py index 4b6ac87c..e5dc7206 100644 --- a/src/debugpy/launcher/debuggee.py +++ b/src/debugpy/launcher/debuggee.py @@ -91,7 +91,7 @@ def spawn(process_name, cmdline, env, redirect_output): try: global process - process = subprocess.Popen(cmdline, env=env, bufsize=0, **kwargs) # type: ignore + process = subprocess.Popen(cmdline, env=env, bufsize=0, **kwargs) except Exception as exc: raise messaging.MessageHandlingError( "Couldn't spawn debuggee: {0}\n\nCommand line:{1!r}".format( @@ -244,7 +244,7 @@ def _wait_for_user_input(): log.debug("msvcrt available - waiting for user input via getch()") sys.stdout.write("Press any key to continue . . . ") sys.stdout.flush() - msvcrt.getch() # type: ignore + msvcrt.getch() # pyright: ignore[reportPossiblyUnboundVariable, reportAttributeAccessIssue] else: log.debug("msvcrt not available - waiting for user input via read()") sys.stdout.write("Press Enter to continue . . . ") diff --git a/src/debugpy/launcher/winapi.py b/src/debugpy/launcher/winapi.py index e65d3ee9..4b470f5f 100644 --- a/src/debugpy/launcher/winapi.py +++ b/src/debugpy/launcher/winapi.py @@ -64,14 +64,14 @@ def _errcheck(is_error_result=(lambda result: not result)): def impl(result, func, args): if is_error_result(result): log.debug("{0} returned {1}", func.__name__, result) - raise ctypes.WinError() # type: ignore + raise ctypes.WinError() # pyright: ignore[reportAttributeAccessIssue] else: return result return impl -kernel32 = ctypes.windll.kernel32 # type: ignore +kernel32 = ctypes.windll.kernel32 # pyright: ignore[reportAttributeAccessIssue] kernel32.AssignProcessToJobObject.errcheck = _errcheck() kernel32.AssignProcessToJobObject.restype = BOOL diff --git a/src/debugpy/server/api.py b/src/debugpy/server/api.py index f1698142..6be27cf8 100644 --- a/src/debugpy/server/api.py +++ b/src/debugpy/server/api.py @@ -54,16 +54,16 @@ class _settrace(): def ensure_logging(): """Starts logging to log.log_dir, if it hasn't already been done.""" - if ensure_logging.ensured: # type: ignore + if ensure_logging.ensured: # pyright: ignore[reportFunctionMemberAccess] return - ensure_logging.ensured = True # type: ignore + ensure_logging.ensured = True # pyright: ignore[reportFunctionMemberAccess] log.to_file(prefix="debugpy.server") log.describe_environment("Initial environment:") if log.log_dir is not None: pydevd.log_to(log.log_dir + "/debugpy.pydevd.log") -ensure_logging.ensured = False # type: ignore +ensure_logging.ensured = False # pyright: ignore[reportFunctionMemberAccess] def log_to(path):