##// END OF EJS Templates
Make sure prompt color doesn't affect rest of line
Gábor Luk -
Show More
@@ -1,589 +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 # 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' % (Colors.prompt, prompt) # 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 except KeyboardInterrupt:
285 except KeyboardInterrupt:
286 self.shell.write('\n' + self.shell.get_exception_only())
286 self.shell.write('\n' + self.shell.get_exception_only())
287 break
287 break
288 else:
288 else:
289 break
289 break
290
290
291 def new_do_up(self, arg):
291 def new_do_up(self, arg):
292 OldPdb.do_up(self, arg)
292 OldPdb.do_up(self, arg)
293 self.shell.set_completer_frame(self.curframe)
293 self.shell.set_completer_frame(self.curframe)
294 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)
295
295
296 def new_do_down(self, arg):
296 def new_do_down(self, arg):
297 OldPdb.do_down(self, arg)
297 OldPdb.do_down(self, arg)
298 self.shell.set_completer_frame(self.curframe)
298 self.shell.set_completer_frame(self.curframe)
299
299
300 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)
301
301
302 def new_do_frame(self, arg):
302 def new_do_frame(self, arg):
303 OldPdb.do_frame(self, arg)
303 OldPdb.do_frame(self, arg)
304 self.shell.set_completer_frame(self.curframe)
304 self.shell.set_completer_frame(self.curframe)
305
305
306 def new_do_quit(self, arg):
306 def new_do_quit(self, arg):
307
307
308 if hasattr(self, 'old_all_completions'):
308 if hasattr(self, 'old_all_completions'):
309 self.shell.Completer.all_completions=self.old_all_completions
309 self.shell.Completer.all_completions=self.old_all_completions
310
310
311 # Pdb sets readline delimiters, so set them back to our own
311 # Pdb sets readline delimiters, so set them back to our own
312 if self.shell.readline is not None:
312 if self.shell.readline is not None:
313 self.shell.readline.set_completer_delims(self.shell.readline_delims)
313 self.shell.readline.set_completer_delims(self.shell.readline_delims)
314
314
315 return OldPdb.do_quit(self, arg)
315 return OldPdb.do_quit(self, arg)
316
316
317 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)
318
318
319 def new_do_restart(self, arg):
319 def new_do_restart(self, arg):
320 """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
321 thing as 'quit'."""
321 thing as 'quit'."""
322 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
322 self.msg("Restart doesn't make sense here. Using 'quit' instead.")
323 return self.do_quit(arg)
323 return self.do_quit(arg)
324
324
325 def postloop(self):
325 def postloop(self):
326 self.shell.set_completer_frame(None)
326 self.shell.set_completer_frame(None)
327
327
328 def print_stack_trace(self):
328 def print_stack_trace(self):
329 try:
329 try:
330 for frame_lineno in self.stack:
330 for frame_lineno in self.stack:
331 self.print_stack_entry(frame_lineno, context = 5)
331 self.print_stack_entry(frame_lineno, context = 5)
332 except KeyboardInterrupt:
332 except KeyboardInterrupt:
333 pass
333 pass
334
334
335 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
335 def print_stack_entry(self,frame_lineno,prompt_prefix='\n-> ',
336 context = 3):
336 context = 3):
337 #frame, lineno = frame_lineno
337 #frame, lineno = frame_lineno
338 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
338 print(self.format_stack_entry(frame_lineno, '', context), file=io.stdout)
339
339
340 # vds: >>
340 # vds: >>
341 frame, lineno = frame_lineno
341 frame, lineno = frame_lineno
342 filename = frame.f_code.co_filename
342 filename = frame.f_code.co_filename
343 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
343 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
344 # vds: <<
344 # vds: <<
345
345
346 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
346 def format_stack_entry(self, frame_lineno, lprefix=': ', context = 3):
347 try:
347 try:
348 import reprlib # Py 3
348 import reprlib # Py 3
349 except ImportError:
349 except ImportError:
350 import repr as reprlib # Py 2
350 import repr as reprlib # Py 2
351
351
352 ret = []
352 ret = []
353
353
354 Colors = self.color_scheme_table.active_colors
354 Colors = self.color_scheme_table.active_colors
355 ColorsNormal = Colors.Normal
355 ColorsNormal = Colors.Normal
356 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
356 tpl_link = u'%s%%s%s' % (Colors.filenameEm, ColorsNormal)
357 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)
358 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
358 tpl_line = u'%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
359 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,
360 ColorsNormal)
360 ColorsNormal)
361
361
362 frame, lineno = frame_lineno
362 frame, lineno = frame_lineno
363
363
364 return_value = ''
364 return_value = ''
365 if '__return__' in frame.f_locals:
365 if '__return__' in frame.f_locals:
366 rv = frame.f_locals['__return__']
366 rv = frame.f_locals['__return__']
367 #return_value += '->'
367 #return_value += '->'
368 return_value += reprlib.repr(rv) + '\n'
368 return_value += reprlib.repr(rv) + '\n'
369 ret.append(return_value)
369 ret.append(return_value)
370
370
371 #s = filename + '(' + `lineno` + ')'
371 #s = filename + '(' + `lineno` + ')'
372 filename = self.canonic(frame.f_code.co_filename)
372 filename = self.canonic(frame.f_code.co_filename)
373 link = tpl_link % py3compat.cast_unicode(filename)
373 link = tpl_link % py3compat.cast_unicode(filename)
374
374
375 if frame.f_code.co_name:
375 if frame.f_code.co_name:
376 func = frame.f_code.co_name
376 func = frame.f_code.co_name
377 else:
377 else:
378 func = "<lambda>"
378 func = "<lambda>"
379
379
380 call = ''
380 call = ''
381 if func != '?':
381 if func != '?':
382 if '__args__' in frame.f_locals:
382 if '__args__' in frame.f_locals:
383 args = reprlib.repr(frame.f_locals['__args__'])
383 args = reprlib.repr(frame.f_locals['__args__'])
384 else:
384 else:
385 args = '()'
385 args = '()'
386 call = tpl_call % (func, args)
386 call = tpl_call % (func, args)
387
387
388 # 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
389 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
389 # avoid breaking the pdbtrack functionality of python-mode in *emacs.
390 if frame is self.curframe:
390 if frame is self.curframe:
391 ret.append('> ')
391 ret.append('> ')
392 else:
392 else:
393 ret.append(' ')
393 ret.append(' ')
394 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
394 ret.append(u'%s(%s)%s\n' % (link,lineno,call))
395
395
396 start = lineno - 1 - context//2
396 start = lineno - 1 - context//2
397 lines = ulinecache.getlines(filename)
397 lines = ulinecache.getlines(filename)
398 start = min(start, len(lines) - context)
398 start = min(start, len(lines) - context)
399 start = max(start, 0)
399 start = max(start, 0)
400 lines = lines[start : start + context]
400 lines = lines[start : start + context]
401
401
402 for i,line in enumerate(lines):
402 for i,line in enumerate(lines):
403 show_arrow = (start + 1 + i == lineno)
403 show_arrow = (start + 1 + i == lineno)
404 linetpl = (frame is self.curframe or show_arrow) \
404 linetpl = (frame is self.curframe or show_arrow) \
405 and tpl_line_em \
405 and tpl_line_em \
406 or tpl_line
406 or tpl_line
407 ret.append(self.__format_line(linetpl, filename,
407 ret.append(self.__format_line(linetpl, filename,
408 start + 1 + i, line,
408 start + 1 + i, line,
409 arrow = show_arrow) )
409 arrow = show_arrow) )
410 return ''.join(ret)
410 return ''.join(ret)
411
411
412 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
412 def __format_line(self, tpl_line, filename, lineno, line, arrow = False):
413 bp_mark = ""
413 bp_mark = ""
414 bp_mark_color = ""
414 bp_mark_color = ""
415
415
416 scheme = self.color_scheme_table.active_scheme_name
416 scheme = self.color_scheme_table.active_scheme_name
417 new_line, err = self.parser.format2(line, 'str', scheme)
417 new_line, err = self.parser.format2(line, 'str', scheme)
418 if not err: line = new_line
418 if not err: line = new_line
419
419
420 bp = None
420 bp = None
421 if lineno in self.get_file_breaks(filename):
421 if lineno in self.get_file_breaks(filename):
422 bps = self.get_breaks(filename, lineno)
422 bps = self.get_breaks(filename, lineno)
423 bp = bps[-1]
423 bp = bps[-1]
424
424
425 if bp:
425 if bp:
426 Colors = self.color_scheme_table.active_colors
426 Colors = self.color_scheme_table.active_colors
427 bp_mark = str(bp.number)
427 bp_mark = str(bp.number)
428 bp_mark_color = Colors.breakpoint_enabled
428 bp_mark_color = Colors.breakpoint_enabled
429 if not bp.enabled:
429 if not bp.enabled:
430 bp_mark_color = Colors.breakpoint_disabled
430 bp_mark_color = Colors.breakpoint_disabled
431
431
432 numbers_width = 7
432 numbers_width = 7
433 if arrow:
433 if arrow:
434 # This is the line with the error
434 # This is the line with the error
435 pad = numbers_width - len(str(lineno)) - len(bp_mark)
435 pad = numbers_width - len(str(lineno)) - len(bp_mark)
436 if pad >= 3:
436 if pad >= 3:
437 marker = '-'*(pad-3) + '-> '
437 marker = '-'*(pad-3) + '-> '
438 elif pad == 2:
438 elif pad == 2:
439 marker = '> '
439 marker = '> '
440 elif pad == 1:
440 elif pad == 1:
441 marker = '>'
441 marker = '>'
442 else:
442 else:
443 marker = ''
443 marker = ''
444 num = '%s%s' % (marker, str(lineno))
444 num = '%s%s' % (marker, str(lineno))
445 line = tpl_line % (bp_mark_color + bp_mark, num, line)
445 line = tpl_line % (bp_mark_color + bp_mark, num, line)
446 else:
446 else:
447 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
447 num = '%*s' % (numbers_width - len(bp_mark), str(lineno))
448 line = tpl_line % (bp_mark_color + bp_mark, num, line)
448 line = tpl_line % (bp_mark_color + bp_mark, num, line)
449
449
450 return line
450 return line
451
451
452 def list_command_pydb(self, arg):
452 def list_command_pydb(self, arg):
453 """List command to use if we have a newer pydb installed"""
453 """List command to use if we have a newer pydb installed"""
454 filename, first, last = OldPdb.parse_list_cmd(self, arg)
454 filename, first, last = OldPdb.parse_list_cmd(self, arg)
455 if filename is not None:
455 if filename is not None:
456 self.print_list_lines(filename, first, last)
456 self.print_list_lines(filename, first, last)
457
457
458 def print_list_lines(self, filename, first, last):
458 def print_list_lines(self, filename, first, last):
459 """The printing (as opposed to the parsing part of a 'list'
459 """The printing (as opposed to the parsing part of a 'list'
460 command."""
460 command."""
461 try:
461 try:
462 Colors = self.color_scheme_table.active_colors
462 Colors = self.color_scheme_table.active_colors
463 ColorsNormal = Colors.Normal
463 ColorsNormal = Colors.Normal
464 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
464 tpl_line = '%%s%s%%s %s%%s' % (Colors.lineno, ColorsNormal)
465 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)
466 src = []
466 src = []
467 if filename == "<string>" and hasattr(self, "_exec_filename"):
467 if filename == "<string>" and hasattr(self, "_exec_filename"):
468 filename = self._exec_filename
468 filename = self._exec_filename
469
469
470 for lineno in range(first, last+1):
470 for lineno in range(first, last+1):
471 line = ulinecache.getline(filename, lineno)
471 line = ulinecache.getline(filename, lineno)
472 if not line:
472 if not line:
473 break
473 break
474
474
475 if lineno == self.curframe.f_lineno:
475 if lineno == self.curframe.f_lineno:
476 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)
477 else:
477 else:
478 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
478 line = self.__format_line(tpl_line, filename, lineno, line, arrow = False)
479
479
480 src.append(line)
480 src.append(line)
481 self.lineno = lineno
481 self.lineno = lineno
482
482
483 print(''.join(src), file=io.stdout)
483 print(''.join(src), file=io.stdout)
484
484
485 except KeyboardInterrupt:
485 except KeyboardInterrupt:
486 pass
486 pass
487
487
488 def do_list(self, arg):
488 def do_list(self, arg):
489 self.lastcmd = 'list'
489 self.lastcmd = 'list'
490 last = None
490 last = None
491 if arg:
491 if arg:
492 try:
492 try:
493 x = eval(arg, {}, {})
493 x = eval(arg, {}, {})
494 if type(x) == type(()):
494 if type(x) == type(()):
495 first, last = x
495 first, last = x
496 first = int(first)
496 first = int(first)
497 last = int(last)
497 last = int(last)
498 if last < first:
498 if last < first:
499 # Assume it's a count
499 # Assume it's a count
500 last = first + last
500 last = first + last
501 else:
501 else:
502 first = max(1, int(x) - 5)
502 first = max(1, int(x) - 5)
503 except:
503 except:
504 print('*** Error in argument:', repr(arg))
504 print('*** Error in argument:', repr(arg))
505 return
505 return
506 elif self.lineno is None:
506 elif self.lineno is None:
507 first = max(1, self.curframe.f_lineno - 5)
507 first = max(1, self.curframe.f_lineno - 5)
508 else:
508 else:
509 first = self.lineno + 1
509 first = self.lineno + 1
510 if last is None:
510 if last is None:
511 last = first + 10
511 last = first + 10
512 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)
513
513
514 # vds: >>
514 # vds: >>
515 lineno = first
515 lineno = first
516 filename = self.curframe.f_code.co_filename
516 filename = self.curframe.f_code.co_filename
517 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
517 self.shell.hooks.synchronize_with_editor(filename, lineno, 0)
518 # vds: <<
518 # vds: <<
519
519
520 do_l = do_list
520 do_l = do_list
521
521
522 def getsourcelines(self, obj):
522 def getsourcelines(self, obj):
523 lines, lineno = inspect.findsource(obj)
523 lines, lineno = inspect.findsource(obj)
524 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:
525 # 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
526 return lines, 1
526 return lines, 1
527 elif inspect.ismodule(obj):
527 elif inspect.ismodule(obj):
528 return lines, 1
528 return lines, 1
529 return inspect.getblock(lines[lineno:]), lineno+1
529 return inspect.getblock(lines[lineno:]), lineno+1
530
530
531 def do_longlist(self, arg):
531 def do_longlist(self, arg):
532 self.lastcmd = 'longlist'
532 self.lastcmd = 'longlist'
533 filename = self.curframe.f_code.co_filename
533 filename = self.curframe.f_code.co_filename
534 breaklist = self.get_file_breaks(filename)
534 breaklist = self.get_file_breaks(filename)
535 try:
535 try:
536 lines, lineno = self.getsourcelines(self.curframe)
536 lines, lineno = self.getsourcelines(self.curframe)
537 except OSError as err:
537 except OSError as err:
538 self.error(err)
538 self.error(err)
539 return
539 return
540 last = lineno + len(lines)
540 last = lineno + len(lines)
541 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)
542 do_ll = do_longlist
542 do_ll = do_longlist
543
543
544 def do_pdef(self, arg):
544 def do_pdef(self, arg):
545 """Print the call signature for any callable object.
545 """Print the call signature for any callable object.
546
546
547 The debugger interface to %pdef"""
547 The debugger interface to %pdef"""
548 namespaces = [('Locals', self.curframe.f_locals),
548 namespaces = [('Locals', self.curframe.f_locals),
549 ('Globals', self.curframe.f_globals)]
549 ('Globals', self.curframe.f_globals)]
550 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
550 self.shell.find_line_magic('pdef')(arg, namespaces=namespaces)
551
551
552 def do_pdoc(self, arg):
552 def do_pdoc(self, arg):
553 """Print the docstring for an object.
553 """Print the docstring for an object.
554
554
555 The debugger interface to %pdoc."""
555 The debugger interface to %pdoc."""
556 namespaces = [('Locals', self.curframe.f_locals),
556 namespaces = [('Locals', self.curframe.f_locals),
557 ('Globals', self.curframe.f_globals)]
557 ('Globals', self.curframe.f_globals)]
558 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
558 self.shell.find_line_magic('pdoc')(arg, namespaces=namespaces)
559
559
560 def do_pfile(self, arg):
560 def do_pfile(self, arg):
561 """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.
562
562
563 The debugger interface to %pfile.
563 The debugger interface to %pfile.
564 """
564 """
565 namespaces = [('Locals', self.curframe.f_locals),
565 namespaces = [('Locals', self.curframe.f_locals),
566 ('Globals', self.curframe.f_globals)]
566 ('Globals', self.curframe.f_globals)]
567 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
567 self.shell.find_line_magic('pfile')(arg, namespaces=namespaces)
568
568
569 def do_pinfo(self, arg):
569 def do_pinfo(self, arg):
570 """Provide detailed information about an object.
570 """Provide detailed information about an object.
571
571
572 The debugger interface to %pinfo, i.e., obj?."""
572 The debugger interface to %pinfo, i.e., obj?."""
573 namespaces = [('Locals', self.curframe.f_locals),
573 namespaces = [('Locals', self.curframe.f_locals),
574 ('Globals', self.curframe.f_globals)]
574 ('Globals', self.curframe.f_globals)]
575 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
575 self.shell.find_line_magic('pinfo')(arg, namespaces=namespaces)
576
576
577 def do_pinfo2(self, arg):
577 def do_pinfo2(self, arg):
578 """Provide extra detailed information about an object.
578 """Provide extra detailed information about an object.
579
579
580 The debugger interface to %pinfo2, i.e., obj??."""
580 The debugger interface to %pinfo2, i.e., obj??."""
581 namespaces = [('Locals', self.curframe.f_locals),
581 namespaces = [('Locals', self.curframe.f_locals),
582 ('Globals', self.curframe.f_globals)]
582 ('Globals', self.curframe.f_globals)]
583 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
583 self.shell.find_line_magic('pinfo2')(arg, namespaces=namespaces)
584
584
585 def do_psource(self, arg):
585 def do_psource(self, arg):
586 """Print (or run through pager) the source code for an object."""
586 """Print (or run through pager) the source code for an object."""
587 namespaces = [('Locals', self.curframe.f_locals),
587 namespaces = [('Locals', self.curframe.f_locals),
588 ('Globals', self.curframe.f_globals)]
588 ('Globals', self.curframe.f_globals)]
589 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