Show More
@@ -391,85 +391,6 b' class PrefilterTransformer(Configurable):' | |||
|
391 | 391 | self.__class__.__name__, self.priority, self.enabled) |
|
392 | 392 | |
|
393 | 393 | |
|
394 | _assign_system_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
|
395 | r'\s*=\s*!(?P<cmd>.*)') | |
|
396 | ||
|
397 | ||
|
398 | class AssignSystemTransformer(PrefilterTransformer): | |
|
399 | """Handle the `files = !ls` syntax.""" | |
|
400 | ||
|
401 | priority = Integer(100, config=True) | |
|
402 | ||
|
403 | def transform(self, line, continue_prompt): | |
|
404 | m = _assign_system_re.match(line) | |
|
405 | if m is not None: | |
|
406 | cmd = m.group('cmd') | |
|
407 | lhs = m.group('lhs') | |
|
408 | expr = "sc =%s" % cmd | |
|
409 | new_line = '%s = get_ipython().magic(%r)' % (lhs, expr) | |
|
410 | return new_line | |
|
411 | return line | |
|
412 | ||
|
413 | ||
|
414 | _assign_magic_re = re.compile(r'(?P<lhs>(\s*)([\w\.]+)((\s*,\s*[\w\.]+)*))' | |
|
415 | r'\s*=\s*%(?P<cmd>.*)') | |
|
416 | ||
|
417 | class AssignMagicTransformer(PrefilterTransformer): | |
|
418 | """Handle the `a = %who` syntax.""" | |
|
419 | ||
|
420 | priority = Integer(200, config=True) | |
|
421 | ||
|
422 | def transform(self, line, continue_prompt): | |
|
423 | m = _assign_magic_re.match(line) | |
|
424 | if m is not None: | |
|
425 | cmd = m.group('cmd') | |
|
426 | lhs = m.group('lhs') | |
|
427 | new_line = '%s = get_ipython().magic(%r)' % (lhs, cmd) | |
|
428 | return new_line | |
|
429 | return line | |
|
430 | ||
|
431 | ||
|
432 | _classic_prompt_re = re.compile(r'(^[ \t]*>>> |^[ \t]*\.\.\. )') | |
|
433 | ||
|
434 | class PyPromptTransformer(PrefilterTransformer): | |
|
435 | """Handle inputs that start with '>>> ' syntax.""" | |
|
436 | ||
|
437 | priority = Integer(50, config=True) | |
|
438 | ||
|
439 | def transform(self, line, continue_prompt): | |
|
440 | ||
|
441 | if not line or line.isspace() or line.strip() == '...': | |
|
442 | # This allows us to recognize multiple input prompts separated by | |
|
443 | # blank lines and pasted in a single chunk, very common when | |
|
444 | # pasting doctests or long tutorial passages. | |
|
445 | return '' | |
|
446 | m = _classic_prompt_re.match(line) | |
|
447 | if m: | |
|
448 | return line[len(m.group(0)):] | |
|
449 | else: | |
|
450 | return line | |
|
451 | ||
|
452 | ||
|
453 | _ipy_prompt_re = re.compile(r'(^[ \t]*In \[\d+\]: |^[ \t]*\ \ \ \.\.\.+: )') | |
|
454 | ||
|
455 | class IPyPromptTransformer(PrefilterTransformer): | |
|
456 | """Handle inputs that start classic IPython prompt syntax.""" | |
|
457 | ||
|
458 | priority = Integer(50, config=True) | |
|
459 | ||
|
460 | def transform(self, line, continue_prompt): | |
|
461 | ||
|
462 | if not line or line.isspace() or line.strip() == '...': | |
|
463 | # This allows us to recognize multiple input prompts separated by | |
|
464 | # blank lines and pasted in a single chunk, very common when | |
|
465 | # pasting doctests or long tutorial passages. | |
|
466 | return '' | |
|
467 | m = _ipy_prompt_re.match(line) | |
|
468 | if m: | |
|
469 | return line[len(m.group(0)):] | |
|
470 | else: | |
|
471 | return line | |
|
472 | ||
|
473 | 394 | #----------------------------------------------------------------------------- |
|
474 | 395 | # Prefilter checkers |
|
475 | 396 | #----------------------------------------------------------------------------- |
@@ -511,15 +432,6 b' class EmacsChecker(PrefilterChecker):' | |||
|
511 | 432 | return None |
|
512 | 433 | |
|
513 | 434 | |
|
514 | class ShellEscapeChecker(PrefilterChecker): | |
|
515 | ||
|
516 | priority = Integer(200, config=True) | |
|
517 | ||
|
518 | def check(self, line_info): | |
|
519 | if line_info.line.lstrip().startswith(ESC_SHELL): | |
|
520 | return self.prefilter_manager.get_handler_by_name('shell') | |
|
521 | ||
|
522 | ||
|
523 | 435 | class MacroChecker(PrefilterChecker): |
|
524 | 436 | |
|
525 | 437 | priority = Integer(250, config=True) |
@@ -546,43 +458,6 b' class IPyAutocallChecker(PrefilterChecker):' | |||
|
546 | 458 | return None |
|
547 | 459 | |
|
548 | 460 | |
|
549 | class MultiLineMagicChecker(PrefilterChecker): | |
|
550 | ||
|
551 | priority = Integer(400, config=True) | |
|
552 | ||
|
553 | def check(self, line_info): | |
|
554 | "Allow ! and !! in multi-line statements if multi_line_specials is on" | |
|
555 | # Note that this one of the only places we check the first character of | |
|
556 | # ifun and *not* the pre_char. Also note that the below test matches | |
|
557 | # both ! and !!. | |
|
558 | if line_info.continue_prompt \ | |
|
559 | and self.prefilter_manager.multi_line_specials: | |
|
560 | if line_info.esc == ESC_MAGIC: | |
|
561 | return self.prefilter_manager.get_handler_by_name('magic') | |
|
562 | else: | |
|
563 | return None | |
|
564 | ||
|
565 | ||
|
566 | class EscCharsChecker(PrefilterChecker): | |
|
567 | ||
|
568 | priority = Integer(500, config=True) | |
|
569 | ||
|
570 | def check(self, line_info): | |
|
571 | """Check for escape character and return either a handler to handle it, | |
|
572 | or None if there is no escape char.""" | |
|
573 | if line_info.line[-1] == ESC_HELP \ | |
|
574 | and line_info.esc != ESC_SHELL \ | |
|
575 | and line_info.esc != ESC_SH_CAP: | |
|
576 | # the ? can be at the end, but *not* for either kind of shell escape, | |
|
577 | # because a ? can be a vaild final char in a shell cmd | |
|
578 | return self.prefilter_manager.get_handler_by_name('help') | |
|
579 | else: | |
|
580 | if line_info.pre: | |
|
581 | return None | |
|
582 | # This returns None like it should if no handler exists | |
|
583 | return self.prefilter_manager.get_handler_by_esc(line_info.esc) | |
|
584 | ||
|
585 | ||
|
586 | 461 | class AssignmentChecker(PrefilterChecker): |
|
587 | 462 | |
|
588 | 463 | priority = Integer(600, config=True) |
@@ -742,33 +617,6 b' class AliasHandler(PrefilterHandler):' | |||
|
742 | 617 | return line_out |
|
743 | 618 | |
|
744 | 619 | |
|
745 | class ShellEscapeHandler(PrefilterHandler): | |
|
746 | ||
|
747 | handler_name = Unicode('shell') | |
|
748 | esc_strings = List([ESC_SHELL, ESC_SH_CAP]) | |
|
749 | ||
|
750 | def handle(self, line_info): | |
|
751 | """Execute the line in a shell, empty return value""" | |
|
752 | magic_handler = self.prefilter_manager.get_handler_by_name('magic') | |
|
753 | ||
|
754 | line = line_info.line | |
|
755 | if line.lstrip().startswith(ESC_SH_CAP): | |
|
756 | # rewrite LineInfo's line, ifun and the_rest to properly hold the | |
|
757 | # call to %sx and the actual command to be executed, so | |
|
758 | # handle_magic can work correctly. Note that this works even if | |
|
759 | # the line is indented, so it handles multi_line_specials | |
|
760 | # properly. | |
|
761 | new_rest = line.lstrip()[2:] | |
|
762 | line_info.line = '%ssx %s' % (ESC_MAGIC, new_rest) | |
|
763 | line_info.ifun = 'sx' | |
|
764 | line_info.the_rest = new_rest | |
|
765 | return magic_handler.handle(line_info) | |
|
766 | else: | |
|
767 | cmd = line.lstrip().lstrip(ESC_SHELL) | |
|
768 | line_out = '%sget_ipython().system(%r)' % (line_info.pre_whitespace, cmd) | |
|
769 | return line_out | |
|
770 | ||
|
771 | ||
|
772 | 620 | class MacroHandler(PrefilterHandler): |
|
773 | 621 | handler_name = Unicode("macro") |
|
774 | 622 | |
@@ -865,44 +713,6 b' class AutoHandler(PrefilterHandler):' | |||
|
865 | 713 | return newcmd |
|
866 | 714 | |
|
867 | 715 | |
|
868 | class HelpHandler(PrefilterHandler): | |
|
869 | ||
|
870 | handler_name = Unicode('help') | |
|
871 | esc_strings = List([ESC_HELP]) | |
|
872 | ||
|
873 | def handle(self, line_info): | |
|
874 | """Try to get some help for the object. | |
|
875 | ||
|
876 | obj? or ?obj -> basic information. | |
|
877 | obj?? or ??obj -> more details. | |
|
878 | """ | |
|
879 | normal_handler = self.prefilter_manager.get_handler_by_name('normal') | |
|
880 | line = line_info.line | |
|
881 | # We need to make sure that we don't process lines which would be | |
|
882 | # otherwise valid python, such as "x=1 # what?" | |
|
883 | try: | |
|
884 | codeop.compile_command(line) | |
|
885 | except SyntaxError: | |
|
886 | # We should only handle as help stuff which is NOT valid syntax | |
|
887 | if line[0]==ESC_HELP: | |
|
888 | line = line[1:] | |
|
889 | elif line[-1]==ESC_HELP: | |
|
890 | line = line[:-1] | |
|
891 | if line: | |
|
892 | #print 'line:<%r>' % line # dbg | |
|
893 | self.shell.magic('pinfo %s' % line_info.ifun) | |
|
894 | else: | |
|
895 | self.shell.show_usage() | |
|
896 | return '' # Empty string is needed here! | |
|
897 | except: | |
|
898 | raise | |
|
899 | # Pass any other exceptions through to the normal handler | |
|
900 | return normal_handler.handle(line_info) | |
|
901 | else: | |
|
902 | # If the code compiles ok, we should handle it normally | |
|
903 | return normal_handler.handle(line_info) | |
|
904 | ||
|
905 | ||
|
906 | 716 | class EmacsHandler(PrefilterHandler): |
|
907 | 717 | |
|
908 | 718 | handler_name = Unicode('emacs') |
@@ -924,19 +734,12 b' class EmacsHandler(PrefilterHandler):' | |||
|
924 | 734 | |
|
925 | 735 | |
|
926 | 736 | _default_transformers = [ |
|
927 | AssignSystemTransformer, | |
|
928 | AssignMagicTransformer, | |
|
929 | PyPromptTransformer, | |
|
930 | IPyPromptTransformer, | |
|
931 | 737 | ] |
|
932 | 738 | |
|
933 | 739 | _default_checkers = [ |
|
934 | 740 | EmacsChecker, |
|
935 | ShellEscapeChecker, | |
|
936 | 741 | MacroChecker, |
|
937 | 742 | IPyAutocallChecker, |
|
938 | MultiLineMagicChecker, | |
|
939 | EscCharsChecker, | |
|
940 | 743 | AssignmentChecker, |
|
941 | 744 | AutoMagicChecker, |
|
942 | 745 | AliasChecker, |
@@ -947,10 +750,8 b' _default_checkers = [' | |||
|
947 | 750 | _default_handlers = [ |
|
948 | 751 | PrefilterHandler, |
|
949 | 752 | AliasHandler, |
|
950 | ShellEscapeHandler, | |
|
951 | 753 | MacroHandler, |
|
952 | 754 | MagicHandler, |
|
953 | 755 | AutoHandler, |
|
954 | HelpHandler, | |
|
955 | 756 | EmacsHandler |
|
956 | 757 | ] |
@@ -75,49 +75,8 b' def test_handlers():' | |||
|
75 | 75 | # line. |
|
76 | 76 | run([(i,py3compat.u_format(o)) for i,o in \ |
|
77 | 77 | [('"no change"', '"no change"'), # normal |
|
78 | (u"!true", "get_ipython().system({u}'true')"), # shell_escapes | |
|
79 | (u"!! true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic | |
|
80 | (u"!!true", "get_ipython().magic({u}'sx true')"), # shell_escapes + magic | |
|
81 | (u"%lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic | |
|
82 | 78 | (u"lsmagic", "get_ipython().magic({u}'lsmagic ')"), # magic |
|
83 | 79 | #("a = b # PYTHON-MODE", '_i'), # emacs -- avoids _in cache |
|
84 | ||
|
85 | # post-esc-char whitespace goes inside | |
|
86 | (u"! true", "get_ipython().system({u}' true')"), | |
|
87 | ||
|
88 | # handle_help | |
|
89 | ||
|
90 | # These are weak tests -- just looking at what the help handlers | |
|
91 | # logs, which is not how it really does its work. But it still | |
|
92 | # lets us check the key paths through the handler. | |
|
93 | ||
|
94 | ("x=1 # what?", "x=1 # what?"), # no help if valid python | |
|
95 | ]]) | |
|
96 | ||
|
97 | # multi_line_specials | |
|
98 | ip.prefilter_manager.multi_line_specials = False | |
|
99 | # W/ multi_line_specials off, leading ws kills esc chars/autoexpansion | |
|
100 | run([ | |
|
101 | (u'if 1:\n !true', u'if 1:\n !true'), | |
|
102 | (u'if 1:\n lsmagic', u'if 1:\n lsmagic'), | |
|
103 | (u'if 1:\n an_alias', u'if 1:\n an_alias'), | |
|
104 | ]) | |
|
105 | ||
|
106 | ip.prefilter_manager.multi_line_specials = True | |
|
107 | # initial indents must be preserved. | |
|
108 | run([(i,py3compat.u_format(o)) for i,o in \ | |
|
109 | [(u'if 1:\n !true', "if 1:\n get_ipython().system({u}'true')"), | |
|
110 | (u'if 2:\n lsmagic', "if 2:\n get_ipython().magic({u}'lsmagic ')"), | |
|
111 | (u'if 1:\n an_alias', "if 1:\n get_ipython().system({u}'true ')"), | |
|
112 | # Weird one | |
|
113 | (u'if 1:\n !!true', "if 1:\n get_ipython().magic({u}'sx true')"), | |
|
114 | ||
|
115 | # Even with m_l_s on, autocall is off even with special chars | |
|
116 | ('if 1:\n /fun 1 2', 'if 1:\n /fun 1 2'), | |
|
117 | ('if 1:\n ;fun 1 2', 'if 1:\n ;fun 1 2'), | |
|
118 | ('if 1:\n ,fun 1 2', 'if 1:\n ,fun 1 2'), | |
|
119 | ('if 1:\n ?fun 1 2', 'if 1:\n ?fun 1 2'), | |
|
120 | # What about !! | |
|
121 | 80 | ]]) |
|
122 | 81 | |
|
123 | 82 | # Objects which are instances of IPyAutocall are *always* autocalled |
@@ -133,15 +92,9 b' def test_handlers():' | |||
|
133 | 92 | ('autocallable', 'autocallable()'), |
|
134 | 93 | # Don't add extra brackets (gh-1117) |
|
135 | 94 | ('autocallable()', 'autocallable()'), |
|
136 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
137 | (";list 1 2 3", 'list("1 2 3")'), | |
|
138 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
139 | 95 | ]) |
|
140 | 96 | ip.magic('autocall 1') |
|
141 | 97 | run([ |
|
142 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
143 | (";list 1 2 3", 'list("1 2 3")'), | |
|
144 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
145 | 98 | ('len "abc"', 'len("abc")'), |
|
146 | 99 | ('len "abc";', 'len("abc");'), # ; is special -- moves out of parens |
|
147 | 100 | # Autocall is turned off if first arg is [] and the object |
@@ -153,9 +106,6 b' def test_handlers():' | |||
|
153 | 106 | ]) |
|
154 | 107 | ip.magic('autocall 2') |
|
155 | 108 | run([ |
|
156 | (",list 1 2 3", 'list("1", "2", "3")'), | |
|
157 | (";list 1 2 3", 'list("1 2 3")'), | |
|
158 | ("/len range(1,4)", 'len(range(1,4))'), | |
|
159 | 109 | ('len "abc"', 'len("abc")'), |
|
160 | 110 | ('len "abc";', 'len("abc");'), |
|
161 | 111 | ('len [1,2]', 'len([1,2])'), |
@@ -283,22 +283,18 b' def test_tb_syntaxerror():' | |||
|
283 | 283 | nt.assert_equal(last_line, "SyntaxError: invalid syntax") |
|
284 | 284 | |
|
285 | 285 | |
|
286 | @py3compat.doctest_refactor_print | |
|
287 | def doctest_time(): | |
|
288 | """ | |
|
289 | In [10]: %time None | |
|
290 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
|
291 | Wall time: 0.00 s | |
|
286 | def test_time(): | |
|
287 | ip = get_ipython() | |
|
292 | 288 | |
|
293 | In [11]: def f(kmjy): | |
|
294 | ....: %time print 2*kmjy | |
|
289 | with tt.AssertPrints("CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s"): | |
|
290 | ip.run_cell("%time None") | |
|
295 | 291 |
|
|
296 | In [12]: f(3) | |
|
297 | 6 | |
|
298 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
|
299 | Wall time: 0.00 s | |
|
300 | """ | |
|
292 | ip.run_cell("def f(kmjy):\n" | |
|
293 | " %time print (2*kmjy)") | |
|
301 | 294 | |
|
295 | with tt.AssertPrints("CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s"): | |
|
296 | with tt.AssertPrints("hihi", suppress=False): | |
|
297 | ip.run_cell("f('hi')") | |
|
302 | 298 | |
|
303 | 299 | def test_doctest_mode(): |
|
304 | 300 | "Toggle doctest_mode twice, it should be a no-op and run without error" |
@@ -20,17 +20,6 b' def test_prefilter():' | |||
|
20 | 20 | |
|
21 | 21 | # pairs of (raw, expected correct) input |
|
22 | 22 | pairs = [ ('2+2','2+2'), |
|
23 | ('>>> 2+2','2+2'), | |
|
24 | ('>>> # This is a comment\n' | |
|
25 | '... 2+2', | |
|
26 | '# This is a comment\n' | |
|
27 | '2+2'), | |
|
28 | # Some IPython input | |
|
29 | ('In [1]: 1', '1'), | |
|
30 | ('In [2]: for i in range(5):\n' | |
|
31 | ' ...: print i,', | |
|
32 | 'for i in range(5):\n' | |
|
33 | ' print i,'), | |
|
34 | 23 | ] |
|
35 | 24 | |
|
36 | 25 | for raw, correct in pairs: |
@@ -47,6 +47,12 b' import nose.core' | |||
|
47 | 47 | from nose.plugins import doctests, Plugin |
|
48 | 48 | from nose.util import anyp, getpackage, test_address, resolve_name, tolist |
|
49 | 49 | |
|
50 | # Our own imports | |
|
51 | ||
|
52 | # We're temporarily using TerminalMagics.cleanup_input() until the functionality | |
|
53 | # is moved into core. | |
|
54 | from IPython.frontend.terminal.interactiveshell import TerminalMagics | |
|
55 | ||
|
50 | 56 | #----------------------------------------------------------------------------- |
|
51 | 57 | # Module globals and other constants |
|
52 | 58 | #----------------------------------------------------------------------------- |
@@ -380,17 +386,7 b' class IPDocTestParser(doctest.DocTestParser):' | |||
|
380 | 386 | |
|
381 | 387 | def ip2py(self,source): |
|
382 | 388 | """Convert input IPython source into valid Python.""" |
|
383 | out = [] | |
|
384 | newline = out.append | |
|
385 | #print 'IPSRC:\n',source,'\n###' # dbg | |
|
386 | # The input source must be first stripped of all bracketing whitespace | |
|
387 | # and turned into lines, so it looks to the parser like regular user | |
|
388 | # input | |
|
389 | for lnum,line in enumerate(source.strip().splitlines()): | |
|
390 | newline(_ip.prefilter(line,lnum>0)) | |
|
391 | newline('') # ensure a closing newline, needed by doctest | |
|
392 | #print "PYSRC:", '\n'.join(out) # dbg | |
|
393 | return '\n'.join(out) | |
|
389 | return TerminalMagics(_ip).cleanup_input(source) | |
|
394 | 390 | |
|
395 | 391 | def parse(self, string, name='<string>'): |
|
396 | 392 | """ |
@@ -11,3 +11,13 b' especially intenting/deindenting blocks that is now bound to Ctrl+] and ctr+[' | |||
|
11 | 11 | * Exception types can now be displayed with a custom traceback, by defining a |
|
12 | 12 | ``_render_traceback_()`` method which returns a list of strings, each |
|
13 | 13 | containing one line of the traceback. |
|
14 | ||
|
15 | Backwards incompatible changes | |
|
16 | ------------------------------ | |
|
17 | ||
|
18 | * Calling :meth:`InteractiveShell.prefilter` will no longer perform static | |
|
19 | transformations - the processing of escaped commands such as ``%magic`` and | |
|
20 | ``!system``, and stripping input prompts from code blocks. This functionality | |
|
21 | was duplicated in :mod:`IPython.core.inputsplitter`, and the latter version | |
|
22 | was already what IPython relied on. A new API to transform input will be ready | |
|
23 | before release. |
General Comments 0
You need to be logged in to leave comments.
Login now