##// END OF EJS Templates
restore check for readline...
Min RK -
Show More
@@ -1,587 +1,588 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 Pdb debugger class.
3 Pdb debugger class.
4
4
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
5 Modified from the standard pdb.Pdb class to avoid including readline, so that
6 the command line completion of other programs which include this isn't
6 the command line completion of other programs which include this isn't
7 damaged.
7 damaged.
8
8
9 In the future, this class will be expanded with improvements over the standard
9 In the future, this class will be expanded with improvements over the standard
10 pdb.
10 pdb.
11
11
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
12 The code in this file is mainly lifted out of cmd.py in Python 2.2, with minor
13 changes. Licensing should therefore be under the standard Python terms. For
13 changes. Licensing should therefore be under the standard Python terms. For
14 details on the PSF (Python Software Foundation) standard license, see:
14 details on the PSF (Python Software Foundation) standard license, see:
15
15
16 http://www.python.org/2.2.3/license.html"""
16 http://www.python.org/2.2.3/license.html"""
17
17
18 #*****************************************************************************
18 #*****************************************************************************
19 #
19 #
20 # This file is licensed under the PSF license.
20 # This file is licensed under the PSF license.
21 #
21 #
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
22 # Copyright (C) 2001 Python Software Foundation, www.python.org
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
23 # Copyright (C) 2005-2006 Fernando Perez. <fperez@colorado.edu>
24 #
24 #
25 #
25 #
26 #*****************************************************************************
26 #*****************************************************************************
27 from __future__ import print_function
27 from __future__ import print_function
28
28
29 import bdb
29 import bdb
30 import functools
30 import functools
31 import inspect
31 import inspect
32 import linecache
32 import linecache
33 import sys
33 import sys
34
34
35 from IPython import get_ipython
35 from IPython import get_ipython
36 from IPython.utils import PyColorize, ulinecache
36 from IPython.utils import PyColorize, ulinecache
37 from IPython.utils import coloransi, io, py3compat
37 from IPython.utils import coloransi, io, py3compat
38 from IPython.core.excolors import exception_colors
38 from IPython.core.excolors import exception_colors
39 from IPython.testing.skipdoctest import skip_doctest
39 from IPython.testing.skipdoctest import skip_doctest
40
40
41 # See if we can use pydb.
41 # See if we can use pydb.
42 has_pydb = False
42 has_pydb = False
43 prompt = 'ipdb> '
43 prompt = 'ipdb> '
44 #We have to check this directly from sys.argv, config struct not yet available
44 #We have to check this directly from sys.argv, config struct not yet available
45 if '--pydb' in sys.argv:
45 if '--pydb' in sys.argv:
46 try:
46 try:
47 import pydb
47 import pydb
48 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
48 if hasattr(pydb.pydb, "runl") and pydb.version>'1.17':
49 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
49 # Version 1.17 is broken, and that's what ships with Ubuntu Edgy, so we
50 # better protect against it.
50 # better protect against it.
51 has_pydb = True
51 has_pydb = True
52 except ImportError:
52 except ImportError:
53 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
53 print("Pydb (http://bashdb.sourceforge.net/pydb/) does not seem to be available")
54
54
55 if has_pydb:
55 if has_pydb:
56 from pydb import Pdb as OldPdb
56 from pydb import Pdb as OldPdb
57 #print "Using pydb for %run -d and post-mortem" #dbg
57 #print "Using pydb for %run -d and post-mortem" #dbg
58 prompt = 'ipydb> '
58 prompt = 'ipydb> '
59 else:
59 else:
60 from pdb import Pdb as OldPdb
60 from pdb import Pdb as OldPdb
61
61
62 # Allow the set_trace code to operate outside of an ipython instance, even if
62 # Allow the set_trace code to operate outside of an ipython instance, even if
63 # it does so with some limitations. The rest of this support is implemented in
63 # it does so with some limitations. The rest of this support is implemented in
64 # the Tracer constructor.
64 # the Tracer constructor.
65 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
65 def BdbQuit_excepthook(et, ev, tb, excepthook=None):
66 """Exception hook which handles `BdbQuit` exceptions.
66 """Exception hook which handles `BdbQuit` exceptions.
67
67
68 All other exceptions are processed using the `excepthook`
68 All other exceptions are processed using the `excepthook`
69 parameter.
69 parameter.
70 """
70 """
71 if et==bdb.BdbQuit:
71 if et==bdb.BdbQuit:
72 print('Exiting Debugger.')
72 print('Exiting Debugger.')
73 elif excepthook is not None:
73 elif excepthook is not None:
74 excepthook(et, ev, tb)
74 excepthook(et, ev, tb)
75 else:
75 else:
76 # Backwards compatibility. Raise deprecation warning?
76 # Backwards compatibility. Raise deprecation warning?
77 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
77 BdbQuit_excepthook.excepthook_ori(et,ev,tb)
78
78
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
79 def BdbQuit_IPython_excepthook(self,et,ev,tb,tb_offset=None):
80 print('Exiting Debugger.')
80 print('Exiting Debugger.')
81
81
82
82
83 class Tracer(object):
83 class Tracer(object):
84 """Class for local debugging, similar to pdb.set_trace.
84 """Class for local debugging, similar to pdb.set_trace.
85
85
86 Instances of this class, when called, behave like pdb.set_trace, but
86 Instances of this class, when called, behave like pdb.set_trace, but
87 providing IPython's enhanced capabilities.
87 providing IPython's enhanced capabilities.
88
88
89 This is implemented as a class which must be initialized in your own code
89 This is implemented as a class which must be initialized in your own code
90 and not as a standalone function because we need to detect at runtime
90 and not as a standalone function because we need to detect at runtime
91 whether IPython is already active or not. That detection is done in the
91 whether IPython is already active or not. That detection is done in the
92 constructor, ensuring that this code plays nicely with a running IPython,
92 constructor, ensuring that this code plays nicely with a running IPython,
93 while functioning acceptably (though with limitations) if outside of it.
93 while functioning acceptably (though with limitations) if outside of it.
94 """
94 """
95
95
96 @skip_doctest
96 @skip_doctest
97 def __init__(self,colors=None):
97 def __init__(self,colors=None):
98 """Create a local debugger instance.
98 """Create a local debugger instance.
99
99
100 Parameters
100 Parameters
101 ----------
101 ----------
102
102
103 colors : str, optional
103 colors : str, optional
104 The name of the color scheme to use, it must be one of IPython's
104 The name of the color scheme to use, it must be one of IPython's
105 valid color schemes. If not given, the function will default to
105 valid color schemes. If not given, the function will default to
106 the current IPython scheme when running inside IPython, and to
106 the current IPython scheme when running inside IPython, and to
107 'NoColor' otherwise.
107 'NoColor' otherwise.
108
108
109 Examples
109 Examples
110 --------
110 --------
111 ::
111 ::
112
112
113 from IPython.core.debugger import Tracer; debug_here = Tracer()
113 from IPython.core.debugger import Tracer; debug_here = Tracer()
114
114
115 Later in your code::
115 Later in your code::
116
116
117 debug_here() # -> will open up the debugger at that point.
117 debug_here() # -> will open up the debugger at that point.
118
118
119 Once the debugger activates, you can use all of its regular commands to
119 Once the debugger activates, you can use all of its regular commands to
120 step through code, set breakpoints, etc. See the pdb documentation
120 step through code, set breakpoints, etc. See the pdb documentation
121 from the Python standard library for usage details.
121 from the Python standard library for usage details.
122 """
122 """
123
123
124 ip = get_ipython()
124 ip = get_ipython()
125 if ip is None:
125 if ip is None:
126 # Outside of ipython, we set our own exception hook manually
126 # Outside of ipython, we set our own exception hook manually
127 sys.excepthook = functools.partial(BdbQuit_excepthook,
127 sys.excepthook = functools.partial(BdbQuit_excepthook,
128 excepthook=sys.excepthook)
128 excepthook=sys.excepthook)
129 def_colors = 'NoColor'
129 def_colors = 'NoColor'
130 try:
130 try:
131 # Limited tab completion support
131 # Limited tab completion support
132 import readline
132 import readline
133 readline.parse_and_bind('tab: complete')
133 readline.parse_and_bind('tab: complete')
134 except ImportError:
134 except ImportError:
135 pass
135 pass
136 else:
136 else:
137 # In ipython, we use its custom exception handler mechanism
137 # In ipython, we use its custom exception handler mechanism
138 def_colors = ip.colors
138 def_colors = ip.colors
139 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
139 ip.set_custom_exc((bdb.BdbQuit,), BdbQuit_IPython_excepthook)
140
140
141 if colors is None:
141 if colors is None:
142 colors = def_colors
142 colors = def_colors
143
143
144 # The stdlib debugger internally uses a modified repr from the `repr`
144 # The stdlib debugger internally uses a modified repr from the `repr`
145 # module, that limits the length of printed strings to a hardcoded
145 # module, that limits the length of printed strings to a hardcoded
146 # limit of 30 characters. That much trimming is too aggressive, let's
146 # limit of 30 characters. That much trimming is too aggressive, let's
147 # at least raise that limit to 80 chars, which should be enough for
147 # at least raise that limit to 80 chars, which should be enough for
148 # most interactive uses.
148 # most interactive uses.
149 try:
149 try:
150 try:
150 try:
151 from reprlib import aRepr # Py 3
151 from reprlib import aRepr # Py 3
152 except ImportError:
152 except ImportError:
153 from repr import aRepr # Py 2
153 from repr import aRepr # Py 2
154 aRepr.maxstring = 80
154 aRepr.maxstring = 80
155 except:
155 except:
156 # This is only a user-facing convenience, so any error we encounter
156 # This is only a user-facing convenience, so any error we encounter
157 # here can be warned about but can be otherwise ignored. These
157 # here can be warned about but can be otherwise ignored. These
158 # printouts will tell us about problems if this API changes
158 # printouts will tell us about problems if this API changes
159 import traceback
159 import traceback
160 traceback.print_exc()
160 traceback.print_exc()
161
161
162 self.debugger = Pdb(colors)
162 self.debugger = Pdb(colors)
163
163
164 def __call__(self):
164 def __call__(self):
165 """Starts an interactive debugger at the point where called.
165 """Starts an interactive debugger at the point where called.
166
166
167 This is similar to the pdb.set_trace() function from the std lib, but
167 This is similar to the pdb.set_trace() function from the std lib, but
168 using IPython's enhanced debugger."""
168 using IPython's enhanced debugger."""
169
169
170 self.debugger.set_trace(sys._getframe().f_back)
170 self.debugger.set_trace(sys._getframe().f_back)
171
171
172
172
173 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
173 def decorate_fn_with_doc(new_fn, old_fn, additional_text=""):
174 """Make new_fn have old_fn's doc string. This is particularly useful
174 """Make new_fn have old_fn's doc string. This is particularly useful
175 for the ``do_...`` commands that hook into the help system.
175 for the ``do_...`` commands that hook into the help system.
176 Adapted from from a comp.lang.python posting
176 Adapted from from a comp.lang.python posting
177 by Duncan Booth."""
177 by Duncan Booth."""
178 def wrapper(*args, **kw):
178 def wrapper(*args, **kw):
179 return new_fn(*args, **kw)
179 return new_fn(*args, **kw)
180 if old_fn.__doc__:
180 if old_fn.__doc__:
181 wrapper.__doc__ = old_fn.__doc__ + additional_text
181 wrapper.__doc__ = old_fn.__doc__ + additional_text
182 return wrapper
182 return wrapper
183
183
184
184
185 def _file_lines(fname):
185 def _file_lines(fname):
186 """Return the contents of a named file as a list of lines.
186 """Return the contents of a named file as a list of lines.
187
187
188 This function never raises an IOError exception: if the file can't be
188 This function never raises an IOError exception: if the file can't be
189 read, it simply returns an empty list."""
189 read, it simply returns an empty list."""
190
190
191 try:
191 try:
192 outfile = open(fname)
192 outfile = open(fname)
193 except IOError:
193 except IOError:
194 return []
194 return []
195 else:
195 else:
196 out = outfile.readlines()
196 out = outfile.readlines()
197 outfile.close()
197 outfile.close()
198 return out
198 return out
199
199
200
200
201 class Pdb(OldPdb):
201 class Pdb(OldPdb):
202 """Modified Pdb class, does not load readline."""
202 """Modified Pdb class, does not load readline."""
203
203
204 def __init__(self,color_scheme='NoColor',completekey=None,
204 def __init__(self,color_scheme='NoColor',completekey=None,
205 stdin=None, stdout=None):
205 stdin=None, stdout=None):
206
206
207 # Parent constructor:
207 # Parent constructor:
208 if has_pydb and completekey is None:
208 if has_pydb and completekey is None:
209 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
209 OldPdb.__init__(self,stdin=stdin,stdout=io.stdout)
210 else:
210 else:
211 OldPdb.__init__(self,completekey,stdin,stdout)
211 OldPdb.__init__(self,completekey,stdin,stdout)
212
212
213 # IPython changes...
213 # IPython changes...
214 self.is_pydb = has_pydb
214 self.is_pydb = has_pydb
215
215
216 self.shell = get_ipython()
216 self.shell = get_ipython()
217
217
218 if self.shell is None:
218 if self.shell is None:
219 # No IPython instance running, we must create one
219 # No IPython instance running, we must create one
220 from IPython.terminal.interactiveshell import \
220 from IPython.terminal.interactiveshell import \
221 TerminalInteractiveShell
221 TerminalInteractiveShell
222 self.shell = TerminalInteractiveShell.instance()
222 self.shell = TerminalInteractiveShell.instance()
223
223
224 if self.is_pydb:
224 if self.is_pydb:
225
225
226 # interactiveshell.py's ipalias seems to want pdb's checkline
226 # interactiveshell.py's ipalias seems to want pdb's checkline
227 # which located in pydb.fn
227 # which located in pydb.fn
228 import pydb.fns
228 import pydb.fns
229 self.checkline = lambda filename, lineno: \
229 self.checkline = lambda filename, lineno: \
230 pydb.fns.checkline(self, filename, lineno)
230 pydb.fns.checkline(self, filename, lineno)
231
231
232 self.curframe = None
232 self.curframe = None
233 self.do_restart = self.new_do_restart
233 self.do_restart = self.new_do_restart
234
234
235 self.old_all_completions = self.shell.Completer.all_completions
235 self.old_all_completions = self.shell.Completer.all_completions
236 self.shell.Completer.all_completions=self.all_completions
236 self.shell.Completer.all_completions=self.all_completions
237
237
238 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
238 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
239 OldPdb.do_list)
239 OldPdb.do_list)
240 self.do_l = self.do_list
240 self.do_l = self.do_list
241 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
241 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
242 OldPdb.do_frame)
242 OldPdb.do_frame)
243
243
244 self.aliases = {}
244 self.aliases = {}
245
245
246 # Create color table: we copy the default one from the traceback
246 # Create color table: we copy the default one from the traceback
247 # module and add a few attributes needed for debugging
247 # module and add a few attributes needed for debugging
248 self.color_scheme_table = exception_colors()
248 self.color_scheme_table = exception_colors()
249
249
250 # shorthands
250 # shorthands
251 C = coloransi.TermColors
251 C = coloransi.TermColors
252 cst = self.color_scheme_table
252 cst = self.color_scheme_table
253
253
254 cst['NoColor'].colors.prompt = C.NoColor
254 cst['NoColor'].colors.prompt = C.NoColor
255 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
255 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
256 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
256 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
257
257
258 cst['Linux'].colors.prompt = C.Green
258 cst['Linux'].colors.prompt = C.Green
259 cst['Linux'].colors.breakpoint_enabled = C.LightRed
259 cst['Linux'].colors.breakpoint_enabled = C.LightRed
260 cst['Linux'].colors.breakpoint_disabled = C.Red
260 cst['Linux'].colors.breakpoint_disabled = C.Red
261
261
262 cst['LightBG'].colors.prompt = C.Blue
262 cst['LightBG'].colors.prompt = C.Blue
263 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
263 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
264 cst['LightBG'].colors.breakpoint_disabled = C.Red
264 cst['LightBG'].colors.breakpoint_disabled = C.Red
265
265
266 self.set_colors(color_scheme)
266 self.set_colors(color_scheme)
267
267
268 # Add a python parser so we can syntax highlight source while
268 # Add a python parser so we can syntax highlight source while
269 # debugging.
269 # debugging.
270 self.parser = PyColorize.Parser()
270 self.parser = PyColorize.Parser()
271
271
272 # Set the prompt
272 # Set the prompt
273 Colors = cst.active_colors
273 Colors = cst.active_colors
274 self.prompt = u'%s%s%s' % (Colors.prompt, prompt, Colors.Normal) # The default prompt is '(Pdb)'
274 self.prompt = u'%s%s%s' % (Colors.prompt, prompt, Colors.Normal) # The default prompt is '(Pdb)'
275
275
276 def set_colors(self, scheme):
276 def set_colors(self, scheme):
277 """Shorthand access to the color table scheme selector method."""
277 """Shorthand access to the color table scheme selector method."""
278 self.color_scheme_table.set_active_scheme(scheme)
278 self.color_scheme_table.set_active_scheme(scheme)
279
279
280 def interaction(self, frame, traceback):
280 def interaction(self, frame, traceback):
281 self.shell.set_completer_frame(frame)
281 self.shell.set_completer_frame(frame)
282 while True:
282 while True:
283 try:
283 try:
284 OldPdb.interaction(self, frame, traceback)
284 OldPdb.interaction(self, frame, traceback)
285 break
285 break
286 except KeyboardInterrupt:
286 except KeyboardInterrupt:
287 self.shell.write('\n' + self.shell.get_exception_only())
287 self.shell.write('\n' + self.shell.get_exception_only())
288 break
288 break
289 finally:
289 finally:
290 # Pdb sets readline delimiters, so set them back to our own
290 # Pdb sets readline delimiters, so set them back to our own
291 if self.shell.readline is not None:
291 self.shell.readline.set_completer_delims(self.shell.readline_delims)
292 self.shell.readline.set_completer_delims(self.shell.readline_delims)
292
293
293 def new_do_up(self, arg):
294 def new_do_up(self, arg):
294 OldPdb.do_up(self, arg)
295 OldPdb.do_up(self, arg)
295 self.shell.set_completer_frame(self.curframe)
296 self.shell.set_completer_frame(self.curframe)
296 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
297 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
297
298
298 def new_do_down(self, arg):
299 def new_do_down(self, arg):
299 OldPdb.do_down(self, arg)
300 OldPdb.do_down(self, arg)
300 self.shell.set_completer_frame(self.curframe)
301 self.shell.set_completer_frame(self.curframe)
301
302
302 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
303 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
303
304
304 def new_do_frame(self, arg):
305 def new_do_frame(self, arg):
305 OldPdb.do_frame(self, arg)
306 OldPdb.do_frame(self, arg)
306 self.shell.set_completer_frame(self.curframe)
307 self.shell.set_completer_frame(self.curframe)
307
308
308 def new_do_quit(self, arg):
309 def new_do_quit(self, arg):
309
310
310 if hasattr(self, 'old_all_completions'):
311 if hasattr(self, 'old_all_completions'):
311 self.shell.Completer.all_completions=self.old_all_completions
312 self.shell.Completer.all_completions=self.old_all_completions
312
313
313 return OldPdb.do_quit(self, arg)
314 return OldPdb.do_quit(self, arg)
314
315
315 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
316 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
316
317
317 def new_do_restart(self, arg):
318 def new_do_restart(self, arg):
318 """Restart command. In the context of ipython this is exactly the same
319 """Restart command. In the context of ipython this is exactly the same
319 thing as 'quit'."""
320 thing as 'quit'."""
320 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
321 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
321 return self.do_quit(arg)
322 return self.do_quit(arg)
322
323
323 def postloop(self):
324 def postloop(self):
324 self.shell.set_completer_frame(None)
325 self.shell.set_completer_frame(None)
325
326
326 def print_stack_trace(self):
327 def print_stack_trace(self):
327 try:
328 try:
328 for frame_lineno in self.stack:
329 for frame_lineno in self.stack:
329 self.print_stack_entry(frame_lineno, context = 5)
330 self.print_stack_entry(frame_lineno, context = 5)
330 except KeyboardInterrupt:
331 except KeyboardInterrupt:
331 pass
332 pass
332
333
333 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
334 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
334 context = 3):
335 context = 3):
335 #frame, lineno = frame_lineno
336 #frame, lineno = frame_lineno
336 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
337 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
337
338
338 # vds: >>
339 # vds: >>
339 frame, lineno = frame_lineno
340 frame, lineno = frame_lineno
340 filename = frame.f_code.co_filename
341 filename = frame.f_code.co_filename
341 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
342 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
342 # vds: <<
343 # vds: <<
343
344
344 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
345 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
345 try:
346 try:
346 import reprlib # Py 3
347 import reprlib # Py 3
347 except ImportError:
348 except ImportError:
348 import repr as reprlib # Py 2
349 import repr as reprlib # Py 2
349
350
350 ret = []
351 ret = []
351
352
352 Colors = self.color_scheme_table.active_colors
353 Colors = self.color_scheme_table.active_colors
353 ColorsNormal = Colors.Normal
354 ColorsNormal = Colors.Normal
354 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
355 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
355 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
356 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
356 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
357 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
357 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
358 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
358 ColorsNormal)
359 ColorsNormal)
359
360
360 frame, lineno = frame_lineno
361 frame, lineno = frame_lineno
361
362
362 return_value = ''
363 return_value = ''
363 if '__return__' in frame.f_locals:
364 if '__return__' in frame.f_locals:
364 rv = frame.f_locals['__return__']
365 rv = frame.f_locals['__return__']
365 #return_value += '->'
366 #return_value += '->'
366 return_value += reprlib.repr(rv) + '\n'
367 return_value += reprlib.repr(rv) + '\n'
367 ret.append(return_value)
368 ret.append(return_value)
368
369
369 #s = filename + '(' + `lineno` + ')'
370 #s = filename + '(' + `lineno` + ')'
370 filename = self.canonic(frame.f_code.co_filename)
371 filename = self.canonic(frame.f_code.co_filename)
371 link = tpl_link % py3compat.cast_unicode(filename)
372 link = tpl_link % py3compat.cast_unicode(filename)
372
373
373 if frame.f_code.co_name:
374 if frame.f_code.co_name:
374 func = frame.f_code.co_name
375 func = frame.f_code.co_name
375 else:
376 else:
376 func = "<lambda>"
377 func = "<lambda>"
377
378
378 call = ''
379 call = ''
379 if func != '?':
380 if func != '?':
380 if '__args__' in frame.f_locals:
381 if '__args__' in frame.f_locals:
381 args = reprlib.repr(frame.f_locals['__args__'])
382 args = reprlib.repr(frame.f_locals['__args__'])
382 else:
383 else:
383 args = '()'
384 args = '()'
384 call = tpl_call % (func, args)
385 call = tpl_call % (func, args)
385
386
386 # The level info should be generated in the same format pdb uses, to
387 # The level info should be generated in the same format pdb uses, to
387 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
388 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
388 if frame is self.curframe:
389 if frame is self.curframe:
389 ret.append('> ')
390 ret.append('> ')
390 else:
391 else:
391 ret.append(' ')
392 ret.append(' ')
392 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
393 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
393
394
394 start = lineno - 1 - context//2
395 start = lineno - 1 - context//2
395 lines = ulinecache.getlines(filename)
396 lines = ulinecache.getlines(filename)
396 start = min(start, len(lines) - context)
397 start = min(start, len(lines) - context)
397 start = max(start, 0)
398 start = max(start, 0)
398 lines = lines[start : start + context]
399 lines = lines[start : start + context]
399
400
400 for i,line in enumerate(lines):
401 for i,line in enumerate(lines):
401 show_arrow = (start + 1 + i == lineno)
402 show_arrow = (start + 1 + i == lineno)
402 linetpl = (frame is self.curframe or show_arrow) \
403 linetpl = (frame is self.curframe or show_arrow) \
403 and tpl_line_em \
404 and tpl_line_em \
404 or tpl_line
405 or tpl_line
405 ret.append(self.__format_line(linetpl, filename,
406 ret.append(self.__format_line(linetpl, filename,
406 start + 1 + i, line,
407 start + 1 + i, line,
407 arrow = show_arrow) )
408 arrow = show_arrow) )
408 return ''.join(ret)
409 return ''.join(ret)
409
410
410 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
411 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
411 bp_mark = ""
412 bp_mark = ""
412 bp_mark_color = ""
413 bp_mark_color = ""
413
414
414 scheme = self.color_scheme_table.active_scheme_name
415 scheme = self.color_scheme_table.active_scheme_name
415 new_line, err = self.parser.format2(line, 'str', scheme)
416 new_line, err = self.parser.format2(line, 'str', scheme)
416 if not err: line = new_line
417 if not err: line = new_line
417
418
418 bp = None
419 bp = None
419 if lineno in self.get_file_breaks(filename):
420 if lineno in self.get_file_breaks(filename):
420 bps = self.get_breaks(filename, lineno)
421 bps = self.get_breaks(filename, lineno)
421 bp = bps[-1]
422 bp = bps[-1]
422
423
423 if bp:
424 if bp:
424 Colors = self.color_scheme_table.active_colors
425 Colors = self.color_scheme_table.active_colors
425 bp_mark = str(bp.number)
426 bp_mark = str(bp.number)
426 bp_mark_color = Colors.breakpoint_enabled
427 bp_mark_color = Colors.breakpoint_enabled
427 if not bp.enabled:
428 if not bp.enabled:
428 bp_mark_color = Colors.breakpoint_disabled
429 bp_mark_color = Colors.breakpoint_disabled
429
430
430 numbers_width = 7
431 numbers_width = 7
431 if arrow:
432 if arrow:
432 # This is the line with the error
433 # This is the line with the error
433 pad = numbers_width - len(str(lineno)) - len(bp_mark)
434 pad = numbers_width - len(str(lineno)) - len(bp_mark)
434 if pad >= 3:
435 if pad >= 3:
435 marker = '-'*(pad-3) + '-> '
436 marker = '-'*(pad-3) + '-> '
436 elif pad == 2:
437 elif pad == 2:
437 marker = '> '
438 marker = '> '
438 elif pad == 1:
439 elif pad == 1:
439 marker = '>'
440 marker = '>'
440 else:
441 else:
441 marker = ''
442 marker = ''
442 num = '%s%s' % (marker, str(lineno))
443 num = '%s%s' % (marker, str(lineno))
443 line = tpl_line % (bp_mark_color + bp_mark, num, line)
444 line = tpl_line % (bp_mark_color + bp_mark, num, line)
444 else:
445 else:
445 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
446 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
446 line = tpl_line % (bp_mark_color + bp_mark, num, line)
447 line = tpl_line % (bp_mark_color + bp_mark, num, line)
447
448
448 return line
449 return line
449
450
450 def list_command_pydb(self, arg):
451 def list_command_pydb(self, arg):
451 """List command to use if we have a newer pydb installed"""
452 """List command to use if we have a newer pydb installed"""
452 filename, first, last = OldPdb.parse_list_cmd(self, arg)
453 filename, first, last = OldPdb.parse_list_cmd(self, arg)
453 if filename is not None:
454 if filename is not None:
454 self.print_list_lines(filename, first, last)
455 self.print_list_lines(filename, first, last)
455
456
456 def print_list_lines(self, filename, first, last):
457 def print_list_lines(self, filename, first, last):
457 """The printing (as opposed to the parsing part of a 'list'
458 """The printing (as opposed to the parsing part of a 'list'
458 command."""
459 command."""
459 try:
460 try:
460 Colors = self.color_scheme_table.active_colors
461 Colors = self.color_scheme_table.active_colors
461 ColorsNormal = Colors.Normal
462 ColorsNormal = Colors.Normal
462 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
463 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
463 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
464 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
464 src = []
465 src = []
465 if filename == "<string>" and hasattr(self, "_exec_filename"):
466 if filename == "<string>" and hasattr(self, "_exec_filename"):
466 filename = self._exec_filename
467 filename = self._exec_filename
467
468
468 for lineno in range(first, last+1):
469 for lineno in range(first, last+1):
469 line = ulinecache.getline(filename, lineno)
470 line = ulinecache.getline(filename, lineno)
470 if not line:
471 if not line:
471 break
472 break
472
473
473 if lineno == self.curframe.f_lineno:
474 if lineno == self.curframe.f_lineno:
474 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
475 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
475 else:
476 else:
476 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
477 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
477
478
478 src.append(line)
479 src.append(line)
479 self.lineno = lineno
480 self.lineno = lineno
480
481
481 print(''.join(src), file=io.stdout)
482 print(''.join(src), file=io.stdout)
482
483
483 except KeyboardInterrupt:
484 except KeyboardInterrupt:
484 pass
485 pass
485
486
486 def do_list(self, arg):
487 def do_list(self, arg):
487 self.lastcmd = 'list'
488 self.lastcmd = 'list'
488 last = None
489 last = None
489 if arg:
490 if arg:
490 try:
491 try:
491 x = eval(arg, {}, {})
492 x = eval(arg, {}, {})
492 if type(x) == type(()):
493 if type(x) == type(()):
493 first, last = x
494 first, last = x
494 first = int(first)
495 first = int(first)
495 last = int(last)
496 last = int(last)
496 if last < first:
497 if last < first:
497 # Assume it's a count
498 # Assume it's a count
498 last = first + last
499 last = first + last
499 else:
500 else:
500 first = max(1, int(x) - 5)
501 first = max(1, int(x) - 5)
501 except:
502 except:
502 print('*** Error in argument:', repr(arg))
503 print('*** Error in argument:', repr(arg))
503 return
504 return
504 elif self.lineno is None:
505 elif self.lineno is None:
505 first = max(1, self.curframe.f_lineno - 5)
506 first = max(1, self.curframe.f_lineno - 5)
506 else:
507 else:
507 first = self.lineno + 1
508 first = self.lineno + 1
508 if last is None:
509 if last is None:
509 last = first + 10
510 last = first + 10
510 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
511 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
511
512
512 # vds: >>
513 # vds: >>
513 lineno = first
514 lineno = first
514 filename = self.curframe.f_code.co_filename
515 filename = self.curframe.f_code.co_filename
515 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
516 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
516 # vds: <<
517 # vds: <<
517
518
518 do_l = do_list
519 do_l = do_list
519
520
520 def getsourcelines(self, obj):
521 def getsourcelines(self, obj):
521 lines, lineno = inspect.findsource(obj)
522 lines, lineno = inspect.findsource(obj)
522 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
523 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
523 # must be a module frame: do not try to cut a block out of it
524 # must be a module frame: do not try to cut a block out of it
524 return lines, 1
525 return lines, 1
525 elif inspect.ismodule(obj):
526 elif inspect.ismodule(obj):
526 return lines, 1
527 return lines, 1
527 return inspect.getblock(lines[lineno:]), lineno+1
528 return inspect.getblock(lines[lineno:]), lineno+1
528
529
529 def do_longlist(self, arg):
530 def do_longlist(self, arg):
530 self.lastcmd = 'longlist'
531 self.lastcmd = 'longlist'
531 filename = self.curframe.f_code.co_filename
532 filename = self.curframe.f_code.co_filename
532 breaklist = self.get_file_breaks(filename)
533 breaklist = self.get_file_breaks(filename)
533 try:
534 try:
534 lines, lineno = self.getsourcelines(self.curframe)
535 lines, lineno = self.getsourcelines(self.curframe)
535 except OSError as err:
536 except OSError as err:
536 self.error(err)
537 self.error(err)
537 return
538 return
538 last = lineno + len(lines)
539 last = lineno + len(lines)
539 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
540 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
540 do_ll = do_longlist
541 do_ll = do_longlist
541
542
542 def do_pdef(self, arg):
543 def do_pdef(self, arg):
543 """Print the call signature for any callable object.
544 """Print the call signature for any callable object.
544
545
545 The debugger interface to %pdef"""
546 The debugger interface to %pdef"""
546 namespaces = [('Locals', self.curframe.f_locals),
547 namespaces = [('Locals', self.curframe.f_locals),
547 ('Globals', self.curframe.f_globals)]
548 ('Globals', self.curframe.f_globals)]
548 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
549 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
549
550
550 def do_pdoc(self, arg):
551 def do_pdoc(self, arg):
551 """Print the docstring for an object.
552 """Print the docstring for an object.
552
553
553 The debugger interface to %pdoc."""
554 The debugger interface to %pdoc."""
554 namespaces = [('Locals', self.curframe.f_locals),
555 namespaces = [('Locals', self.curframe.f_locals),
555 ('Globals', self.curframe.f_globals)]
556 ('Globals', self.curframe.f_globals)]
556 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
557 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
557
558
558 def do_pfile(self, arg):
559 def do_pfile(self, arg):
559 """Print (or run through pager) the file where an object is defined.
560 """Print (or run through pager) the file where an object is defined.
560
561
561 The debugger interface to %pfile.
562 The debugger interface to %pfile.
562 """
563 """
563 namespaces = [('Locals', self.curframe.f_locals),
564 namespaces = [('Locals', self.curframe.f_locals),
564 ('Globals', self.curframe.f_globals)]
565 ('Globals', self.curframe.f_globals)]
565 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
566 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
566
567
567 def do_pinfo(self, arg):
568 def do_pinfo(self, arg):
568 """Provide detailed information about an object.
569 """Provide detailed information about an object.
569
570
570 The debugger interface to %pinfo, i.e., obj?."""
571 The debugger interface to %pinfo, i.e., obj?."""
571 namespaces = [('Locals', self.curframe.f_locals),
572 namespaces = [('Locals', self.curframe.f_locals),
572 ('Globals', self.curframe.f_globals)]
573 ('Globals', self.curframe.f_globals)]
573 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
574 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
574
575
575 def do_pinfo2(self, arg):
576 def do_pinfo2(self, arg):
576 """Provide extra detailed information about an object.
577 """Provide extra detailed information about an object.
577
578
578 The debugger interface to %pinfo2, i.e., obj??."""
579 The debugger interface to %pinfo2, i.e., obj??."""
579 namespaces = [('Locals', self.curframe.f_locals),
580 namespaces = [('Locals', self.curframe.f_locals),
580 ('Globals', self.curframe.f_globals)]
581 ('Globals', self.curframe.f_globals)]
581 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
582 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
582
583
583 def do_psource(self, arg):
584 def do_psource(self, arg):
584 """Print (or run through pager) the source code for an object."""
585 """Print (or run through pager) the source code for an object."""
585 namespaces = [('Locals', self.curframe.f_locals),
586 namespaces = [('Locals', self.curframe.f_locals),
586 ('Globals', self.curframe.f_globals)]
587 ('Globals', self.curframe.f_globals)]
587 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
588 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
General Comments 0
You need to be logged in to leave comments. Login now