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