Skip to content

Commit c50b2a1

Browse files
committed
Add test and fix trepan.api
1 parent 4591168 commit c50b2a1

3 files changed

Lines changed: 67 additions & 47 deletions

File tree

test/unit/lib/test_lib_thread.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import sys
44
import threading
55

6+
import pytest
7+
68
from trepan.lib.thred import (
79
current_thread_name,
810
find_debugged_frame,
@@ -21,8 +23,6 @@ def run(self):
2123
self.id_name_checker()
2224
return
2325

24-
pass
25-
2626

2727
def id_name_checker():
2828
"""Helper for testing map_thread_names and id2thread"""
@@ -35,17 +35,17 @@ def id_name_checker():
3535

3636

3737
def test_current_thread_name():
38-
assert "MainThread", current_thread_name()
39-
return
38+
"""Test trepan.lib.thred.current_thread_name"""
39+
assert "MainThread" == current_thread_name()
4040

4141

42+
@pytest.mark.skip(reason="Fix have an intermittent failure")
4243
def test_id2thread_name():
43-
"""Test ``map_thread_names`` and ``id2thread``. """
44+
"""Test ``map_thread_names`` and ``id2thread``."""
4445
thread_id = _thread.get_ident()
4546
assert "MainThread" == id2thread_name(thread_id)
4647
id_name_checker()
4748

4849
background = BgThread(id_name_checker)
4950
background.start()
5051
background.join() # Wait for the background task to finish
51-
return

trepan/api.py

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
# we see below. So for now, we'll live with the code duplication.
3636

3737
import sys
38+
from typing import Callable, Optional
3839

3940
from trepan.debugger import Trepan, debugger_obj
4041
from trepan.post_mortem import post_mortem_excepthook, uncaught_exception
@@ -48,11 +49,11 @@ def debugger_on_post_mortem():
4849

4950
def run_eval(
5051
expression,
51-
debug_opts=None,
52-
start_opts=None,
53-
globals_=None,
54-
locals_=None,
55-
tb_fn=None,
52+
debug_opts: Optional[dict] = None,
53+
start_opts: Optional[dict] = None,
54+
globals_: Optional[dict] = None,
55+
locals_: Optional[dict] = None,
56+
tb_fn: Optional[Callable] = None,
5657
):
5758
"""Evaluate the expression (given as a string) under debugger
5859
control starting with the statement after the place that
@@ -79,7 +80,13 @@ def run_eval(
7980
return
8081

8182

82-
def run_call(func, *args, **kwds):
83+
def run_call(
84+
func: Callable,
85+
*args,
86+
debug_opts: Optional[dict] = None,
87+
start_opts: Optional[dict] = None,
88+
**kwds,
89+
):
8390
"""Call the function (a function or method object, not a string)
8491
with the given arguments starting with the statement after
8592
the place that this appears in your program.
@@ -88,7 +95,7 @@ def run_call(func, *args, **kwds):
8895
returned. The debugger prompt appears as soon as the function is
8996
entered."""
9097

91-
dbg = Trepan()
98+
dbg = Trepan(opts=debug_opts)
9299
try:
93100
return dbg.run_call(func, *args, **kwds)
94101
except Exception:
@@ -278,26 +285,41 @@ def stop(opts=None):
278285
if __name__ == "__main__":
279286
import tracer
280287

281-
def foo(n):
282-
y = n
283-
for i in range(n):
284-
print(i)
285-
pass
286-
return y
288+
def plus5(n: int) -> int:
289+
return n + 5
287290

291+
from trepan.inout.stringarray import StringArrayInput, StringArrayOutput
288292
from trepan.lib.default import DEBUGGER_SETTINGS
289293

290294
settings = dict(DEBUGGER_SETTINGS)
291295
settings.update({"trace": True, "printset": tracer.ALL_EVENTS})
292-
debug_opts = {"step_ignore": -1, "settings": settings}
296+
debugger_input = StringArrayInput()
297+
debugger_output = StringArrayOutput()
298+
debug_opts = {
299+
"step_ignore": -1,
300+
"settings": settings,
301+
"input": debugger_input,
302+
"output": debugger_output,
303+
}
293304
print('Issuing: run_eval("1+2")')
294-
print(run_eval("1+2", debug_opts=debug_opts))
295-
print('Issuing: run_exec("x=1; y=2")')
296-
run_exec("x=1; y=2", debug_opts=debug_opts)
297-
print("Issuing: run_call(foo, debug_opts, None, 2)")
305+
run_eval("1+2", debug_opts=debug_opts)
306+
print(debugger_output.output)
307+
# print('Issuing: run_exec("x=1; y=2")')
308+
# run_exec("x=1; y=2", debug_opts=debug_opts)
309+
debugger_input = StringArrayInput(["step", "list", "continue"])
310+
debugger_output = StringArrayOutput()
311+
debug_opts = {
312+
"step_ignore": -1,
313+
"settings": settings,
314+
"input": debugger_input,
315+
"output": debugger_output,
316+
}
298317
if len(sys.argv) > 1:
299-
print(f"Issuing interactive: run_call(foo, {debug_opts}, None, {sys.argv[1]})")
300-
run_call(foo, debug_opts, int(sys.argv[1]))
318+
print(
319+
f"Issuing interactive: run_call(plus5, {int(sys.argv[1])}, debug_opts={debug_opts})"
320+
)
321+
run_call(plus5, int(sys.argv[1]), debug_opts=debug_opts)
301322
else:
302-
run_call(foo, debug_opts, 2)
323+
print(f"Issuing interactive: run_call(plus5, 2, debug_opts={debug_opts})")
324+
run_call(plus5, 2, debug_opts=debug_opts)
303325
pass

trepan/debugger.py

Lines changed: 18 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# -*- coding: utf-8 -*-
22
#
3-
# Copyright (C) 2008-2010, 2013-2015, 2018, 2023 Rocky Bernstein
4-
# <rocky@gnu.org>
3+
# Copyright (C) 2008-2010, 2013-2015, 2018, 2023-2024
4+
# Rocky Bernstein <rocky@gnu.org>
55
#
66
# This program is free software: you can redistribute it and/or modify
77
# it under the terms of the GNU General Public License as published by
@@ -29,26 +29,23 @@
2929
user or client-side code for connecting to server'd debugged program.
3030
"""
3131

32-
# Our local modules
33-
34-
# Common Python packages
3532
import sys
3633
import types
34+
from typing import Any, Callable
3735

3836
import pyficache
3937
import tracefilter
4038

4139
# External Egg packages
4240
import tracer
4341

44-
import trepan
4542
import trepan.interfaces.user as Muser
4643

4744
# Default settings used here
4845
import trepan.lib.default as Mdefault
4946
import trepan.lib.sighandler as Msig
50-
5147
from trepan.exception import DebuggerQuit, DebuggerRestart
48+
from trepan.lib.core import TrepanCore
5249
from trepan.misc import option_set
5350

5451
debugger_obj = None
@@ -138,7 +135,7 @@ def run_exec(self, cmd, start_opts=None, globals_=None, locals_=None):
138135
self.core.stop()
139136
return
140137

141-
def run_call(self, func, start_opts=None, *args, **kwds):
138+
def run_call(self, func: Callable, *args, start_opts=None, **kwds):
142139
"""Run debugger on function call: `func(*args, **kwds)'
143140
144141
See also `run_eval' if what you want to run is an eval'able
@@ -221,7 +218,7 @@ def run_script(self, filename, start_opts=None, globals_=None, locals_=None):
221218
try:
222219
compiled = compile(open(self.mainpyfile).read(), self.mainpyfile, "exec")
223220
except SyntaxError:
224-
self.intf[0].errmsg("Python can't compile %s" % self.mainpyfile)
221+
self.intf[0].errmsg(f"Python can't compile {self.mainpyfile}")
225222
self.intf[0].errmsg(sys.exc_info()[1])
226223
retval = False
227224
pass
@@ -293,13 +290,15 @@ def __init__(self, opts=None):
293290
See also Debugger.start and Debugger.stop.
294291
"""
295292

296-
import trepan.lib.core as Mcore
297-
298293
self.mainpyfile = None
299294
self.thread = None
300295
self.eval_string = None
301-
get_option = lambda key: option_set(opts, key, self.DEFAULT_INIT_OPTS)
302-
completer = lambda text, state: self.complete(text, state)
296+
297+
def get_option(key: str) -> Any:
298+
return option_set(opts, key, self.DEFAULT_INIT_OPTS)
299+
300+
def completer(text: str, state):
301+
return self.complete(text, state)
303302

304303
# set the instance variables that come directly from options.
305304
for opt in ("settings", "orig_sys_argv", "from_ipython"):
@@ -324,20 +323,19 @@ def __init__(self, opts=None):
324323
"debugger_name": "trepan3k",
325324
}
326325
# FIXME when I pass in opts=opts things break
327-
interface = get_option("interface") or Muser.UserInterface(opts=interface_opts)
328-
self.intf = [interface]
329326

330-
inp = get_option("input")
331-
if inp:
332-
self.intf[-1].input = inp
333-
pass
327+
inp = opts.get("input", None) if opts else None
328+
interface = get_option("interface") or Muser.UserInterface(
329+
inp=inp, opts=interface_opts
330+
)
331+
self.intf = [interface]
334332

335333
out = get_option("output")
336334
if out:
337335
self.intf[-1].output = out
338336
pass
339337

340-
self.core = trepan.lib.core.TrepanCore(self, core_opts)
338+
self.core = TrepanCore(self, core_opts)
341339
self.core.add_ignore(self.core.stop)
342340

343341
# When set True, we'll also suspend our debug-hook tracing.

0 commit comments

Comments
 (0)