##// END OF EJS Templates
Added try/finally block to set using_paste_magics
mr.Shu -
Show More
@@ -1,736 +1,738 b''
1 1 # -*- coding: utf-8 -*-
2 2 """Subclass of InteractiveShell for terminal based frontends."""
3 3
4 4 #-----------------------------------------------------------------------------
5 5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 7 # Copyright (C) 2008-2011 The IPython Development Team
8 8 #
9 9 # Distributed under the terms of the BSD License. The full license is in
10 10 # the file COPYING, distributed as part of this software.
11 11 #-----------------------------------------------------------------------------
12 12
13 13 #-----------------------------------------------------------------------------
14 14 # Imports
15 15 #-----------------------------------------------------------------------------
16 16 from __future__ import print_function
17 17
18 18 import bdb
19 19 import os
20 20 import re
21 21 import sys
22 22 import textwrap
23 23
24 24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
25 25 # use the with keyword's new builtin support for nested managers
26 26 try:
27 27 from contextlib import nested
28 28 except:
29 29 from IPython.utils.nested_context import nested
30 30
31 31 from IPython.core.error import TryNext, UsageError
32 32 from IPython.core.usage import interactive_usage, default_banner
33 33 from IPython.core.inputsplitter import IPythonInputSplitter
34 34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
35 35 from IPython.core.magic import Magics, magics_class, line_magic
36 36 from IPython.testing.skipdoctest import skip_doctest
37 37 from IPython.utils.encoding import get_stream_enc
38 38 from IPython.utils import py3compat
39 39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
40 40 from IPython.utils.process import abbrev_cwd
41 41 from IPython.utils.warn import warn, error
42 42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
43 43 from IPython.utils.traitlets import Integer, CBool, Unicode
44 44
45 45 #-----------------------------------------------------------------------------
46 46 # Utilities
47 47 #-----------------------------------------------------------------------------
48 48
49 49 def get_default_editor():
50 50 try:
51 51 ed = os.environ['EDITOR']
52 52 except KeyError:
53 53 if os.name == 'posix':
54 54 ed = 'vi' # the only one guaranteed to be there!
55 55 else:
56 56 ed = 'notepad' # same in Windows!
57 57 return ed
58 58
59 59
60 60 def get_pasted_lines(sentinel, l_input=py3compat.input):
61 61 """ Yield pasted lines until the user enters the given sentinel value.
62 62 """
63 63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
64 64 % sentinel)
65 65 while True:
66 66 try:
67 67 l = l_input(':')
68 68 if l == sentinel:
69 69 return
70 70 else:
71 71 yield l
72 72 except EOFError:
73 73 print('<EOF>')
74 74 return
75 75
76 76
77 77 #------------------------------------------------------------------------
78 78 # Terminal-specific magics
79 79 #------------------------------------------------------------------------
80 80
81 81 @magics_class
82 82 class TerminalMagics(Magics):
83 83 def __init__(self, shell):
84 84 super(TerminalMagics, self).__init__(shell)
85 85 self.input_splitter = IPythonInputSplitter(input_mode='line')
86 86
87 87 def cleanup_input(self, block):
88 88 """Apply all possible IPython cleanups to an input block.
89 89
90 90 This means:
91 91
92 92 - remove any global leading whitespace (dedent)
93 93 - remove any email quotes ('>') if they are present in *all* lines
94 94 - apply all static inputsplitter transforms and break into sub-blocks
95 95 - apply prefilter() to each sub-block that is a single line.
96 96
97 97 Parameters
98 98 ----------
99 99 block : str
100 100 A possibly multiline input string of code.
101 101
102 102 Returns
103 103 -------
104 104 transformed block : str
105 105 The input, with all transformations above applied.
106 106 """
107 107 # We have to effectively implement client-side the loop that is done by
108 108 # the terminal frontend, and furthermore do it on a block that can
109 109 # possibly contain multiple statments pasted in one go.
110 110
111 111 # First, run the input through the block splitting code. We should
112 112 # eventually make this a self-contained method in the inputsplitter.
113 113 isp = self.input_splitter
114 114 isp.reset()
115 115 b = textwrap.dedent(block)
116 116
117 117 # Remove email quotes first. These must be consistently applied to
118 118 # *all* lines to be removed
119 119 b = strip_email_quotes(b)
120 120
121 121 # Split the input into independent sub-blocks so we can later do
122 122 # prefiltering (which must be done *only* to single-line inputs)
123 123 blocks = []
124 124 last_block = []
125 125 for line in b.splitlines():
126 126 isp.push(line)
127 127 last_block.append(line)
128 128 if not isp.push_accepts_more():
129 129 blocks.append(isp.source_reset())
130 130 last_block = []
131 131 if last_block:
132 132 blocks.append('\n'.join(last_block))
133 133
134 134 # Now, apply prefiltering to any one-line block to match the behavior
135 135 # of the interactive terminal
136 136 final_blocks = []
137 137 for block in blocks:
138 138 lines = block.splitlines()
139 139 if len(lines) == 1:
140 140 final_blocks.append(self.shell.prefilter(lines[0]))
141 141 else:
142 142 final_blocks.append(block)
143 143
144 144 # We now have the final version of the input code as a list of blocks,
145 145 # with all inputsplitter transformations applied and single-line blocks
146 146 # run through prefilter. For further processing, turn into a single
147 147 # string as the rest of our apis use string inputs.
148 148 return '\n'.join(final_blocks)
149 149
150 150 def store_or_execute(self, block, name):
151 151 """ Execute a block, or store it in a variable, per the user's request.
152 152 """
153 153
154 154 b = self.cleanup_input(block)
155 155 if name:
156 156 # If storing it for further editing
157 157 self.shell.user_ns[name] = SList(b.splitlines())
158 158 print("Block assigned to '%s'" % name)
159 159 else:
160 160 self.shell.user_ns['pasted_block'] = b
161 161 self.shell.using_paste_magics = True
162 self.shell.run_cell(b)
163 self.shell.using_paste_magics = True
162 try:
163 self.shell.run_cell(b)
164 finally:
165 self.shell.using_paste_magics = False
164 166
165 167 def rerun_pasted(self, name='pasted_block'):
166 168 """ Rerun a previously pasted command.
167 169 """
168 170 b = self.shell.user_ns.get(name)
169 171
170 172 # Sanity checks
171 173 if b is None:
172 174 raise UsageError('No previous pasted block available')
173 175 if not isinstance(b, basestring):
174 176 raise UsageError(
175 177 "Variable 'pasted_block' is not a string, can't execute")
176 178
177 179 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
178 180 self.shell.run_cell(b)
179 181
180 182 @line_magic
181 183 def autoindent(self, parameter_s = ''):
182 184 """Toggle autoindent on/off (if available)."""
183 185
184 186 self.shell.set_autoindent()
185 187 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
186 188
187 189 @skip_doctest
188 190 @line_magic
189 191 def cpaste(self, parameter_s=''):
190 192 """Paste & execute a pre-formatted code block from clipboard.
191 193
192 194 You must terminate the block with '--' (two minus-signs) or Ctrl-D
193 195 alone on the line. You can also provide your own sentinel with '%paste
194 196 -s %%' ('%%' is the new sentinel for this operation)
195 197
196 198 The block is dedented prior to execution to enable execution of method
197 199 definitions. '>' and '+' characters at the beginning of a line are
198 200 ignored, to allow pasting directly from e-mails, diff files and
199 201 doctests (the '...' continuation prompt is also stripped). The
200 202 executed block is also assigned to variable named 'pasted_block' for
201 203 later editing with '%edit pasted_block'.
202 204
203 205 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
204 206 This assigns the pasted block to variable 'foo' as string, without
205 207 dedenting or executing it (preceding >>> and + is still stripped)
206 208
207 209 '%cpaste -r' re-executes the block previously entered by cpaste.
208 210
209 211 Do not be alarmed by garbled output on Windows (it's a readline bug).
210 212 Just press enter and type -- (and press enter again) and the block
211 213 will be what was just pasted.
212 214
213 215 IPython statements (magics, shell escapes) are not supported (yet).
214 216
215 217 See also
216 218 --------
217 219 paste: automatically pull code from clipboard.
218 220
219 221 Examples
220 222 --------
221 223 ::
222 224
223 225 In [8]: %cpaste
224 226 Pasting code; enter '--' alone on the line to stop.
225 227 :>>> a = ["world!", "Hello"]
226 228 :>>> print " ".join(sorted(a))
227 229 :--
228 230 Hello world!
229 231 """
230 232 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
231 233 if 'r' in opts:
232 234 self.rerun_pasted()
233 235 return
234 236
235 237 sentinel = opts.get('s', '--')
236 238 block = '\n'.join(get_pasted_lines(sentinel))
237 239 self.store_or_execute(block, name)
238 240
239 241 @line_magic
240 242 def paste(self, parameter_s=''):
241 243 """Paste & execute a pre-formatted code block from clipboard.
242 244
243 245 The text is pulled directly from the clipboard without user
244 246 intervention and printed back on the screen before execution (unless
245 247 the -q flag is given to force quiet mode).
246 248
247 249 The block is dedented prior to execution to enable execution of method
248 250 definitions. '>' and '+' characters at the beginning of a line are
249 251 ignored, to allow pasting directly from e-mails, diff files and
250 252 doctests (the '...' continuation prompt is also stripped). The
251 253 executed block is also assigned to variable named 'pasted_block' for
252 254 later editing with '%edit pasted_block'.
253 255
254 256 You can also pass a variable name as an argument, e.g. '%paste foo'.
255 257 This assigns the pasted block to variable 'foo' as string, without
256 258 executing it (preceding >>> and + is still stripped).
257 259
258 260 Options
259 261 -------
260 262
261 263 -r: re-executes the block previously entered by cpaste.
262 264
263 265 -q: quiet mode: do not echo the pasted text back to the terminal.
264 266
265 267 IPython statements (magics, shell escapes) are not supported (yet).
266 268
267 269 See also
268 270 --------
269 271 cpaste: manually paste code into terminal until you mark its end.
270 272 """
271 273 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
272 274 if 'r' in opts:
273 275 self.rerun_pasted()
274 276 return
275 277 try:
276 278 block = self.shell.hooks.clipboard_get()
277 279 except TryNext as clipboard_exc:
278 280 message = getattr(clipboard_exc, 'args')
279 281 if message:
280 282 error(message[0])
281 283 else:
282 284 error('Could not get text from the clipboard.')
283 285 return
284 286
285 287 # By default, echo back to terminal unless quiet mode is requested
286 288 if 'q' not in opts:
287 289 write = self.shell.write
288 290 write(self.shell.pycolorize(block))
289 291 if not block.endswith('\n'):
290 292 write('\n')
291 293 write("## -- End pasted text --\n")
292 294
293 295 self.store_or_execute(block, name)
294 296
295 297 # Class-level: add a '%cls' magic only on Windows
296 298 if sys.platform == 'win32':
297 299 @line_magic
298 300 def cls(self, s):
299 301 """Clear screen.
300 302 """
301 303 os.system("cls")
302 304
303 305 #-----------------------------------------------------------------------------
304 306 # Main class
305 307 #-----------------------------------------------------------------------------
306 308
307 309 class TerminalInteractiveShell(InteractiveShell):
308 310
309 311 autoedit_syntax = CBool(False, config=True,
310 312 help="auto editing of files with syntax errors.")
311 313 banner = Unicode('')
312 314 banner1 = Unicode(default_banner, config=True,
313 315 help="""The part of the banner to be printed before the profile"""
314 316 )
315 317 banner2 = Unicode('', config=True,
316 318 help="""The part of the banner to be printed after the profile"""
317 319 )
318 320 confirm_exit = CBool(True, config=True,
319 321 help="""
320 322 Set to confirm when you try to exit IPython with an EOF (Control-D
321 323 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
322 324 you can force a direct exit without any confirmation.""",
323 325 )
324 326 # This display_banner only controls whether or not self.show_banner()
325 327 # is called when mainloop/interact are called. The default is False
326 328 # because for the terminal based application, the banner behavior
327 329 # is controlled by Global.display_banner, which IPythonApp looks at
328 330 # to determine if *it* should call show_banner() by hand or not.
329 331 display_banner = CBool(False) # This isn't configurable!
330 332 embedded = CBool(False)
331 333 embedded_active = CBool(False)
332 334 editor = Unicode(get_default_editor(), config=True,
333 335 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
334 336 )
335 337 pager = Unicode('less', config=True,
336 338 help="The shell program to be used for paging.")
337 339
338 340 screen_length = Integer(0, config=True,
339 341 help=
340 342 """Number of lines of your screen, used to control printing of very
341 343 long strings. Strings longer than this number of lines will be sent
342 344 through a pager instead of directly printed. The default value for
343 345 this is 0, which means IPython will auto-detect your screen size every
344 346 time it needs to print certain potentially long strings (this doesn't
345 347 change the behavior of the 'print' keyword, it's only triggered
346 348 internally). If for some reason this isn't working well (it needs
347 349 curses support), specify it yourself. Otherwise don't change the
348 350 default.""",
349 351 )
350 352 term_title = CBool(False, config=True,
351 353 help="Enable auto setting the terminal title."
352 354 )
353 355
354 356 # This `using_paste_magics` is used to detect whether the code is being
355 357 # executed via paste magics functions
356 358 using_paste_magics = CBool(False)
357 359
358 360 # In the terminal, GUI control is done via PyOS_InputHook
359 361 from IPython.lib.inputhook import enable_gui
360 362 enable_gui = staticmethod(enable_gui)
361 363
362 364 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
363 365 user_ns=None, user_module=None, custom_exceptions=((),None),
364 366 usage=None, banner1=None, banner2=None, display_banner=None):
365 367
366 368 super(TerminalInteractiveShell, self).__init__(
367 369 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
368 370 user_module=user_module, custom_exceptions=custom_exceptions
369 371 )
370 372 # use os.system instead of utils.process.system by default,
371 373 # because piped system doesn't make sense in the Terminal:
372 374 self.system = self.system_raw
373 375
374 376 self.init_term_title()
375 377 self.init_usage(usage)
376 378 self.init_banner(banner1, banner2, display_banner)
377 379
378 380 #-------------------------------------------------------------------------
379 381 # Things related to the terminal
380 382 #-------------------------------------------------------------------------
381 383
382 384 @property
383 385 def usable_screen_length(self):
384 386 if self.screen_length == 0:
385 387 return 0
386 388 else:
387 389 num_lines_bot = self.separate_in.count('\n')+1
388 390 return self.screen_length - num_lines_bot
389 391
390 392 def init_term_title(self):
391 393 # Enable or disable the terminal title.
392 394 if self.term_title:
393 395 toggle_set_term_title(True)
394 396 set_term_title('IPython: ' + abbrev_cwd())
395 397 else:
396 398 toggle_set_term_title(False)
397 399
398 400 #-------------------------------------------------------------------------
399 401 # Things related to aliases
400 402 #-------------------------------------------------------------------------
401 403
402 404 def init_alias(self):
403 405 # The parent class defines aliases that can be safely used with any
404 406 # frontend.
405 407 super(TerminalInteractiveShell, self).init_alias()
406 408
407 409 # Now define aliases that only make sense on the terminal, because they
408 410 # need direct access to the console in a way that we can't emulate in
409 411 # GUI or web frontend
410 412 if os.name == 'posix':
411 413 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
412 414 ('man', 'man')]
413 415 elif os.name == 'nt':
414 416 aliases = [('cls', 'cls')]
415 417
416 418
417 419 for name, cmd in aliases:
418 420 self.alias_manager.define_alias(name, cmd)
419 421
420 422 #-------------------------------------------------------------------------
421 423 # Things related to the banner and usage
422 424 #-------------------------------------------------------------------------
423 425
424 426 def _banner1_changed(self):
425 427 self.compute_banner()
426 428
427 429 def _banner2_changed(self):
428 430 self.compute_banner()
429 431
430 432 def _term_title_changed(self, name, new_value):
431 433 self.init_term_title()
432 434
433 435 def init_banner(self, banner1, banner2, display_banner):
434 436 if banner1 is not None:
435 437 self.banner1 = banner1
436 438 if banner2 is not None:
437 439 self.banner2 = banner2
438 440 if display_banner is not None:
439 441 self.display_banner = display_banner
440 442 self.compute_banner()
441 443
442 444 def show_banner(self, banner=None):
443 445 if banner is None:
444 446 banner = self.banner
445 447 self.write(banner)
446 448
447 449 def compute_banner(self):
448 450 self.banner = self.banner1
449 451 if self.profile and self.profile != 'default':
450 452 self.banner += '\nIPython profile: %s\n' % self.profile
451 453 if self.banner2:
452 454 self.banner += '\n' + self.banner2
453 455
454 456 def init_usage(self, usage=None):
455 457 if usage is None:
456 458 self.usage = interactive_usage
457 459 else:
458 460 self.usage = usage
459 461
460 462 #-------------------------------------------------------------------------
461 463 # Mainloop and code execution logic
462 464 #-------------------------------------------------------------------------
463 465
464 466 def mainloop(self, display_banner=None):
465 467 """Start the mainloop.
466 468
467 469 If an optional banner argument is given, it will override the
468 470 internally created default banner.
469 471 """
470 472
471 473 with nested(self.builtin_trap, self.display_trap):
472 474
473 475 while 1:
474 476 try:
475 477 self.interact(display_banner=display_banner)
476 478 #self.interact_with_readline()
477 479 # XXX for testing of a readline-decoupled repl loop, call
478 480 # interact_with_readline above
479 481 break
480 482 except KeyboardInterrupt:
481 483 # this should not be necessary, but KeyboardInterrupt
482 484 # handling seems rather unpredictable...
483 485 self.write("\nKeyboardInterrupt in interact()\n")
484 486
485 487 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
486 488 """Store multiple lines as a single entry in history"""
487 489
488 490 # do nothing without readline or disabled multiline
489 491 if not self.has_readline or not self.multiline_history:
490 492 return hlen_before_cell
491 493
492 494 # windows rl has no remove_history_item
493 495 if not hasattr(self.readline, "remove_history_item"):
494 496 return hlen_before_cell
495 497
496 498 # skip empty cells
497 499 if not source_raw.rstrip():
498 500 return hlen_before_cell
499 501
500 502 # nothing changed do nothing, e.g. when rl removes consecutive dups
501 503 hlen = self.readline.get_current_history_length()
502 504 if hlen == hlen_before_cell:
503 505 return hlen_before_cell
504 506
505 507 for i in range(hlen - hlen_before_cell):
506 508 self.readline.remove_history_item(hlen - i - 1)
507 509 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
508 510 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
509 511 stdin_encoding))
510 512 return self.readline.get_current_history_length()
511 513
512 514 def interact(self, display_banner=None):
513 515 """Closely emulate the interactive Python console."""
514 516
515 517 # batch run -> do not interact
516 518 if self.exit_now:
517 519 return
518 520
519 521 if display_banner is None:
520 522 display_banner = self.display_banner
521 523
522 524 if isinstance(display_banner, basestring):
523 525 self.show_banner(display_banner)
524 526 elif display_banner:
525 527 self.show_banner()
526 528
527 529 more = False
528 530
529 531 if self.has_readline:
530 532 self.readline_startup_hook(self.pre_readline)
531 533 hlen_b4_cell = self.readline.get_current_history_length()
532 534 else:
533 535 hlen_b4_cell = 0
534 536 # exit_now is set by a call to %Exit or %Quit, through the
535 537 # ask_exit callback.
536 538
537 539 while not self.exit_now:
538 540 self.hooks.pre_prompt_hook()
539 541 if more:
540 542 try:
541 543 prompt = self.prompt_manager.render('in2')
542 544 except:
543 545 self.showtraceback()
544 546 if self.autoindent:
545 547 self.rl_do_indent = True
546 548
547 549 else:
548 550 try:
549 551 prompt = self.separate_in + self.prompt_manager.render('in')
550 552 except:
551 553 self.showtraceback()
552 554 try:
553 555 line = self.raw_input(prompt)
554 556 if self.exit_now:
555 557 # quick exit on sys.std[in|out] close
556 558 break
557 559 if self.autoindent:
558 560 self.rl_do_indent = False
559 561
560 562 except KeyboardInterrupt:
561 563 #double-guard against keyboardinterrupts during kbdint handling
562 564 try:
563 565 self.write('\nKeyboardInterrupt\n')
564 566 source_raw = self.input_splitter.source_raw_reset()[1]
565 567 hlen_b4_cell = \
566 568 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
567 569 more = False
568 570 except KeyboardInterrupt:
569 571 pass
570 572 except EOFError:
571 573 if self.autoindent:
572 574 self.rl_do_indent = False
573 575 if self.has_readline:
574 576 self.readline_startup_hook(None)
575 577 self.write('\n')
576 578 self.exit()
577 579 except bdb.BdbQuit:
578 580 warn('The Python debugger has exited with a BdbQuit exception.\n'
579 581 'Because of how pdb handles the stack, it is impossible\n'
580 582 'for IPython to properly format this particular exception.\n'
581 583 'IPython will resume normal operation.')
582 584 except:
583 585 # exceptions here are VERY RARE, but they can be triggered
584 586 # asynchronously by signal handlers, for example.
585 587 self.showtraceback()
586 588 else:
587 589 self.input_splitter.push(line)
588 590 more = self.input_splitter.push_accepts_more()
589 591 if (self.SyntaxTB.last_syntax_error and
590 592 self.autoedit_syntax):
591 593 self.edit_syntax_error()
592 594 if not more:
593 595 source_raw = self.input_splitter.source_raw_reset()[1]
594 596 self.run_cell(source_raw, store_history=True)
595 597 hlen_b4_cell = \
596 598 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
597 599
598 600 # Turn off the exit flag, so the mainloop can be restarted if desired
599 601 self.exit_now = False
600 602
601 603 def raw_input(self, prompt=''):
602 604 """Write a prompt and read a line.
603 605
604 606 The returned line does not include the trailing newline.
605 607 When the user enters the EOF key sequence, EOFError is raised.
606 608
607 609 Optional inputs:
608 610
609 611 - prompt(''): a string to be printed to prompt the user.
610 612
611 613 - continue_prompt(False): whether this line is the first one or a
612 614 continuation in a sequence of inputs.
613 615 """
614 616 # Code run by the user may have modified the readline completer state.
615 617 # We must ensure that our completer is back in place.
616 618
617 619 if self.has_readline:
618 620 self.set_readline_completer()
619 621
620 622 # raw_input expects str, but we pass it unicode sometimes
621 623 prompt = py3compat.cast_bytes_py2(prompt)
622 624
623 625 try:
624 626 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
625 627 except ValueError:
626 628 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
627 629 " or sys.stdout.close()!\nExiting IPython!\n")
628 630 self.ask_exit()
629 631 return ""
630 632
631 633 # Try to be reasonably smart about not re-indenting pasted input more
632 634 # than necessary. We do this by trimming out the auto-indent initial
633 635 # spaces, if the user's actual input started itself with whitespace.
634 636 if self.autoindent:
635 637 if num_ini_spaces(line) > self.indent_current_nsp:
636 638 line = line[self.indent_current_nsp:]
637 639 self.indent_current_nsp = 0
638 640
639 641 return line
640 642
641 643 #-------------------------------------------------------------------------
642 644 # Methods to support auto-editing of SyntaxErrors.
643 645 #-------------------------------------------------------------------------
644 646
645 647 def edit_syntax_error(self):
646 648 """The bottom half of the syntax error handler called in the main loop.
647 649
648 650 Loop until syntax error is fixed or user cancels.
649 651 """
650 652
651 653 while self.SyntaxTB.last_syntax_error:
652 654 # copy and clear last_syntax_error
653 655 err = self.SyntaxTB.clear_err_state()
654 656 if not self._should_recompile(err):
655 657 return
656 658 try:
657 659 # may set last_syntax_error again if a SyntaxError is raised
658 660 self.safe_execfile(err.filename,self.user_ns)
659 661 except:
660 662 self.showtraceback()
661 663 else:
662 664 try:
663 665 f = open(err.filename)
664 666 try:
665 667 # This should be inside a display_trap block and I
666 668 # think it is.
667 669 sys.displayhook(f.read())
668 670 finally:
669 671 f.close()
670 672 except:
671 673 self.showtraceback()
672 674
673 675 def _should_recompile(self,e):
674 676 """Utility routine for edit_syntax_error"""
675 677
676 678 if e.filename in ('<ipython console>','<input>','<string>',
677 679 '<console>','<BackgroundJob compilation>',
678 680 None):
679 681
680 682 return False
681 683 try:
682 684 if (self.autoedit_syntax and
683 685 not self.ask_yes_no('Return to editor to correct syntax error? '
684 686 '[Y/n] ','y')):
685 687 return False
686 688 except EOFError:
687 689 return False
688 690
689 691 def int0(x):
690 692 try:
691 693 return int(x)
692 694 except TypeError:
693 695 return 0
694 696 # always pass integer line and offset values to editor hook
695 697 try:
696 698 self.hooks.fix_error_editor(e.filename,
697 699 int0(e.lineno),int0(e.offset),e.msg)
698 700 except TryNext:
699 701 warn('Could not open editor')
700 702 return False
701 703 return True
702 704
703 705 #-------------------------------------------------------------------------
704 706 # Things related to exiting
705 707 #-------------------------------------------------------------------------
706 708
707 709 def ask_exit(self):
708 710 """ Ask the shell to exit. Can be overiden and used as a callback. """
709 711 self.exit_now = True
710 712
711 713 def exit(self):
712 714 """Handle interactive exit.
713 715
714 716 This method calls the ask_exit callback."""
715 717 if self.confirm_exit:
716 718 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
717 719 self.ask_exit()
718 720 else:
719 721 self.ask_exit()
720 722
721 723 #-------------------------------------------------------------------------
722 724 # Things related to magics
723 725 #-------------------------------------------------------------------------
724 726
725 727 def init_magics(self):
726 728 super(TerminalInteractiveShell, self).init_magics()
727 729 self.register_magics(TerminalMagics)
728 730
729 731 def showindentationerror(self):
730 732 super(TerminalInteractiveShell, self).showindentationerror()
731 733 if not self.using_paste_magics:
732 734 print("If you want to paste code into IPython, try the "
733 735 "%paste and %cpaste magic functions.")
734 736
735 737
736 738 InteractiveShellABC.register(TerminalInteractiveShell)
General Comments 0
You need to be logged in to leave comments. Login now