"""
Provides a breakpoint registry that can be sent to another process (via
getBreakpointList()).
"""
import os
try: from cPickle import Pickler,Unpickler
except: from pickle import Pickler,Unpickler
class FileBreakpointList:
def __init__(self):
self.lines = {} # lineno -> [{'temporary', 'cond', 'enabled', 'ignore'}]
def loadBreakpoints(self, fn):
try:
if os.path.exists(fn):
f = open(fn, 'rb')
u = Unpickler(f)
newlines = u.load()
# The following line isn't quite correct
# when multiple breakpoints are set on a
# single line.
self.lines.update(newlines)
return 1
else:
return 0
except:
self.lines = {}
return 0
def saveBreakpoints(self, fn):
try:
if len(self.lines):
savelines = {}
# Filter out the temporary lines when saving.
for lineno, linebreaks in self.lines.items():
savelines[lineno] = saveline = []
for brk in linebreaks:
if not brk['temporary']:
saveline.append(brk)
f = open(fn, 'wb')
p = Pickler(f)
p.dump(savelines)
else:
os.remove(fn)
except:
pass
def addBreakpoint(self, lineno, temp=0, cond='', ignore=0):
newbrk = {'temporary':temp, 'cond':cond, 'enabled':1, 'ignore':ignore}
if self.lines.has_key(lineno):
linebreaks = self.lines[lineno]
for brk in linebreaks:
if brk['temporary'] == temp and brk['cond'] == cond:
# Already added.
return
linebreaks.append(newbrk)
else:
self.lines[lineno] = linebreaks = [newbrk]
def deleteBreakpoints(self, lineno):
if self.lines.has_key(lineno):
del self.lines[lineno]
def moveBreakpoint(self, lineno, newlineno):
if lineno != newlineno and self.lines.has_key(lineno):
bp = self.lines[lineno]
del self.lines[lineno]
self.lines[lineno] = bp
def adjustBreakpoints(self, lineno, delta):
set_breaks = []
# traverse list twice, first deleting then re-adding to avoid stepping
# on our own toes
for brklineno, breaks in self.lines.items():
if lineno < brklineno-1:
del self.lines[brklineno]
set_breaks.append( (brklineno+delta, breaks) )
for brklineno, breaks in set_breaks:
self.lines[brklineno] = breaks
def enableBreakpoints(self, lineno, enable=1):
if self.lines.has_key(lineno):
linebreaks = self.lines[lineno]
for brk in linebreaks:
brk['enabled'] = enable
def ignoreBreakpoints(self, lineno, ignore=0):
if self.lines.has_key(lineno):
linebreaks = self.lines[lineno]
for brk in linebreaks:
brk['ignore'] = ignore
def conditionalBreakpoints(self, lineno, cond=''):
if self.lines.has_key(lineno):
linebreaks = self.lines[lineno]
for brk in linebreaks:
brk['cond'] = cond
def listBreakpoints(self):
rval = []
for lineno, linebreaks in self.lines.items():
for brk in linebreaks:
brkinfo = {'lineno':lineno}
brkinfo.update(brk)
rval.append(brkinfo)
return rval
def hasBreakpoint(self, lineno, endlineno=-1):
if endlineno < 0:
return self.lines.has_key(lineno)
else:
for line in self.lines.keys():
if line >= lineno and line <= endlineno:
return 1
return 0
def clearTemporaryBreakpoints(self, lineno):
if self.lines.has_key(lineno):
linebreaks = self.lines[lineno]
idx = 0
while idx < len(linebreaks):
brk = linebreaks[idx]
if brk['temporary']:
del linebreaks[idx]
else:
idx = idx + 1
def clearAllBreakpoints(self):
self.lines = {}
class BreakpointList:
def __init__(self):
self.files = {} # filename -> FileBreakpointList
def normalize(self, filename):
if filename.find('://') < 0:
filename = 'file://' + filename
return filename
def addBreakpoint(self, filename, lineno, temp=0, cond='', ignore=0):
filename = self.normalize(filename)
filelist = self.getFileBreakpoints(filename)
filelist.addBreakpoint(lineno, temp, cond, ignore)
def deleteBreakpoints(self, filename, lineno):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.deleteBreakpoints(lineno)
def moveBreakpoint(self, filename, lineno, newlineno):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.moveBreakpoint(lineno, newlineno)
def adjustBreakpoints(self, filename, lineno, delta):
if self.files.has_key(filename):
filelist = self.files[filename]
return filelist.adjustBreakpoints(lineno, delta)
return 0
def enableBreakpoints(self, filename, lineno, enable=1):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.enableBreakpoints(lineno, enable)
def ignoreBreakpoints(self, filename, lineno, ignore=0):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.ignoreBreakpoints(lineno, ignore)
def conditionalBreakpoints(self, filename, lineno, cond=''):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.conditionalBreakpoints(lineno, cond)
def clearTemporaryBreakpoints(self, filename, lineno):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
filelist.clearTemporaryBreakpoints(lineno)
def renameFileBreakpoints(self, oldname, newname):
oldname = self.normalize(oldname)
newname = self.normalize(newname)
if self.files.has_key(oldname):
filelist = self.files[oldname]
filelist.clearAllBreakpoints()
del self.files[oldname]
self.files[newname] = filelist
def getFileBreakpoints(self, filename):
filename = self.normalize(filename)
if self.files.has_key(filename):
return self.files[filename]
else:
self.files[filename] = filelist = FileBreakpointList()
return filelist
def hasBreakpoint(self, filename, lineno, endlineno=-1):
filename = self.normalize(filename)
if self.files.has_key(filename):
filelist = self.files[filename]
return filelist.hasBreakpoint(lineno, endlineno)
return 0
def getBreakpointList(self, fn=None):
"""Returns a list designed to pass to the setAllBreakpoints()
debugger method.
The optional fn constrains the return value to breakpoints in
a specified file."""
rval = []
if fn is not None:
fn = self.normalize(fn)
for filename, filelist in self.files.items():
if fn is None or filename == fn:
for lineno, linebreaks in filelist.lines.items():
for brk in linebreaks:
brkinfo = {'filename': filename,
'lineno': lineno}
brkinfo.update(brk)
rval.append(brkinfo)
return rval
# ??? Should this really be a global variable?
bplist = BreakpointList()
|