##// END OF EJS Templates
Merge pull request #8842 from gaborluk/master...
Min RK -
r21696:32ee8c1d merge
parent child Browse files
Show More
@@ -1,584 +1,589 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 self.prompt = prompt # The default prompt is '(Pdb)'
214
215 # IPython changes...
213 # IPython changes...
216 self.is_pydb = has_pydb
214 self.is_pydb = has_pydb
217
215
218 self.shell = get_ipython()
216 self.shell = get_ipython()
219
217
220 if self.shell is None:
218 if self.shell is None:
221 # No IPython instance running, we must create one
219 # No IPython instance running, we must create one
222 from IPython.terminal.interactiveshell import \
220 from IPython.terminal.interactiveshell import \
223 TerminalInteractiveShell
221 TerminalInteractiveShell
224 self.shell = TerminalInteractiveShell.instance()
222 self.shell = TerminalInteractiveShell.instance()
225
223
226 if self.is_pydb:
224 if self.is_pydb:
227
225
228 # interactiveshell.py's ipalias seems to want pdb's checkline
226 # interactiveshell.py's ipalias seems to want pdb's checkline
229 # which located in pydb.fn
227 # which located in pydb.fn
230 import pydb.fns
228 import pydb.fns
231 self.checkline = lambda filename, lineno: \
229 self.checkline = lambda filename, lineno: \
232 pydb.fns.checkline(self, filename, lineno)
230 pydb.fns.checkline(self, filename, lineno)
233
231
234 self.curframe = None
232 self.curframe = None
235 self.do_restart = self.new_do_restart
233 self.do_restart = self.new_do_restart
236
234
237 self.old_all_completions = self.shell.Completer.all_completions
235 self.old_all_completions = self.shell.Completer.all_completions
238 self.shell.Completer.all_completions=self.all_completions
236 self.shell.Completer.all_completions=self.all_completions
239
237
240 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
238 self.do_list = decorate_fn_with_doc(self.list_command_pydb,
241 OldPdb.do_list)
239 OldPdb.do_list)
242 self.do_l = self.do_list
240 self.do_l = self.do_list
243 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
241 self.do_frame = decorate_fn_with_doc(self.new_do_frame,
244 OldPdb.do_frame)
242 OldPdb.do_frame)
245
243
246 self.aliases = {}
244 self.aliases = {}
247
245
248 # Create color table: we copy the default one from the traceback
246 # Create color table: we copy the default one from the traceback
249 # module and add a few attributes needed for debugging
247 # module and add a few attributes needed for debugging
250 self.color_scheme_table = exception_colors()
248 self.color_scheme_table = exception_colors()
251
249
252 # shorthands
250 # shorthands
253 C = coloransi.TermColors
251 C = coloransi.TermColors
254 cst = self.color_scheme_table
252 cst = self.color_scheme_table
255
253
254 cst['NoColor'].colors.prompt = C.NoColor
256 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
255 cst['NoColor'].colors.breakpoint_enabled = C.NoColor
257 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
256 cst['NoColor'].colors.breakpoint_disabled = C.NoColor
258
257
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.breakpoint_enabled = C.LightRed
263 cst['LightBG'].colors.breakpoint_enabled = C.LightRed
263 cst['LightBG'].colors.breakpoint_disabled = C.Red
264 cst['LightBG'].colors.breakpoint_disabled = C.Red
264
265
265 self.set_colors(color_scheme)
266 self.set_colors(color_scheme)
266
267
267 # Add a python parser so we can syntax highlight source while
268 # Add a python parser so we can syntax highlight source while
268 # debugging.
269 # debugging.
269 self.parser = PyColorize.Parser()
270 self.parser = PyColorize.Parser()
270
271
272 # Set the prompt
273 Colors = cst.active_colors
274 self.prompt = u'%s%s%s' % (Colors.prompt, prompt, Colors.Normal) # The default prompt is '(Pdb)'
275
271 def set_colors(self, scheme):
276 def set_colors(self, scheme):
272 """Shorthand access to the color table scheme selector method."""
277 """Shorthand access to the color table scheme selector method."""
273 self.color_scheme_table.set_active_scheme(scheme)
278 self.color_scheme_table.set_active_scheme(scheme)
274
279
275 def interaction(self, frame, traceback):
280 def interaction(self, frame, traceback):
276 self.shell.set_completer_frame(frame)
281 self.shell.set_completer_frame(frame)
277 while True:
282 while True:
278 try:
283 try:
279 OldPdb.interaction(self, frame, traceback)
284 OldPdb.interaction(self, frame, traceback)
280 except KeyboardInterrupt:
285 except KeyboardInterrupt:
281 self.shell.write('\n' + self.shell.get_exception_only())
286 self.shell.write('\n' + self.shell.get_exception_only())
282 break
287 break
283 else:
288 else:
284 break
289 break
285
290
286 def new_do_up(self, arg):
291 def new_do_up(self, arg):
287 OldPdb.do_up(self, arg)
292 OldPdb.do_up(self, arg)
288 self.shell.set_completer_frame(self.curframe)
293 self.shell.set_completer_frame(self.curframe)
289 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
294 do_u = do_up = decorate_fn_with_doc(new_do_up, OldPdb.do_up)
290
295
291 def new_do_down(self, arg):
296 def new_do_down(self, arg):
292 OldPdb.do_down(self, arg)
297 OldPdb.do_down(self, arg)
293 self.shell.set_completer_frame(self.curframe)
298 self.shell.set_completer_frame(self.curframe)
294
299
295 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
300 do_d = do_down = decorate_fn_with_doc(new_do_down, OldPdb.do_down)
296
301
297 def new_do_frame(self, arg):
302 def new_do_frame(self, arg):
298 OldPdb.do_frame(self, arg)
303 OldPdb.do_frame(self, arg)
299 self.shell.set_completer_frame(self.curframe)
304 self.shell.set_completer_frame(self.curframe)
300
305
301 def new_do_quit(self, arg):
306 def new_do_quit(self, arg):
302
307
303 if hasattr(self, 'old_all_completions'):
308 if hasattr(self, 'old_all_completions'):
304 self.shell.Completer.all_completions=self.old_all_completions
309 self.shell.Completer.all_completions=self.old_all_completions
305
310
306 # Pdb sets readline delimiters, so set them back to our own
311 # Pdb sets readline delimiters, so set them back to our own
307 if self.shell.readline is not None:
312 if self.shell.readline is not None:
308 self.shell.readline.set_completer_delims(self.shell.readline_delims)
313 self.shell.readline.set_completer_delims(self.shell.readline_delims)
309
314
310 return OldPdb.do_quit(self, arg)
315 return OldPdb.do_quit(self, arg)
311
316
312 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
317 do_q = do_quit = decorate_fn_with_doc(new_do_quit, OldPdb.do_quit)
313
318
314 def new_do_restart(self, arg):
319 def new_do_restart(self, arg):
315 """Restart command. In the context of ipython this is exactly the same
320 """Restart command. In the context of ipython this is exactly the same
316 thing as 'quit'."""
321 thing as 'quit'."""
317 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
322 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
318 return self.do_quit(arg)
323 return self.do_quit(arg)
319
324
320 def postloop(self):
325 def postloop(self):
321 self.shell.set_completer_frame(None)
326 self.shell.set_completer_frame(None)
322
327
323 def print_stack_trace(self):
328 def print_stack_trace(self):
324 try:
329 try:
325 for frame_lineno in self.stack:
330 for frame_lineno in self.stack:
326 self.print_stack_entry(frame_lineno, context = 5)
331 self.print_stack_entry(frame_lineno, context = 5)
327 except KeyboardInterrupt:
332 except KeyboardInterrupt:
328 pass
333 pass
329
334
330 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
335 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
331 context = 3):
336 context = 3):
332 #frame, lineno = frame_lineno
337 #frame, lineno = frame_lineno
333 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
338 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
334
339
335 # vds: >>
340 # vds: >>
336 frame, lineno = frame_lineno
341 frame, lineno = frame_lineno
337 filename = frame.f_code.co_filename
342 filename = frame.f_code.co_filename
338 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
343 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
339 # vds: <<
344 # vds: <<
340
345
341 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
346 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
342 try:
347 try:
343 import reprlib # Py 3
348 import reprlib # Py 3
344 except ImportError:
349 except ImportError:
345 import repr as reprlib # Py 2
350 import repr as reprlib # Py 2
346
351
347 ret = []
352 ret = []
348
353
349 Colors = self.color_scheme_table.active_colors
354 Colors = self.color_scheme_table.active_colors
350 ColorsNormal = Colors.Normal
355 ColorsNormal = Colors.Normal
351 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
356 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
352 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
357 tpl_call = u'%s%%s%s%%s%s' % (Colors.vName, Colors.valEm, ColorsNormal)
353 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
358 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
354 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
359 tpl_line_em = u'%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line,
355 ColorsNormal)
360 ColorsNormal)
356
361
357 frame, lineno = frame_lineno
362 frame, lineno = frame_lineno
358
363
359 return_value = ''
364 return_value = ''
360 if '__return__' in frame.f_locals:
365 if '__return__' in frame.f_locals:
361 rv = frame.f_locals['__return__']
366 rv = frame.f_locals['__return__']
362 #return_value += '->'
367 #return_value += '->'
363 return_value += reprlib.repr(rv) + '\n'
368 return_value += reprlib.repr(rv) + '\n'
364 ret.append(return_value)
369 ret.append(return_value)
365
370
366 #s = filename + '(' + `lineno` + ')'
371 #s = filename + '(' + `lineno` + ')'
367 filename = self.canonic(frame.f_code.co_filename)
372 filename = self.canonic(frame.f_code.co_filename)
368 link = tpl_link % py3compat.cast_unicode(filename)
373 link = tpl_link % py3compat.cast_unicode(filename)
369
374
370 if frame.f_code.co_name:
375 if frame.f_code.co_name:
371 func = frame.f_code.co_name
376 func = frame.f_code.co_name
372 else:
377 else:
373 func = "<lambda>"
378 func = "<lambda>"
374
379
375 call = ''
380 call = ''
376 if func != '?':
381 if func != '?':
377 if '__args__' in frame.f_locals:
382 if '__args__' in frame.f_locals:
378 args = reprlib.repr(frame.f_locals['__args__'])
383 args = reprlib.repr(frame.f_locals['__args__'])
379 else:
384 else:
380 args = '()'
385 args = '()'
381 call = tpl_call % (func, args)
386 call = tpl_call % (func, args)
382
387
383 # The level info should be generated in the same format pdb uses, to
388 # The level info should be generated in the same format pdb uses, to
384 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
389 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
385 if frame is self.curframe:
390 if frame is self.curframe:
386 ret.append('> ')
391 ret.append('> ')
387 else:
392 else:
388 ret.append(' ')
393 ret.append(' ')
389 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
394 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
390
395
391 start = lineno - 1 - context//2
396 start = lineno - 1 - context//2
392 lines = ulinecache.getlines(filename)
397 lines = ulinecache.getlines(filename)
393 start = min(start, len(lines) - context)
398 start = min(start, len(lines) - context)
394 start = max(start, 0)
399 start = max(start, 0)
395 lines = lines[start : start + context]
400 lines = lines[start : start + context]
396
401
397 for i,line in enumerate(lines):
402 for i,line in enumerate(lines):
398 show_arrow = (start + 1 + i == lineno)
403 show_arrow = (start + 1 + i == lineno)
399 linetpl = (frame is self.curframe or show_arrow) \
404 linetpl = (frame is self.curframe or show_arrow) \
400 and tpl_line_em \
405 and tpl_line_em \
401 or tpl_line
406 or tpl_line
402 ret.append(self.__format_line(linetpl, filename,
407 ret.append(self.__format_line(linetpl, filename,
403 start + 1 + i, line,
408 start + 1 + i, line,
404 arrow = show_arrow) )
409 arrow = show_arrow) )
405 return ''.join(ret)
410 return ''.join(ret)
406
411
407 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
412 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
408 bp_mark = ""
413 bp_mark = ""
409 bp_mark_color = ""
414 bp_mark_color = ""
410
415
411 scheme = self.color_scheme_table.active_scheme_name
416 scheme = self.color_scheme_table.active_scheme_name
412 new_line, err = self.parser.format2(line, 'str', scheme)
417 new_line, err = self.parser.format2(line, 'str', scheme)
413 if not err: line = new_line
418 if not err: line = new_line
414
419
415 bp = None
420 bp = None
416 if lineno in self.get_file_breaks(filename):
421 if lineno in self.get_file_breaks(filename):
417 bps = self.get_breaks(filename, lineno)
422 bps = self.get_breaks(filename, lineno)
418 bp = bps[-1]
423 bp = bps[-1]
419
424
420 if bp:
425 if bp:
421 Colors = self.color_scheme_table.active_colors
426 Colors = self.color_scheme_table.active_colors
422 bp_mark = str(bp.number)
427 bp_mark = str(bp.number)
423 bp_mark_color = Colors.breakpoint_enabled
428 bp_mark_color = Colors.breakpoint_enabled
424 if not bp.enabled:
429 if not bp.enabled:
425 bp_mark_color = Colors.breakpoint_disabled
430 bp_mark_color = Colors.breakpoint_disabled
426
431
427 numbers_width = 7
432 numbers_width = 7
428 if arrow:
433 if arrow:
429 # This is the line with the error
434 # This is the line with the error
430 pad = numbers_width - len(str(lineno)) - len(bp_mark)
435 pad = numbers_width - len(str(lineno)) - len(bp_mark)
431 if pad >= 3:
436 if pad >= 3:
432 marker = '-'*(pad-3) + '-> '
437 marker = '-'*(pad-3) + '-> '
433 elif pad == 2:
438 elif pad == 2:
434 marker = '> '
439 marker = '> '
435 elif pad == 1:
440 elif pad == 1:
436 marker = '>'
441 marker = '>'
437 else:
442 else:
438 marker = ''
443 marker = ''
439 num = '%s%s' % (marker, str(lineno))
444 num = '%s%s' % (marker, str(lineno))
440 line = tpl_line % (bp_mark_color + bp_mark, num, line)
445 line = tpl_line % (bp_mark_color + bp_mark, num, line)
441 else:
446 else:
442 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
447 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
443 line = tpl_line % (bp_mark_color + bp_mark, num, line)
448 line = tpl_line % (bp_mark_color + bp_mark, num, line)
444
449
445 return line
450 return line
446
451
447 def list_command_pydb(self, arg):
452 def list_command_pydb(self, arg):
448 """List command to use if we have a newer pydb installed"""
453 """List command to use if we have a newer pydb installed"""
449 filename, first, last = OldPdb.parse_list_cmd(self, arg)
454 filename, first, last = OldPdb.parse_list_cmd(self, arg)
450 if filename is not None:
455 if filename is not None:
451 self.print_list_lines(filename, first, last)
456 self.print_list_lines(filename, first, last)
452
457
453 def print_list_lines(self, filename, first, last):
458 def print_list_lines(self, filename, first, last):
454 """The printing (as opposed to the parsing part of a 'list'
459 """The printing (as opposed to the parsing part of a 'list'
455 command."""
460 command."""
456 try:
461 try:
457 Colors = self.color_scheme_table.active_colors
462 Colors = self.color_scheme_table.active_colors
458 ColorsNormal = Colors.Normal
463 ColorsNormal = Colors.Normal
459 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
464 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
460 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
465 tpl_line_em = '%%s%s%%s %s%%s%s' % (Colors.linenoEm, Colors.line, ColorsNormal)
461 src = []
466 src = []
462 if filename == "<string>" and hasattr(self, "_exec_filename"):
467 if filename == "<string>" and hasattr(self, "_exec_filename"):
463 filename = self._exec_filename
468 filename = self._exec_filename
464
469
465 for lineno in range(first, last+1):
470 for lineno in range(first, last+1):
466 line = ulinecache.getline(filename, lineno)
471 line = ulinecache.getline(filename, lineno)
467 if not line:
472 if not line:
468 break
473 break
469
474
470 if lineno == self.curframe.f_lineno:
475 if lineno == self.curframe.f_lineno:
471 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
476 line = self.__format_line(tpl_line_em, filename, lineno, line, arrow = True)
472 else:
477 else:
473 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
478 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
474
479
475 src.append(line)
480 src.append(line)
476 self.lineno = lineno
481 self.lineno = lineno
477
482
478 print(''.join(src), file=io.stdout)
483 print(''.join(src), file=io.stdout)
479
484
480 except KeyboardInterrupt:
485 except KeyboardInterrupt:
481 pass
486 pass
482
487
483 def do_list(self, arg):
488 def do_list(self, arg):
484 self.lastcmd = 'list'
489 self.lastcmd = 'list'
485 last = None
490 last = None
486 if arg:
491 if arg:
487 try:
492 try:
488 x = eval(arg, {}, {})
493 x = eval(arg, {}, {})
489 if type(x) == type(()):
494 if type(x) == type(()):
490 first, last = x
495 first, last = x
491 first = int(first)
496 first = int(first)
492 last = int(last)
497 last = int(last)
493 if last < first:
498 if last < first:
494 # Assume it's a count
499 # Assume it's a count
495 last = first + last
500 last = first + last
496 else:
501 else:
497 first = max(1, int(x) - 5)
502 first = max(1, int(x) - 5)
498 except:
503 except:
499 print('*** Error in argument:', repr(arg))
504 print('*** Error in argument:', repr(arg))
500 return
505 return
501 elif self.lineno is None:
506 elif self.lineno is None:
502 first = max(1, self.curframe.f_lineno - 5)
507 first = max(1, self.curframe.f_lineno - 5)
503 else:
508 else:
504 first = self.lineno + 1
509 first = self.lineno + 1
505 if last is None:
510 if last is None:
506 last = first + 10
511 last = first + 10
507 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
512 self.print_list_lines(self.curframe.f_code.co_filename, first, last)
508
513
509 # vds: >>
514 # vds: >>
510 lineno = first
515 lineno = first
511 filename = self.curframe.f_code.co_filename
516 filename = self.curframe.f_code.co_filename
512 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
517 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
513 # vds: <<
518 # vds: <<
514
519
515 do_l = do_list
520 do_l = do_list
516
521
517 def getsourcelines(self, obj):
522 def getsourcelines(self, obj):
518 lines, lineno = inspect.findsource(obj)
523 lines, lineno = inspect.findsource(obj)
519 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
524 if inspect.isframe(obj) and obj.f_globals is obj.f_locals:
520 # must be a module frame: do not try to cut a block out of it
525 # must be a module frame: do not try to cut a block out of it
521 return lines, 1
526 return lines, 1
522 elif inspect.ismodule(obj):
527 elif inspect.ismodule(obj):
523 return lines, 1
528 return lines, 1
524 return inspect.getblock(lines[lineno:]), lineno+1
529 return inspect.getblock(lines[lineno:]), lineno+1
525
530
526 def do_longlist(self, arg):
531 def do_longlist(self, arg):
527 self.lastcmd = 'longlist'
532 self.lastcmd = 'longlist'
528 filename = self.curframe.f_code.co_filename
533 filename = self.curframe.f_code.co_filename
529 breaklist = self.get_file_breaks(filename)
534 breaklist = self.get_file_breaks(filename)
530 try:
535 try:
531 lines, lineno = self.getsourcelines(self.curframe)
536 lines, lineno = self.getsourcelines(self.curframe)
532 except OSError as err:
537 except OSError as err:
533 self.error(err)
538 self.error(err)
534 return
539 return
535 last = lineno + len(lines)
540 last = lineno + len(lines)
536 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
541 self.print_list_lines(self.curframe.f_code.co_filename, lineno, last)
537 do_ll = do_longlist
542 do_ll = do_longlist
538
543
539 def do_pdef(self, arg):
544 def do_pdef(self, arg):
540 """Print the call signature for any callable object.
545 """Print the call signature for any callable object.
541
546
542 The debugger interface to %pdef"""
547 The debugger interface to %pdef"""
543 namespaces = [('Locals', self.curframe.f_locals),
548 namespaces = [('Locals', self.curframe.f_locals),
544 ('Globals', self.curframe.f_globals)]
549 ('Globals', self.curframe.f_globals)]
545 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
550 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
546
551
547 def do_pdoc(self, arg):
552 def do_pdoc(self, arg):
548 """Print the docstring for an object.
553 """Print the docstring for an object.
549
554
550 The debugger interface to %pdoc."""
555 The debugger interface to %pdoc."""
551 namespaces = [('Locals', self.curframe.f_locals),
556 namespaces = [('Locals', self.curframe.f_locals),
552 ('Globals', self.curframe.f_globals)]
557 ('Globals', self.curframe.f_globals)]
553 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
558 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
554
559
555 def do_pfile(self, arg):
560 def do_pfile(self, arg):
556 """Print (or run through pager) the file where an object is defined.
561 """Print (or run through pager) the file where an object is defined.
557
562
558 The debugger interface to %pfile.
563 The debugger interface to %pfile.
559 """
564 """
560 namespaces = [('Locals', self.curframe.f_locals),
565 namespaces = [('Locals', self.curframe.f_locals),
561 ('Globals', self.curframe.f_globals)]
566 ('Globals', self.curframe.f_globals)]
562 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
567 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
563
568
564 def do_pinfo(self, arg):
569 def do_pinfo(self, arg):
565 """Provide detailed information about an object.
570 """Provide detailed information about an object.
566
571
567 The debugger interface to %pinfo, i.e., obj?."""
572 The debugger interface to %pinfo, i.e., obj?."""
568 namespaces = [('Locals', self.curframe.f_locals),
573 namespaces = [('Locals', self.curframe.f_locals),
569 ('Globals', self.curframe.f_globals)]
574 ('Globals', self.curframe.f_globals)]
570 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
575 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
571
576
572 def do_pinfo2(self, arg):
577 def do_pinfo2(self, arg):
573 """Provide extra detailed information about an object.
578 """Provide extra detailed information about an object.
574
579
575 The debugger interface to %pinfo2, i.e., obj??."""
580 The debugger interface to %pinfo2, i.e., obj??."""
576 namespaces = [('Locals', self.curframe.f_locals),
581 namespaces = [('Locals', self.curframe.f_locals),
577 ('Globals', self.curframe.f_globals)]
582 ('Globals', self.curframe.f_globals)]
578 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
583 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
579
584
580 def do_psource(self, arg):
585 def do_psource(self, arg):
581 """Print (or run through pager) the source code for an object."""
586 """Print (or run through pager) the source code for an object."""
582 namespaces = [('Locals', self.curframe.f_locals),
587 namespaces = [('Locals', self.curframe.f_locals),
583 ('Globals', self.curframe.f_globals)]
588 ('Globals', self.curframe.f_globals)]
584 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
589 self.shell.find_line_magic('psource')(arg, namespaces=namespaces)
General Comments 0
You need to be logged in to leave comments. Login now