[Python-checkins] r47111 - in sandbox/trunk/pdb: mconnection.py mpdb.py mthread.py test/test_mconnection.py test/test_mpdb.py test/thread_script.py
matt.fleming
python-checkins at python.org
Tue Jun 27 00:08:11 CEST 2006
Author: matt.fleming
Date: Tue Jun 27 00:08:11 2006
New Revision: 47111
Added:
sandbox/trunk/pdb/test/thread_script.py
Modified:
sandbox/trunk/pdb/mconnection.py
sandbox/trunk/pdb/mpdb.py
sandbox/trunk/pdb/mthread.py
sandbox/trunk/pdb/test/test_mconnection.py
sandbox/trunk/pdb/test/test_mpdb.py
Log:
start implementing the thread command and of course, unit tests ;-)
Modified: sandbox/trunk/pdb/mconnection.py
==============================================================================
--- sandbox/trunk/pdb/mconnection.py (original)
+++ sandbox/trunk/pdb/mconnection.py Tue Jun 27 00:08:11 2006
@@ -57,8 +57,8 @@
"""
self._dev = device
try:
- self.output = open(self._dev, 'w')
self.input = open(self._dev, 'r')
+ self.output = open(self._dev, 'w')
except IOError,e:
# Use e[1] for more detail about why the connection failed
raise ConnectionFailed, e[1]
Modified: sandbox/trunk/pdb/mpdb.py
==============================================================================
--- sandbox/trunk/pdb/mpdb.py (original)
+++ sandbox/trunk/pdb/mpdb.py Tue Jun 27 00:08:11 2006
@@ -53,6 +53,7 @@
self.waiter = threading.Event()
self.tracers = []
self.threads = []
+ self.current_thread = threading.currentThread()
self._info_cmds.append('target')
def _rebind_input(self, new_input):
@@ -151,12 +152,10 @@
return # Thread not being traced
self.threads.append(threading.currentThread())
- self.msg('New thread: %s' % self.threads[-1].getName())
- m = MTracer(self.stdout)
+ self.msg('New thread: %s' % self.threads[-1])
+ m = MTracer(self.breaks, self.stdout)
self.tracers.append(m)
sys.settrace(m.trace_dispatch)
-
-
# Debugger commands
def do_attach(self, addr):
@@ -232,7 +231,7 @@
self.errmsg('Unknown target type')
return
self.connection = eval(target+'()')
- try:
+ try:
self.connection.connect(addr)
except ConnectionFailed, err:
self.errmsg("Failed to connect to %s: (%s)" % (addr, err))
@@ -324,6 +323,39 @@
self._rebind_input(self.connection)
self._rebind_output(self.connection)
+ def do_thread(self, arg):
+ """Use this command to switch between threads.
+The new thread ID must be currently known.
+
+List of thread subcommands:
+
+thread apply -- Apply a command to a thread
+
+Type "help thread" followed by thread subcommand name for full documentation.
+Command name abbreviations are allowed if unambiguous.
+"""
+ args = arg.split()
+ if len(args) == 0:
+ self.msg('Current thread is %s' % self.current_thread)
+ return
+ if 'apply'.startswith(args[0]):
+ if len(args) < 2:
+ self.errmsg('Please specify a thread ID')
+ return
+ if len(args) < 3:
+ self.errmsg('Please specify a command following the thread' \
+ + ' ID')
+ return
+ # These should always be in sync
+ if len(self.threads) == 0:
+ self.errmsg('No threads')
+ return
+ t = self.threads[int(args[1])-1]
+ t_tracer = self.tracers[int(args[1])-1]
+ func = args[2]
+ cmd = eval('t.' + func)
+ result = cmd(args[3:])
+
def pdbserver(addr):
""" This method sets up a pdbserver debugger that allows debuggers
to connect to 'address' using 'protocol'. The argument 'filename'
Modified: sandbox/trunk/pdb/mthread.py
==============================================================================
--- sandbox/trunk/pdb/mthread.py (original)
+++ sandbox/trunk/pdb/mthread.py Tue Jun 27 00:08:11 2006
@@ -1,18 +1,60 @@
""" This file contains all code for allowing the debugging of threads. """
+from bdb import Breakpoint
+import os
import sys
import threading
class MTracer(object):
- """ A class to trace a thread. """
- def __init__(self, stdout=None):
+ """ A class to trace a thread. Breakpoints can be passed from
+ a main debugger to this debugger through the constructor
+ which is useful, for instance, if a breakpoint occurs inside
+ a thread's run() method.
+ """
+ def __init__(self, breaks=None, stdout=None):
self.thread = threading.currentThread()
- # No other thread can be debugged whilst this is set
- # (including the MainThread)
if stdout is None:
stdout = sys.stdout
self.out = stdout
+ # Each tracer instance must keep track of its own breakpoints
+ if breaks is None:
+ breaks = {}
+ self.breaks = breaks
+ self.fncache = {}
+
+ def canonic(self, filename):
+ if filename == "<" + filename[1:-1] + ">":
+ return filename
+ canonic = self.fncache.get(filename)
+ if not canonic:
+ canonic = os.path.abspath(filename)
+ canonic = os.path.normcase(canonic)
+ self.fncache[filename] = canonic
+ return canonic
+
+ def info(self, arg):
+ args = arg.split()
+ if 'break'.startswith(args[0]):
+ return self.breaks
+
+ def _get_break(self, filename, lineno):
+ """ Return the breakpoint at [filename:]lineno. """
+ filename = self.canonic(filename)
+ return filename in self.breaks and \
+ lineno in self.breaks[filename]
+
+ def _get_breaks(self, filename, lineno):
+ """ Return all the breakpoints set in this thread. """
+ filename = self.canonic(filename)
+ return filename in self.breaks and \
+ lineno in self.breaks[filename] and \
+ Breakpoint.bplist[filename, lineno] or []
+ def _set_break(self, filename, lineno, temporary=0, cond = None,
+ funcname=None):
+ """ Set a breakpoint in this thread. """
+ pass
+
def trace_dispatch(self, frame, event, arg):
if event == 'line':
print >> self.out, self.thread.getName(),'*** line'
Modified: sandbox/trunk/pdb/test/test_mconnection.py
==============================================================================
--- sandbox/trunk/pdb/test/test_mconnection.py (original)
+++ sandbox/trunk/pdb/test/test_mconnection.py Tue Jun 27 00:08:11 2006
@@ -57,6 +57,7 @@
def testDisconnectDisconnected(self):
"""(tcp) Disconnect a disconnected session. """
s = MConnectionServerTCP()
+
s.disconnect()
s.disconnect()
@@ -142,6 +143,12 @@
line = self.server.readline()
self.assertEquals('', line, 'Could not read third line.')
+ def testInvalidFilename(self):
+ """(serial) Connect to an invalid server. """
+ client = MConnectionSerial()
+ self.assertRaises(ConnectionFailed, client.connect,
+ '/dev/pleasepleasepleasedontexit')
+
def tearDown(self):
self.server.disconnect()
self.client.disconnect()
Modified: sandbox/trunk/pdb/test/test_mpdb.py
==============================================================================
--- sandbox/trunk/pdb/test/test_mpdb.py (original)
+++ sandbox/trunk/pdb/test/test_mpdb.py Tue Jun 27 00:08:11 2006
@@ -40,6 +40,7 @@
def __init__(self):
MPdb.__init__(self)
self.lines = []
+ self.botframe = None
def msg_nocr(self, msg):
self.lines.append(msg)
@@ -70,7 +71,6 @@
line = self.server2.lines[0]
self.assertEquals('*** Unknown protocol\n', line)
-
def testTarget(self):
""" Test the target command. """
server = MConnectionServerTCP()
@@ -80,13 +80,25 @@
connect_to_target(self.client1)
self.client2 = MPdbTest()
-
self.client2.do_target('dlkdlksldkslkd')
line = self.client2.lines[0]
self.assertEquals('*** Invalid arguments\n', line)
+ # Hope there's nothing running on this port
+ self.client2.do_target('tcp localhost:9000')
+ line = self.client2.lines[1]
+ errmsg = '*** Failed to connect to localhost:9000: (Connection' \
+ + ' refused)\n'
+ self.assertEquals(errmsg, line)
+
+ addr = 'serial /dev/hopefullythisdevicenamedoesntexist'
+ self.client2.do_target(addr)
+ line = self.client2.lines[2]
+ errmsg = '*** Failed to connect to ' \
+ + '/dev/hopefullythisdevicenamedoesntexist:' \
+ + ' (No such file or directory)\n'
- self.client3 = MPdbTest()
+ self.assertEquals(errmsg, line)
server.disconnect()
@@ -102,7 +114,6 @@
line = f.readline()
f.close()
self.assertEquals('some text\n', line, 'Could not rebind output')
-
def testRebindInput(self):
""" Test rebinding input. """
@@ -116,13 +127,39 @@
self.server._rebind_input(f)
line = self.server.stdin.readline()
+ f.close()
self.assertEquals(line, 'help', 'Could not rebind input.')
- def testTargetRoutine(self):
- """ Test that the top-level target routine works properly. """
- #invalid_address = 'tcp ::::::'
- pass
+ def testThread(self):
+ """ Test the thread command. """
+ server = MConnectionServerTCP()
+ thread.start_new_thread(server.connect, (__addr__,))
+
+ self.client1 = MPdbTest()
+ connect_to_target(self.client1)
+ # Thread with no commands should return current thread
+ self.client1.onecmd('thread')
+ assert 'MainThread' in self.client1.lines[0]
+
+ # 'thread apply' without thread ID should return an error message
+ self.client1.onecmd('thread apply')
+ line = self.client1.lines[1]
+ self.assertEquals('*** Please specify a thread ID\n', line)
+
+ # Need a command to actually apply to a thread
+ self.client1.onecmd('thread apply 49843')
+ line = self.client1.lines[2]
+ errmsg = '*** Please specify a command following the thread ID\n'
+ self.assertEquals(errmsg, line)
+
+ # We've still not started any threads
+ self.client1.onecmd('thread apply 2 info break')
+ line = self.client1.lines[3]
+ errmsg = '*** No threads\n'
+ self.assertEquals(errmsg, line)
+
+ server.disconnect()
def test_main():
test_support.run_unittest(TestRemoteDebugging)
Added: sandbox/trunk/pdb/test/thread_script.py
==============================================================================
--- (empty file)
+++ sandbox/trunk/pdb/test/thread_script.py Tue Jun 27 00:08:11 2006
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+""" This is a script that is being used to debug whilst trying to get
+the thread debugging features working.
+"""
+
+import threading
+
+class MyThread(threading.Thread):
+ def run(self):
+ for i in range(10):
+ print i
+
+def func():
+ t = MyThread()
+ t.start()
+ t.join()
+
+if __name__ == '__main__':
+ func()
+
+
More information about the Python-checkins
mailing list