##// END OF EJS Templates
Typo
Maor Kleinberger -
Show More
@@ -1,188 +1,188 b''
1 import asyncio
1 import asyncio
2 import os
2 import os
3 import sys
3 import sys
4
4
5 from IPython.core.debugger import Pdb
5 from IPython.core.debugger import Pdb
6 from IPython.core.completer import IPCompleter
6 from IPython.core.completer import IPCompleter
7 from .ptutils import IPythonPTCompleter
7 from .ptutils import IPythonPTCompleter
8 from .shortcuts import create_ipython_shortcuts
8 from .shortcuts import create_ipython_shortcuts
9 from . import embed
9 from . import embed
10
10
11 from pathlib import Path
11 from pathlib import Path
12 from pygments.token import Token
12 from pygments.token import Token
13 from prompt_toolkit.application import create_app_session
13 from prompt_toolkit.application import create_app_session
14 from prompt_toolkit.shortcuts.prompt import PromptSession
14 from prompt_toolkit.shortcuts.prompt import PromptSession
15 from prompt_toolkit.enums import EditingMode
15 from prompt_toolkit.enums import EditingMode
16 from prompt_toolkit.formatted_text import PygmentsTokens
16 from prompt_toolkit.formatted_text import PygmentsTokens
17 from prompt_toolkit.history import InMemoryHistory, FileHistory
17 from prompt_toolkit.history import InMemoryHistory, FileHistory
18 from concurrent.futures import ThreadPoolExecutor
18 from concurrent.futures import ThreadPoolExecutor
19
19
20 from prompt_toolkit import __version__ as ptk_version
20 from prompt_toolkit import __version__ as ptk_version
21 PTK3 = ptk_version.startswith('3.')
21 PTK3 = ptk_version.startswith('3.')
22
22
23
23
24 # we want to avoid ptk as much as possible when using subprocesses
24 # we want to avoid ptk as much as possible when using subprocesses
25 # as it uses cursor positioning requests, deletes color ....
25 # as it uses cursor positioning requests, deletes color ....
26 _use_simple_prompt = "IPY_TEST_SIMPLE_PROMPT" in os.environ
26 _use_simple_prompt = "IPY_TEST_SIMPLE_PROMPT" in os.environ
27
27
28
28
29 class TerminalPdb(Pdb):
29 class TerminalPdb(Pdb):
30 """Standalone IPython debugger."""
30 """Standalone IPython debugger."""
31
31
32 def __init__(self, *args, pt_session_options=None, **kwargs):
32 def __init__(self, *args, pt_session_options=None, **kwargs):
33 Pdb.__init__(self, *args, **kwargs)
33 Pdb.__init__(self, *args, **kwargs)
34 self._ptcomp = None
34 self._ptcomp = None
35 self.pt_init(pt_session_options)
35 self.pt_init(pt_session_options)
36 self.thread_executor = ThreadPoolExecutor(1)
36 self.thread_executor = ThreadPoolExecutor(1)
37
37
38 def pt_init(self, pt_session_options=None):
38 def pt_init(self, pt_session_options=None):
39 """Initialize the prompt session and the prompt loop
39 """Initialize the prompt session and the prompt loop
40 and store them in self.pt_app and self.pt_loop.
40 and store them in self.pt_app and self.pt_loop.
41
41
42 Additional keyword arguments for the PromptSession class
42 Additional keyword arguments for the PromptSession class
43 can be specified in pt_session_options.
43 can be specified in pt_session_options.
44 """
44 """
45 if pt_session_options is None:
45 if pt_session_options is None:
46 pt_session_options = {}
46 pt_session_options = {}
47
47
48 def get_prompt_tokens():
48 def get_prompt_tokens():
49 return [(Token.Prompt, self.prompt)]
49 return [(Token.Prompt, self.prompt)]
50
50
51 if self._ptcomp is None:
51 if self._ptcomp is None:
52 compl = IPCompleter(
52 compl = IPCompleter(
53 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
53 shell=self.shell, namespace={}, global_namespace={}, parent=self.shell
54 )
54 )
55 # add a completer for all the do_ methods
55 # add a completer for all the do_ methods
56 methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
56 methods_names = [m[3:] for m in dir(self) if m.startswith("do_")]
57
57
58 def gen_comp(self, text):
58 def gen_comp(self, text):
59 return [m for m in methods_names if m.startswith(text)]
59 return [m for m in methods_names if m.startswith(text)]
60 import types
60 import types
61 newcomp = types.MethodType(gen_comp, compl)
61 newcomp = types.MethodType(gen_comp, compl)
62 compl.custom_matchers.insert(0, newcomp)
62 compl.custom_matchers.insert(0, newcomp)
63 # end add completer.
63 # end add completer.
64
64
65 self._ptcomp = IPythonPTCompleter(compl)
65 self._ptcomp = IPythonPTCompleter(compl)
66
66
67 # setup history only when we start pdb
67 # setup history only when we start pdb
68 if self.shell.debugger_history is None:
68 if self.shell.debugger_history is None:
69 if self.shell.debugger_history_file is not None:
69 if self.shell.debugger_history_file is not None:
70
70
71 p = Path(self.shell.debugger_history_file).expanduser()
71 p = Path(self.shell.debugger_history_file).expanduser()
72 if not p.exists():
72 if not p.exists():
73 p.touch()
73 p.touch()
74 self.debugger_history = FileHistory(os.path.expanduser(str(p)))
74 self.debugger_history = FileHistory(os.path.expanduser(str(p)))
75 else:
75 else:
76 self.debugger_history = InMemoryHistory()
76 self.debugger_history = InMemoryHistory()
77 else:
77 else:
78 self.debugger_history = self.shell.debugger_history
78 self.debugger_history = self.shell.debugger_history
79
79
80 options = dict(
80 options = dict(
81 message=(lambda: PygmentsTokens(get_prompt_tokens())),
81 message=(lambda: PygmentsTokens(get_prompt_tokens())),
82 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
82 editing_mode=getattr(EditingMode, self.shell.editing_mode.upper()),
83 key_bindings=create_ipython_shortcuts(self.shell),
83 key_bindings=create_ipython_shortcuts(self.shell),
84 history=self.debugger_history,
84 history=self.debugger_history,
85 completer=self._ptcomp,
85 completer=self._ptcomp,
86 enable_history_search=True,
86 enable_history_search=True,
87 mouse_support=self.shell.mouse_support,
87 mouse_support=self.shell.mouse_support,
88 complete_style=self.shell.pt_complete_style,
88 complete_style=self.shell.pt_complete_style,
89 style=getattr(self.shell, "style", None),
89 style=getattr(self.shell, "style", None),
90 color_depth=self.shell.color_depth,
90 color_depth=self.shell.color_depth,
91 )
91 )
92
92
93 if not PTK3:
93 if not PTK3:
94 options['inputhook'] = self.shell.inputhook
94 options['inputhook'] = self.shell.inputhook
95 options.update(pt_session_options)
95 options.update(pt_session_options)
96 if not _use_simple_prompt:
96 if not _use_simple_prompt:
97 self.pt_loop = asyncio.new_event_loop()
97 self.pt_loop = asyncio.new_event_loop()
98 self.pt_app = PromptSession(**options)
98 self.pt_app = PromptSession(**options)
99
99
100 def _prompt(self):
100 def _prompt(self):
101 """
101 """
102 In case another prompt_toolkit apps have to run in parallel to this one (e.g. in madbg),
102 In case other prompt_toolkit apps have to run in parallel to this one (e.g. in madbg),
103 create_app_session must be used to prevent mixing up between them. According to the prompt_toolkit docs:
103 create_app_session must be used to prevent mixing up between them. According to the prompt_toolkit docs:
104
104
105 If you need multiple applications running at the same time, you have to create a separate
105 > If you need multiple applications running at the same time, you have to create a separate
106 `AppSession` using a `with create_app_session():` block.
106 > `AppSession` using a `with create_app_session():` block.
107 """
107 """
108 with create_app_session():
108 with create_app_session():
109 return self.pt_app.prompt()
109 return self.pt_app.prompt()
110
110
111 def cmdloop(self, intro=None):
111 def cmdloop(self, intro=None):
112 """Repeatedly issue a prompt, accept input, parse an initial prefix
112 """Repeatedly issue a prompt, accept input, parse an initial prefix
113 off the received input, and dispatch to action methods, passing them
113 off the received input, and dispatch to action methods, passing them
114 the remainder of the line as argument.
114 the remainder of the line as argument.
115
115
116 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
116 override the same methods from cmd.Cmd to provide prompt toolkit replacement.
117 """
117 """
118 if not self.use_rawinput:
118 if not self.use_rawinput:
119 raise ValueError('Sorry ipdb does not support use_rawinput=False')
119 raise ValueError('Sorry ipdb does not support use_rawinput=False')
120
120
121 # In order to make sure that prompt, which uses asyncio doesn't
121 # In order to make sure that prompt, which uses asyncio doesn't
122 # interfere with applications in which it's used, we always run the
122 # interfere with applications in which it's used, we always run the
123 # prompt itself in a different thread (we can't start an event loop
123 # prompt itself in a different thread (we can't start an event loop
124 # within an event loop). This new thread won't have any event loop
124 # within an event loop). This new thread won't have any event loop
125 # running, and here we run our prompt-loop.
125 # running, and here we run our prompt-loop.
126 self.preloop()
126 self.preloop()
127
127
128 try:
128 try:
129 if intro is not None:
129 if intro is not None:
130 self.intro = intro
130 self.intro = intro
131 if self.intro:
131 if self.intro:
132 print(self.intro, file=self.stdout)
132 print(self.intro, file=self.stdout)
133 stop = None
133 stop = None
134 while not stop:
134 while not stop:
135 if self.cmdqueue:
135 if self.cmdqueue:
136 line = self.cmdqueue.pop(0)
136 line = self.cmdqueue.pop(0)
137 else:
137 else:
138 self._ptcomp.ipy_completer.namespace = self.curframe_locals
138 self._ptcomp.ipy_completer.namespace = self.curframe_locals
139 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
139 self._ptcomp.ipy_completer.global_namespace = self.curframe.f_globals
140
140
141 # Run the prompt in a different thread.
141 # Run the prompt in a different thread.
142 if not _use_simple_prompt:
142 if not _use_simple_prompt:
143 try:
143 try:
144 line = self.thread_executor.submit(self._prompt).result()
144 line = self.thread_executor.submit(self._prompt).result()
145 except EOFError:
145 except EOFError:
146 line = "EOF"
146 line = "EOF"
147 else:
147 else:
148 line = input("ipdb> ")
148 line = input("ipdb> ")
149
149
150 line = self.precmd(line)
150 line = self.precmd(line)
151 stop = self.onecmd(line)
151 stop = self.onecmd(line)
152 stop = self.postcmd(stop, line)
152 stop = self.postcmd(stop, line)
153 self.postloop()
153 self.postloop()
154 except Exception:
154 except Exception:
155 raise
155 raise
156
156
157 def do_interact(self, arg):
157 def do_interact(self, arg):
158 ipshell = embed.InteractiveShellEmbed(
158 ipshell = embed.InteractiveShellEmbed(
159 config=self.shell.config,
159 config=self.shell.config,
160 banner1="*interactive*",
160 banner1="*interactive*",
161 exit_msg="*exiting interactive console...*",
161 exit_msg="*exiting interactive console...*",
162 )
162 )
163 global_ns = self.curframe.f_globals
163 global_ns = self.curframe.f_globals
164 ipshell(
164 ipshell(
165 module=sys.modules.get(global_ns["__name__"], None),
165 module=sys.modules.get(global_ns["__name__"], None),
166 local_ns=self.curframe_locals,
166 local_ns=self.curframe_locals,
167 )
167 )
168
168
169
169
170 def set_trace(frame=None):
170 def set_trace(frame=None):
171 """
171 """
172 Start debugging from `frame`.
172 Start debugging from `frame`.
173
173
174 If frame is not specified, debugging starts from caller's frame.
174 If frame is not specified, debugging starts from caller's frame.
175 """
175 """
176 TerminalPdb().set_trace(frame or sys._getframe().f_back)
176 TerminalPdb().set_trace(frame or sys._getframe().f_back)
177
177
178
178
179 if __name__ == '__main__':
179 if __name__ == '__main__':
180 import pdb
180 import pdb
181 # IPython.core.debugger.Pdb.trace_dispatch shall not catch
181 # IPython.core.debugger.Pdb.trace_dispatch shall not catch
182 # bdb.BdbQuit. When started through __main__ and an exception
182 # bdb.BdbQuit. When started through __main__ and an exception
183 # happened after hitting "c", this is needed in order to
183 # happened after hitting "c", this is needed in order to
184 # be able to quit the debugging session (see #9950).
184 # be able to quit the debugging session (see #9950).
185 old_trace_dispatch = pdb.Pdb.trace_dispatch
185 old_trace_dispatch = pdb.Pdb.trace_dispatch
186 pdb.Pdb = TerminalPdb # type: ignore
186 pdb.Pdb = TerminalPdb # type: ignore
187 pdb.Pdb.trace_dispatch = old_trace_dispatch # type: ignore
187 pdb.Pdb.trace_dispatch = old_trace_dispatch # type: ignore
188 pdb.main()
188 pdb.main()
General Comments 0
You need to be logged in to leave comments. Login now