Skip to content

[gdb] Complete stubs for gdb.dap #14269

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions stubs/gdb/@tests/stubtest_allowlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,3 @@ gdb.Progspace.xmethods

# stubtest thinks this can't be sub-classed at runtime, but it is
gdb.disassembler.DisassemblerPart

# incomplete modules
gdb\.dap\.[a-z_]+\.[A-Za-z_]+
10 changes: 8 additions & 2 deletions stubs/gdb/gdb/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import threading
from _typeshed import Incomplete
from collections.abc import Callable, Iterator, Mapping, Sequence
from contextlib import AbstractContextManager
from typing import Any, Final, Generic, Literal, Protocol, TypeVar, final, overload, type_check_only
from typing import Any, Final, Generic, Literal, Protocol, TypedDict, TypeVar, final, overload, type_check_only
from typing_extensions import TypeAlias, deprecated

import gdb.FrameDecorator
Expand Down Expand Up @@ -860,10 +860,16 @@ class LazyString:

# Architectures

@type_check_only
class _Instruction(TypedDict):
addr: int
asm: str
length: int

@final
class Architecture:
def name(self) -> str: ...
def disassemble(self, start_pc: int, end_pc: int = ..., count: int = ...) -> list[dict[str, object]]: ...
def disassemble(self, start_pc: int, end_pc: int = ..., count: int = ...) -> list[_Instruction]: ...
def integer_type(self, size: int, signed: bool = ...) -> Type: ...
def registers(self, reggroup: str = ...) -> RegisterDescriptorIterator: ...
def register_groups(self) -> RegisterGroupsIterator: ...
Expand Down
24 changes: 16 additions & 8 deletions stubs/gdb/gdb/dap/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
from typing import Any

class Server:
def __init__(self, in_stream, out_stream, child_stream) -> None: ...
def main_loop(self) -> None: ...
def send_event(self, event: str, body: Any | None = None) -> None: ... # body is an arbitrary object
def send_event_later(self, event: str, body: Any | None = None) -> None: ... # body is an arbitrary object
def shutdown(self) -> None: ...
from . import (
breakpoint as breakpoint,
bt as bt,
evaluate as evaluate,
launch as launch,
locations as locations,
memory as memory,
modules as modules,
next as next,
pause as pause,
scopes as scopes,
sources as sources,
startup as startup,
threads as threads,
)
from .server import Server as Server

def pre_command_loop() -> None: ...
def run() -> None: ...
Expand Down
50 changes: 49 additions & 1 deletion stubs/gdb/gdb/dap/breakpoint.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,49 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Incomplete, Unused
from collections.abc import Sequence
from contextlib import AbstractContextManager
from typing import TypedDict, type_check_only
from typing_extensions import NotRequired

import gdb

from .sources import Source

@type_check_only
class _SourceBreakpoint(TypedDict):
source: str
line: int
condition: NotRequired[str | None]
hitCondition: NotRequired[str | None]
logMessage: NotRequired[str | None]

@type_check_only
class _ExceptionFilterOptions(TypedDict):
filderId: str
condition: NotRequired[str | None]

@type_check_only
class _BreakpointDescriptor(TypedDict):
id: int
verified: bool
reason: NotRequired[str] # only present when verified is False. Possibly only literal "pending" or "failed"
message: NotRequired[str] # only present when reason == "failed"
source: NotRequired[Source]
line: NotRequired[int]
instructionReference: NotRequired[str]

@type_check_only
class _SetBreakpointResult(TypedDict):
breakpoints: list[_BreakpointDescriptor]

# frozenset entries are tuples from _SourceBreakpoint.items() or _ExceptionFilterOptions.items()
breakpoint_map: dict[str, dict[frozenset[Incomplete], gdb.Breakpoint]]

def suppress_new_breakpoint_event() -> AbstractContextManager[None]: ...
def set_breakpoint(*, source: Source, breakpoints: Sequence[_SourceBreakpoint] = (), **args: Unused) -> _SetBreakpointResult: ...
def set_fn_breakpoint(*, breakpoints: Sequence[_SourceBreakpoint], **args: Unused) -> _SetBreakpointResult: ...
def set_insn_breakpoints(
*, breakpoints: Sequence[_SourceBreakpoint], offset: int | None = None, **args: Unused
) -> _SetBreakpointResult: ...
def set_exception_breakpoints(
*, filters: Sequence[str], filterOptions: Sequence[_ExceptionFilterOptions] = (), **args: Unused
) -> _SetBreakpointResult: ...
50 changes: 49 additions & 1 deletion stubs/gdb/gdb/dap/bt.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,49 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import TypedDict, type_check_only
from typing_extensions import NotRequired

from .sources import Source
from .varref import _ValueFormat

@type_check_only
class _StackFrameFormat(_ValueFormat, total=False):
parameters: bool
parameterTypes: bool
parameterNames: bool
parameterValues: bool
line: bool
module: bool
includeAll: bool

@type_check_only
class _StackFrame(TypedDict):
id: int
name: str
line: int
column: int
instructionPointerReference: str
moduleId: NotRequired[str | None]
source: NotRequired[Source]

@type_check_only
class _StackTraceResult(TypedDict):
stackFrames: list[_StackFrame]

def check_stack_frame(
*,
# From source:
# Note that StackFrameFormat extends ValueFormat, which is why
# "hex" appears here.
hex: bool = False,
parameters: bool = False,
parameterTypes: bool = False,
parameterNames: bool = False,
parameterValues: bool = False,
line: bool = False,
module: bool = False,
includeAll: bool = False,
**rest: Unused,
) -> _StackFrameFormat: ...
def stacktrace(
*, levels: int = 0, startFrame: int = 0, threadId: int, format: _StackFrameFormat | None = None, **extra: Unused
) -> _StackTraceResult: ...
23 changes: 22 additions & 1 deletion stubs/gdb/gdb/dap/disassemble.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,22 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import TypedDict, type_check_only
from typing_extensions import NotRequired

from .sources import Source

@type_check_only
class _Instruction(TypedDict):
address: str
instruction: str
instructionBytes: str
symbol: NotRequired[str] # only set if there's a corresponding label
line: NotRequired[int] # only set if source is available
location: NotRequired[Source] # only set if source is available

@type_check_only
class _DisassembleResult(TypedDict):
instructions: list[_Instruction]

def disassemble(
*, memoryReference: str, offset: int = 0, instructionOffset: int = 0, instructionCount: int, **extra: Unused
) -> _DisassembleResult: ...
32 changes: 31 additions & 1 deletion stubs/gdb/gdb/dap/evaluate.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,31 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import Literal, TypedDict, type_check_only

import gdb

from .varref import VariableReference, _ValueFormat, _VariableReferenceDescriptor

class EvaluateResult(VariableReference):
def __init__(self, value: gdb.Value) -> None: ...

@type_check_only
class _VariablesResult(TypedDict):
variables: list[_VariableReferenceDescriptor]

def eval_request(
*,
expression: str,
frameId: int | None = None,
context: Literal["watch", "variables", "hover", "repl"] = "variables",
format: _ValueFormat | None = None,
**args: Unused,
) -> _VariableReferenceDescriptor: ...
def variables(
*, variablesReference: int, start: int = 0, count: int = 0, format: _ValueFormat | None = None, **args: Unused
) -> _VariablesResult: ...
def set_expression(
*, expression: str, value: str, frameId: int | None = None, format: _ValueFormat | None = None, **args: Unused
) -> _VariableReferenceDescriptor: ...
def set_variable(
*, variablesReference: int, name: str, value: str, format: _ValueFormat | None = None, **args: Unused
) -> _VariableReferenceDescriptor: ...
13 changes: 12 additions & 1 deletion stubs/gdb/gdb/dap/events.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,12 @@
def __getattr__(name: str): ... # incomplete module
import gdb

inferior_running: bool

def send_process_event_once() -> None: ...
def expect_process(reason: str) -> None: ...
def thread_event(event: gdb.ThreadEvent, reason: str) -> None: ...
def expect_stop(reason: str) -> None: ...
def exec_and_expect_stop(cmd: str, expected_pause: bool = False) -> None: ...

# Map from gdb stop reasons to DAP stop reasons.
stop_reason_map: dict[str, str]
8 changes: 7 additions & 1 deletion stubs/gdb/gdb/dap/frames.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,7 @@
def __getattr__(name: str): ... # incomplete module
from collections.abc import Generator

import gdb

def frame_for_id(id: int) -> gdb.Frame: ...
def select_frame(id: int) -> None: ...
def dap_frame_generator(frame_low: int, levels: int, include_all: bool) -> Generator[tuple[int, gdb.Frame]]: ...
17 changes: 16 additions & 1 deletion stubs/gdb/gdb/dap/io.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import SupportsFlush, SupportsRead, SupportsReadline, SupportsWrite
from typing import Any, type_check_only

import gdb

from .server import _JSONValue
from .startup import DAPQueue

@type_check_only
class _SupportsReadAndReadlineBytes(SupportsRead[bytes], SupportsReadline[bytes]): ...

@type_check_only
class _SupportsWriteAndFlushBytes(SupportsWrite[bytes], SupportsFlush): ...

def read_json(stream: _SupportsReadAndReadlineBytes) -> Any: ... # returns result of json.loads
def start_json_writer(stream: _SupportsWriteAndFlushBytes, queue: DAPQueue[_JSONValue]) -> gdb.Thread: ...
15 changes: 14 additions & 1 deletion stubs/gdb/gdb/dap/launch.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from collections.abc import Mapping, Sequence

def launch(
*,
program: str | None = None,
cwd: str | None = None,
args: Sequence[str] = (),
env: Mapping[str, str] | None = None,
stopAtBeginningOfMainSubprogram: bool = False,
**extra: Unused,
): ...
def attach(*, program: str | None = None, pid: int | None = None, target: str | None = None, **args: Unused) -> None: ...
def config_done(**args: Unused) -> None: ...
17 changes: 16 additions & 1 deletion stubs/gdb/gdb/dap/locations.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,16 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import TypedDict, type_check_only

from .sources import Source

@type_check_only
class _Line(TypedDict):
line: int

@type_check_only
class _BreakpointLocationsResult(TypedDict):
breakpoints: list[_Line]

def breakpoint_locations(
*, source: Source, line: int, endLine: int | None = None, **extra: Unused
) -> _BreakpointLocationsResult: ...
11 changes: 10 additions & 1 deletion stubs/gdb/gdb/dap/memory.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import TypedDict, type_check_only

@type_check_only
class _ReadMemoryResult(TypedDict):
address: str
data: str

def read_memory(*, memoryReference: str, offset: int = 0, count: int, **extra: Unused) -> _ReadMemoryResult: ...
def write_memory(*, memoryReference: str, offset: int = 0, data: str, **extra: Unused): ...
22 changes: 21 additions & 1 deletion stubs/gdb/gdb/dap/modules.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,21 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import TypedDict, type_check_only
from typing_extensions import NotRequired

import gdb

@type_check_only
class _Module(TypedDict):
id: str | None
name: str | None
path: NotRequired[str | None]

@type_check_only
class _ModulesResult(TypedDict):
modules: list[_Module]
totalModules: int

def module_id(objfile: gdb.Objfile) -> str | None: ...
def is_module(objfile: gdb.Objfile) -> bool: ...
def make_module(objf: gdb.Objfile) -> _Module: ...
def modules(*, startModule: int = 0, moduleCount: int = 0, **args: Unused) -> _ModulesResult: ...
15 changes: 14 additions & 1 deletion stubs/gdb/gdb/dap/next.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,14 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused
from typing import Literal, TypedDict, type_check_only
from typing_extensions import TypeAlias

@type_check_only
class _ContinueRequestResult(TypedDict):
allThreadsContinued: bool

_Granularity: TypeAlias = Literal["statement", "instruction"]

def next(*, threadId: int, singleThread: bool = False, granularity: _Granularity = "statement", **args: Unused) -> None: ...
def step_in(*, threadId: int, singleThread: bool = False, granularity: _Granularity = "statement", **args: Unused) -> None: ...
def step_out(*, threadId: int, singleThread: bool = False, **args: Unused): ...
def continue_request(*, threadId: int, singleThread: bool = False, **args: Unused) -> _ContinueRequestResult: ...
4 changes: 3 additions & 1 deletion stubs/gdb/gdb/dap/pause.pyi
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
def __getattr__(name: str): ... # incomplete module
from _typeshed import Unused

def pause(**args: Unused) -> None: ...
Loading
Loading