Skip to content
Open
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
29 changes: 20 additions & 9 deletions cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,9 +204,23 @@ Blocks until the program hits a breakpoint or exits, then returns auto-context.`
dap debug app.py -- --config prod.yaml --verbose
dap debug --attach localhost:5678 --backend debugpy --break handler.py:15
dap debug --pid 12345 --backend debugpy # attach to running process`,
Args: cobra.MaximumNArgs(1),
Args: func(cmd *cobra.Command, args []string) error {
scriptArgs := args
if dashIdx := cmd.ArgsLenAtDash(); dashIdx >= 0 && dashIdx <= len(args) {
scriptArgs = args[:dashIdx]
}
if len(scriptArgs) > 1 {
return fmt.Errorf("accepts at most 1 arg(s), received %d", len(scriptArgs))
}
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 && attach == "" && pid == 0 {
scriptArgs := args
if dashIdx := cmd.ArgsLenAtDash(); dashIdx >= 0 && dashIdx <= len(args) {
scriptArgs = args[:dashIdx]
}

if len(scriptArgs) == 0 && attach == "" && pid == 0 {
return fmt.Errorf("script path, --attach, or --pid required")
}

Expand All @@ -224,16 +238,13 @@ Blocks until the program hits a breakpoint or exits, then returns auto-context.`
ExceptionFilters: exceptionFilters,
ContextLines: globalFlags.contextLines,
}
if len(args) > 0 {
debugArgs.Script = args[0]
if len(scriptArgs) > 0 {
debugArgs.Script = scriptArgs[0]
}

// Capture program args after --
if dashIdx := cmd.ArgsLenAtDash(); dashIdx >= 0 {
allArgs := cmd.Flags().Args()
if dashIdx < len(allArgs) {
debugArgs.ProgramArgs = allArgs[dashIdx:]
}
if dashIdx := cmd.ArgsLenAtDash(); dashIdx >= 0 && dashIdx < len(args) {
debugArgs.ProgramArgs = append([]string(nil), args[dashIdx:]...)
}

rawArgs, _ := json.Marshal(debugArgs)
Expand Down
42 changes: 42 additions & 0 deletions e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,48 @@ func TestE2E_JSONOutput(t *testing.T) {
}
}

func TestE2E_DebugPython_WithProgramArgs(t *testing.T) {
if err := exec.Command("python3", "-c", "import debugpy").Run(); err != nil {
t.Skip("debugpy not installed")
}

env := newE2EEnv(t)

scriptDir := t.TempDir()
scriptPath := filepath.Join(scriptDir, "args.py")
script := `import argparse

p = argparse.ArgumentParser()
p.add_argument("value")
args = p.parse_args()
value = args.value
print(value)
`
if err := os.WriteFile(scriptPath, []byte(script), 0o644); err != nil {
t.Fatalf("writing script: %v", err)
}

cmd := exec.Command(env.binary,
"--socket", env.socketPath,
"debug", scriptPath,
"--break", scriptPath+":6",
"--",
"example-value",
)
cmd.Dir = projectRoot(t)
out, err := cmd.CombinedOutput()
if err != nil {
t.Fatalf("debug with program args failed: %v\n%s", err, out)
}

if !strings.Contains(string(out), "Stopped: breakpoint") {
t.Errorf("expected breakpoint stop, got:\n%s", out)
}
if !strings.Contains(string(out), "value (str) = 'example-value'") {
t.Errorf("expected parsed CLI arg in locals, got:\n%s", out)
}
Comment on lines +221 to +239
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Breakpoint before assignment 🐞 Bug ✓ Correctness

TestE2E_DebugPython_WithProgramArgs sets a breakpoint on the same line where value is assigned,
but then asserts value is present in locals at the breakpoint stop; locals are collected at the
stop location before executing the current line, so value will not exist yet.
Agent Prompt
### Issue description
`TestE2E_DebugPython_WithProgramArgs` breaks on the `value = args.value` line and then asserts `value` exists in locals. At a line breakpoint, execution typically stops before that assignment runs, so `value` won’t be in locals.

### Issue Context
The test intends to verify that arguments after `--` are forwarded to the debugged program and observable in debugger context.

### Fix Focus Areas
- e2e_test.go[200-239]

### Suggested fix
Change the breakpoint to the next line (the `print(value)` line) so `value` is assigned before locals are collected, e.g. change `--break scriptPath+":6"` to `--break scriptPath+":7"`. Alternatively, keep the breakpoint at `:6` but add a subsequent `step` command and assert on that output instead.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

}

// TestE2E_DebugPython_Scheduler exercises cross-file breakpoints across a
// multifile Python app: main.py → runner.py → resolver.py.
func TestE2E_DebugPython_Scheduler(t *testing.T) {
Expand Down