##// END OF EJS Templates
Refactor paste magics and ipdoctest
Thomas Kluyver -
Show More
@@ -1,204 +1,205 b''
1 """Tests for various magic functions specific to the terminal frontend.
1 """Tests for various magic functions specific to the terminal frontend.
2
2
3 Needs to be run by nose (to make ipython session available).
3 Needs to be run by nose (to make ipython session available).
4 """
4 """
5 from __future__ import absolute_import
5 from __future__ import absolute_import
6
6
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 # Imports
8 # Imports
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 import sys
11 import sys
12 from StringIO import StringIO
12 from StringIO import StringIO
13 from unittest import TestCase
13 from unittest import TestCase
14
14
15 import nose.tools as nt
15 import nose.tools as nt
16
16
17 from IPython.testing import tools as tt
17 from IPython.testing import tools as tt
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Globals
20 # Globals
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22 ip = get_ipython()
22 ip = get_ipython()
23
23
24 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
25 # Test functions begin
25 # Test functions begin
26 #-----------------------------------------------------------------------------
26 #-----------------------------------------------------------------------------
27
27
28 def check_cpaste(code, should_fail=False):
28 def check_cpaste(code, should_fail=False):
29 """Execute code via 'cpaste' and ensure it was executed, unless
29 """Execute code via 'cpaste' and ensure it was executed, unless
30 should_fail is set.
30 should_fail is set.
31 """
31 """
32 ip.user_ns['code_ran'] = False
32 ip.user_ns['code_ran'] = False
33
33
34 src = StringIO()
34 src = StringIO()
35 if not hasattr(src, 'encoding'):
35 if not hasattr(src, 'encoding'):
36 # IPython expects stdin to have an encoding attribute
36 # IPython expects stdin to have an encoding attribute
37 src.encoding = None
37 src.encoding = None
38 src.write(code)
38 src.write(code)
39 src.write('\n--\n')
39 src.write('\n--\n')
40 src.seek(0)
40 src.seek(0)
41
41
42 stdin_save = sys.stdin
42 stdin_save = sys.stdin
43 sys.stdin = src
43 sys.stdin = src
44
44
45 try:
45 try:
46 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
46 context = tt.AssertPrints if should_fail else tt.AssertNotPrints
47 with context("Traceback (most recent call last)"):
47 with context("Traceback (most recent call last)"):
48 ip.magic('cpaste')
48 ip.magic('cpaste')
49
49
50 if not should_fail:
50 if not should_fail:
51 assert ip.user_ns['code_ran']
51 assert ip.user_ns['code_ran'], "%r failed" % code
52 finally:
52 finally:
53 sys.stdin = stdin_save
53 sys.stdin = stdin_save
54
54
55 PY31 = sys.version_info[:2] == (3,1)
55 PY31 = sys.version_info[:2] == (3,1)
56
56
57 def test_cpaste():
57 def test_cpaste():
58 """Test cpaste magic"""
58 """Test cpaste magic"""
59
59
60 def runf():
60 def runf():
61 """Marker function: sets a flag when executed.
61 """Marker function: sets a flag when executed.
62 """
62 """
63 ip.user_ns['code_ran'] = True
63 ip.user_ns['code_ran'] = True
64 return 'runf' # return string so '+ runf()' doesn't result in success
64 return 'runf' # return string so '+ runf()' doesn't result in success
65
65
66 tests = {'pass': ["runf()",
66 tests = {'pass': ["runf()",
67 "In [1]: runf()",
67 "In [1]: runf()",
68 "In [1]: if 1:\n ...: runf()",
68 "In [1]: if 1:\n ...: runf()",
69 "> > > runf()",
69 "> > > runf()",
70 ">>> runf()",
70 ">>> runf()",
71 " >>> runf()",
71 " >>> runf()",
72 ],
72 ],
73
73
74 'fail': ["1 + runf()",
74 'fail': ["1 + runf()",
75 ]}
75 ]}
76
76
77 # I don't know why this is failing specifically on Python 3.1. I've
77 # I don't know why this is failing specifically on Python 3.1. I've
78 # checked it manually interactively, but we don't care enough about 3.1
78 # checked it manually interactively, but we don't care enough about 3.1
79 # to spend time fiddling with the tests, so we just skip it.
79 # to spend time fiddling with the tests, so we just skip it.
80 if not PY31:
80 if not PY31:
81 tests['fail'].append("++ runf()")
81 tests['fail'].append("++ runf()")
82
82
83 ip.user_ns['runf'] = runf
83 ip.user_ns['runf'] = runf
84
84
85 for code in tests['pass']:
85 for code in tests['pass']:
86 check_cpaste(code)
86 check_cpaste(code)
87
87
88 for code in tests['fail']:
88 for code in tests['fail']:
89 check_cpaste(code, should_fail=True)
89 check_cpaste(code, should_fail=True)
90
90
91
91
92 class PasteTestCase(TestCase):
92 class PasteTestCase(TestCase):
93 """Multiple tests for clipboard pasting"""
93 """Multiple tests for clipboard pasting"""
94
94
95 def paste(self, txt, flags='-q'):
95 def paste(self, txt, flags='-q'):
96 """Paste input text, by default in quiet mode"""
96 """Paste input text, by default in quiet mode"""
97 ip.hooks.clipboard_get = lambda : txt
97 ip.hooks.clipboard_get = lambda : txt
98 ip.magic('paste '+flags)
98 ip.magic('paste '+flags)
99
99
100 def setUp(self):
100 def setUp(self):
101 # Inject fake clipboard hook but save original so we can restore it later
101 # Inject fake clipboard hook but save original so we can restore it later
102 self.original_clip = ip.hooks.clipboard_get
102 self.original_clip = ip.hooks.clipboard_get
103
103
104 def tearDown(self):
104 def tearDown(self):
105 # Restore original hook
105 # Restore original hook
106 ip.hooks.clipboard_get = self.original_clip
106 ip.hooks.clipboard_get = self.original_clip
107
107
108 def test_paste(self):
108 def test_paste(self):
109 ip.user_ns.pop('x', None)
109 ip.user_ns.pop('x', None)
110 self.paste('x = 1')
110 self.paste('x = 1')
111 nt.assert_equal(ip.user_ns['x'], 1)
111 nt.assert_equal(ip.user_ns['x'], 1)
112 ip.user_ns.pop('x')
112 ip.user_ns.pop('x')
113
113
114 def test_paste_pyprompt(self):
114 def test_paste_pyprompt(self):
115 ip.user_ns.pop('x', None)
115 ip.user_ns.pop('x', None)
116 self.paste('>>> x=2')
116 self.paste('>>> x=2')
117 nt.assert_equal(ip.user_ns['x'], 2)
117 nt.assert_equal(ip.user_ns['x'], 2)
118 ip.user_ns.pop('x')
118 ip.user_ns.pop('x')
119
119
120 def test_paste_py_multi(self):
120 def test_paste_py_multi(self):
121 self.paste("""
121 self.paste("""
122 >>> x = [1,2,3]
122 >>> x = [1,2,3]
123 >>> y = []
123 >>> y = []
124 >>> for i in x:
124 >>> for i in x:
125 ... y.append(i**2)
125 ... y.append(i**2)
126 ...
126 ...
127 """)
127 """)
128 nt.assert_equal(ip.user_ns['x'], [1,2,3])
128 nt.assert_equal(ip.user_ns['x'], [1,2,3])
129 nt.assert_equal(ip.user_ns['y'], [1,4,9])
129 nt.assert_equal(ip.user_ns['y'], [1,4,9])
130
130
131 def test_paste_py_multi_r(self):
131 def test_paste_py_multi_r(self):
132 "Now, test that self.paste -r works"
132 "Now, test that self.paste -r works"
133 self.test_paste_py_multi()
133 nt.assert_equal(ip.user_ns.pop('x'), [1,2,3])
134 nt.assert_equal(ip.user_ns.pop('x'), [1,2,3])
134 nt.assert_equal(ip.user_ns.pop('y'), [1,4,9])
135 nt.assert_equal(ip.user_ns.pop('y'), [1,4,9])
135 nt.assert_false('x' in ip.user_ns)
136 nt.assert_false('x' in ip.user_ns)
136 ip.magic('paste -r')
137 ip.magic('paste -r')
137 nt.assert_equal(ip.user_ns['x'], [1,2,3])
138 nt.assert_equal(ip.user_ns['x'], [1,2,3])
138 nt.assert_equal(ip.user_ns['y'], [1,4,9])
139 nt.assert_equal(ip.user_ns['y'], [1,4,9])
139
140
140 def test_paste_email(self):
141 def test_paste_email(self):
141 "Test pasting of email-quoted contents"
142 "Test pasting of email-quoted contents"
142 self.paste("""\
143 self.paste("""\
143 >> def foo(x):
144 >> def foo(x):
144 >> return x + 1
145 >> return x + 1
145 >> xx = foo(1.1)""")
146 >> xx = foo(1.1)""")
146 nt.assert_equal(ip.user_ns['xx'], 2.1)
147 nt.assert_equal(ip.user_ns['xx'], 2.1)
147
148
148 def test_paste_email2(self):
149 def test_paste_email2(self):
149 "Email again; some programs add a space also at each quoting level"
150 "Email again; some programs add a space also at each quoting level"
150 self.paste("""\
151 self.paste("""\
151 > > def foo(x):
152 > > def foo(x):
152 > > return x + 1
153 > > return x + 1
153 > > yy = foo(2.1) """)
154 > > yy = foo(2.1) """)
154 nt.assert_equal(ip.user_ns['yy'], 3.1)
155 nt.assert_equal(ip.user_ns['yy'], 3.1)
155
156
156 def test_paste_email_py(self):
157 def test_paste_email_py(self):
157 "Email quoting of interactive input"
158 "Email quoting of interactive input"
158 self.paste("""\
159 self.paste("""\
159 >> >>> def f(x):
160 >> >>> def f(x):
160 >> ... return x+1
161 >> ... return x+1
161 >> ...
162 >> ...
162 >> >>> zz = f(2.5) """)
163 >> >>> zz = f(2.5) """)
163 nt.assert_equal(ip.user_ns['zz'], 3.5)
164 nt.assert_equal(ip.user_ns['zz'], 3.5)
164
165
165 def test_paste_echo(self):
166 def test_paste_echo(self):
166 "Also test self.paste echoing, by temporarily faking the writer"
167 "Also test self.paste echoing, by temporarily faking the writer"
167 w = StringIO()
168 w = StringIO()
168 writer = ip.write
169 writer = ip.write
169 ip.write = w.write
170 ip.write = w.write
170 code = """
171 code = """
171 a = 100
172 a = 100
172 b = 200"""
173 b = 200"""
173 try:
174 try:
174 self.paste(code,'')
175 self.paste(code,'')
175 out = w.getvalue()
176 out = w.getvalue()
176 finally:
177 finally:
177 ip.write = writer
178 ip.write = writer
178 nt.assert_equal(ip.user_ns['a'], 100)
179 nt.assert_equal(ip.user_ns['a'], 100)
179 nt.assert_equal(ip.user_ns['b'], 200)
180 nt.assert_equal(ip.user_ns['b'], 200)
180 nt.assert_equal(out, code+"\n## -- End pasted text --\n")
181 nt.assert_equal(out, code+"\n## -- End pasted text --\n")
181
182
182 def test_paste_leading_commas(self):
183 def test_paste_leading_commas(self):
183 "Test multiline strings with leading commas"
184 "Test multiline strings with leading commas"
184 tm = ip.magics_manager.registry['TerminalMagics']
185 tm = ip.magics_manager.registry['TerminalMagics']
185 s = '''\
186 s = '''\
186 a = """
187 a = """
187 ,1,2,3
188 ,1,2,3
188 """'''
189 """'''
189 ip.user_ns.pop('foo', None)
190 ip.user_ns.pop('foo', None)
190 tm.store_or_execute(s, 'foo')
191 tm.store_or_execute(s, 'foo')
191 nt.assert_in('foo', ip.user_ns)
192 nt.assert_in('foo', ip.user_ns)
192
193
193
194
194 def test_paste_trailing_question(self):
195 def test_paste_trailing_question(self):
195 "Test pasting sources with trailing question marks"
196 "Test pasting sources with trailing question marks"
196 tm = ip.magics_manager.registry['TerminalMagics']
197 tm = ip.magics_manager.registry['TerminalMagics']
197 s = '''\
198 s = '''\
198 def funcfoo():
199 def funcfoo():
199 if True: #am i true?
200 if True: #am i true?
200 return 'fooresult'
201 return 'fooresult'
201 '''
202 '''
202 ip.user_ns.pop('funcfoo', None)
203 ip.user_ns.pop('funcfoo', None)
203 self.paste(s)
204 self.paste(s)
204 nt.assert_equal(ip.user_ns['funcfoo'](), 'fooresult')
205 nt.assert_equal(ip.user_ns['funcfoo'](), 'fooresult')
@@ -1,753 +1,696 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """Subclass of InteractiveShell for terminal based frontends."""
2 """Subclass of InteractiveShell for terminal based frontends."""
3
3
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
5 # Copyright (C) 2001 Janko Hauser <jhauser@zscout.de>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
6 # Copyright (C) 2001-2007 Fernando Perez. <fperez@colorado.edu>
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 import bdb
18 import bdb
19 import os
19 import os
20 import re
20 import re
21 import sys
21 import sys
22 import textwrap
22 import textwrap
23
23
24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
24 # We need to use nested to support python 2.6, once we move to >=2.7, we can
25 # use the with keyword's new builtin support for nested managers
25 # use the with keyword's new builtin support for nested managers
26 try:
26 try:
27 from contextlib import nested
27 from contextlib import nested
28 except:
28 except:
29 from IPython.utils.nested_context import nested
29 from IPython.utils.nested_context import nested
30
30
31 from IPython.core.error import TryNext, UsageError
31 from IPython.core.error import TryNext, UsageError
32 from IPython.core.usage import interactive_usage, default_banner
32 from IPython.core.usage import interactive_usage, default_banner
33 from IPython.core.inputsplitter import IPythonInputSplitter
33 from IPython.core.inputsplitter import IPythonInputSplitter
34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
34 from IPython.core.interactiveshell import InteractiveShell, InteractiveShellABC
35 from IPython.core.magic import Magics, magics_class, line_magic
35 from IPython.core.magic import Magics, magics_class, line_magic
36 from IPython.testing.skipdoctest import skip_doctest
36 from IPython.testing.skipdoctest import skip_doctest
37 from IPython.utils.encoding import get_stream_enc
37 from IPython.utils.encoding import get_stream_enc
38 from IPython.utils import py3compat
38 from IPython.utils import py3compat
39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
39 from IPython.utils.terminal import toggle_set_term_title, set_term_title
40 from IPython.utils.process import abbrev_cwd
40 from IPython.utils.process import abbrev_cwd
41 from IPython.utils.warn import warn, error
41 from IPython.utils.warn import warn, error
42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
42 from IPython.utils.text import num_ini_spaces, SList, strip_email_quotes
43 from IPython.utils.traitlets import Integer, CBool, Unicode
43 from IPython.utils.traitlets import Integer, CBool, Unicode
44
44
45 #-----------------------------------------------------------------------------
45 #-----------------------------------------------------------------------------
46 # Utilities
46 # Utilities
47 #-----------------------------------------------------------------------------
47 #-----------------------------------------------------------------------------
48
48
49 def get_default_editor():
49 def get_default_editor():
50 try:
50 try:
51 ed = os.environ['EDITOR']
51 ed = os.environ['EDITOR']
52 except KeyError:
52 except KeyError:
53 if os.name == 'posix':
53 if os.name == 'posix':
54 ed = 'vi' # the only one guaranteed to be there!
54 ed = 'vi' # the only one guaranteed to be there!
55 else:
55 else:
56 ed = 'notepad' # same in Windows!
56 ed = 'notepad' # same in Windows!
57 return ed
57 return ed
58
58
59
59
60 def get_pasted_lines(sentinel, l_input=py3compat.input):
60 def get_pasted_lines(sentinel, l_input=py3compat.input):
61 """ Yield pasted lines until the user enters the given sentinel value.
61 """ Yield pasted lines until the user enters the given sentinel value.
62 """
62 """
63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
63 print("Pasting code; enter '%s' alone on the line to stop or use Ctrl-D." \
64 % sentinel)
64 % sentinel)
65 while True:
65 while True:
66 try:
66 try:
67 l = l_input(':')
67 l = l_input(':')
68 if l == sentinel:
68 if l == sentinel:
69 return
69 return
70 else:
70 else:
71 yield l
71 yield l
72 except EOFError:
72 except EOFError:
73 print('<EOF>')
73 print('<EOF>')
74 return
74 return
75
75
76
76
77 #------------------------------------------------------------------------
77 #------------------------------------------------------------------------
78 # Terminal-specific magics
78 # Terminal-specific magics
79 #------------------------------------------------------------------------
79 #------------------------------------------------------------------------
80
80
81 @magics_class
81 @magics_class
82 class TerminalMagics(Magics):
82 class TerminalMagics(Magics):
83 def __init__(self, shell):
83 def __init__(self, shell):
84 super(TerminalMagics, self).__init__(shell)
84 super(TerminalMagics, self).__init__(shell)
85 self.input_splitter = IPythonInputSplitter()
85 self.input_splitter = IPythonInputSplitter()
86
87 def cleanup_input(self, block):
88 """Apply all possible IPython cleanups to an input block.
89
90 This means:
91
92 - remove any global leading whitespace (dedent)
93 - remove any email quotes ('>') if they are present in *all* lines
94 - apply all static inputsplitter transforms and break into sub-blocks
95 - apply prefilter() to each sub-block that is a single line.
96
97 Parameters
98 ----------
99 block : str
100 A possibly multiline input string of code.
101
102 Returns
103 -------
104 transformed block : str
105 The input, with all transformations above applied.
106 """
107 # We have to effectively implement client-side the loop that is done by
108 # the terminal frontend, and furthermore do it on a block that can
109 # possibly contain multiple statments pasted in one go.
110
111 # First, run the input through the block splitting code. We should
112 # eventually make this a self-contained method in the inputsplitter.
113 isp = self.input_splitter
114 isp.reset()
115 b = textwrap.dedent(block)
116
117 # Remove email quotes first. These must be consistently applied to
118 # *all* lines to be removed
119 b = strip_email_quotes(b)
120
121 # Split the input into independent sub-blocks so we can later do
122 # prefiltering (which must be done *only* to single-line inputs)
123 blocks = []
124 last_block = []
125 for line in b.splitlines():
126 isp.push(line)
127 last_block.append(line)
128 if not isp.push_accepts_more():
129 blocks.append(isp.source_reset())
130 last_block = []
131 if last_block:
132 blocks.append('\n'.join(last_block))
133
134 # Now, apply prefiltering to any one-line block to match the behavior
135 # of the interactive terminal
136 final_blocks = []
137 for block in blocks:
138 lines = block.splitlines()
139 if len(lines) == 1:
140 final_blocks.append(self.shell.prefilter(lines[0]))
141 else:
142 final_blocks.append(block)
143
144 # We now have the final version of the input code as a list of blocks,
145 # with all inputsplitter transformations applied and single-line blocks
146 # run through prefilter. For further processing, turn into a single
147 # string as the rest of our apis use string inputs.
148 return '\n'.join(final_blocks)
149
86
150 def store_or_execute(self, block, name):
87 def store_or_execute(self, block, name):
151 """ Execute a block, or store it in a variable, per the user's request.
88 """ Execute a block, or store it in a variable, per the user's request.
152 """
89 """
153 if name:
90 if name:
154 # If storing it for further editing
91 # If storing it for further editing
155 self.shell.user_ns[name] = SList(block.splitlines())
92 self.shell.user_ns[name] = SList(block.splitlines())
156 print("Block assigned to '%s'" % name)
93 print("Block assigned to '%s'" % name)
157 else:
94 else:
158 self.shell.user_ns['pasted_block'] = block
95 b = self.preclean_input(block)
159 b = self.shell.input_transformer_manager.transform_cell(block)
96 self.shell.user_ns['pasted_block'] = b
160 self.shell.using_paste_magics = True
97 self.shell.using_paste_magics = True
161 try:
98 try:
162 self.shell.run_cell(b)
99 self.shell.run_cell(b)
163 finally:
100 finally:
164 self.shell.using_paste_magics = False
101 self.shell.using_paste_magics = False
102
103 def preclean_input(self, block):
104 lines = block.splitlines()
105 while lines and not lines[0].strip():
106 lines = lines[1:]
107 return strip_email_quotes('\n'.join(lines))
165
108
166 def rerun_pasted(self, name='pasted_block'):
109 def rerun_pasted(self, name='pasted_block'):
167 """ Rerun a previously pasted command.
110 """ Rerun a previously pasted command.
168 """
111 """
169 b = self.shell.user_ns.get(name)
112 b = self.shell.user_ns.get(name)
170
113
171 # Sanity checks
114 # Sanity checks
172 if b is None:
115 if b is None:
173 raise UsageError('No previous pasted block available')
116 raise UsageError('No previous pasted block available')
174 if not isinstance(b, basestring):
117 if not isinstance(b, basestring):
175 raise UsageError(
118 raise UsageError(
176 "Variable 'pasted_block' is not a string, can't execute")
119 "Variable 'pasted_block' is not a string, can't execute")
177
120
178 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
121 print("Re-executing '%s...' (%d chars)"% (b.split('\n',1)[0], len(b)))
179 self.shell.run_cell(b)
122 self.shell.run_cell(b)
180
123
181 @line_magic
124 @line_magic
182 def autoindent(self, parameter_s = ''):
125 def autoindent(self, parameter_s = ''):
183 """Toggle autoindent on/off (if available)."""
126 """Toggle autoindent on/off (if available)."""
184
127
185 self.shell.set_autoindent()
128 self.shell.set_autoindent()
186 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
129 print("Automatic indentation is:",['OFF','ON'][self.shell.autoindent])
187
130
188 @skip_doctest
131 @skip_doctest
189 @line_magic
132 @line_magic
190 def cpaste(self, parameter_s=''):
133 def cpaste(self, parameter_s=''):
191 """Paste & execute a pre-formatted code block from clipboard.
134 """Paste & execute a pre-formatted code block from clipboard.
192
135
193 You must terminate the block with '--' (two minus-signs) or Ctrl-D
136 You must terminate the block with '--' (two minus-signs) or Ctrl-D
194 alone on the line. You can also provide your own sentinel with '%paste
137 alone on the line. You can also provide your own sentinel with '%paste
195 -s %%' ('%%' is the new sentinel for this operation)
138 -s %%' ('%%' is the new sentinel for this operation)
196
139
197 The block is dedented prior to execution to enable execution of method
140 The block is dedented prior to execution to enable execution of method
198 definitions. '>' and '+' characters at the beginning of a line are
141 definitions. '>' and '+' characters at the beginning of a line are
199 ignored, to allow pasting directly from e-mails, diff files and
142 ignored, to allow pasting directly from e-mails, diff files and
200 doctests (the '...' continuation prompt is also stripped). The
143 doctests (the '...' continuation prompt is also stripped). The
201 executed block is also assigned to variable named 'pasted_block' for
144 executed block is also assigned to variable named 'pasted_block' for
202 later editing with '%edit pasted_block'.
145 later editing with '%edit pasted_block'.
203
146
204 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
147 You can also pass a variable name as an argument, e.g. '%cpaste foo'.
205 This assigns the pasted block to variable 'foo' as string, without
148 This assigns the pasted block to variable 'foo' as string, without
206 dedenting or executing it (preceding >>> and + is still stripped)
149 dedenting or executing it (preceding >>> and + is still stripped)
207
150
208 '%cpaste -r' re-executes the block previously entered by cpaste.
151 '%cpaste -r' re-executes the block previously entered by cpaste.
209
152
210 Do not be alarmed by garbled output on Windows (it's a readline bug).
153 Do not be alarmed by garbled output on Windows (it's a readline bug).
211 Just press enter and type -- (and press enter again) and the block
154 Just press enter and type -- (and press enter again) and the block
212 will be what was just pasted.
155 will be what was just pasted.
213
156
214 IPython statements (magics, shell escapes) are not supported (yet).
157 IPython statements (magics, shell escapes) are not supported (yet).
215
158
216 See also
159 See also
217 --------
160 --------
218 paste: automatically pull code from clipboard.
161 paste: automatically pull code from clipboard.
219
162
220 Examples
163 Examples
221 --------
164 --------
222 ::
165 ::
223
166
224 In [8]: %cpaste
167 In [8]: %cpaste
225 Pasting code; enter '--' alone on the line to stop.
168 Pasting code; enter '--' alone on the line to stop.
226 :>>> a = ["world!", "Hello"]
169 :>>> a = ["world!", "Hello"]
227 :>>> print " ".join(sorted(a))
170 :>>> print " ".join(sorted(a))
228 :--
171 :--
229 Hello world!
172 Hello world!
230 """
173 """
231 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
174 opts, name = self.parse_options(parameter_s, 'rs:', mode='string')
232 if 'r' in opts:
175 if 'r' in opts:
233 self.rerun_pasted()
176 self.rerun_pasted()
234 return
177 return
235
178
236 sentinel = opts.get('s', '--')
179 sentinel = opts.get('s', '--')
237 block = '\n'.join(get_pasted_lines(sentinel))
180 block = '\n'.join(get_pasted_lines(sentinel))
238 self.store_or_execute(block, name)
181 self.store_or_execute(block, name)
239
182
240 @line_magic
183 @line_magic
241 def paste(self, parameter_s=''):
184 def paste(self, parameter_s=''):
242 """Paste & execute a pre-formatted code block from clipboard.
185 """Paste & execute a pre-formatted code block from clipboard.
243
186
244 The text is pulled directly from the clipboard without user
187 The text is pulled directly from the clipboard without user
245 intervention and printed back on the screen before execution (unless
188 intervention and printed back on the screen before execution (unless
246 the -q flag is given to force quiet mode).
189 the -q flag is given to force quiet mode).
247
190
248 The block is dedented prior to execution to enable execution of method
191 The block is dedented prior to execution to enable execution of method
249 definitions. '>' and '+' characters at the beginning of a line are
192 definitions. '>' and '+' characters at the beginning of a line are
250 ignored, to allow pasting directly from e-mails, diff files and
193 ignored, to allow pasting directly from e-mails, diff files and
251 doctests (the '...' continuation prompt is also stripped). The
194 doctests (the '...' continuation prompt is also stripped). The
252 executed block is also assigned to variable named 'pasted_block' for
195 executed block is also assigned to variable named 'pasted_block' for
253 later editing with '%edit pasted_block'.
196 later editing with '%edit pasted_block'.
254
197
255 You can also pass a variable name as an argument, e.g. '%paste foo'.
198 You can also pass a variable name as an argument, e.g. '%paste foo'.
256 This assigns the pasted block to variable 'foo' as string, without
199 This assigns the pasted block to variable 'foo' as string, without
257 executing it (preceding >>> and + is still stripped).
200 executing it (preceding >>> and + is still stripped).
258
201
259 Options
202 Options
260 -------
203 -------
261
204
262 -r: re-executes the block previously entered by cpaste.
205 -r: re-executes the block previously entered by cpaste.
263
206
264 -q: quiet mode: do not echo the pasted text back to the terminal.
207 -q: quiet mode: do not echo the pasted text back to the terminal.
265
208
266 IPython statements (magics, shell escapes) are not supported (yet).
209 IPython statements (magics, shell escapes) are not supported (yet).
267
210
268 See also
211 See also
269 --------
212 --------
270 cpaste: manually paste code into terminal until you mark its end.
213 cpaste: manually paste code into terminal until you mark its end.
271 """
214 """
272 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
215 opts, name = self.parse_options(parameter_s, 'rq', mode='string')
273 if 'r' in opts:
216 if 'r' in opts:
274 self.rerun_pasted()
217 self.rerun_pasted()
275 return
218 return
276 try:
219 try:
277 block = self.shell.hooks.clipboard_get()
220 block = self.shell.hooks.clipboard_get()
278 except TryNext as clipboard_exc:
221 except TryNext as clipboard_exc:
279 message = getattr(clipboard_exc, 'args')
222 message = getattr(clipboard_exc, 'args')
280 if message:
223 if message:
281 error(message[0])
224 error(message[0])
282 else:
225 else:
283 error('Could not get text from the clipboard.')
226 error('Could not get text from the clipboard.')
284 return
227 return
285
228
286 # By default, echo back to terminal unless quiet mode is requested
229 # By default, echo back to terminal unless quiet mode is requested
287 if 'q' not in opts:
230 if 'q' not in opts:
288 write = self.shell.write
231 write = self.shell.write
289 write(self.shell.pycolorize(block))
232 write(self.shell.pycolorize(block))
290 if not block.endswith('\n'):
233 if not block.endswith('\n'):
291 write('\n')
234 write('\n')
292 write("## -- End pasted text --\n")
235 write("## -- End pasted text --\n")
293
236
294 self.store_or_execute(block, name)
237 self.store_or_execute(block, name)
295
238
296 # Class-level: add a '%cls' magic only on Windows
239 # Class-level: add a '%cls' magic only on Windows
297 if sys.platform == 'win32':
240 if sys.platform == 'win32':
298 @line_magic
241 @line_magic
299 def cls(self, s):
242 def cls(self, s):
300 """Clear screen.
243 """Clear screen.
301 """
244 """
302 os.system("cls")
245 os.system("cls")
303
246
304 #-----------------------------------------------------------------------------
247 #-----------------------------------------------------------------------------
305 # Main class
248 # Main class
306 #-----------------------------------------------------------------------------
249 #-----------------------------------------------------------------------------
307
250
308 class TerminalInteractiveShell(InteractiveShell):
251 class TerminalInteractiveShell(InteractiveShell):
309
252
310 autoedit_syntax = CBool(False, config=True,
253 autoedit_syntax = CBool(False, config=True,
311 help="auto editing of files with syntax errors.")
254 help="auto editing of files with syntax errors.")
312 banner = Unicode('')
255 banner = Unicode('')
313 banner1 = Unicode(default_banner, config=True,
256 banner1 = Unicode(default_banner, config=True,
314 help="""The part of the banner to be printed before the profile"""
257 help="""The part of the banner to be printed before the profile"""
315 )
258 )
316 banner2 = Unicode('', config=True,
259 banner2 = Unicode('', config=True,
317 help="""The part of the banner to be printed after the profile"""
260 help="""The part of the banner to be printed after the profile"""
318 )
261 )
319 confirm_exit = CBool(True, config=True,
262 confirm_exit = CBool(True, config=True,
320 help="""
263 help="""
321 Set to confirm when you try to exit IPython with an EOF (Control-D
264 Set to confirm when you try to exit IPython with an EOF (Control-D
322 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
265 in Unix, Control-Z/Enter in Windows). By typing 'exit' or 'quit',
323 you can force a direct exit without any confirmation.""",
266 you can force a direct exit without any confirmation.""",
324 )
267 )
325 # This display_banner only controls whether or not self.show_banner()
268 # This display_banner only controls whether or not self.show_banner()
326 # is called when mainloop/interact are called. The default is False
269 # is called when mainloop/interact are called. The default is False
327 # because for the terminal based application, the banner behavior
270 # because for the terminal based application, the banner behavior
328 # is controlled by Global.display_banner, which IPythonApp looks at
271 # is controlled by Global.display_banner, which IPythonApp looks at
329 # to determine if *it* should call show_banner() by hand or not.
272 # to determine if *it* should call show_banner() by hand or not.
330 display_banner = CBool(False) # This isn't configurable!
273 display_banner = CBool(False) # This isn't configurable!
331 embedded = CBool(False)
274 embedded = CBool(False)
332 embedded_active = CBool(False)
275 embedded_active = CBool(False)
333 editor = Unicode(get_default_editor(), config=True,
276 editor = Unicode(get_default_editor(), config=True,
334 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
277 help="Set the editor used by IPython (default to $EDITOR/vi/notepad)."
335 )
278 )
336 pager = Unicode('less', config=True,
279 pager = Unicode('less', config=True,
337 help="The shell program to be used for paging.")
280 help="The shell program to be used for paging.")
338
281
339 screen_length = Integer(0, config=True,
282 screen_length = Integer(0, config=True,
340 help=
283 help=
341 """Number of lines of your screen, used to control printing of very
284 """Number of lines of your screen, used to control printing of very
342 long strings. Strings longer than this number of lines will be sent
285 long strings. Strings longer than this number of lines will be sent
343 through a pager instead of directly printed. The default value for
286 through a pager instead of directly printed. The default value for
344 this is 0, which means IPython will auto-detect your screen size every
287 this is 0, which means IPython will auto-detect your screen size every
345 time it needs to print certain potentially long strings (this doesn't
288 time it needs to print certain potentially long strings (this doesn't
346 change the behavior of the 'print' keyword, it's only triggered
289 change the behavior of the 'print' keyword, it's only triggered
347 internally). If for some reason this isn't working well (it needs
290 internally). If for some reason this isn't working well (it needs
348 curses support), specify it yourself. Otherwise don't change the
291 curses support), specify it yourself. Otherwise don't change the
349 default.""",
292 default.""",
350 )
293 )
351 term_title = CBool(False, config=True,
294 term_title = CBool(False, config=True,
352 help="Enable auto setting the terminal title."
295 help="Enable auto setting the terminal title."
353 )
296 )
354
297
355 # This `using_paste_magics` is used to detect whether the code is being
298 # This `using_paste_magics` is used to detect whether the code is being
356 # executed via paste magics functions
299 # executed via paste magics functions
357 using_paste_magics = CBool(False)
300 using_paste_magics = CBool(False)
358
301
359 # In the terminal, GUI control is done via PyOS_InputHook
302 # In the terminal, GUI control is done via PyOS_InputHook
360 @staticmethod
303 @staticmethod
361 def enable_gui(gui=None, app=None):
304 def enable_gui(gui=None, app=None):
362 """Switch amongst GUI input hooks by name.
305 """Switch amongst GUI input hooks by name.
363 """
306 """
364 # Deferred import
307 # Deferred import
365 from IPython.lib.inputhook import enable_gui as real_enable_gui
308 from IPython.lib.inputhook import enable_gui as real_enable_gui
366 return real_enable_gui(gui, app)
309 return real_enable_gui(gui, app)
367
310
368 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
311 def __init__(self, config=None, ipython_dir=None, profile_dir=None,
369 user_ns=None, user_module=None, custom_exceptions=((),None),
312 user_ns=None, user_module=None, custom_exceptions=((),None),
370 usage=None, banner1=None, banner2=None, display_banner=None,
313 usage=None, banner1=None, banner2=None, display_banner=None,
371 **kwargs):
314 **kwargs):
372
315
373 super(TerminalInteractiveShell, self).__init__(
316 super(TerminalInteractiveShell, self).__init__(
374 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
317 config=config, ipython_dir=ipython_dir, profile_dir=profile_dir, user_ns=user_ns,
375 user_module=user_module, custom_exceptions=custom_exceptions,
318 user_module=user_module, custom_exceptions=custom_exceptions,
376 **kwargs
319 **kwargs
377 )
320 )
378 # use os.system instead of utils.process.system by default,
321 # use os.system instead of utils.process.system by default,
379 # because piped system doesn't make sense in the Terminal:
322 # because piped system doesn't make sense in the Terminal:
380 self.system = self.system_raw
323 self.system = self.system_raw
381
324
382 self.init_term_title()
325 self.init_term_title()
383 self.init_usage(usage)
326 self.init_usage(usage)
384 self.init_banner(banner1, banner2, display_banner)
327 self.init_banner(banner1, banner2, display_banner)
385
328
386 #-------------------------------------------------------------------------
329 #-------------------------------------------------------------------------
387 # Overrides of init stages
330 # Overrides of init stages
388 #-------------------------------------------------------------------------
331 #-------------------------------------------------------------------------
389
332
390 def init_display_formatter(self):
333 def init_display_formatter(self):
391 super(TerminalInteractiveShell, self).init_display_formatter()
334 super(TerminalInteractiveShell, self).init_display_formatter()
392 # terminal only supports plaintext
335 # terminal only supports plaintext
393 self.display_formatter.active_types = ['text/plain']
336 self.display_formatter.active_types = ['text/plain']
394
337
395 #-------------------------------------------------------------------------
338 #-------------------------------------------------------------------------
396 # Things related to the terminal
339 # Things related to the terminal
397 #-------------------------------------------------------------------------
340 #-------------------------------------------------------------------------
398
341
399 @property
342 @property
400 def usable_screen_length(self):
343 def usable_screen_length(self):
401 if self.screen_length == 0:
344 if self.screen_length == 0:
402 return 0
345 return 0
403 else:
346 else:
404 num_lines_bot = self.separate_in.count('\n')+1
347 num_lines_bot = self.separate_in.count('\n')+1
405 return self.screen_length - num_lines_bot
348 return self.screen_length - num_lines_bot
406
349
407 def init_term_title(self):
350 def init_term_title(self):
408 # Enable or disable the terminal title.
351 # Enable or disable the terminal title.
409 if self.term_title:
352 if self.term_title:
410 toggle_set_term_title(True)
353 toggle_set_term_title(True)
411 set_term_title('IPython: ' + abbrev_cwd())
354 set_term_title('IPython: ' + abbrev_cwd())
412 else:
355 else:
413 toggle_set_term_title(False)
356 toggle_set_term_title(False)
414
357
415 #-------------------------------------------------------------------------
358 #-------------------------------------------------------------------------
416 # Things related to aliases
359 # Things related to aliases
417 #-------------------------------------------------------------------------
360 #-------------------------------------------------------------------------
418
361
419 def init_alias(self):
362 def init_alias(self):
420 # The parent class defines aliases that can be safely used with any
363 # The parent class defines aliases that can be safely used with any
421 # frontend.
364 # frontend.
422 super(TerminalInteractiveShell, self).init_alias()
365 super(TerminalInteractiveShell, self).init_alias()
423
366
424 # Now define aliases that only make sense on the terminal, because they
367 # Now define aliases that only make sense on the terminal, because they
425 # need direct access to the console in a way that we can't emulate in
368 # need direct access to the console in a way that we can't emulate in
426 # GUI or web frontend
369 # GUI or web frontend
427 if os.name == 'posix':
370 if os.name == 'posix':
428 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
371 aliases = [('clear', 'clear'), ('more', 'more'), ('less', 'less'),
429 ('man', 'man')]
372 ('man', 'man')]
430 elif os.name == 'nt':
373 elif os.name == 'nt':
431 aliases = [('cls', 'cls')]
374 aliases = [('cls', 'cls')]
432
375
433
376
434 for name, cmd in aliases:
377 for name, cmd in aliases:
435 self.alias_manager.define_alias(name, cmd)
378 self.alias_manager.define_alias(name, cmd)
436
379
437 #-------------------------------------------------------------------------
380 #-------------------------------------------------------------------------
438 # Things related to the banner and usage
381 # Things related to the banner and usage
439 #-------------------------------------------------------------------------
382 #-------------------------------------------------------------------------
440
383
441 def _banner1_changed(self):
384 def _banner1_changed(self):
442 self.compute_banner()
385 self.compute_banner()
443
386
444 def _banner2_changed(self):
387 def _banner2_changed(self):
445 self.compute_banner()
388 self.compute_banner()
446
389
447 def _term_title_changed(self, name, new_value):
390 def _term_title_changed(self, name, new_value):
448 self.init_term_title()
391 self.init_term_title()
449
392
450 def init_banner(self, banner1, banner2, display_banner):
393 def init_banner(self, banner1, banner2, display_banner):
451 if banner1 is not None:
394 if banner1 is not None:
452 self.banner1 = banner1
395 self.banner1 = banner1
453 if banner2 is not None:
396 if banner2 is not None:
454 self.banner2 = banner2
397 self.banner2 = banner2
455 if display_banner is not None:
398 if display_banner is not None:
456 self.display_banner = display_banner
399 self.display_banner = display_banner
457 self.compute_banner()
400 self.compute_banner()
458
401
459 def show_banner(self, banner=None):
402 def show_banner(self, banner=None):
460 if banner is None:
403 if banner is None:
461 banner = self.banner
404 banner = self.banner
462 self.write(banner)
405 self.write(banner)
463
406
464 def compute_banner(self):
407 def compute_banner(self):
465 self.banner = self.banner1
408 self.banner = self.banner1
466 if self.profile and self.profile != 'default':
409 if self.profile and self.profile != 'default':
467 self.banner += '\nIPython profile: %s\n' % self.profile
410 self.banner += '\nIPython profile: %s\n' % self.profile
468 if self.banner2:
411 if self.banner2:
469 self.banner += '\n' + self.banner2
412 self.banner += '\n' + self.banner2
470
413
471 def init_usage(self, usage=None):
414 def init_usage(self, usage=None):
472 if usage is None:
415 if usage is None:
473 self.usage = interactive_usage
416 self.usage = interactive_usage
474 else:
417 else:
475 self.usage = usage
418 self.usage = usage
476
419
477 #-------------------------------------------------------------------------
420 #-------------------------------------------------------------------------
478 # Mainloop and code execution logic
421 # Mainloop and code execution logic
479 #-------------------------------------------------------------------------
422 #-------------------------------------------------------------------------
480
423
481 def mainloop(self, display_banner=None):
424 def mainloop(self, display_banner=None):
482 """Start the mainloop.
425 """Start the mainloop.
483
426
484 If an optional banner argument is given, it will override the
427 If an optional banner argument is given, it will override the
485 internally created default banner.
428 internally created default banner.
486 """
429 """
487
430
488 with nested(self.builtin_trap, self.display_trap):
431 with nested(self.builtin_trap, self.display_trap):
489
432
490 while 1:
433 while 1:
491 try:
434 try:
492 self.interact(display_banner=display_banner)
435 self.interact(display_banner=display_banner)
493 #self.interact_with_readline()
436 #self.interact_with_readline()
494 # XXX for testing of a readline-decoupled repl loop, call
437 # XXX for testing of a readline-decoupled repl loop, call
495 # interact_with_readline above
438 # interact_with_readline above
496 break
439 break
497 except KeyboardInterrupt:
440 except KeyboardInterrupt:
498 # this should not be necessary, but KeyboardInterrupt
441 # this should not be necessary, but KeyboardInterrupt
499 # handling seems rather unpredictable...
442 # handling seems rather unpredictable...
500 self.write("\nKeyboardInterrupt in interact()\n")
443 self.write("\nKeyboardInterrupt in interact()\n")
501
444
502 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
445 def _replace_rlhist_multiline(self, source_raw, hlen_before_cell):
503 """Store multiple lines as a single entry in history"""
446 """Store multiple lines as a single entry in history"""
504
447
505 # do nothing without readline or disabled multiline
448 # do nothing without readline or disabled multiline
506 if not self.has_readline or not self.multiline_history:
449 if not self.has_readline or not self.multiline_history:
507 return hlen_before_cell
450 return hlen_before_cell
508
451
509 # windows rl has no remove_history_item
452 # windows rl has no remove_history_item
510 if not hasattr(self.readline, "remove_history_item"):
453 if not hasattr(self.readline, "remove_history_item"):
511 return hlen_before_cell
454 return hlen_before_cell
512
455
513 # skip empty cells
456 # skip empty cells
514 if not source_raw.rstrip():
457 if not source_raw.rstrip():
515 return hlen_before_cell
458 return hlen_before_cell
516
459
517 # nothing changed do nothing, e.g. when rl removes consecutive dups
460 # nothing changed do nothing, e.g. when rl removes consecutive dups
518 hlen = self.readline.get_current_history_length()
461 hlen = self.readline.get_current_history_length()
519 if hlen == hlen_before_cell:
462 if hlen == hlen_before_cell:
520 return hlen_before_cell
463 return hlen_before_cell
521
464
522 for i in range(hlen - hlen_before_cell):
465 for i in range(hlen - hlen_before_cell):
523 self.readline.remove_history_item(hlen - i - 1)
466 self.readline.remove_history_item(hlen - i - 1)
524 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
467 stdin_encoding = get_stream_enc(sys.stdin, 'utf-8')
525 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
468 self.readline.add_history(py3compat.unicode_to_str(source_raw.rstrip(),
526 stdin_encoding))
469 stdin_encoding))
527 return self.readline.get_current_history_length()
470 return self.readline.get_current_history_length()
528
471
529 def interact(self, display_banner=None):
472 def interact(self, display_banner=None):
530 """Closely emulate the interactive Python console."""
473 """Closely emulate the interactive Python console."""
531
474
532 # batch run -> do not interact
475 # batch run -> do not interact
533 if self.exit_now:
476 if self.exit_now:
534 return
477 return
535
478
536 if display_banner is None:
479 if display_banner is None:
537 display_banner = self.display_banner
480 display_banner = self.display_banner
538
481
539 if isinstance(display_banner, basestring):
482 if isinstance(display_banner, basestring):
540 self.show_banner(display_banner)
483 self.show_banner(display_banner)
541 elif display_banner:
484 elif display_banner:
542 self.show_banner()
485 self.show_banner()
543
486
544 more = False
487 more = False
545
488
546 if self.has_readline:
489 if self.has_readline:
547 self.readline_startup_hook(self.pre_readline)
490 self.readline_startup_hook(self.pre_readline)
548 hlen_b4_cell = self.readline.get_current_history_length()
491 hlen_b4_cell = self.readline.get_current_history_length()
549 else:
492 else:
550 hlen_b4_cell = 0
493 hlen_b4_cell = 0
551 # exit_now is set by a call to %Exit or %Quit, through the
494 # exit_now is set by a call to %Exit or %Quit, through the
552 # ask_exit callback.
495 # ask_exit callback.
553
496
554 while not self.exit_now:
497 while not self.exit_now:
555 self.hooks.pre_prompt_hook()
498 self.hooks.pre_prompt_hook()
556 if more:
499 if more:
557 try:
500 try:
558 prompt = self.prompt_manager.render('in2')
501 prompt = self.prompt_manager.render('in2')
559 except:
502 except:
560 self.showtraceback()
503 self.showtraceback()
561 if self.autoindent:
504 if self.autoindent:
562 self.rl_do_indent = True
505 self.rl_do_indent = True
563
506
564 else:
507 else:
565 try:
508 try:
566 prompt = self.separate_in + self.prompt_manager.render('in')
509 prompt = self.separate_in + self.prompt_manager.render('in')
567 except:
510 except:
568 self.showtraceback()
511 self.showtraceback()
569 try:
512 try:
570 line = self.raw_input(prompt)
513 line = self.raw_input(prompt)
571 if self.exit_now:
514 if self.exit_now:
572 # quick exit on sys.std[in|out] close
515 # quick exit on sys.std[in|out] close
573 break
516 break
574 if self.autoindent:
517 if self.autoindent:
575 self.rl_do_indent = False
518 self.rl_do_indent = False
576
519
577 except KeyboardInterrupt:
520 except KeyboardInterrupt:
578 #double-guard against keyboardinterrupts during kbdint handling
521 #double-guard against keyboardinterrupts during kbdint handling
579 try:
522 try:
580 self.write('\nKeyboardInterrupt\n')
523 self.write('\nKeyboardInterrupt\n')
581 source_raw = self.input_splitter.source_raw_reset()[1]
524 source_raw = self.input_splitter.source_raw_reset()[1]
582 hlen_b4_cell = \
525 hlen_b4_cell = \
583 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
526 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
584 more = False
527 more = False
585 except KeyboardInterrupt:
528 except KeyboardInterrupt:
586 pass
529 pass
587 except EOFError:
530 except EOFError:
588 if self.autoindent:
531 if self.autoindent:
589 self.rl_do_indent = False
532 self.rl_do_indent = False
590 if self.has_readline:
533 if self.has_readline:
591 self.readline_startup_hook(None)
534 self.readline_startup_hook(None)
592 self.write('\n')
535 self.write('\n')
593 self.exit()
536 self.exit()
594 except bdb.BdbQuit:
537 except bdb.BdbQuit:
595 warn('The Python debugger has exited with a BdbQuit exception.\n'
538 warn('The Python debugger has exited with a BdbQuit exception.\n'
596 'Because of how pdb handles the stack, it is impossible\n'
539 'Because of how pdb handles the stack, it is impossible\n'
597 'for IPython to properly format this particular exception.\n'
540 'for IPython to properly format this particular exception.\n'
598 'IPython will resume normal operation.')
541 'IPython will resume normal operation.')
599 except:
542 except:
600 # exceptions here are VERY RARE, but they can be triggered
543 # exceptions here are VERY RARE, but they can be triggered
601 # asynchronously by signal handlers, for example.
544 # asynchronously by signal handlers, for example.
602 self.showtraceback()
545 self.showtraceback()
603 else:
546 else:
604 self.input_splitter.push(line)
547 self.input_splitter.push(line)
605 more = self.input_splitter.push_accepts_more()
548 more = self.input_splitter.push_accepts_more()
606 if (self.SyntaxTB.last_syntax_error and
549 if (self.SyntaxTB.last_syntax_error and
607 self.autoedit_syntax):
550 self.autoedit_syntax):
608 self.edit_syntax_error()
551 self.edit_syntax_error()
609 if not more:
552 if not more:
610 source_raw = self.input_splitter.source_raw_reset()[1]
553 source_raw = self.input_splitter.source_raw_reset()[1]
611 self.run_cell(source_raw, store_history=True)
554 self.run_cell(source_raw, store_history=True)
612 hlen_b4_cell = \
555 hlen_b4_cell = \
613 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
556 self._replace_rlhist_multiline(source_raw, hlen_b4_cell)
614
557
615 # Turn off the exit flag, so the mainloop can be restarted if desired
558 # Turn off the exit flag, so the mainloop can be restarted if desired
616 self.exit_now = False
559 self.exit_now = False
617
560
618 def raw_input(self, prompt=''):
561 def raw_input(self, prompt=''):
619 """Write a prompt and read a line.
562 """Write a prompt and read a line.
620
563
621 The returned line does not include the trailing newline.
564 The returned line does not include the trailing newline.
622 When the user enters the EOF key sequence, EOFError is raised.
565 When the user enters the EOF key sequence, EOFError is raised.
623
566
624 Optional inputs:
567 Optional inputs:
625
568
626 - prompt(''): a string to be printed to prompt the user.
569 - prompt(''): a string to be printed to prompt the user.
627
570
628 - continue_prompt(False): whether this line is the first one or a
571 - continue_prompt(False): whether this line is the first one or a
629 continuation in a sequence of inputs.
572 continuation in a sequence of inputs.
630 """
573 """
631 # Code run by the user may have modified the readline completer state.
574 # Code run by the user may have modified the readline completer state.
632 # We must ensure that our completer is back in place.
575 # We must ensure that our completer is back in place.
633
576
634 if self.has_readline:
577 if self.has_readline:
635 self.set_readline_completer()
578 self.set_readline_completer()
636
579
637 # raw_input expects str, but we pass it unicode sometimes
580 # raw_input expects str, but we pass it unicode sometimes
638 prompt = py3compat.cast_bytes_py2(prompt)
581 prompt = py3compat.cast_bytes_py2(prompt)
639
582
640 try:
583 try:
641 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
584 line = py3compat.str_to_unicode(self.raw_input_original(prompt))
642 except ValueError:
585 except ValueError:
643 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
586 warn("\n********\nYou or a %run:ed script called sys.stdin.close()"
644 " or sys.stdout.close()!\nExiting IPython!\n")
587 " or sys.stdout.close()!\nExiting IPython!\n")
645 self.ask_exit()
588 self.ask_exit()
646 return ""
589 return ""
647
590
648 # Try to be reasonably smart about not re-indenting pasted input more
591 # Try to be reasonably smart about not re-indenting pasted input more
649 # than necessary. We do this by trimming out the auto-indent initial
592 # than necessary. We do this by trimming out the auto-indent initial
650 # spaces, if the user's actual input started itself with whitespace.
593 # spaces, if the user's actual input started itself with whitespace.
651 if self.autoindent:
594 if self.autoindent:
652 if num_ini_spaces(line) > self.indent_current_nsp:
595 if num_ini_spaces(line) > self.indent_current_nsp:
653 line = line[self.indent_current_nsp:]
596 line = line[self.indent_current_nsp:]
654 self.indent_current_nsp = 0
597 self.indent_current_nsp = 0
655
598
656 return line
599 return line
657
600
658 #-------------------------------------------------------------------------
601 #-------------------------------------------------------------------------
659 # Methods to support auto-editing of SyntaxErrors.
602 # Methods to support auto-editing of SyntaxErrors.
660 #-------------------------------------------------------------------------
603 #-------------------------------------------------------------------------
661
604
662 def edit_syntax_error(self):
605 def edit_syntax_error(self):
663 """The bottom half of the syntax error handler called in the main loop.
606 """The bottom half of the syntax error handler called in the main loop.
664
607
665 Loop until syntax error is fixed or user cancels.
608 Loop until syntax error is fixed or user cancels.
666 """
609 """
667
610
668 while self.SyntaxTB.last_syntax_error:
611 while self.SyntaxTB.last_syntax_error:
669 # copy and clear last_syntax_error
612 # copy and clear last_syntax_error
670 err = self.SyntaxTB.clear_err_state()
613 err = self.SyntaxTB.clear_err_state()
671 if not self._should_recompile(err):
614 if not self._should_recompile(err):
672 return
615 return
673 try:
616 try:
674 # may set last_syntax_error again if a SyntaxError is raised
617 # may set last_syntax_error again if a SyntaxError is raised
675 self.safe_execfile(err.filename,self.user_ns)
618 self.safe_execfile(err.filename,self.user_ns)
676 except:
619 except:
677 self.showtraceback()
620 self.showtraceback()
678 else:
621 else:
679 try:
622 try:
680 f = open(err.filename)
623 f = open(err.filename)
681 try:
624 try:
682 # This should be inside a display_trap block and I
625 # This should be inside a display_trap block and I
683 # think it is.
626 # think it is.
684 sys.displayhook(f.read())
627 sys.displayhook(f.read())
685 finally:
628 finally:
686 f.close()
629 f.close()
687 except:
630 except:
688 self.showtraceback()
631 self.showtraceback()
689
632
690 def _should_recompile(self,e):
633 def _should_recompile(self,e):
691 """Utility routine for edit_syntax_error"""
634 """Utility routine for edit_syntax_error"""
692
635
693 if e.filename in ('<ipython console>','<input>','<string>',
636 if e.filename in ('<ipython console>','<input>','<string>',
694 '<console>','<BackgroundJob compilation>',
637 '<console>','<BackgroundJob compilation>',
695 None):
638 None):
696
639
697 return False
640 return False
698 try:
641 try:
699 if (self.autoedit_syntax and
642 if (self.autoedit_syntax and
700 not self.ask_yes_no('Return to editor to correct syntax error? '
643 not self.ask_yes_no('Return to editor to correct syntax error? '
701 '[Y/n] ','y')):
644 '[Y/n] ','y')):
702 return False
645 return False
703 except EOFError:
646 except EOFError:
704 return False
647 return False
705
648
706 def int0(x):
649 def int0(x):
707 try:
650 try:
708 return int(x)
651 return int(x)
709 except TypeError:
652 except TypeError:
710 return 0
653 return 0
711 # always pass integer line and offset values to editor hook
654 # always pass integer line and offset values to editor hook
712 try:
655 try:
713 self.hooks.fix_error_editor(e.filename,
656 self.hooks.fix_error_editor(e.filename,
714 int0(e.lineno),int0(e.offset),e.msg)
657 int0(e.lineno),int0(e.offset),e.msg)
715 except TryNext:
658 except TryNext:
716 warn('Could not open editor')
659 warn('Could not open editor')
717 return False
660 return False
718 return True
661 return True
719
662
720 #-------------------------------------------------------------------------
663 #-------------------------------------------------------------------------
721 # Things related to exiting
664 # Things related to exiting
722 #-------------------------------------------------------------------------
665 #-------------------------------------------------------------------------
723
666
724 def ask_exit(self):
667 def ask_exit(self):
725 """ Ask the shell to exit. Can be overiden and used as a callback. """
668 """ Ask the shell to exit. Can be overiden and used as a callback. """
726 self.exit_now = True
669 self.exit_now = True
727
670
728 def exit(self):
671 def exit(self):
729 """Handle interactive exit.
672 """Handle interactive exit.
730
673
731 This method calls the ask_exit callback."""
674 This method calls the ask_exit callback."""
732 if self.confirm_exit:
675 if self.confirm_exit:
733 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
676 if self.ask_yes_no('Do you really want to exit ([y]/n)?','y'):
734 self.ask_exit()
677 self.ask_exit()
735 else:
678 else:
736 self.ask_exit()
679 self.ask_exit()
737
680
738 #-------------------------------------------------------------------------
681 #-------------------------------------------------------------------------
739 # Things related to magics
682 # Things related to magics
740 #-------------------------------------------------------------------------
683 #-------------------------------------------------------------------------
741
684
742 def init_magics(self):
685 def init_magics(self):
743 super(TerminalInteractiveShell, self).init_magics()
686 super(TerminalInteractiveShell, self).init_magics()
744 self.register_magics(TerminalMagics)
687 self.register_magics(TerminalMagics)
745
688
746 def showindentationerror(self):
689 def showindentationerror(self):
747 super(TerminalInteractiveShell, self).showindentationerror()
690 super(TerminalInteractiveShell, self).showindentationerror()
748 if not self.using_paste_magics:
691 if not self.using_paste_magics:
749 print("If you want to paste code into IPython, try the "
692 print("If you want to paste code into IPython, try the "
750 "%paste and %cpaste magic functions.")
693 "%paste and %cpaste magic functions.")
751
694
752
695
753 InteractiveShellABC.register(TerminalInteractiveShell)
696 InteractiveShellABC.register(TerminalInteractiveShell)
@@ -1,807 +1,807 b''
1 """Nose Plugin that supports IPython doctests.
1 """Nose Plugin that supports IPython doctests.
2
2
3 Limitations:
3 Limitations:
4
4
5 - When generating examples for use as doctests, make sure that you have
5 - When generating examples for use as doctests, make sure that you have
6 pretty-printing OFF. This can be done either by setting the
6 pretty-printing OFF. This can be done either by setting the
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
7 ``PlainTextFormatter.pprint`` option in your configuration file to False, or
8 by interactively disabling it with %Pprint. This is required so that IPython
8 by interactively disabling it with %Pprint. This is required so that IPython
9 output matches that of normal Python, which is used by doctest for internal
9 output matches that of normal Python, which is used by doctest for internal
10 execution.
10 execution.
11
11
12 - Do not rely on specific prompt numbers for results (such as using
12 - Do not rely on specific prompt numbers for results (such as using
13 '_34==True', for example). For IPython tests run via an external process the
13 '_34==True', for example). For IPython tests run via an external process the
14 prompt numbers may be different, and IPython tests run as normal python code
14 prompt numbers may be different, and IPython tests run as normal python code
15 won't even have these special _NN variables set at all.
15 won't even have these special _NN variables set at all.
16 """
16 """
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Module imports
19 # Module imports
20
20
21 # From the standard library
21 # From the standard library
22 import __builtin__ as builtin_mod
22 import __builtin__ as builtin_mod
23 import commands
23 import commands
24 import doctest
24 import doctest
25 import inspect
25 import inspect
26 import logging
26 import logging
27 import os
27 import os
28 import re
28 import re
29 import sys
29 import sys
30 import traceback
30 import traceback
31 import unittest
31 import unittest
32
32
33 from inspect import getmodule
33 from inspect import getmodule
34 from StringIO import StringIO
34 from StringIO import StringIO
35
35
36 # We are overriding the default doctest runner, so we need to import a few
36 # We are overriding the default doctest runner, so we need to import a few
37 # things from doctest directly
37 # things from doctest directly
38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
38 from doctest import (REPORTING_FLAGS, REPORT_ONLY_FIRST_FAILURE,
39 _unittest_reportflags, DocTestRunner,
39 _unittest_reportflags, DocTestRunner,
40 _extract_future_flags, pdb, _OutputRedirectingPdb,
40 _extract_future_flags, pdb, _OutputRedirectingPdb,
41 _exception_traceback,
41 _exception_traceback,
42 linecache)
42 linecache)
43
43
44 # Third-party modules
44 # Third-party modules
45 import nose.core
45 import nose.core
46
46
47 from nose.plugins import doctests, Plugin
47 from nose.plugins import doctests, Plugin
48 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
48 from nose.util import anyp, getpackage, test_address, resolve_name, tolist
49
49
50 # Our own imports
50 # Our own imports
51
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
56 #-----------------------------------------------------------------------------
52 #-----------------------------------------------------------------------------
57 # Module globals and other constants
53 # Module globals and other constants
58 #-----------------------------------------------------------------------------
54 #-----------------------------------------------------------------------------
59
55
60 log = logging.getLogger(__name__)
56 log = logging.getLogger(__name__)
61
57
62
58
63 #-----------------------------------------------------------------------------
59 #-----------------------------------------------------------------------------
64 # Classes and functions
60 # Classes and functions
65 #-----------------------------------------------------------------------------
61 #-----------------------------------------------------------------------------
66
62
67 def is_extension_module(filename):
63 def is_extension_module(filename):
68 """Return whether the given filename is an extension module.
64 """Return whether the given filename is an extension module.
69
65
70 This simply checks that the extension is either .so or .pyd.
66 This simply checks that the extension is either .so or .pyd.
71 """
67 """
72 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
68 return os.path.splitext(filename)[1].lower() in ('.so','.pyd')
73
69
74
70
75 class DocTestSkip(object):
71 class DocTestSkip(object):
76 """Object wrapper for doctests to be skipped."""
72 """Object wrapper for doctests to be skipped."""
77
73
78 ds_skip = """Doctest to skip.
74 ds_skip = """Doctest to skip.
79 >>> 1 #doctest: +SKIP
75 >>> 1 #doctest: +SKIP
80 """
76 """
81
77
82 def __init__(self,obj):
78 def __init__(self,obj):
83 self.obj = obj
79 self.obj = obj
84
80
85 def __getattribute__(self,key):
81 def __getattribute__(self,key):
86 if key == '__doc__':
82 if key == '__doc__':
87 return DocTestSkip.ds_skip
83 return DocTestSkip.ds_skip
88 else:
84 else:
89 return getattr(object.__getattribute__(self,'obj'),key)
85 return getattr(object.__getattribute__(self,'obj'),key)
90
86
91 # Modified version of the one in the stdlib, that fixes a python bug (doctests
87 # Modified version of the one in the stdlib, that fixes a python bug (doctests
92 # not found in extension modules, http://bugs.python.org/issue3158)
88 # not found in extension modules, http://bugs.python.org/issue3158)
93 class DocTestFinder(doctest.DocTestFinder):
89 class DocTestFinder(doctest.DocTestFinder):
94
90
95 def _from_module(self, module, object):
91 def _from_module(self, module, object):
96 """
92 """
97 Return true if the given object is defined in the given
93 Return true if the given object is defined in the given
98 module.
94 module.
99 """
95 """
100 if module is None:
96 if module is None:
101 return True
97 return True
102 elif inspect.isfunction(object):
98 elif inspect.isfunction(object):
103 return module.__dict__ is object.func_globals
99 return module.__dict__ is object.func_globals
104 elif inspect.isbuiltin(object):
100 elif inspect.isbuiltin(object):
105 return module.__name__ == object.__module__
101 return module.__name__ == object.__module__
106 elif inspect.isclass(object):
102 elif inspect.isclass(object):
107 return module.__name__ == object.__module__
103 return module.__name__ == object.__module__
108 elif inspect.ismethod(object):
104 elif inspect.ismethod(object):
109 # This one may be a bug in cython that fails to correctly set the
105 # This one may be a bug in cython that fails to correctly set the
110 # __module__ attribute of methods, but since the same error is easy
106 # __module__ attribute of methods, but since the same error is easy
111 # to make by extension code writers, having this safety in place
107 # to make by extension code writers, having this safety in place
112 # isn't such a bad idea
108 # isn't such a bad idea
113 return module.__name__ == object.im_class.__module__
109 return module.__name__ == object.im_class.__module__
114 elif inspect.getmodule(object) is not None:
110 elif inspect.getmodule(object) is not None:
115 return module is inspect.getmodule(object)
111 return module is inspect.getmodule(object)
116 elif hasattr(object, '__module__'):
112 elif hasattr(object, '__module__'):
117 return module.__name__ == object.__module__
113 return module.__name__ == object.__module__
118 elif isinstance(object, property):
114 elif isinstance(object, property):
119 return True # [XX] no way not be sure.
115 return True # [XX] no way not be sure.
120 else:
116 else:
121 raise ValueError("object must be a class or function")
117 raise ValueError("object must be a class or function")
122
118
123 def _find(self, tests, obj, name, module, source_lines, globs, seen):
119 def _find(self, tests, obj, name, module, source_lines, globs, seen):
124 """
120 """
125 Find tests for the given object and any contained objects, and
121 Find tests for the given object and any contained objects, and
126 add them to `tests`.
122 add them to `tests`.
127 """
123 """
128 #print '_find for:', obj, name, module # dbg
124 #print '_find for:', obj, name, module # dbg
129 if hasattr(obj,"skip_doctest"):
125 if hasattr(obj,"skip_doctest"):
130 #print 'SKIPPING DOCTEST FOR:',obj # dbg
126 #print 'SKIPPING DOCTEST FOR:',obj # dbg
131 obj = DocTestSkip(obj)
127 obj = DocTestSkip(obj)
132
128
133 doctest.DocTestFinder._find(self,tests, obj, name, module,
129 doctest.DocTestFinder._find(self,tests, obj, name, module,
134 source_lines, globs, seen)
130 source_lines, globs, seen)
135
131
136 # Below we re-run pieces of the above method with manual modifications,
132 # Below we re-run pieces of the above method with manual modifications,
137 # because the original code is buggy and fails to correctly identify
133 # because the original code is buggy and fails to correctly identify
138 # doctests in extension modules.
134 # doctests in extension modules.
139
135
140 # Local shorthands
136 # Local shorthands
141 from inspect import isroutine, isclass, ismodule
137 from inspect import isroutine, isclass, ismodule
142
138
143 # Look for tests in a module's contained objects.
139 # Look for tests in a module's contained objects.
144 if inspect.ismodule(obj) and self._recurse:
140 if inspect.ismodule(obj) and self._recurse:
145 for valname, val in obj.__dict__.items():
141 for valname, val in obj.__dict__.items():
146 valname1 = '%s.%s' % (name, valname)
142 valname1 = '%s.%s' % (name, valname)
147 if ( (isroutine(val) or isclass(val))
143 if ( (isroutine(val) or isclass(val))
148 and self._from_module(module, val) ):
144 and self._from_module(module, val) ):
149
145
150 self._find(tests, val, valname1, module, source_lines,
146 self._find(tests, val, valname1, module, source_lines,
151 globs, seen)
147 globs, seen)
152
148
153 # Look for tests in a class's contained objects.
149 # Look for tests in a class's contained objects.
154 if inspect.isclass(obj) and self._recurse:
150 if inspect.isclass(obj) and self._recurse:
155 #print 'RECURSE into class:',obj # dbg
151 #print 'RECURSE into class:',obj # dbg
156 for valname, val in obj.__dict__.items():
152 for valname, val in obj.__dict__.items():
157 # Special handling for staticmethod/classmethod.
153 # Special handling for staticmethod/classmethod.
158 if isinstance(val, staticmethod):
154 if isinstance(val, staticmethod):
159 val = getattr(obj, valname)
155 val = getattr(obj, valname)
160 if isinstance(val, classmethod):
156 if isinstance(val, classmethod):
161 val = getattr(obj, valname).im_func
157 val = getattr(obj, valname).im_func
162
158
163 # Recurse to methods, properties, and nested classes.
159 # Recurse to methods, properties, and nested classes.
164 if ((inspect.isfunction(val) or inspect.isclass(val) or
160 if ((inspect.isfunction(val) or inspect.isclass(val) or
165 inspect.ismethod(val) or
161 inspect.ismethod(val) or
166 isinstance(val, property)) and
162 isinstance(val, property)) and
167 self._from_module(module, val)):
163 self._from_module(module, val)):
168 valname = '%s.%s' % (name, valname)
164 valname = '%s.%s' % (name, valname)
169 self._find(tests, val, valname, module, source_lines,
165 self._find(tests, val, valname, module, source_lines,
170 globs, seen)
166 globs, seen)
171
167
172
168
173 class IPDoctestOutputChecker(doctest.OutputChecker):
169 class IPDoctestOutputChecker(doctest.OutputChecker):
174 """Second-chance checker with support for random tests.
170 """Second-chance checker with support for random tests.
175
171
176 If the default comparison doesn't pass, this checker looks in the expected
172 If the default comparison doesn't pass, this checker looks in the expected
177 output string for flags that tell us to ignore the output.
173 output string for flags that tell us to ignore the output.
178 """
174 """
179
175
180 random_re = re.compile(r'#\s*random\s+')
176 random_re = re.compile(r'#\s*random\s+')
181
177
182 def check_output(self, want, got, optionflags):
178 def check_output(self, want, got, optionflags):
183 """Check output, accepting special markers embedded in the output.
179 """Check output, accepting special markers embedded in the output.
184
180
185 If the output didn't pass the default validation but the special string
181 If the output didn't pass the default validation but the special string
186 '#random' is included, we accept it."""
182 '#random' is included, we accept it."""
187
183
188 # Let the original tester verify first, in case people have valid tests
184 # Let the original tester verify first, in case people have valid tests
189 # that happen to have a comment saying '#random' embedded in.
185 # that happen to have a comment saying '#random' embedded in.
190 ret = doctest.OutputChecker.check_output(self, want, got,
186 ret = doctest.OutputChecker.check_output(self, want, got,
191 optionflags)
187 optionflags)
192 if not ret and self.random_re.search(want):
188 if not ret and self.random_re.search(want):
193 #print >> sys.stderr, 'RANDOM OK:',want # dbg
189 #print >> sys.stderr, 'RANDOM OK:',want # dbg
194 return True
190 return True
195
191
196 return ret
192 return ret
197
193
198
194
199 class DocTestCase(doctests.DocTestCase):
195 class DocTestCase(doctests.DocTestCase):
200 """Proxy for DocTestCase: provides an address() method that
196 """Proxy for DocTestCase: provides an address() method that
201 returns the correct address for the doctest case. Otherwise
197 returns the correct address for the doctest case. Otherwise
202 acts as a proxy to the test case. To provide hints for address(),
198 acts as a proxy to the test case. To provide hints for address(),
203 an obj may also be passed -- this will be used as the test object
199 an obj may also be passed -- this will be used as the test object
204 for purposes of determining the test address, if it is provided.
200 for purposes of determining the test address, if it is provided.
205 """
201 """
206
202
207 # Note: this method was taken from numpy's nosetester module.
203 # Note: this method was taken from numpy's nosetester module.
208
204
209 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
205 # Subclass nose.plugins.doctests.DocTestCase to work around a bug in
210 # its constructor that blocks non-default arguments from being passed
206 # its constructor that blocks non-default arguments from being passed
211 # down into doctest.DocTestCase
207 # down into doctest.DocTestCase
212
208
213 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
209 def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
214 checker=None, obj=None, result_var='_'):
210 checker=None, obj=None, result_var='_'):
215 self._result_var = result_var
211 self._result_var = result_var
216 doctests.DocTestCase.__init__(self, test,
212 doctests.DocTestCase.__init__(self, test,
217 optionflags=optionflags,
213 optionflags=optionflags,
218 setUp=setUp, tearDown=tearDown,
214 setUp=setUp, tearDown=tearDown,
219 checker=checker)
215 checker=checker)
220 # Now we must actually copy the original constructor from the stdlib
216 # Now we must actually copy the original constructor from the stdlib
221 # doctest class, because we can't call it directly and a bug in nose
217 # doctest class, because we can't call it directly and a bug in nose
222 # means it never gets passed the right arguments.
218 # means it never gets passed the right arguments.
223
219
224 self._dt_optionflags = optionflags
220 self._dt_optionflags = optionflags
225 self._dt_checker = checker
221 self._dt_checker = checker
226 self._dt_test = test
222 self._dt_test = test
227 self._dt_test_globs_ori = test.globs
223 self._dt_test_globs_ori = test.globs
228 self._dt_setUp = setUp
224 self._dt_setUp = setUp
229 self._dt_tearDown = tearDown
225 self._dt_tearDown = tearDown
230
226
231 # XXX - store this runner once in the object!
227 # XXX - store this runner once in the object!
232 runner = IPDocTestRunner(optionflags=optionflags,
228 runner = IPDocTestRunner(optionflags=optionflags,
233 checker=checker, verbose=False)
229 checker=checker, verbose=False)
234 self._dt_runner = runner
230 self._dt_runner = runner
235
231
236
232
237 # Each doctest should remember the directory it was loaded from, so
233 # Each doctest should remember the directory it was loaded from, so
238 # things like %run work without too many contortions
234 # things like %run work without too many contortions
239 self._ori_dir = os.path.dirname(test.filename)
235 self._ori_dir = os.path.dirname(test.filename)
240
236
241 # Modified runTest from the default stdlib
237 # Modified runTest from the default stdlib
242 def runTest(self):
238 def runTest(self):
243 test = self._dt_test
239 test = self._dt_test
244 runner = self._dt_runner
240 runner = self._dt_runner
245
241
246 old = sys.stdout
242 old = sys.stdout
247 new = StringIO()
243 new = StringIO()
248 optionflags = self._dt_optionflags
244 optionflags = self._dt_optionflags
249
245
250 if not (optionflags & REPORTING_FLAGS):
246 if not (optionflags & REPORTING_FLAGS):
251 # The option flags don't include any reporting flags,
247 # The option flags don't include any reporting flags,
252 # so add the default reporting flags
248 # so add the default reporting flags
253 optionflags |= _unittest_reportflags
249 optionflags |= _unittest_reportflags
254
250
255 try:
251 try:
256 # Save our current directory and switch out to the one where the
252 # Save our current directory and switch out to the one where the
257 # test was originally created, in case another doctest did a
253 # test was originally created, in case another doctest did a
258 # directory change. We'll restore this in the finally clause.
254 # directory change. We'll restore this in the finally clause.
259 curdir = os.getcwdu()
255 curdir = os.getcwdu()
260 #print 'runTest in dir:', self._ori_dir # dbg
256 #print 'runTest in dir:', self._ori_dir # dbg
261 os.chdir(self._ori_dir)
257 os.chdir(self._ori_dir)
262
258
263 runner.DIVIDER = "-"*70
259 runner.DIVIDER = "-"*70
264 failures, tries = runner.run(test,out=new.write,
260 failures, tries = runner.run(test,out=new.write,
265 clear_globs=False)
261 clear_globs=False)
266 finally:
262 finally:
267 sys.stdout = old
263 sys.stdout = old
268 os.chdir(curdir)
264 os.chdir(curdir)
269
265
270 if failures:
266 if failures:
271 raise self.failureException(self.format_failure(new.getvalue()))
267 raise self.failureException(self.format_failure(new.getvalue()))
272
268
273 def setUp(self):
269 def setUp(self):
274 """Modified test setup that syncs with ipython namespace"""
270 """Modified test setup that syncs with ipython namespace"""
275 #print "setUp test", self._dt_test.examples # dbg
271 #print "setUp test", self._dt_test.examples # dbg
276 if isinstance(self._dt_test.examples[0], IPExample):
272 if isinstance(self._dt_test.examples[0], IPExample):
277 # for IPython examples *only*, we swap the globals with the ipython
273 # for IPython examples *only*, we swap the globals with the ipython
278 # namespace, after updating it with the globals (which doctest
274 # namespace, after updating it with the globals (which doctest
279 # fills with the necessary info from the module being tested).
275 # fills with the necessary info from the module being tested).
280 self.user_ns_orig = {}
276 self.user_ns_orig = {}
281 self.user_ns_orig.update(_ip.user_ns)
277 self.user_ns_orig.update(_ip.user_ns)
282 _ip.user_ns.update(self._dt_test.globs)
278 _ip.user_ns.update(self._dt_test.globs)
283 # We must remove the _ key in the namespace, so that Python's
279 # We must remove the _ key in the namespace, so that Python's
284 # doctest code sets it naturally
280 # doctest code sets it naturally
285 _ip.user_ns.pop('_', None)
281 _ip.user_ns.pop('_', None)
286 _ip.user_ns['__builtins__'] = builtin_mod
282 _ip.user_ns['__builtins__'] = builtin_mod
287 self._dt_test.globs = _ip.user_ns
283 self._dt_test.globs = _ip.user_ns
288
284
289 super(DocTestCase, self).setUp()
285 super(DocTestCase, self).setUp()
290
286
291 def tearDown(self):
287 def tearDown(self):
292
288
293 # Undo the test.globs reassignment we made, so that the parent class
289 # Undo the test.globs reassignment we made, so that the parent class
294 # teardown doesn't destroy the ipython namespace
290 # teardown doesn't destroy the ipython namespace
295 if isinstance(self._dt_test.examples[0], IPExample):
291 if isinstance(self._dt_test.examples[0], IPExample):
296 self._dt_test.globs = self._dt_test_globs_ori
292 self._dt_test.globs = self._dt_test_globs_ori
297 _ip.user_ns.clear()
293 _ip.user_ns.clear()
298 _ip.user_ns.update(self.user_ns_orig)
294 _ip.user_ns.update(self.user_ns_orig)
299
295
300 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
296 # XXX - fperez: I am not sure if this is truly a bug in nose 0.11, but
301 # it does look like one to me: its tearDown method tries to run
297 # it does look like one to me: its tearDown method tries to run
302 #
298 #
303 # delattr(__builtin__, self._result_var)
299 # delattr(__builtin__, self._result_var)
304 #
300 #
305 # without checking that the attribute really is there; it implicitly
301 # without checking that the attribute really is there; it implicitly
306 # assumes it should have been set via displayhook. But if the
302 # assumes it should have been set via displayhook. But if the
307 # displayhook was never called, this doesn't necessarily happen. I
303 # displayhook was never called, this doesn't necessarily happen. I
308 # haven't been able to find a little self-contained example outside of
304 # haven't been able to find a little self-contained example outside of
309 # ipython that would show the problem so I can report it to the nose
305 # ipython that would show the problem so I can report it to the nose
310 # team, but it does happen a lot in our code.
306 # team, but it does happen a lot in our code.
311 #
307 #
312 # So here, we just protect as narrowly as possible by trapping an
308 # So here, we just protect as narrowly as possible by trapping an
313 # attribute error whose message would be the name of self._result_var,
309 # attribute error whose message would be the name of self._result_var,
314 # and letting any other error propagate.
310 # and letting any other error propagate.
315 try:
311 try:
316 super(DocTestCase, self).tearDown()
312 super(DocTestCase, self).tearDown()
317 except AttributeError as exc:
313 except AttributeError as exc:
318 if exc.args[0] != self._result_var:
314 if exc.args[0] != self._result_var:
319 raise
315 raise
320
316
321
317
322 # A simple subclassing of the original with a different class name, so we can
318 # A simple subclassing of the original with a different class name, so we can
323 # distinguish and treat differently IPython examples from pure python ones.
319 # distinguish and treat differently IPython examples from pure python ones.
324 class IPExample(doctest.Example): pass
320 class IPExample(doctest.Example): pass
325
321
326
322
327 class IPExternalExample(doctest.Example):
323 class IPExternalExample(doctest.Example):
328 """Doctest examples to be run in an external process."""
324 """Doctest examples to be run in an external process."""
329
325
330 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
326 def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
331 options=None):
327 options=None):
332 # Parent constructor
328 # Parent constructor
333 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
329 doctest.Example.__init__(self,source,want,exc_msg,lineno,indent,options)
334
330
335 # An EXTRA newline is needed to prevent pexpect hangs
331 # An EXTRA newline is needed to prevent pexpect hangs
336 self.source += '\n'
332 self.source += '\n'
337
333
338
334
339 class IPDocTestParser(doctest.DocTestParser):
335 class IPDocTestParser(doctest.DocTestParser):
340 """
336 """
341 A class used to parse strings containing doctest examples.
337 A class used to parse strings containing doctest examples.
342
338
343 Note: This is a version modified to properly recognize IPython input and
339 Note: This is a version modified to properly recognize IPython input and
344 convert any IPython examples into valid Python ones.
340 convert any IPython examples into valid Python ones.
345 """
341 """
346 # This regular expression is used to find doctest examples in a
342 # This regular expression is used to find doctest examples in a
347 # string. It defines three groups: `source` is the source code
343 # string. It defines three groups: `source` is the source code
348 # (including leading indentation and prompts); `indent` is the
344 # (including leading indentation and prompts); `indent` is the
349 # indentation of the first (PS1) line of the source code; and
345 # indentation of the first (PS1) line of the source code; and
350 # `want` is the expected output (including leading indentation).
346 # `want` is the expected output (including leading indentation).
351
347
352 # Classic Python prompts or default IPython ones
348 # Classic Python prompts or default IPython ones
353 _PS1_PY = r'>>>'
349 _PS1_PY = r'>>>'
354 _PS2_PY = r'\.\.\.'
350 _PS2_PY = r'\.\.\.'
355
351
356 _PS1_IP = r'In\ \[\d+\]:'
352 _PS1_IP = r'In\ \[\d+\]:'
357 _PS2_IP = r'\ \ \ \.\.\.+:'
353 _PS2_IP = r'\ \ \ \.\.\.+:'
358
354
359 _RE_TPL = r'''
355 _RE_TPL = r'''
360 # Source consists of a PS1 line followed by zero or more PS2 lines.
356 # Source consists of a PS1 line followed by zero or more PS2 lines.
361 (?P<source>
357 (?P<source>
362 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
358 (?:^(?P<indent> [ ]*) (?P<ps1> %s) .*) # PS1 line
363 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
359 (?:\n [ ]* (?P<ps2> %s) .*)*) # PS2 lines
364 \n? # a newline
360 \n? # a newline
365 # Want consists of any non-blank lines that do not start with PS1.
361 # Want consists of any non-blank lines that do not start with PS1.
366 (?P<want> (?:(?![ ]*$) # Not a blank line
362 (?P<want> (?:(?![ ]*$) # Not a blank line
367 (?![ ]*%s) # Not a line starting with PS1
363 (?![ ]*%s) # Not a line starting with PS1
368 (?![ ]*%s) # Not a line starting with PS2
364 (?![ ]*%s) # Not a line starting with PS2
369 .*$\n? # But any other line
365 .*$\n? # But any other line
370 )*)
366 )*)
371 '''
367 '''
372
368
373 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
369 _EXAMPLE_RE_PY = re.compile( _RE_TPL % (_PS1_PY,_PS2_PY,_PS1_PY,_PS2_PY),
374 re.MULTILINE | re.VERBOSE)
370 re.MULTILINE | re.VERBOSE)
375
371
376 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
372 _EXAMPLE_RE_IP = re.compile( _RE_TPL % (_PS1_IP,_PS2_IP,_PS1_IP,_PS2_IP),
377 re.MULTILINE | re.VERBOSE)
373 re.MULTILINE | re.VERBOSE)
378
374
379 # Mark a test as being fully random. In this case, we simply append the
375 # Mark a test as being fully random. In this case, we simply append the
380 # random marker ('#random') to each individual example's output. This way
376 # random marker ('#random') to each individual example's output. This way
381 # we don't need to modify any other code.
377 # we don't need to modify any other code.
382 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
378 _RANDOM_TEST = re.compile(r'#\s*all-random\s+')
383
379
384 # Mark tests to be executed in an external process - currently unsupported.
380 # Mark tests to be executed in an external process - currently unsupported.
385 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
381 _EXTERNAL_IP = re.compile(r'#\s*ipdoctest:\s*EXTERNAL')
386
382
387 def ip2py(self,source):
383 def ip2py(self,source):
388 """Convert input IPython source into valid Python."""
384 """Convert input IPython source into valid Python."""
389 return TerminalMagics(_ip).cleanup_input(source)
385 block = _ip.input_transformer_manager.transform_cell(source)
386 if len(block.splitlines()) == 1:
387 return _ip.prefilter(block)
388 else:
389 return block
390
390
391 def parse(self, string, name='<string>'):
391 def parse(self, string, name='<string>'):
392 """
392 """
393 Divide the given string into examples and intervening text,
393 Divide the given string into examples and intervening text,
394 and return them as a list of alternating Examples and strings.
394 and return them as a list of alternating Examples and strings.
395 Line numbers for the Examples are 0-based. The optional
395 Line numbers for the Examples are 0-based. The optional
396 argument `name` is a name identifying this string, and is only
396 argument `name` is a name identifying this string, and is only
397 used for error messages.
397 used for error messages.
398 """
398 """
399
399
400 #print 'Parse string:\n',string # dbg
400 #print 'Parse string:\n',string # dbg
401
401
402 string = string.expandtabs()
402 string = string.expandtabs()
403 # If all lines begin with the same indentation, then strip it.
403 # If all lines begin with the same indentation, then strip it.
404 min_indent = self._min_indent(string)
404 min_indent = self._min_indent(string)
405 if min_indent > 0:
405 if min_indent > 0:
406 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
406 string = '\n'.join([l[min_indent:] for l in string.split('\n')])
407
407
408 output = []
408 output = []
409 charno, lineno = 0, 0
409 charno, lineno = 0, 0
410
410
411 # We make 'all random' tests by adding the '# random' mark to every
411 # We make 'all random' tests by adding the '# random' mark to every
412 # block of output in the test.
412 # block of output in the test.
413 if self._RANDOM_TEST.search(string):
413 if self._RANDOM_TEST.search(string):
414 random_marker = '\n# random'
414 random_marker = '\n# random'
415 else:
415 else:
416 random_marker = ''
416 random_marker = ''
417
417
418 # Whether to convert the input from ipython to python syntax
418 # Whether to convert the input from ipython to python syntax
419 ip2py = False
419 ip2py = False
420 # Find all doctest examples in the string. First, try them as Python
420 # Find all doctest examples in the string. First, try them as Python
421 # examples, then as IPython ones
421 # examples, then as IPython ones
422 terms = list(self._EXAMPLE_RE_PY.finditer(string))
422 terms = list(self._EXAMPLE_RE_PY.finditer(string))
423 if terms:
423 if terms:
424 # Normal Python example
424 # Normal Python example
425 #print '-'*70 # dbg
425 #print '-'*70 # dbg
426 #print 'PyExample, Source:\n',string # dbg
426 #print 'PyExample, Source:\n',string # dbg
427 #print '-'*70 # dbg
427 #print '-'*70 # dbg
428 Example = doctest.Example
428 Example = doctest.Example
429 else:
429 else:
430 # It's an ipython example. Note that IPExamples are run
430 # It's an ipython example. Note that IPExamples are run
431 # in-process, so their syntax must be turned into valid python.
431 # in-process, so their syntax must be turned into valid python.
432 # IPExternalExamples are run out-of-process (via pexpect) so they
432 # IPExternalExamples are run out-of-process (via pexpect) so they
433 # don't need any filtering (a real ipython will be executing them).
433 # don't need any filtering (a real ipython will be executing them).
434 terms = list(self._EXAMPLE_RE_IP.finditer(string))
434 terms = list(self._EXAMPLE_RE_IP.finditer(string))
435 if self._EXTERNAL_IP.search(string):
435 if self._EXTERNAL_IP.search(string):
436 #print '-'*70 # dbg
436 #print '-'*70 # dbg
437 #print 'IPExternalExample, Source:\n',string # dbg
437 #print 'IPExternalExample, Source:\n',string # dbg
438 #print '-'*70 # dbg
438 #print '-'*70 # dbg
439 Example = IPExternalExample
439 Example = IPExternalExample
440 else:
440 else:
441 #print '-'*70 # dbg
441 #print '-'*70 # dbg
442 #print 'IPExample, Source:\n',string # dbg
442 #print 'IPExample, Source:\n',string # dbg
443 #print '-'*70 # dbg
443 #print '-'*70 # dbg
444 Example = IPExample
444 Example = IPExample
445 ip2py = True
445 ip2py = True
446
446
447 for m in terms:
447 for m in terms:
448 # Add the pre-example text to `output`.
448 # Add the pre-example text to `output`.
449 output.append(string[charno:m.start()])
449 output.append(string[charno:m.start()])
450 # Update lineno (lines before this example)
450 # Update lineno (lines before this example)
451 lineno += string.count('\n', charno, m.start())
451 lineno += string.count('\n', charno, m.start())
452 # Extract info from the regexp match.
452 # Extract info from the regexp match.
453 (source, options, want, exc_msg) = \
453 (source, options, want, exc_msg) = \
454 self._parse_example(m, name, lineno,ip2py)
454 self._parse_example(m, name, lineno,ip2py)
455
455
456 # Append the random-output marker (it defaults to empty in most
456 # Append the random-output marker (it defaults to empty in most
457 # cases, it's only non-empty for 'all-random' tests):
457 # cases, it's only non-empty for 'all-random' tests):
458 want += random_marker
458 want += random_marker
459
459
460 if Example is IPExternalExample:
460 if Example is IPExternalExample:
461 options[doctest.NORMALIZE_WHITESPACE] = True
461 options[doctest.NORMALIZE_WHITESPACE] = True
462 want += '\n'
462 want += '\n'
463
463
464 # Create an Example, and add it to the list.
464 # Create an Example, and add it to the list.
465 if not self._IS_BLANK_OR_COMMENT(source):
465 if not self._IS_BLANK_OR_COMMENT(source):
466 output.append(Example(source, want, exc_msg,
466 output.append(Example(source, want, exc_msg,
467 lineno=lineno,
467 lineno=lineno,
468 indent=min_indent+len(m.group('indent')),
468 indent=min_indent+len(m.group('indent')),
469 options=options))
469 options=options))
470 # Update lineno (lines inside this example)
470 # Update lineno (lines inside this example)
471 lineno += string.count('\n', m.start(), m.end())
471 lineno += string.count('\n', m.start(), m.end())
472 # Update charno.
472 # Update charno.
473 charno = m.end()
473 charno = m.end()
474 # Add any remaining post-example text to `output`.
474 # Add any remaining post-example text to `output`.
475 output.append(string[charno:])
475 output.append(string[charno:])
476 return output
476 return output
477
477
478 def _parse_example(self, m, name, lineno,ip2py=False):
478 def _parse_example(self, m, name, lineno,ip2py=False):
479 """
479 """
480 Given a regular expression match from `_EXAMPLE_RE` (`m`),
480 Given a regular expression match from `_EXAMPLE_RE` (`m`),
481 return a pair `(source, want)`, where `source` is the matched
481 return a pair `(source, want)`, where `source` is the matched
482 example's source code (with prompts and indentation stripped);
482 example's source code (with prompts and indentation stripped);
483 and `want` is the example's expected output (with indentation
483 and `want` is the example's expected output (with indentation
484 stripped).
484 stripped).
485
485
486 `name` is the string's name, and `lineno` is the line number
486 `name` is the string's name, and `lineno` is the line number
487 where the example starts; both are used for error messages.
487 where the example starts; both are used for error messages.
488
488
489 Optional:
489 Optional:
490 `ip2py`: if true, filter the input via IPython to convert the syntax
490 `ip2py`: if true, filter the input via IPython to convert the syntax
491 into valid python.
491 into valid python.
492 """
492 """
493
493
494 # Get the example's indentation level.
494 # Get the example's indentation level.
495 indent = len(m.group('indent'))
495 indent = len(m.group('indent'))
496
496
497 # Divide source into lines; check that they're properly
497 # Divide source into lines; check that they're properly
498 # indented; and then strip their indentation & prompts.
498 # indented; and then strip their indentation & prompts.
499 source_lines = m.group('source').split('\n')
499 source_lines = m.group('source').split('\n')
500
500
501 # We're using variable-length input prompts
501 # We're using variable-length input prompts
502 ps1 = m.group('ps1')
502 ps1 = m.group('ps1')
503 ps2 = m.group('ps2')
503 ps2 = m.group('ps2')
504 ps1_len = len(ps1)
504 ps1_len = len(ps1)
505
505
506 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
506 self._check_prompt_blank(source_lines, indent, name, lineno,ps1_len)
507 if ps2:
507 if ps2:
508 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
508 self._check_prefix(source_lines[1:], ' '*indent + ps2, name, lineno)
509
509
510 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
510 source = '\n'.join([sl[indent+ps1_len+1:] for sl in source_lines])
511
511
512 if ip2py:
512 if ip2py:
513 # Convert source input from IPython into valid Python syntax
513 # Convert source input from IPython into valid Python syntax
514 source = self.ip2py(source)
514 source = self.ip2py(source)
515
515
516 # Divide want into lines; check that it's properly indented; and
516 # Divide want into lines; check that it's properly indented; and
517 # then strip the indentation. Spaces before the last newline should
517 # then strip the indentation. Spaces before the last newline should
518 # be preserved, so plain rstrip() isn't good enough.
518 # be preserved, so plain rstrip() isn't good enough.
519 want = m.group('want')
519 want = m.group('want')
520 want_lines = want.split('\n')
520 want_lines = want.split('\n')
521 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
521 if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
522 del want_lines[-1] # forget final newline & spaces after it
522 del want_lines[-1] # forget final newline & spaces after it
523 self._check_prefix(want_lines, ' '*indent, name,
523 self._check_prefix(want_lines, ' '*indent, name,
524 lineno + len(source_lines))
524 lineno + len(source_lines))
525
525
526 # Remove ipython output prompt that might be present in the first line
526 # Remove ipython output prompt that might be present in the first line
527 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
527 want_lines[0] = re.sub(r'Out\[\d+\]: \s*?\n?','',want_lines[0])
528
528
529 want = '\n'.join([wl[indent:] for wl in want_lines])
529 want = '\n'.join([wl[indent:] for wl in want_lines])
530
530
531 # If `want` contains a traceback message, then extract it.
531 # If `want` contains a traceback message, then extract it.
532 m = self._EXCEPTION_RE.match(want)
532 m = self._EXCEPTION_RE.match(want)
533 if m:
533 if m:
534 exc_msg = m.group('msg')
534 exc_msg = m.group('msg')
535 else:
535 else:
536 exc_msg = None
536 exc_msg = None
537
537
538 # Extract options from the source.
538 # Extract options from the source.
539 options = self._find_options(source, name, lineno)
539 options = self._find_options(source, name, lineno)
540
540
541 return source, options, want, exc_msg
541 return source, options, want, exc_msg
542
542
543 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
543 def _check_prompt_blank(self, lines, indent, name, lineno, ps1_len):
544 """
544 """
545 Given the lines of a source string (including prompts and
545 Given the lines of a source string (including prompts and
546 leading indentation), check to make sure that every prompt is
546 leading indentation), check to make sure that every prompt is
547 followed by a space character. If any line is not followed by
547 followed by a space character. If any line is not followed by
548 a space character, then raise ValueError.
548 a space character, then raise ValueError.
549
549
550 Note: IPython-modified version which takes the input prompt length as a
550 Note: IPython-modified version which takes the input prompt length as a
551 parameter, so that prompts of variable length can be dealt with.
551 parameter, so that prompts of variable length can be dealt with.
552 """
552 """
553 space_idx = indent+ps1_len
553 space_idx = indent+ps1_len
554 min_len = space_idx+1
554 min_len = space_idx+1
555 for i, line in enumerate(lines):
555 for i, line in enumerate(lines):
556 if len(line) >= min_len and line[space_idx] != ' ':
556 if len(line) >= min_len and line[space_idx] != ' ':
557 raise ValueError('line %r of the docstring for %s '
557 raise ValueError('line %r of the docstring for %s '
558 'lacks blank after %s: %r' %
558 'lacks blank after %s: %r' %
559 (lineno+i+1, name,
559 (lineno+i+1, name,
560 line[indent:space_idx], line))
560 line[indent:space_idx], line))
561
561
562
562
563 SKIP = doctest.register_optionflag('SKIP')
563 SKIP = doctest.register_optionflag('SKIP')
564
564
565
565
566 class IPDocTestRunner(doctest.DocTestRunner,object):
566 class IPDocTestRunner(doctest.DocTestRunner,object):
567 """Test runner that synchronizes the IPython namespace with test globals.
567 """Test runner that synchronizes the IPython namespace with test globals.
568 """
568 """
569
569
570 def run(self, test, compileflags=None, out=None, clear_globs=True):
570 def run(self, test, compileflags=None, out=None, clear_globs=True):
571
571
572 # Hack: ipython needs access to the execution context of the example,
572 # Hack: ipython needs access to the execution context of the example,
573 # so that it can propagate user variables loaded by %run into
573 # so that it can propagate user variables loaded by %run into
574 # test.globs. We put them here into our modified %run as a function
574 # test.globs. We put them here into our modified %run as a function
575 # attribute. Our new %run will then only make the namespace update
575 # attribute. Our new %run will then only make the namespace update
576 # when called (rather than unconconditionally updating test.globs here
576 # when called (rather than unconconditionally updating test.globs here
577 # for all examples, most of which won't be calling %run anyway).
577 # for all examples, most of which won't be calling %run anyway).
578 #_ip._ipdoctest_test_globs = test.globs
578 #_ip._ipdoctest_test_globs = test.globs
579 #_ip._ipdoctest_test_filename = test.filename
579 #_ip._ipdoctest_test_filename = test.filename
580
580
581 test.globs.update(_ip.user_ns)
581 test.globs.update(_ip.user_ns)
582
582
583 return super(IPDocTestRunner,self).run(test,
583 return super(IPDocTestRunner,self).run(test,
584 compileflags,out,clear_globs)
584 compileflags,out,clear_globs)
585
585
586
586
587 class DocFileCase(doctest.DocFileCase):
587 class DocFileCase(doctest.DocFileCase):
588 """Overrides to provide filename
588 """Overrides to provide filename
589 """
589 """
590 def address(self):
590 def address(self):
591 return (self._dt_test.filename, None, None)
591 return (self._dt_test.filename, None, None)
592
592
593
593
594 class ExtensionDoctest(doctests.Doctest):
594 class ExtensionDoctest(doctests.Doctest):
595 """Nose Plugin that supports doctests in extension modules.
595 """Nose Plugin that supports doctests in extension modules.
596 """
596 """
597 name = 'extdoctest' # call nosetests with --with-extdoctest
597 name = 'extdoctest' # call nosetests with --with-extdoctest
598 enabled = True
598 enabled = True
599
599
600 def __init__(self,exclude_patterns=None):
600 def __init__(self,exclude_patterns=None):
601 """Create a new ExtensionDoctest plugin.
601 """Create a new ExtensionDoctest plugin.
602
602
603 Parameters
603 Parameters
604 ----------
604 ----------
605
605
606 exclude_patterns : sequence of strings, optional
606 exclude_patterns : sequence of strings, optional
607 These patterns are compiled as regular expressions, subsequently used
607 These patterns are compiled as regular expressions, subsequently used
608 to exclude any filename which matches them from inclusion in the test
608 to exclude any filename which matches them from inclusion in the test
609 suite (using pattern.search(), NOT pattern.match() ).
609 suite (using pattern.search(), NOT pattern.match() ).
610 """
610 """
611
611
612 if exclude_patterns is None:
612 if exclude_patterns is None:
613 exclude_patterns = []
613 exclude_patterns = []
614 self.exclude_patterns = map(re.compile,exclude_patterns)
614 self.exclude_patterns = map(re.compile,exclude_patterns)
615 doctests.Doctest.__init__(self)
615 doctests.Doctest.__init__(self)
616
616
617 def options(self, parser, env=os.environ):
617 def options(self, parser, env=os.environ):
618 Plugin.options(self, parser, env)
618 Plugin.options(self, parser, env)
619 parser.add_option('--doctest-tests', action='store_true',
619 parser.add_option('--doctest-tests', action='store_true',
620 dest='doctest_tests',
620 dest='doctest_tests',
621 default=env.get('NOSE_DOCTEST_TESTS',True),
621 default=env.get('NOSE_DOCTEST_TESTS',True),
622 help="Also look for doctests in test modules. "
622 help="Also look for doctests in test modules. "
623 "Note that classes, methods and functions should "
623 "Note that classes, methods and functions should "
624 "have either doctests or non-doctest tests, "
624 "have either doctests or non-doctest tests, "
625 "not both. [NOSE_DOCTEST_TESTS]")
625 "not both. [NOSE_DOCTEST_TESTS]")
626 parser.add_option('--doctest-extension', action="append",
626 parser.add_option('--doctest-extension', action="append",
627 dest="doctestExtension",
627 dest="doctestExtension",
628 help="Also look for doctests in files with "
628 help="Also look for doctests in files with "
629 "this extension [NOSE_DOCTEST_EXTENSION]")
629 "this extension [NOSE_DOCTEST_EXTENSION]")
630 # Set the default as a list, if given in env; otherwise
630 # Set the default as a list, if given in env; otherwise
631 # an additional value set on the command line will cause
631 # an additional value set on the command line will cause
632 # an error.
632 # an error.
633 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
633 env_setting = env.get('NOSE_DOCTEST_EXTENSION')
634 if env_setting is not None:
634 if env_setting is not None:
635 parser.set_defaults(doctestExtension=tolist(env_setting))
635 parser.set_defaults(doctestExtension=tolist(env_setting))
636
636
637
637
638 def configure(self, options, config):
638 def configure(self, options, config):
639 Plugin.configure(self, options, config)
639 Plugin.configure(self, options, config)
640 # Pull standard doctest plugin out of config; we will do doctesting
640 # Pull standard doctest plugin out of config; we will do doctesting
641 config.plugins.plugins = [p for p in config.plugins.plugins
641 config.plugins.plugins = [p for p in config.plugins.plugins
642 if p.name != 'doctest']
642 if p.name != 'doctest']
643 self.doctest_tests = options.doctest_tests
643 self.doctest_tests = options.doctest_tests
644 self.extension = tolist(options.doctestExtension)
644 self.extension = tolist(options.doctestExtension)
645
645
646 self.parser = doctest.DocTestParser()
646 self.parser = doctest.DocTestParser()
647 self.finder = DocTestFinder()
647 self.finder = DocTestFinder()
648 self.checker = IPDoctestOutputChecker()
648 self.checker = IPDoctestOutputChecker()
649 self.globs = None
649 self.globs = None
650 self.extraglobs = None
650 self.extraglobs = None
651
651
652
652
653 def loadTestsFromExtensionModule(self,filename):
653 def loadTestsFromExtensionModule(self,filename):
654 bpath,mod = os.path.split(filename)
654 bpath,mod = os.path.split(filename)
655 modname = os.path.splitext(mod)[0]
655 modname = os.path.splitext(mod)[0]
656 try:
656 try:
657 sys.path.append(bpath)
657 sys.path.append(bpath)
658 module = __import__(modname)
658 module = __import__(modname)
659 tests = list(self.loadTestsFromModule(module))
659 tests = list(self.loadTestsFromModule(module))
660 finally:
660 finally:
661 sys.path.pop()
661 sys.path.pop()
662 return tests
662 return tests
663
663
664 # NOTE: the method below is almost a copy of the original one in nose, with
664 # NOTE: the method below is almost a copy of the original one in nose, with
665 # a few modifications to control output checking.
665 # a few modifications to control output checking.
666
666
667 def loadTestsFromModule(self, module):
667 def loadTestsFromModule(self, module):
668 #print '*** ipdoctest - lTM',module # dbg
668 #print '*** ipdoctest - lTM',module # dbg
669
669
670 if not self.matches(module.__name__):
670 if not self.matches(module.__name__):
671 log.debug("Doctest doesn't want module %s", module)
671 log.debug("Doctest doesn't want module %s", module)
672 return
672 return
673
673
674 tests = self.finder.find(module,globs=self.globs,
674 tests = self.finder.find(module,globs=self.globs,
675 extraglobs=self.extraglobs)
675 extraglobs=self.extraglobs)
676 if not tests:
676 if not tests:
677 return
677 return
678
678
679 # always use whitespace and ellipsis options
679 # always use whitespace and ellipsis options
680 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
680 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
681
681
682 tests.sort()
682 tests.sort()
683 module_file = module.__file__
683 module_file = module.__file__
684 if module_file[-4:] in ('.pyc', '.pyo'):
684 if module_file[-4:] in ('.pyc', '.pyo'):
685 module_file = module_file[:-1]
685 module_file = module_file[:-1]
686 for test in tests:
686 for test in tests:
687 if not test.examples:
687 if not test.examples:
688 continue
688 continue
689 if not test.filename:
689 if not test.filename:
690 test.filename = module_file
690 test.filename = module_file
691
691
692 yield DocTestCase(test,
692 yield DocTestCase(test,
693 optionflags=optionflags,
693 optionflags=optionflags,
694 checker=self.checker)
694 checker=self.checker)
695
695
696
696
697 def loadTestsFromFile(self, filename):
697 def loadTestsFromFile(self, filename):
698 #print "ipdoctest - from file", filename # dbg
698 #print "ipdoctest - from file", filename # dbg
699 if is_extension_module(filename):
699 if is_extension_module(filename):
700 for t in self.loadTestsFromExtensionModule(filename):
700 for t in self.loadTestsFromExtensionModule(filename):
701 yield t
701 yield t
702 else:
702 else:
703 if self.extension and anyp(filename.endswith, self.extension):
703 if self.extension and anyp(filename.endswith, self.extension):
704 name = os.path.basename(filename)
704 name = os.path.basename(filename)
705 dh = open(filename)
705 dh = open(filename)
706 try:
706 try:
707 doc = dh.read()
707 doc = dh.read()
708 finally:
708 finally:
709 dh.close()
709 dh.close()
710 test = self.parser.get_doctest(
710 test = self.parser.get_doctest(
711 doc, globs={'__file__': filename}, name=name,
711 doc, globs={'__file__': filename}, name=name,
712 filename=filename, lineno=0)
712 filename=filename, lineno=0)
713 if test.examples:
713 if test.examples:
714 #print 'FileCase:',test.examples # dbg
714 #print 'FileCase:',test.examples # dbg
715 yield DocFileCase(test)
715 yield DocFileCase(test)
716 else:
716 else:
717 yield False # no tests to load
717 yield False # no tests to load
718
718
719 def wantFile(self,filename):
719 def wantFile(self,filename):
720 """Return whether the given filename should be scanned for tests.
720 """Return whether the given filename should be scanned for tests.
721
721
722 Modified version that accepts extension modules as valid containers for
722 Modified version that accepts extension modules as valid containers for
723 doctests.
723 doctests.
724 """
724 """
725 #print '*** ipdoctest- wantFile:',filename # dbg
725 #print '*** ipdoctest- wantFile:',filename # dbg
726
726
727 for pat in self.exclude_patterns:
727 for pat in self.exclude_patterns:
728 if pat.search(filename):
728 if pat.search(filename):
729 # print '###>>> SKIP:',filename # dbg
729 # print '###>>> SKIP:',filename # dbg
730 return False
730 return False
731
731
732 if is_extension_module(filename):
732 if is_extension_module(filename):
733 return True
733 return True
734 else:
734 else:
735 return doctests.Doctest.wantFile(self,filename)
735 return doctests.Doctest.wantFile(self,filename)
736
736
737 def wantDirectory(self, directory):
737 def wantDirectory(self, directory):
738 """Return whether the given directory should be scanned for tests.
738 """Return whether the given directory should be scanned for tests.
739
739
740 Modified version that supports exclusions.
740 Modified version that supports exclusions.
741 """
741 """
742
742
743 for pat in self.exclude_patterns:
743 for pat in self.exclude_patterns:
744 if pat.search(directory):
744 if pat.search(directory):
745 return False
745 return False
746 return True
746 return True
747
747
748
748
749 class IPythonDoctest(ExtensionDoctest):
749 class IPythonDoctest(ExtensionDoctest):
750 """Nose Plugin that supports doctests in extension modules.
750 """Nose Plugin that supports doctests in extension modules.
751 """
751 """
752 name = 'ipdoctest' # call nosetests with --with-ipdoctest
752 name = 'ipdoctest' # call nosetests with --with-ipdoctest
753 enabled = True
753 enabled = True
754
754
755 def makeTest(self, obj, parent):
755 def makeTest(self, obj, parent):
756 """Look for doctests in the given object, which will be a
756 """Look for doctests in the given object, which will be a
757 function, method or class.
757 function, method or class.
758 """
758 """
759 #print 'Plugin analyzing:', obj, parent # dbg
759 #print 'Plugin analyzing:', obj, parent # dbg
760 # always use whitespace and ellipsis options
760 # always use whitespace and ellipsis options
761 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
761 optionflags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS
762
762
763 doctests = self.finder.find(obj, module=getmodule(parent))
763 doctests = self.finder.find(obj, module=getmodule(parent))
764 if doctests:
764 if doctests:
765 for test in doctests:
765 for test in doctests:
766 if len(test.examples) == 0:
766 if len(test.examples) == 0:
767 continue
767 continue
768
768
769 yield DocTestCase(test, obj=obj,
769 yield DocTestCase(test, obj=obj,
770 optionflags=optionflags,
770 optionflags=optionflags,
771 checker=self.checker)
771 checker=self.checker)
772
772
773 def options(self, parser, env=os.environ):
773 def options(self, parser, env=os.environ):
774 #print "Options for nose plugin:", self.name # dbg
774 #print "Options for nose plugin:", self.name # dbg
775 Plugin.options(self, parser, env)
775 Plugin.options(self, parser, env)
776 parser.add_option('--ipdoctest-tests', action='store_true',
776 parser.add_option('--ipdoctest-tests', action='store_true',
777 dest='ipdoctest_tests',
777 dest='ipdoctest_tests',
778 default=env.get('NOSE_IPDOCTEST_TESTS',True),
778 default=env.get('NOSE_IPDOCTEST_TESTS',True),
779 help="Also look for doctests in test modules. "
779 help="Also look for doctests in test modules. "
780 "Note that classes, methods and functions should "
780 "Note that classes, methods and functions should "
781 "have either doctests or non-doctest tests, "
781 "have either doctests or non-doctest tests, "
782 "not both. [NOSE_IPDOCTEST_TESTS]")
782 "not both. [NOSE_IPDOCTEST_TESTS]")
783 parser.add_option('--ipdoctest-extension', action="append",
783 parser.add_option('--ipdoctest-extension', action="append",
784 dest="ipdoctest_extension",
784 dest="ipdoctest_extension",
785 help="Also look for doctests in files with "
785 help="Also look for doctests in files with "
786 "this extension [NOSE_IPDOCTEST_EXTENSION]")
786 "this extension [NOSE_IPDOCTEST_EXTENSION]")
787 # Set the default as a list, if given in env; otherwise
787 # Set the default as a list, if given in env; otherwise
788 # an additional value set on the command line will cause
788 # an additional value set on the command line will cause
789 # an error.
789 # an error.
790 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
790 env_setting = env.get('NOSE_IPDOCTEST_EXTENSION')
791 if env_setting is not None:
791 if env_setting is not None:
792 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
792 parser.set_defaults(ipdoctest_extension=tolist(env_setting))
793
793
794 def configure(self, options, config):
794 def configure(self, options, config):
795 #print "Configuring nose plugin:", self.name # dbg
795 #print "Configuring nose plugin:", self.name # dbg
796 Plugin.configure(self, options, config)
796 Plugin.configure(self, options, config)
797 # Pull standard doctest plugin out of config; we will do doctesting
797 # Pull standard doctest plugin out of config; we will do doctesting
798 config.plugins.plugins = [p for p in config.plugins.plugins
798 config.plugins.plugins = [p for p in config.plugins.plugins
799 if p.name != 'doctest']
799 if p.name != 'doctest']
800 self.doctest_tests = options.ipdoctest_tests
800 self.doctest_tests = options.ipdoctest_tests
801 self.extension = tolist(options.ipdoctest_extension)
801 self.extension = tolist(options.ipdoctest_extension)
802
802
803 self.parser = IPDocTestParser()
803 self.parser = IPDocTestParser()
804 self.finder = DocTestFinder(parser=self.parser)
804 self.finder = DocTestFinder(parser=self.parser)
805 self.checker = IPDoctestOutputChecker()
805 self.checker = IPDoctestOutputChecker()
806 self.globs = None
806 self.globs = None
807 self.extraglobs = None
807 self.extraglobs = None
General Comments 0
You need to be logged in to leave comments. Login now