Show More
@@ -0,0 +1,73 b'' | |||||
|
1 | """ Debug a script (like %run -d) in IPython process, Using WinPdb | |||
|
2 | ||||
|
3 | Usage: | |||
|
4 | ||||
|
5 | %wdb test.py | |||
|
6 | run test.py, with a winpdb breakpoint at start of the file | |||
|
7 | ||||
|
8 | %wdb pass | |||
|
9 | Change the password (e.g. if you have forgotten the old one) | |||
|
10 | """ | |||
|
11 | ||||
|
12 | import os | |||
|
13 | ||||
|
14 | import IPython.ipapi | |||
|
15 | import rpdb2 | |||
|
16 | ||||
|
17 | ip = IPython.ipapi.get() | |||
|
18 | ||||
|
19 | rpdb_started = False | |||
|
20 | ||||
|
21 | def wdb_f(self, arg): | |||
|
22 | """ Debug a script (like %run -d) in IPython process, Using WinPdb | |||
|
23 | ||||
|
24 | Usage: | |||
|
25 | ||||
|
26 | %wdb test.py | |||
|
27 | run test.py, with a winpdb breakpoint at start of the file | |||
|
28 | ||||
|
29 | %wdb pass | |||
|
30 | Change the password (e.g. if you have forgotten the old one) | |||
|
31 | ||||
|
32 | Note that after the script has been run, you need to do "Go" (f5) | |||
|
33 | in WinPdb to resume normal IPython operation. | |||
|
34 | """ | |||
|
35 | ||||
|
36 | global rpdb_started | |||
|
37 | if not arg.strip(): | |||
|
38 | print __doc__ | |||
|
39 | return | |||
|
40 | ||||
|
41 | if arg.strip() == 'pass': | |||
|
42 | passwd = raw_input('Enter new winpdb session password: ') | |||
|
43 | ip.db['winpdb_pass'] = passwd | |||
|
44 | print "Winpdb password changed" | |||
|
45 | if rpdb_started: | |||
|
46 | print "You need to restart IPython to use the new password" | |||
|
47 | return | |||
|
48 | ||||
|
49 | path = os.path.abspath(arg) | |||
|
50 | if not os.path.isfile(path): | |||
|
51 | raise IPython.ipapi.UsageError("%%wdb: file %s does not exist" % path) | |||
|
52 | if not rpdb_started: | |||
|
53 | passwd = ip.db.get('winpdb_pass', None) | |||
|
54 | if passwd is None: | |||
|
55 | import textwrap | |||
|
56 | print textwrap.dedent("""\ | |||
|
57 | Winpdb sessions need a password that you use for attaching the external | |||
|
58 | winpdb session. IPython will remember this. You can change the password later | |||
|
59 | by '%wpdb pass' | |||
|
60 | """) | |||
|
61 | passwd = raw_input('Enter new winpdb session password: ') | |||
|
62 | ip.db['winpdb_pass'] = passwd | |||
|
63 | ||||
|
64 | print "Starting rpdb2 in IPython process" | |||
|
65 | rpdb2.start_embedded_debugger(passwd, timeout = 0) | |||
|
66 | rpdb_started = True | |||
|
67 | ||||
|
68 | rpdb2.set_temp_breakpoint(path) | |||
|
69 | print 'It is time to attach with WinPdb (launch WinPdb if needed, File -> Attach)' | |||
|
70 | ip.magic('%run ' + arg) | |||
|
71 | ||||
|
72 | ||||
|
73 | ip.expose_magic('wdb', wdb_f) |
@@ -87,6 +87,8 b' def main():' | |||||
87 | # For bzr completer, requires bzrlib (the python installation of bzr) |
|
87 | # For bzr completer, requires bzrlib (the python installation of bzr) | |
88 | #import ipy_bzr |
|
88 | #import ipy_bzr | |
89 |
|
89 | |||
|
90 | ||||
|
91 | ||||
90 | # some config helper functions you can use |
|
92 | # some config helper functions you can use | |
91 | def import_all(modules): |
|
93 | def import_all(modules): | |
92 | """ Usage: import_all("os sys") """ |
|
94 | """ Usage: import_all("os sys") """ |
@@ -92,7 +92,7 b' class NonBlockingIPShell(object):' | |||||
92 |
|
92 | |||
93 | def __init__(self,argv=[],user_ns={},user_global_ns=None, |
|
93 | def __init__(self,argv=[],user_ns={},user_global_ns=None, | |
94 | cin=None, cout=None, cerr=None, |
|
94 | cin=None, cout=None, cerr=None, | |
95 | ask_exit_handler=None): |
|
95 | ask_exit_handler=None, rawinput=None): | |
96 | ''' |
|
96 | ''' | |
97 | @param argv: Command line options for IPython |
|
97 | @param argv: Command line options for IPython | |
98 | @type argv: list |
|
98 | @type argv: list | |
@@ -114,7 +114,7 b' class NonBlockingIPShell(object):' | |||||
114 | #ipython0 initialisation |
|
114 | #ipython0 initialisation | |
115 | self.initIpython0(argv, user_ns, user_global_ns, |
|
115 | self.initIpython0(argv, user_ns, user_global_ns, | |
116 | cin, cout, cerr, |
|
116 | cin, cout, cerr, | |
117 | ask_exit_handler) |
|
117 | ask_exit_handler, rawinput) | |
118 |
|
118 | |||
119 | #vars used by _execute |
|
119 | #vars used by _execute | |
120 | self._iter_more = 0 |
|
120 | self._iter_more = 0 | |
@@ -133,7 +133,7 b' class NonBlockingIPShell(object):' | |||||
133 |
|
133 | |||
134 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, |
|
134 | def initIpython0(self, argv=[], user_ns={}, user_global_ns=None, | |
135 | cin=None, cout=None, cerr=None, |
|
135 | cin=None, cout=None, cerr=None, | |
136 | ask_exit_handler=None): |
|
136 | ask_exit_handler=None, rawinput=None): | |
137 | #first we redefine in/out/error functions of IPython |
|
137 | #first we redefine in/out/error functions of IPython | |
138 | if cin: |
|
138 | if cin: | |
139 | IPython.Shell.Term.cin = cin |
|
139 | IPython.Shell.Term.cin = cin | |
@@ -167,7 +167,8 b' class NonBlockingIPShell(object):' | |||||
167 | self._IP.set_hook('shell_hook',self._shell) |
|
167 | self._IP.set_hook('shell_hook',self._shell) | |
168 |
|
168 | |||
169 | #we replace the ipython default input command caller by our method |
|
169 | #we replace the ipython default input command caller by our method | |
170 |
IPython.iplib.raw_input_original = |
|
170 | IPython.iplib.raw_input_original = rawinput | |
|
171 | ||||
171 | #we replace the ipython default exit command by our method |
|
172 | #we replace the ipython default exit command by our method | |
172 | self._IP.exit = ask_exit_handler |
|
173 | self._IP.exit = ask_exit_handler | |
173 | #we replace the help command |
|
174 | #we replace the help command | |
@@ -339,12 +340,6 b' class NonBlockingIPShell(object):' | |||||
339 | ''' |
|
340 | ''' | |
340 | pass |
|
341 | pass | |
341 |
|
342 | |||
342 | #def _askExit(self): |
|
|||
343 | # ''' |
|
|||
344 | # Can be redefined to generate post event to exit the Ipython shell |
|
|||
345 | # ''' |
|
|||
346 | # pass |
|
|||
347 |
|
||||
348 | def _getHistoryMaxIndex(self): |
|
343 | def _getHistoryMaxIndex(self): | |
349 | ''' |
|
344 | ''' | |
350 | returns the max length of the history buffer |
|
345 | returns the max length of the history buffer | |
@@ -385,18 +380,6 b' class NonBlockingIPShell(object):' | |||||
385 | ''' |
|
380 | ''' | |
386 | self._doc_text = text |
|
381 | self._doc_text = text | |
387 |
|
382 | |||
388 | def _raw_input(self, prompt=''): |
|
|||
389 | ''' |
|
|||
390 | Custom raw_input() replacement. Get's current line from console buffer. |
|
|||
391 |
|
||||
392 | @param prompt: Prompt to print. Here for compatability as replacement. |
|
|||
393 | @type prompt: string |
|
|||
394 |
|
||||
395 | @return: The current command line text. |
|
|||
396 | @rtype: string |
|
|||
397 | ''' |
|
|||
398 | return self._line_to_execute |
|
|||
399 |
|
||||
400 | def _execute(self): |
|
383 | def _execute(self): | |
401 | ''' |
|
384 | ''' | |
402 | Executes the current line provided by the shell object. |
|
385 | Executes the current line provided by the shell object. |
@@ -47,11 +47,12 b' class WxNonBlockingIPShell(NonBlockingIPShell):' | |||||
47 | def __init__(self, parent, |
|
47 | def __init__(self, parent, | |
48 | argv=[],user_ns={},user_global_ns=None, |
|
48 | argv=[],user_ns={},user_global_ns=None, | |
49 | cin=None, cout=None, cerr=None, |
|
49 | cin=None, cout=None, cerr=None, | |
50 | ask_exit_handler=None): |
|
50 | ask_exit_handler=None, rawinput=None): | |
51 |
|
51 | |||
52 | NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns, |
|
52 | NonBlockingIPShell.__init__(self,argv,user_ns,user_global_ns, | |
53 | cin, cout, cerr, |
|
53 | cin, cout, cerr, | |
54 |
ask_exit_handler |
|
54 | ask_exit_handler, | |
|
55 | rawinput) | |||
55 |
|
56 | |||
56 | self.parent = parent |
|
57 | self.parent = parent | |
57 |
|
58 | |||
@@ -302,18 +303,6 b' class WxConsoleView(stc.StyledTextCtrl):' | |||||
302 | return self.GetTextRange(self.getCurrentPromptStart(), |
|
303 | return self.GetTextRange(self.getCurrentPromptStart(), | |
303 | self.getCurrentLineEnd()) |
|
304 | self.getCurrentLineEnd()) | |
304 |
|
305 | |||
305 | def showReturned(self, text): |
|
|||
306 | ''' |
|
|||
307 | Show returned text from last command and print new prompt. |
|
|||
308 |
|
||||
309 | @param text: Text to show. |
|
|||
310 | @type text: string |
|
|||
311 | ''' |
|
|||
312 | self.write('\n'+text) |
|
|||
313 | if text: |
|
|||
314 | self.write('\n') |
|
|||
315 | self.showPrompt() |
|
|||
316 |
|
||||
317 | def moveCursorOnNewValidKey(self): |
|
306 | def moveCursorOnNewValidKey(self): | |
318 | #If cursor is at wrong position put it at last line... |
|
307 | #If cursor is at wrong position put it at last line... | |
319 | if self.GetCurrentPos() < self.getCurrentPromptStart(): |
|
308 | if self.GetCurrentPos() < self.getCurrentPromptStart(): | |
@@ -406,7 +395,7 b' class WxConsoleView(stc.StyledTextCtrl):' | |||||
406 | elif event.GetKeyCode() == wx.WXK_BACK: |
|
395 | elif event.GetKeyCode() == wx.WXK_BACK: | |
407 | self.moveCursorOnNewValidKey() |
|
396 | self.moveCursorOnNewValidKey() | |
408 | if self.getCursorPos() > self.getCurrentPromptStart(): |
|
397 | if self.getCursorPos() > self.getCurrentPromptStart(): | |
409 | self.removeFromTo(self.getCursorPos()-1,self.getCursorPos()) |
|
398 | event.Skip() | |
410 | return True |
|
399 | return True | |
411 |
|
400 | |||
412 | if skip: |
|
401 | if skip: | |
@@ -461,6 +450,7 b' class IPShellWidget(wx.Panel):' | |||||
461 | because it seems to be more useful |
|
450 | because it seems to be more useful | |
462 | Any idea to make it more 'generic' welcomed. |
|
451 | Any idea to make it more 'generic' welcomed. | |
463 | ''' |
|
452 | ''' | |
|
453 | ||||
464 | def __init__(self, parent, intro=None, |
|
454 | def __init__(self, parent, intro=None, | |
465 | background_color="BLACK", add_button_handler=None, |
|
455 | background_color="BLACK", add_button_handler=None, | |
466 | wx_ip_shell=None, |
|
456 | wx_ip_shell=None, | |
@@ -475,15 +465,15 b' class IPShellWidget(wx.Panel):' | |||||
475 |
|
465 | |||
476 | ### IPython non blocking shell instanciation ### |
|
466 | ### IPython non blocking shell instanciation ### | |
477 | self.cout = StringIO() |
|
467 | self.cout = StringIO() | |
478 |
|
||||
479 | self.add_button_handler = add_button_handler |
|
468 | self.add_button_handler = add_button_handler | |
480 |
|
469 | |||
481 | if wx_ip_shell is not None: |
|
470 | if wx_ip_shell is not None: | |
482 | self.IP = wx_ip_shell |
|
471 | self.IP = wx_ip_shell | |
483 | else: |
|
472 | else: | |
484 | self.IP = WxNonBlockingIPShell(self, |
|
473 | self.IP = WxNonBlockingIPShell(self, | |
485 | cout = self.cout,cerr = self.cout, |
|
474 | cout = self.cout, cerr = self.cout, | |
486 |
ask_exit_handler = self.askExitCallback |
|
475 | ask_exit_handler = self.askExitCallback, | |
|
476 | rawinput = self.rawInput) | |||
487 |
|
477 | |||
488 | ### IPython wx console view instanciation ### |
|
478 | ### IPython wx console view instanciation ### | |
489 | #If user didn't defined an intro text, we create one for him |
|
479 | #If user didn't defined an intro text, we create one for him | |
@@ -501,9 +491,11 b' class IPShellWidget(wx.Panel):' | |||||
501 | self.IP.getPrompt(), |
|
491 | self.IP.getPrompt(), | |
502 | intro=welcome_text, |
|
492 | intro=welcome_text, | |
503 | background_color=background_color) |
|
493 | background_color=background_color) | |
|
494 | ||||
|
495 | self.cout.write = self.text_ctrl.write | |||
504 |
|
496 | |||
505 | self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl) |
|
497 | self.text_ctrl.Bind(wx.EVT_KEY_DOWN, self.keyPress, self.text_ctrl) | |
506 |
|
498 | |||
507 | ### making the layout of the panel ### |
|
499 | ### making the layout of the panel ### | |
508 | sizer = wx.BoxSizer(wx.VERTICAL) |
|
500 | sizer = wx.BoxSizer(wx.VERTICAL) | |
509 | sizer.Add(self.text_ctrl, 1, wx.EXPAND) |
|
501 | sizer.Add(self.text_ctrl, 1, wx.EXPAND) | |
@@ -525,6 +517,7 b' class IPShellWidget(wx.Panel):' | |||||
525 | def stateDoExecuteLine(self): |
|
517 | def stateDoExecuteLine(self): | |
526 | #print >>sys.__stdout__,"command:",self.getCurrentLine() |
|
518 | #print >>sys.__stdout__,"command:",self.getCurrentLine() | |
527 | line=self.text_ctrl.getCurrentLine() |
|
519 | line=self.text_ctrl.getCurrentLine() | |
|
520 | self.text_ctrl.write('\n') | |||
528 | self.IP.doExecute((line.replace('\t',' '*4)).encode('cp1252')) |
|
521 | self.IP.doExecute((line.replace('\t',' '*4)).encode('cp1252')) | |
529 | self.updateHistoryTracker(self.text_ctrl.getCurrentLine()) |
|
522 | self.updateHistoryTracker(self.text_ctrl.getCurrentLine()) | |
530 | self.setCurrentState('WAIT_END_OF_EXECUTION') |
|
523 | self.setCurrentState('WAIT_END_OF_EXECUTION') | |
@@ -550,19 +543,24 b' class IPShellWidget(wx.Panel):' | |||||
550 | self.text_ctrl.setPrompt(self.IP.getPrompt()) |
|
543 | self.text_ctrl.setPrompt(self.IP.getPrompt()) | |
551 | self.text_ctrl.setIndentation(self.IP.getIndentation()) |
|
544 | self.text_ctrl.setIndentation(self.IP.getIndentation()) | |
552 | self.text_ctrl.setPromptCount(self.IP.getPromptCount()) |
|
545 | self.text_ctrl.setPromptCount(self.IP.getPromptCount()) | |
553 | rv = self.cout.getvalue() |
|
546 | self.text_ctrl.showPrompt() | |
554 | if rv: rv = rv.strip('\n') |
|
|||
555 | self.text_ctrl.showReturned(rv) |
|
|||
556 | self.cout.truncate(0) |
|
|||
557 | self.IP.initHistoryIndex() |
|
547 | self.IP.initHistoryIndex() | |
558 | self.setCurrentState('IDLE') |
|
548 | self.setCurrentState('IDLE') | |
559 |
|
549 | |||
560 | def setCurrentState(self, state): |
|
550 | def setCurrentState(self, state): | |
561 | self.cur_state = state |
|
551 | self.cur_state = state | |
562 | self.updateStatusTracker(self.cur_state) |
|
552 | self.updateStatusTracker(self.cur_state) | |
563 |
|
553 | #---------------------------- Ipython raw_input ----------------------------------- | ||
|
554 | def rawInput(self, prompt=''): | |||
|
555 | self.setCurrentState('WAITING_USER_INPUT') | |||
|
556 | while self.cur_state != 'WAIT_END_OF_EXECUTION': | |||
|
557 | pass | |||
|
558 | line = self.text_ctrl.getCurrentLine() | |||
|
559 | line = line.split('\n') | |||
|
560 | return line[-2] | |||
|
561 | ||||
564 | #---------------------------- IPython pager --------------------------------------- |
|
562 | #---------------------------- IPython pager --------------------------------------- | |
565 | def pager(self,text):#,start=0,screen_lines=0,pager_cmd = None): |
|
563 | def pager(self,text): | |
566 |
|
564 | |||
567 | if self.pager_state == 'INIT': |
|
565 | if self.pager_state == 'INIT': | |
568 | #print >>sys.__stdout__,"PAGER state:",self.pager_state |
|
566 | #print >>sys.__stdout__,"PAGER state:",self.pager_state | |
@@ -635,13 +633,21 b' class IPShellWidget(wx.Panel):' | |||||
635 | self.pager(self.doc) |
|
633 | self.pager(self.doc) | |
636 | return |
|
634 | return | |
637 |
|
635 | |||
|
636 | if self.cur_state == 'WAITING_USER_INPUT': | |||
|
637 | line=self.text_ctrl.getCurrentLine() | |||
|
638 | self.text_ctrl.write('\n') | |||
|
639 | self.setCurrentState('WAIT_END_OF_EXECUTION') | |||
|
640 | return | |||
|
641 | ||||
638 | if event.GetKeyCode() in [ord('q'),ord('Q')]: |
|
642 | if event.GetKeyCode() in [ord('q'),ord('Q')]: | |
639 | if self.pager_state == 'WAITING': |
|
643 | if self.pager_state == 'WAITING': | |
640 | self.pager_state = 'DONE' |
|
644 | self.pager_state = 'DONE' | |
641 | self.stateShowPrompt() |
|
645 | self.stateShowPrompt() | |
642 | return |
|
646 | return | |
643 |
|
647 | |||
644 | #scroll_position = self.text_ctrl.GetScrollPos(wx.VERTICAL) |
|
648 | if self.cur_state == 'WAITING_USER_INPUT': | |
|
649 | event.Skip() | |||
|
650 | ||||
645 | if self.cur_state == 'IDLE': |
|
651 | if self.cur_state == 'IDLE': | |
646 | if event.KeyCode == wx.WXK_UP: |
|
652 | if event.KeyCode == wx.WXK_UP: | |
647 | history = self.IP.historyBack() |
|
653 | history = self.IP.historyBack() | |
@@ -669,7 +675,7 b' class IPShellWidget(wx.Panel):' | |||||
669 |
|
675 | |||
670 | return |
|
676 | return | |
671 | event.Skip() |
|
677 | event.Skip() | |
672 |
|
678 | |||
673 | #------------------------ Hook Section ----------------------------------- |
|
679 | #------------------------ Hook Section ----------------------------------- | |
674 | def updateHistoryTracker(self,command_line): |
|
680 | def updateHistoryTracker(self,command_line): | |
675 | ''' |
|
681 | ''' |
@@ -36,8 +36,7 b' class MyFrame(wx.Frame):' | |||||
36 |
|
36 | |||
37 | self.ipython_panel = IPShellWidget(self,background_color = "BLACK") |
|
37 | self.ipython_panel = IPShellWidget(self,background_color = "BLACK") | |
38 |
|
38 | |||
39 |
#self.ipython_panel = |
|
39 | #self.ipython_panel = IPShellWidget(self,background_color = "WHITE") | |
40 | # background_color = "WHITE") |
|
|||
41 |
|
40 | |||
42 | self.ipython_panel.setHistoryTrackerHook(self.history_panel.write) |
|
41 | self.ipython_panel.setHistoryTrackerHook(self.history_panel.write) | |
43 | self.ipython_panel.setStatusTrackerHook(self.updateStatus) |
|
42 | self.ipython_panel.setStatusTrackerHook(self.updateStatus) | |
@@ -122,6 +121,7 b' class MyFrame(wx.Frame):' | |||||
122 | states = {'IDLE':'Idle', |
|
121 | states = {'IDLE':'Idle', | |
123 | 'DO_EXECUTE_LINE':'Send command', |
|
122 | 'DO_EXECUTE_LINE':'Send command', | |
124 | 'WAIT_END_OF_EXECUTION':'Running command', |
|
123 | 'WAIT_END_OF_EXECUTION':'Running command', | |
|
124 | 'WAITING_USER_INPUT':'Waiting user input', | |||
125 | 'SHOW_DOC':'Showing doc', |
|
125 | 'SHOW_DOC':'Showing doc', | |
126 | 'SHOW_PROMPT':'Showing prompt'} |
|
126 | 'SHOW_PROMPT':'Showing prompt'} | |
127 | self.statusbar.SetStatusText(states[text], 0) |
|
127 | self.statusbar.SetStatusText(states[text], 0) |
General Comments 0
You need to be logged in to leave comments.
Login now