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