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