Skip to content

Add more typing to debugpy and switch to 'standard' type checking mode#1637

Open
rchiodo wants to merge 34 commits into
microsoft:mainfrom
rchiodo:rchiodo/type_standard
Open

Add more typing to debugpy and switch to 'standard' type checking mode#1637
rchiodo wants to merge 34 commits into
microsoft:mainfrom
rchiodo:rchiodo/type_standard

Conversation

@rchiodo

@rchiodo rchiodo commented Jul 24, 2024

Copy link
Copy Markdown
Contributor

This is entirely necessary but I was using this to test Pylance. Seems like a good thing to be more strictly typed though.

@rchiodo
rchiodo requested a review from a team as a code owner July 24, 2024 21:34
Comment thread src/debugpy/adapter/clients.py Outdated
Comment thread src/debugpy/adapter/clients.py Outdated
Comment thread src/debugpy/common/messaging.py Outdated
Comment thread src/debugpy/common/messaging.py Outdated
debonte
debonte previously approved these changes Jul 24, 2024
…odo/type_standard

# Conflicts:
#	CONTRIBUTING.md
#	src/debugpy/adapter/clients.py
#	src/debugpy/adapter/launchers.py
#	src/debugpy/adapter/servers.py
#	src/debugpy/common/sockets.py
#	src/debugpy/server/api.py
#	src/debugpy/server/cli.py
#	tests/requirements.txt
@rchiodo
rchiodo requested a review from a team as a code owner July 16, 2026 19:00
@heejaechang

heejaechang commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

🔒 Automated review in progress — @heejaechang is auto-reviewing this PR.

Comment thread src/debugpy/adapter/servers.py Outdated
@heejaechang

Copy link
Copy Markdown
Contributor

Overall this is a solid, well-tested typing pass. A few non-blocking notes below about failing-fast vs. substituting degraded fallback values on the newly-added None paths, plus one latent -O-mode crash path in servers.py. Nothing here blocks merge.

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

Address review feedback on the typing pass: replace silently-degraded None fallbacks with fail-fast asserts, and make ThreadSafeSingleton.assert_locked side-effect-free.

- singleton.py: assert_locked now checks lock._is_owned() instead of acquire()/release(), avoiding RLock recursion-count mutation and an unbalanced release() under python -O.

- servers.py: assert pydevdSystemInfo result is non-exception (pid/ppid always assigned before use); assert listener in inject() rather than connecting to an empty address.

- clients.py: assert servers.listener in attach_request and the client listener in notify_of_subprocess instead of substituting ("", 0)/None.

- debuggee.py: assert process in wait_for_exit rather than reporting a bogus clean exit (code 0).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread tests/debugpy/common/test_messaging.py Outdated
Comment thread tests/debugpy/server/test_api.py Outdated
Comment thread tests/debugpy/server/test_api.py Outdated
Comment thread src/debugpy/server/api.py Outdated
@heejaechang

Copy link
Copy Markdown
Contributor

Overall the added typing and the _settrace success-latching fix look good. Two things to resolve before merge: (1) tighten the new/changed test assertions to exact-match per the repo's partial-assert rule, and (2) confirm the intended contract for the new configure() "already running" guard, since _settrace.called is a process-global latch that is never cleared.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/debugpy/launcher/output.py Outdated

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/debugpy/adapter/components.py Outdated
Comment thread src/debugpy/common/log.py
…numeration

- components.py: cast to the TypeVar T instead of the runtime 	ype parameter (reportInvalidTypeForm).
- log.py: extend the protocol/guard to require both name and version so pkg.version is valid.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/debugpy/common/messaging.py Outdated
@heejaechang

Copy link
Copy Markdown
Contributor

GitHub cannot anchor PR review comments to unchanged lines in the diff. Falling back to a general PR comment for src/debugpy/common/messaging.py:L726.

📍 src/debugpy/common/messaging.py:726
Response._parse can pass its default body=None for a successful response without a body, but Response.__init__ now accepts only MessageDict | Exception. Model empty successful responses in this contract (or normalize them) so standard type checking passes and matches the runtime behavior.

…l__ and Response

- Message.__call__ now raises exception payloads explicitly instead of relying on
  an assert, so behavior is consistent when assertions are stripped under python -O.
- Request.respond normalizes a None body for successful empty responses to an empty
  payload, so Response.body is always a MessageDict or Exception (fixes standard
  type checking and matches how incoming empty responses are parsed).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rchiodo

rchiodo commented Jul 20, 2026

Copy link
Copy Markdown
Contributor Author

Fixed in d9532bb (re: src/debugpy/common/messaging.py:726, empty successful responses). Request.respond now normalizes a None body for a successful no-body response into an empty payload (_payload(None)) before constructing the Response, so Response.body is always a MessageDict or an Exception. This makes standard type checking pass (Response.init keeps its MessageDict | Exception contract) and matches how incoming empty responses are already parsed (Response._parse fills a missing body with an empty dict), so the outgoing and incoming paths are now consistent. The emitted JSON is unchanged — an empty/None body is still omitted from the wire message.

Comment thread src/debugpy/adapter/clients.py

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

The configurationDone_request guard was changed from a silently ineffective
request.cant_handle(...) into a fail-fast raise. Add targeted coverage for
receiving configurationDone before a start request and after startup has
already begun, verifying a failure response is sent and startup side effects
do not run.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/debugpy/adapter/clients.py

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

…ards

The _start_message_handler handle() only ever receives launch/attach
requests (enforced by the assert on entry). Typing it as messaging.Message
forced isinstance(request, messaging.Request) fallbacks that, with
assertions disabled (python -O), could let a non-request message skip
initialization/response and leave the client waiting. Type the parameter
as messaging.Request and remove the now-redundant guards.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread src/debugpy/server/api.py Outdated

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

sock_io.read() returns b'' at EOF, not None, so the previous is None
guard never fired and an empty adapter handshake fell through to
json.loads producing a JSONDecodeError. Use a non-shadowing name and
check
ot data.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

@heejaechang heejaechang left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved via Review Center.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants