##// END OF EJS Templates
Rename PTInteractiveShell to TerminalInteractiveShell...
Thomas Kluyver -
Show More
@@ -1,368 +1,368 b''
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 """
4 4 The :class:`~IPython.core.application.Application` object for the command
5 5 line :command:`ipython` program.
6 6 """
7 7
8 8 # Copyright (c) IPython Development Team.
9 9 # Distributed under the terms of the Modified BSD License.
10 10
11 11 from __future__ import absolute_import
12 12 from __future__ import print_function
13 13
14 14 import logging
15 15 import os
16 16 import sys
17 17
18 18 from traitlets.config.loader import Config
19 19 from traitlets.config.application import boolean_flag, catch_config_error, Application
20 20 from IPython.core import release
21 21 from IPython.core import usage
22 22 from IPython.core.completer import IPCompleter
23 23 from IPython.core.crashhandler import CrashHandler
24 24 from IPython.core.formatters import PlainTextFormatter
25 25 from IPython.core.history import HistoryManager
26 26 from IPython.core.prompts import PromptManager
27 27 from IPython.core.application import (
28 28 ProfileDir, BaseIPythonApplication, base_flags, base_aliases
29 29 )
30 30 from IPython.core.magics import ScriptMagics
31 31 from IPython.core.shellapp import (
32 32 InteractiveShellApp, shell_flags, shell_aliases
33 33 )
34 34 from IPython.extensions.storemagic import StoreMagics
35 from .ptshell import PTInteractiveShell as TerminalInteractiveShell
35 from .ptshell import TerminalInteractiveShell
36 36 from IPython.utils import warn
37 37 from IPython.paths import get_ipython_dir
38 38 from traitlets import (
39 39 Bool, List, Dict,
40 40 )
41 41
42 42 #-----------------------------------------------------------------------------
43 43 # Globals, utilities and helpers
44 44 #-----------------------------------------------------------------------------
45 45
46 46 _examples = """
47 47 ipython --matplotlib # enable matplotlib integration
48 48 ipython --matplotlib=qt # enable matplotlib integration with qt4 backend
49 49
50 50 ipython --log-level=DEBUG # set logging to DEBUG
51 51 ipython --profile=foo # start with profile foo
52 52
53 53 ipython profile create foo # create profile foo w/ default config files
54 54 ipython help profile # show the help for the profile subcmd
55 55
56 56 ipython locate # print the path to the IPython directory
57 57 ipython locate profile foo # print the path to the directory for profile `foo`
58 58 """
59 59
60 60 #-----------------------------------------------------------------------------
61 61 # Crash handler for this application
62 62 #-----------------------------------------------------------------------------
63 63
64 64 class IPAppCrashHandler(CrashHandler):
65 65 """sys.excepthook for IPython itself, leaves a detailed report on disk."""
66 66
67 67 def __init__(self, app):
68 68 contact_name = release.author
69 69 contact_email = release.author_email
70 70 bug_tracker = 'https://github.com/ipython/ipython/issues'
71 71 super(IPAppCrashHandler,self).__init__(
72 72 app, contact_name, contact_email, bug_tracker
73 73 )
74 74
75 75 def make_report(self,traceback):
76 76 """Return a string containing a crash report."""
77 77
78 78 sec_sep = self.section_sep
79 79 # Start with parent report
80 80 report = [super(IPAppCrashHandler, self).make_report(traceback)]
81 81 # Add interactive-specific info we may have
82 82 rpt_add = report.append
83 83 try:
84 84 rpt_add(sec_sep+"History of session input:")
85 85 for line in self.app.shell.user_ns['_ih']:
86 86 rpt_add(line)
87 87 rpt_add('\n*** Last line of input (may not be in above history):\n')
88 88 rpt_add(self.app.shell._last_input_line+'\n')
89 89 except:
90 90 pass
91 91
92 92 return ''.join(report)
93 93
94 94 #-----------------------------------------------------------------------------
95 95 # Aliases and Flags
96 96 #-----------------------------------------------------------------------------
97 97 flags = dict(base_flags)
98 98 flags.update(shell_flags)
99 99 frontend_flags = {}
100 100 addflag = lambda *args: frontend_flags.update(boolean_flag(*args))
101 101 addflag('autoedit-syntax', 'TerminalInteractiveShell.autoedit_syntax',
102 102 'Turn on auto editing of files with syntax errors.',
103 103 'Turn off auto editing of files with syntax errors.'
104 104 )
105 105 addflag('banner', 'TerminalIPythonApp.display_banner',
106 106 "Display a banner upon starting IPython.",
107 107 "Don't display a banner upon starting IPython."
108 108 )
109 109 addflag('confirm-exit', 'TerminalInteractiveShell.confirm_exit',
110 110 """Set to confirm when you try to exit IPython with an EOF (Control-D
111 111 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
112 112 you can force a direct exit without any confirmation.""",
113 113 "Don't prompt the user when exiting."
114 114 )
115 115 addflag('term-title', 'TerminalInteractiveShell.term_title',
116 116 "Enable auto setting the terminal title.",
117 117 "Disable auto setting the terminal title."
118 118 )
119 119 classic_config = Config()
120 120 classic_config.InteractiveShell.cache_size = 0
121 121 classic_config.PlainTextFormatter.pprint = False
122 122 classic_config.PromptManager.in_template = '>>> '
123 123 classic_config.PromptManager.in2_template = '... '
124 124 classic_config.PromptManager.out_template = ''
125 125 classic_config.InteractiveShell.separate_in = ''
126 126 classic_config.InteractiveShell.separate_out = ''
127 127 classic_config.InteractiveShell.separate_out2 = ''
128 128 classic_config.InteractiveShell.colors = 'NoColor'
129 129 classic_config.InteractiveShell.xmode = 'Plain'
130 130
131 131 frontend_flags['classic']=(
132 132 classic_config,
133 133 "Gives IPython a similar feel to the classic Python prompt."
134 134 )
135 135 # # log doesn't make so much sense this way anymore
136 136 # paa('--log','-l',
137 137 # action='store_true', dest='InteractiveShell.logstart',
138 138 # help="Start logging to the default log file (./ipython_log.py).")
139 139 #
140 140 # # quick is harder to implement
141 141 frontend_flags['quick']=(
142 142 {'TerminalIPythonApp' : {'quick' : True}},
143 143 "Enable quick startup with no config files."
144 144 )
145 145
146 146 frontend_flags['i'] = (
147 147 {'TerminalIPythonApp' : {'force_interact' : True}},
148 148 """If running code from the command line, become interactive afterwards.
149 149 It is often useful to follow this with `--` to treat remaining flags as
150 150 script arguments.
151 151 """
152 152 )
153 153 flags.update(frontend_flags)
154 154
155 155 aliases = dict(base_aliases)
156 156 aliases.update(shell_aliases)
157 157
158 158 #-----------------------------------------------------------------------------
159 159 # Main classes and functions
160 160 #-----------------------------------------------------------------------------
161 161
162 162
163 163 class LocateIPythonApp(BaseIPythonApplication):
164 164 description = """print the path to the IPython dir"""
165 165 subcommands = Dict(dict(
166 166 profile=('IPython.core.profileapp.ProfileLocate',
167 167 "print the path to an IPython profile directory",
168 168 ),
169 169 ))
170 170 def start(self):
171 171 if self.subapp is not None:
172 172 return self.subapp.start()
173 173 else:
174 174 print(self.ipython_dir)
175 175
176 176
177 177 class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):
178 178 name = u'ipython'
179 179 description = usage.cl_usage
180 180 crash_handler_class = IPAppCrashHandler
181 181 examples = _examples
182 182
183 183 flags = Dict(flags)
184 184 aliases = Dict(aliases)
185 185 classes = List()
186 186 def _classes_default(self):
187 187 """This has to be in a method, for TerminalIPythonApp to be available."""
188 188 return [
189 189 InteractiveShellApp, # ShellApp comes before TerminalApp, because
190 190 self.__class__, # it will also affect subclasses (e.g. QtConsole)
191 191 TerminalInteractiveShell,
192 192 PromptManager,
193 193 HistoryManager,
194 194 ProfileDir,
195 195 PlainTextFormatter,
196 196 IPCompleter,
197 197 ScriptMagics,
198 198 StoreMagics,
199 199 ]
200 200
201 201 deprecated_subcommands = dict(
202 202 qtconsole=('qtconsole.qtconsoleapp.JupyterQtConsoleApp',
203 203 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter Qt Console."""
204 204 ),
205 205 notebook=('notebook.notebookapp.NotebookApp',
206 206 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter HTML Notebook Server."""
207 207 ),
208 208 console=('jupyter_console.app.ZMQTerminalIPythonApp',
209 209 """DEPRECATED, Will be removed in IPython 6.0 : Launch the Jupyter terminal-based Console."""
210 210 ),
211 211 nbconvert=('nbconvert.nbconvertapp.NbConvertApp',
212 212 "DEPRECATED, Will be removed in IPython 6.0 : Convert notebooks to/from other formats."
213 213 ),
214 214 trust=('nbformat.sign.TrustNotebookApp',
215 215 "DEPRECATED, Will be removed in IPython 6.0 : Sign notebooks to trust their potentially unsafe contents at load."
216 216 ),
217 217 kernelspec=('jupyter_client.kernelspecapp.KernelSpecApp',
218 218 "DEPRECATED, Will be removed in IPython 6.0 : Manage Jupyter kernel specifications."
219 219 ),
220 220 )
221 221 subcommands = dict(
222 222 profile = ("IPython.core.profileapp.ProfileApp",
223 223 "Create and manage IPython profiles."
224 224 ),
225 225 kernel = ("ipykernel.kernelapp.IPKernelApp",
226 226 "Start a kernel without an attached frontend."
227 227 ),
228 228 locate=('IPython.terminal.ipapp.LocateIPythonApp',
229 229 LocateIPythonApp.description
230 230 ),
231 231 history=('IPython.core.historyapp.HistoryApp',
232 232 "Manage the IPython history database."
233 233 ),
234 234 )
235 235 deprecated_subcommands['install-nbextension'] = (
236 236 "notebook.nbextensions.InstallNBExtensionApp",
237 237 "DEPRECATED, Will be removed in IPython 6.0 : Install Jupyter notebook extension files"
238 238 )
239 239 subcommands.update(deprecated_subcommands)
240 240
241 241 # *do* autocreate requested profile, but don't create the config file.
242 242 auto_create=Bool(True)
243 243 # configurables
244 244 quick = Bool(False, config=True,
245 245 help="""Start IPython quickly by skipping the loading of config files."""
246 246 )
247 247 def _quick_changed(self, name, old, new):
248 248 if new:
249 249 self.load_config_file = lambda *a, **kw: None
250 250
251 251 display_banner = Bool(True, config=True,
252 252 help="Whether to display a banner upon starting IPython."
253 253 )
254 254
255 255 # if there is code of files to run from the cmd line, don't interact
256 256 # unless the --i flag (App.force_interact) is true.
257 257 force_interact = Bool(False, config=True,
258 258 help="""If a command or file is given via the command-line,
259 259 e.g. 'ipython foo.py', start an interactive shell after executing the
260 260 file or command."""
261 261 )
262 262 def _force_interact_changed(self, name, old, new):
263 263 if new:
264 264 self.interact = True
265 265
266 266 def _file_to_run_changed(self, name, old, new):
267 267 if new:
268 268 self.something_to_run = True
269 269 if new and not self.force_interact:
270 270 self.interact = False
271 271 _code_to_run_changed = _file_to_run_changed
272 272 _module_to_run_changed = _file_to_run_changed
273 273
274 274 # internal, not-configurable
275 275 something_to_run=Bool(False)
276 276
277 277 def parse_command_line(self, argv=None):
278 278 """override to allow old '-pylab' flag with deprecation warning"""
279 279
280 280 argv = sys.argv[1:] if argv is None else argv
281 281
282 282 if '-pylab' in argv:
283 283 # deprecated `-pylab` given,
284 284 # warn and transform into current syntax
285 285 argv = argv[:] # copy, don't clobber
286 286 idx = argv.index('-pylab')
287 287 warn.warn("`-pylab` flag has been deprecated.\n"
288 288 " Use `--matplotlib <backend>` and import pylab manually.")
289 289 argv[idx] = '--pylab'
290 290
291 291 return super(TerminalIPythonApp, self).parse_command_line(argv)
292 292
293 293 @catch_config_error
294 294 def initialize(self, argv=None):
295 295 """Do actions after construct, but before starting the app."""
296 296 super(TerminalIPythonApp, self).initialize(argv)
297 297 if self.subapp is not None:
298 298 # don't bother initializing further, starting subapp
299 299 return
300 300 # print self.extra_args
301 301 if self.extra_args and not self.something_to_run:
302 302 self.file_to_run = self.extra_args[0]
303 303 self.init_path()
304 304 # create the shell
305 305 self.init_shell()
306 306 # and draw the banner
307 307 self.init_banner()
308 308 # Now a variety of things that happen after the banner is printed.
309 309 self.init_gui_pylab()
310 310 self.init_extensions()
311 311 self.init_code()
312 312
313 313 def init_shell(self):
314 314 """initialize the InteractiveShell instance"""
315 315 # Create an InteractiveShell instance.
316 316 # shell.display_banner should always be False for the terminal
317 317 # based app, because we call shell.show_banner() by hand below
318 318 # so the banner shows *before* all extension loading stuff.
319 319 self.shell = TerminalInteractiveShell.instance(parent=self,
320 320 display_banner=False, profile_dir=self.profile_dir,
321 321 ipython_dir=self.ipython_dir, user_ns=self.user_ns)
322 322 self.shell.configurables.append(self)
323 323
324 324 def init_banner(self):
325 325 """optionally display the banner"""
326 326 if self.display_banner and self.interact:
327 327 self.shell.show_banner()
328 328 # Make sure there is a space below the banner.
329 329 if self.log_level <= logging.INFO: print()
330 330
331 331 def _pylab_changed(self, name, old, new):
332 332 """Replace --pylab='inline' with --pylab='auto'"""
333 333 if new == 'inline':
334 334 warn.warn("'inline' not available as pylab backend, "
335 335 "using 'auto' instead.")
336 336 self.pylab = 'auto'
337 337
338 338 def start(self):
339 339 if self.subapp is not None:
340 340 return self.subapp.start()
341 341 # perform any prexec steps:
342 342 if self.interact:
343 343 self.log.debug("Starting IPython's mainloop...")
344 344 self.shell.mainloop()
345 345 else:
346 346 self.log.debug("IPython not interactive...")
347 347
348 348 def load_default_config(ipython_dir=None):
349 349 """Load the default config file from the default ipython_dir.
350 350
351 351 This is useful for embedded shells.
352 352 """
353 353 if ipython_dir is None:
354 354 ipython_dir = get_ipython_dir()
355 355
356 356 profile_dir = os.path.join(ipython_dir, 'profile_default')
357 357
358 358 config = Config()
359 359 for cf in Application._load_config_files("ipython_config", path=profile_dir):
360 360 config.update(cf)
361 361
362 362 return config
363 363
364 364 launch_new_instance = TerminalIPythonApp.launch_instance
365 365
366 366
367 367 if __name__ == '__main__':
368 368 launch_new_instance()
@@ -1,240 +1,240 b''
1 1 """IPython terminal interface using prompt_toolkit in place of readline"""
2 2 from __future__ import print_function
3 3
4 4 import sys
5 5
6 6 from IPython.core.interactiveshell import InteractiveShell
7 7 from IPython.utils.py3compat import PY3, cast_unicode_py2, input
8 8 from traitlets import Bool, Unicode, Dict
9 9
10 10 from prompt_toolkit.completion import Completer, Completion
11 11 from prompt_toolkit.enums import DEFAULT_BUFFER
12 12 from prompt_toolkit.filters import HasFocus, HasSelection
13 13 from prompt_toolkit.history import InMemoryHistory
14 14 from prompt_toolkit.shortcuts import create_prompt_application, create_eventloop
15 15 from prompt_toolkit.interface import CommandLineInterface
16 16 from prompt_toolkit.key_binding.manager import KeyBindingManager
17 17 from prompt_toolkit.key_binding.vi_state import InputMode
18 18 from prompt_toolkit.key_binding.bindings.vi import ViStateFilter
19 19 from prompt_toolkit.keys import Keys
20 20 from prompt_toolkit.layout.lexers import PygmentsLexer
21 21 from prompt_toolkit.styles import PygmentsStyle
22 22
23 23 from pygments.styles import get_style_by_name
24 24 from pygments.lexers import Python3Lexer, PythonLexer
25 25 from pygments.token import Token
26 26
27 27 from .pt_inputhooks import get_inputhook_func
28 28 from .interactiveshell import get_default_editor
29 29
30 30
31 31 class IPythonPTCompleter(Completer):
32 32 """Adaptor to provide IPython completions to prompt_toolkit"""
33 33 def __init__(self, ipy_completer):
34 34 self.ipy_completer = ipy_completer
35 35
36 36 def get_completions(self, document, complete_event):
37 37 if not document.current_line.strip():
38 38 return
39 39
40 40 used, matches = self.ipy_completer.complete(
41 41 line_buffer=document.current_line,
42 42 cursor_pos=document.cursor_position_col
43 43 )
44 44 start_pos = -len(used)
45 45 for m in matches:
46 46 yield Completion(m, start_position=start_pos)
47 47
48 class PTInteractiveShell(InteractiveShell):
48 class TerminalInteractiveShell(InteractiveShell):
49 49 colors_force = True
50 50
51 51 pt_cli = None
52 52
53 53 vi_mode = Bool(False, config=True,
54 54 help="Use vi style keybindings at the prompt",
55 55 )
56 56
57 57 mouse_support = Bool(False, config=True,
58 58 help="Enable mouse support in the prompt"
59 59 )
60 60
61 61 highlighting_style = Unicode('', config=True,
62 62 help="The name of a Pygments style to use for syntax highlighting"
63 63 )
64 64
65 65 highlighting_style_overrides = Dict(config=True,
66 66 help="Override highlighting format for specific tokens"
67 67 )
68 68
69 69 editor = Unicode(get_default_editor(), config=True,
70 70 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
71 71 )
72 72
73 73 def get_prompt_tokens(self, cli):
74 74 return [
75 75 (Token.Prompt, 'In ['),
76 76 (Token.PromptNum, str(self.execution_count)),
77 77 (Token.Prompt, ']: '),
78 78 ]
79 79
80 80 def get_continuation_tokens(self, cli, width):
81 81 return [
82 82 (Token.Prompt, (' ' * (width - 2)) + ': '),
83 83 ]
84 84
85 85 def init_prompt_toolkit_cli(self):
86 86 if not sys.stdin.isatty():
87 87 # Piped input - e.g. for tests. Fall back to plain non-interactive
88 88 # output. This is very limited, and only accepts a single line.
89 89 def prompt():
90 90 return cast_unicode_py2(input('In [%d]: ' % self.execution_count))
91 91 self.prompt_for_code = prompt
92 92 return
93 93
94 94 kbmanager = KeyBindingManager.for_prompt(enable_vi_mode=self.vi_mode)
95 95 insert_mode = ViStateFilter(kbmanager.get_vi_state, InputMode.INSERT)
96 96 # Ctrl+J == Enter, seemingly
97 97 @kbmanager.registry.add_binding(Keys.ControlJ,
98 98 filter=(HasFocus(DEFAULT_BUFFER)
99 99 & ~HasSelection()
100 100 & insert_mode
101 101 ))
102 102 def _(event):
103 103 b = event.current_buffer
104 104 d = b.document
105 105 if not (d.on_last_line or d.cursor_position_row >= d.line_count
106 106 - d.empty_line_count_at_the_end()):
107 107 b.newline()
108 108 return
109 109
110 110 status, indent = self.input_splitter.check_complete(d.text)
111 111
112 112 if (status != 'incomplete') and b.accept_action.is_returnable:
113 113 b.accept_action.validate_and_handle(event.cli, b)
114 114 else:
115 115 b.insert_text('\n' + (' ' * (indent or 0)))
116 116
117 117 @kbmanager.registry.add_binding(Keys.ControlC)
118 118 def _(event):
119 119 event.current_buffer.reset()
120 120
121 121 # Pre-populate history from IPython's history database
122 122 history = InMemoryHistory()
123 123 last_cell = u""
124 124 for _, _, cell in self.history_manager.get_tail(self.history_load_length,
125 125 include_latest=True):
126 126 # Ignore blank lines and consecutive duplicates
127 127 cell = cell.rstrip()
128 128 if cell and (cell != last_cell):
129 129 history.append(cell)
130 130
131 131 style_overrides = {
132 132 Token.Prompt: '#009900',
133 133 Token.PromptNum: '#00ff00 bold',
134 134 }
135 135 if self.highlighting_style:
136 136 style_cls = get_style_by_name(self.highlighting_style)
137 137 else:
138 138 style_cls = get_style_by_name('default')
139 139 # The default theme needs to be visible on both a dark background
140 140 # and a light background, because we can't tell what the terminal
141 141 # looks like. These tweaks to the default theme help with that.
142 142 style_overrides.update({
143 143 Token.Number: '#007700',
144 144 Token.Operator: 'noinherit',
145 145 Token.String: '#BB6622',
146 146 Token.Name.Function: '#2080D0',
147 147 Token.Name.Class: 'bold #2080D0',
148 148 Token.Name.Namespace: 'bold #2080D0',
149 149 })
150 150 style_overrides.update(self.highlighting_style_overrides)
151 151 style = PygmentsStyle.from_defaults(pygments_style_cls=style_cls,
152 152 style_dict=style_overrides)
153 153
154 154 app = create_prompt_application(multiline=True,
155 155 lexer=PygmentsLexer(Python3Lexer if PY3 else PythonLexer),
156 156 get_prompt_tokens=self.get_prompt_tokens,
157 157 # The line below is waiting for a new release of
158 158 # prompt_toolkit (> 0.57)
159 159 #get_continuation_tokens=self.get_continuation_tokens,
160 160 key_bindings_registry=kbmanager.registry,
161 161 history=history,
162 162 completer=IPythonPTCompleter(self.Completer),
163 163 enable_history_search=True,
164 164 style=style,
165 165 mouse_support=self.mouse_support,
166 166 )
167 167
168 168 self.pt_cli = CommandLineInterface(app,
169 169 eventloop=create_eventloop(self.inputhook))
170 170
171 171 def prompt_for_code(self):
172 172 document = self.pt_cli.run(pre_run=self.pre_prompt)
173 173 return document.text
174 174
175 175 def init_io(self):
176 176 if sys.platform not in {'win32', 'cli'}:
177 177 return
178 178
179 179 import colorama
180 180 colorama.init()
181 181
182 182 # For some reason we make these wrappers around stdout/stderr.
183 183 # For now, we need to reset them so all output gets coloured.
184 184 # https://github.com/ipython/ipython/issues/8669
185 185 from IPython.utils import io
186 186 io.stdout = io.IOStream(sys.stdout)
187 187 io.stderr = io.IOStream(sys.stderr)
188 188
189 189 def __init__(self, *args, **kwargs):
190 super(PTInteractiveShell, self).__init__(*args, **kwargs)
190 super(TerminalInteractiveShell, self).__init__(*args, **kwargs)
191 191 self.init_prompt_toolkit_cli()
192 192 self.keep_running = True
193 193
194 194 def ask_exit(self):
195 195 self.keep_running = False
196 196
197 197 rl_next_input = None
198 198
199 199 def pre_prompt(self):
200 200 if self.rl_next_input:
201 201 self.pt_cli.application.buffer.text = cast_unicode_py2(self.rl_next_input)
202 202 self.rl_next_input = None
203 203
204 204 def interact(self):
205 205 while self.keep_running:
206 206 print(self.separate_in, end='')
207 207
208 208 try:
209 209 code = self.prompt_for_code()
210 210 except EOFError:
211 211 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
212 212 self.ask_exit()
213 213
214 214 else:
215 215 if code:
216 216 self.run_cell(code, store_history=True)
217 217
218 218 def mainloop(self):
219 219 # An extra layer of protection in case someone mashing Ctrl-C breaks
220 220 # out of our internal code.
221 221 while True:
222 222 try:
223 223 self.interact()
224 224 break
225 225 except KeyboardInterrupt:
226 226 print("\nKeyboardInterrupt escaped interact()\n")
227 227
228 228 _inputhook = None
229 229 def inputhook(self, context):
230 230 if self._inputhook is not None:
231 231 self._inputhook(context)
232 232
233 233 def enable_gui(self, gui=None):
234 234 if gui:
235 235 self._inputhook = get_inputhook_func(gui)
236 236 else:
237 237 self._inputhook = None
238 238
239 239 if __name__ == '__main__':
240 PTInteractiveShell.instance().interact()
240 TerminalInteractiveShell.instance().interact()
General Comments 0
You need to be logged in to leave comments. Login now