Skip to content

Instantly share code, notes, and snippets.

@ltvolks
Created March 23, 2010 20:32
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ltvolks/341619 to your computer and use it in GitHub Desktop.
Save ltvolks/341619 to your computer and use it in GitHub Desktop.
Use TextMate Bookmarks as PDB breakpoints
#!/usr/bin/env python
"""
mate_pdb.py
Execute a script file in the debugger using breakpoints set
via Bookmarked Lines in TextMate.
Intended usage is to call from within a TextMate Command in
your Python bundle
but can be called like so:
python mate_pdb.py scriptfile.py
This is functionally equivalent to:
python -m pdb scriptfile.py
If the xattributes exist for bookmarked lines, they will be added
as breakpoints to the pdb session.
Requires xattr module: http://pypi.python.org/pypi/xattr
Kickstarted by this listbot.org posting: http://listbot.org/blog/python/2010/03/22/pdb/
TODO:
* Optionally use ipdb
* Execute until first set breakpoint instead of starting session on line 1
"""
import os, sys, zlib
from pdb import Pdb
import xattr
def xattr_to_list(unzipped):
return (unzipped.replace('(','').replace(')','').replace('\n','').replace(' ','')).split(",")
def main():
if not sys.argv[1:]:
print "usage: mate_pdb.py scriptfile [arg] ..."
sys.exit(2)
mainpyfile = sys.argv[1] # Get script filename
if not os.path.exists(mainpyfile):
print 'Error:', mainpyfile, 'does not exist'
sys.exit(1)
del sys.argv[0] # Hide "pdb.py" from argument list
# Replace pdb's dir with script's dir in front of module search path.
sys.path[0] = os.path.dirname(mainpyfile)
# Create breakpoint list from TM bookmark attributes
rcLines = []
try:
breakpoint_list = xattr.getxattr('%s' % mainpyfile, 'com.macromates.bookmarked_lines')
except IOError, x:
# Attributes may not exist in the target script, ignore
pass
else:
try:
breakpoint_list = breakpoint_list.decode('zip')
except zlib.error:
pass
for breakpoint in xattr_to_list(breakpoint_list):
rcLines.append("b %s:%d\n" % (mainpyfile, (int(breakpoint) + 1)))
pdb = Pdb()
pdb.rcLines.extend(rcLines)
while 1:
try:
pdb._runscript(mainpyfile)
if pdb._user_requested_quit:
break
print "The program finished and will be restarted"
except SystemExit:
# In most cases SystemExit does not warrant a post-mortem session.
print "The program exited via sys.exit(). Exit status: ",
print sys.exc_info()[1]
except:
traceback.print_exc()
print "Uncaught exception. Entering post mortem debugging"
print "Running 'cont' or 'step' will restart the program"
t = sys.exc_info()[2]
while t.tb_next is not None:
t = t.tb_next
pdb.interaction(t.tb_frame,t)
print "Post mortem debugger finished. The "+mainpyfile+" will be restarted"
# When invoked as main program, invoke the debugger on a script
if __name__=='__main__':
main()
###########################################################################
# Start Python in debug mode using either Terminal.app or iTerm.app
# Textmate bookmarks are set as breakpoints in the debug session
# Requires the existence of TM_PDB_SCRIPT (mate_pdb.py) to set
# breakpoints and run the target in the debugger
#
# Note also that if iTerm is used, it expects iPython to be available, so
# Terminal --> plain python
# iTerm --> iPython
#
# Installation:
# Add a new Command to the Python Bundle in TM: "Debug Script w/ Bookmarks"
# Set Activation: Key Equivalent = to your desired keystroke combo
# suggested : (SHIFT + APPLE + D)
# Scope Selector: source.python
#
# Add the mate_pdb.py script somewhere on your path and make sure to set
# TM_PDB_SCRIPT in TextMate.
#
#
# The following Shell Variables should be set in TextMate:
#
# TM_TERM_PROG = Terminal program (iTerm or Terminal)
# default = Terminal
# TM_PYTHON = python interpreter
# default = python
# TM_PDB_SCRIPT = path to mate_pdb.py script
# default = ~/bin/mate_pdb.py
#
###########################################################################
TP=${TM_TERM_PROG:=Terminal}
TPY=${TM_PYTHON:=python}
TMPDB=${TM_PDB_SCRIPT:=~/bin/mate_pdb.py}
USER_NAME=`whoami`
if [ "$TP" == iTerm ]; then
osascript <<END
tell application "iTerm"
activate
set myTerm to the first terminal
tell myTerm
-- Conditionally create ipython session
set sessionexists to ((count (get every session whose name is "iPython")))
if sessionexists > 0 then
tell session "iPython"
--activate
write text "%run '$TMPDB' '$TM_FILEPATH'"
end tell
else
-- create new session
set ipysession to (make new session at the end of sessions)
tell ipysession
set name to "iPython"
exec command "login -fp $USER_NAME"
write text "cd '$TM_DIRECTORY'"
write text "clear"
write text "ipython"
write text "%run '$TMPDB' '$TM_FILEPATH'"
end tell
end if
end tell
end tell
END
else
osascript <<END2
tell application "Terminal"
activate
do script with command "$TPY $TMPDB $TM_FILEPATH"
end tell
END2
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment