##// END OF EJS Templates
Disable the pager for the test suite....
Thomas Kluyver -
Show More
@@ -1,19 +1,20 b''
1 #-----------------------------------------------------------------------------
1 #-----------------------------------------------------------------------------
2 # Copyright (C) 2010 The IPython Development Team.
2 # Copyright (C) 2010 The IPython Development Team.
3 #
3 #
4 # Distributed under the terms of the BSD License.
4 # Distributed under the terms of the BSD License.
5 #
5 #
6 # The full license is in the file COPYING.txt, distributed with this software.
6 # The full license is in the file COPYING.txt, distributed with this software.
7 #-----------------------------------------------------------------------------
7 #-----------------------------------------------------------------------------
8 import io
8 import io
9
9
10 # N.B. For the test suite, page.page is overridden (see IPython.testing.globalipapp)
10 from IPython.core import page
11 from IPython.core import page
11
12
12 def test_detect_screen_size():
13 def test_detect_screen_size():
13 """Simple smoketest for page._detect_screen_size."""
14 """Simple smoketest for page._detect_screen_size."""
14 try:
15 try:
15 page._detect_screen_size(True, 25)
16 page._detect_screen_size(True, 25)
16 except (TypeError, io.UnsupportedOperation):
17 except (TypeError, io.UnsupportedOperation):
17 # This can happen in the test suite, because stdout may not have a
18 # This can happen in the test suite, because stdout may not have a
18 # fileno.
19 # fileno.
19 pass
20 pass
@@ -1,232 +1,240 b''
1 """Global IPython app to support test running.
1 """Global IPython app to support test running.
2
2
3 We must start our own ipython object and heavily muck with it so that all the
3 We must start our own ipython object and heavily muck with it so that all the
4 modifications IPython makes to system behavior don't send the doctest machinery
4 modifications IPython makes to system behavior don't send the doctest machinery
5 into a fit. This code should be considered a gross hack, but it gets the job
5 into a fit. This code should be considered a gross hack, but it gets the job
6 done.
6 done.
7 """
7 """
8 from __future__ import absolute_import
8 from __future__ import absolute_import
9 from __future__ import print_function
9 from __future__ import print_function
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Copyright (C) 2009-2010 The IPython Development Team
12 # Copyright (C) 2009-2010 The IPython Development Team
13 #
13 #
14 # Distributed under the terms of the BSD License. The full license is in
14 # Distributed under the terms of the BSD License. The full license is in
15 # the file COPYING, distributed as part of this software.
15 # the file COPYING, distributed as part of this software.
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17
17
18 #-----------------------------------------------------------------------------
18 #-----------------------------------------------------------------------------
19 # Imports
19 # Imports
20 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
21
21
22 # stdlib
22 # stdlib
23 import __builtin__ as builtin_mod
23 import __builtin__ as builtin_mod
24 import os
24 import os
25 import sys
25 import sys
26
26
27 # our own
27 # our own
28 from . import tools
28 from . import tools
29
29
30 from IPython.core import page
30 from IPython.utils import io
31 from IPython.utils import io
31 from IPython.utils import py3compat
32 from IPython.utils import py3compat
32 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
33 from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell
33
34
34 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
35 # Functions
36 # Functions
36 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
37
38
38 class StreamProxy(io.IOStream):
39 class StreamProxy(io.IOStream):
39 """Proxy for sys.stdout/err. This will request the stream *at call time*
40 """Proxy for sys.stdout/err. This will request the stream *at call time*
40 allowing for nose's Capture plugin's redirection of sys.stdout/err.
41 allowing for nose's Capture plugin's redirection of sys.stdout/err.
41
42
42 Parameters
43 Parameters
43 ----------
44 ----------
44 name : str
45 name : str
45 The name of the stream. This will be requested anew at every call
46 The name of the stream. This will be requested anew at every call
46 """
47 """
47
48
48 def __init__(self, name):
49 def __init__(self, name):
49 self.name=name
50 self.name=name
50
51
51 @property
52 @property
52 def stream(self):
53 def stream(self):
53 return getattr(sys, self.name)
54 return getattr(sys, self.name)
54
55
55 def flush(self):
56 def flush(self):
56 self.stream.flush()
57 self.stream.flush()
57
58
58 # Hack to modify the %run command so we can sync the user's namespace with the
59 # Hack to modify the %run command so we can sync the user's namespace with the
59 # test globals. Once we move over to a clean magic system, this will be done
60 # test globals. Once we move over to a clean magic system, this will be done
60 # with much less ugliness.
61 # with much less ugliness.
61
62
62 class py_file_finder(object):
63 class py_file_finder(object):
63 def __init__(self,test_filename):
64 def __init__(self,test_filename):
64 self.test_filename = test_filename
65 self.test_filename = test_filename
65
66
66 def __call__(self,name,win32=False):
67 def __call__(self,name,win32=False):
67 from IPython.utils.path import get_py_filename
68 from IPython.utils.path import get_py_filename
68 try:
69 try:
69 return get_py_filename(name,win32=win32)
70 return get_py_filename(name,win32=win32)
70 except IOError:
71 except IOError:
71 test_dir = os.path.dirname(self.test_filename)
72 test_dir = os.path.dirname(self.test_filename)
72 new_path = os.path.join(test_dir,name)
73 new_path = os.path.join(test_dir,name)
73 return get_py_filename(new_path,win32=win32)
74 return get_py_filename(new_path,win32=win32)
74
75
75
76
76 def _run_ns_sync(self,arg_s,runner=None):
77 def _run_ns_sync(self,arg_s,runner=None):
77 """Modified version of %run that syncs testing namespaces.
78 """Modified version of %run that syncs testing namespaces.
78
79
79 This is strictly needed for running doctests that call %run.
80 This is strictly needed for running doctests that call %run.
80 """
81 """
81 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
82 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
82 finder = py_file_finder(arg_s)
83 finder = py_file_finder(arg_s)
83 return get_ipython().magic_run_ori(arg_s, runner, finder)
84 return get_ipython().magic_run_ori(arg_s, runner, finder)
84
85
85
86
86 class ipnsdict(dict):
87 class ipnsdict(dict):
87 """A special subclass of dict for use as an IPython namespace in doctests.
88 """A special subclass of dict for use as an IPython namespace in doctests.
88
89
89 This subclass adds a simple checkpointing capability so that when testing
90 This subclass adds a simple checkpointing capability so that when testing
90 machinery clears it (we use it as the test execution context), it doesn't
91 machinery clears it (we use it as the test execution context), it doesn't
91 get completely destroyed.
92 get completely destroyed.
92
93
93 In addition, it can handle the presence of the '_' key in a special manner,
94 In addition, it can handle the presence of the '_' key in a special manner,
94 which is needed because of how Python's doctest machinery operates with
95 which is needed because of how Python's doctest machinery operates with
95 '_'. See constructor and :meth:`update` for details.
96 '_'. See constructor and :meth:`update` for details.
96 """
97 """
97
98
98 def __init__(self,*a):
99 def __init__(self,*a):
99 dict.__init__(self,*a)
100 dict.__init__(self,*a)
100 self._savedict = {}
101 self._savedict = {}
101 # If this flag is True, the .update() method will unconditionally
102 # If this flag is True, the .update() method will unconditionally
102 # remove a key named '_'. This is so that such a dict can be used as a
103 # remove a key named '_'. This is so that such a dict can be used as a
103 # namespace in doctests that call '_'.
104 # namespace in doctests that call '_'.
104 self.protect_underscore = False
105 self.protect_underscore = False
105
106
106 def clear(self):
107 def clear(self):
107 dict.clear(self)
108 dict.clear(self)
108 self.update(self._savedict)
109 self.update(self._savedict)
109
110
110 def _checkpoint(self):
111 def _checkpoint(self):
111 self._savedict.clear()
112 self._savedict.clear()
112 self._savedict.update(self)
113 self._savedict.update(self)
113
114
114 def update(self,other):
115 def update(self,other):
115 self._checkpoint()
116 self._checkpoint()
116 dict.update(self,other)
117 dict.update(self,other)
117
118
118 if self.protect_underscore:
119 if self.protect_underscore:
119 # If '_' is in the namespace, python won't set it when executing
120 # If '_' is in the namespace, python won't set it when executing
120 # code *in doctests*, and we have multiple doctests that use '_'.
121 # code *in doctests*, and we have multiple doctests that use '_'.
121 # So we ensure that the namespace is always 'clean' of it before
122 # So we ensure that the namespace is always 'clean' of it before
122 # it's used for test code execution.
123 # it's used for test code execution.
123 # This flag is only turned on by the doctest machinery, so that
124 # This flag is only turned on by the doctest machinery, so that
124 # normal test code can assume the _ key is updated like any other
125 # normal test code can assume the _ key is updated like any other
125 # key and can test for its presence after cell executions.
126 # key and can test for its presence after cell executions.
126 self.pop('_', None)
127 self.pop('_', None)
127
128
128 # The builtins namespace must *always* be the real __builtin__ module,
129 # The builtins namespace must *always* be the real __builtin__ module,
129 # else weird stuff happens. The main ipython code does have provisions
130 # else weird stuff happens. The main ipython code does have provisions
130 # to ensure this after %run, but since in this class we do some
131 # to ensure this after %run, but since in this class we do some
131 # aggressive low-level cleaning of the execution namespace, we need to
132 # aggressive low-level cleaning of the execution namespace, we need to
132 # correct for that ourselves, to ensure consitency with the 'real'
133 # correct for that ourselves, to ensure consitency with the 'real'
133 # ipython.
134 # ipython.
134 self['__builtins__'] = builtin_mod
135 self['__builtins__'] = builtin_mod
135
136
136 def __delitem__(self, key):
137 def __delitem__(self, key):
137 """Part of the test suite checks that we can release all
138 """Part of the test suite checks that we can release all
138 references to an object. So we need to make sure that we're not
139 references to an object. So we need to make sure that we're not
139 keeping a reference in _savedict."""
140 keeping a reference in _savedict."""
140 dict.__delitem__(self, key)
141 dict.__delitem__(self, key)
141 try:
142 try:
142 del self._savedict[key]
143 del self._savedict[key]
143 except KeyError:
144 except KeyError:
144 pass
145 pass
145
146
146
147
147 def get_ipython():
148 def get_ipython():
148 # This will get replaced by the real thing once we start IPython below
149 # This will get replaced by the real thing once we start IPython below
149 return start_ipython()
150 return start_ipython()
150
151
151
152
152 # A couple of methods to override those in the running IPython to interact
153 # A couple of methods to override those in the running IPython to interact
153 # better with doctest (doctest captures on raw stdout, so we need to direct
154 # better with doctest (doctest captures on raw stdout, so we need to direct
154 # various types of output there otherwise it will miss them).
155 # various types of output there otherwise it will miss them).
155
156
156 def xsys(self, cmd):
157 def xsys(self, cmd):
157 """Replace the default system call with a capturing one for doctest.
158 """Replace the default system call with a capturing one for doctest.
158 """
159 """
159 # We use getoutput, but we need to strip it because pexpect captures
160 # We use getoutput, but we need to strip it because pexpect captures
160 # the trailing newline differently from commands.getoutput
161 # the trailing newline differently from commands.getoutput
161 print(self.getoutput(cmd, split=False).rstrip(), end='', file=sys.stdout)
162 print(self.getoutput(cmd, split=False).rstrip(), end='', file=sys.stdout)
162 sys.stdout.flush()
163 sys.stdout.flush()
163
164
164
165
165 def _showtraceback(self, etype, evalue, stb):
166 def _showtraceback(self, etype, evalue, stb):
166 """Print the traceback purely on stdout for doctest to capture it.
167 """Print the traceback purely on stdout for doctest to capture it.
167 """
168 """
168 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
169 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
169
170
170
171
171 def start_ipython():
172 def start_ipython():
172 """Start a global IPython shell, which we need for IPython-specific syntax.
173 """Start a global IPython shell, which we need for IPython-specific syntax.
173 """
174 """
174 global get_ipython
175 global get_ipython
175
176
176 # This function should only ever run once!
177 # This function should only ever run once!
177 if hasattr(start_ipython, 'already_called'):
178 if hasattr(start_ipython, 'already_called'):
178 return
179 return
179 start_ipython.already_called = True
180 start_ipython.already_called = True
180
181
181 # Store certain global objects that IPython modifies
182 # Store certain global objects that IPython modifies
182 _displayhook = sys.displayhook
183 _displayhook = sys.displayhook
183 _excepthook = sys.excepthook
184 _excepthook = sys.excepthook
184 _main = sys.modules.get('__main__')
185 _main = sys.modules.get('__main__')
185
186
186 # Create custom argv and namespaces for our IPython to be test-friendly
187 # Create custom argv and namespaces for our IPython to be test-friendly
187 config = tools.default_config()
188 config = tools.default_config()
188
189
189 # Create and initialize our test-friendly IPython instance.
190 # Create and initialize our test-friendly IPython instance.
190 shell = TerminalInteractiveShell.instance(config=config,
191 shell = TerminalInteractiveShell.instance(config=config,
191 user_ns=ipnsdict(),
192 user_ns=ipnsdict(),
192 user_global_ns={}
193 user_global_ns={}
193 )
194 )
194
195
195 # A few more tweaks needed for playing nicely with doctests...
196 # A few more tweaks needed for playing nicely with doctests...
196
197
197 # remove history file
198 # remove history file
198 shell.tempfiles.append(config.HistoryManager.hist_file)
199 shell.tempfiles.append(config.HistoryManager.hist_file)
199
200
200 # These traps are normally only active for interactive use, set them
201 # These traps are normally only active for interactive use, set them
201 # permanently since we'll be mocking interactive sessions.
202 # permanently since we'll be mocking interactive sessions.
202 shell.builtin_trap.activate()
203 shell.builtin_trap.activate()
203
204
204 # Modify the IPython system call with one that uses getoutput, so that we
205 # Modify the IPython system call with one that uses getoutput, so that we
205 # can capture subcommands and print them to Python's stdout, otherwise the
206 # can capture subcommands and print them to Python's stdout, otherwise the
206 # doctest machinery would miss them.
207 # doctest machinery would miss them.
207 shell.system = py3compat.MethodType(xsys, shell)
208 shell.system = py3compat.MethodType(xsys, shell)
208
209
209
210
210 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
211 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
211
212
212 # IPython is ready, now clean up some global state...
213 # IPython is ready, now clean up some global state...
213
214
214 # Deactivate the various python system hooks added by ipython for
215 # Deactivate the various python system hooks added by ipython for
215 # interactive convenience so we don't confuse the doctest system
216 # interactive convenience so we don't confuse the doctest system
216 sys.modules['__main__'] = _main
217 sys.modules['__main__'] = _main
217 sys.displayhook = _displayhook
218 sys.displayhook = _displayhook
218 sys.excepthook = _excepthook
219 sys.excepthook = _excepthook
219
220
220 # So that ipython magics and aliases can be doctested (they work by making
221 # So that ipython magics and aliases can be doctested (they work by making
221 # a call into a global _ip object). Also make the top-level get_ipython
222 # a call into a global _ip object). Also make the top-level get_ipython
222 # now return this without recursively calling here again.
223 # now return this without recursively calling here again.
223 _ip = shell
224 _ip = shell
224 get_ipython = _ip.get_ipython
225 get_ipython = _ip.get_ipython
225 builtin_mod._ip = _ip
226 builtin_mod._ip = _ip
226 builtin_mod.get_ipython = get_ipython
227 builtin_mod.get_ipython = get_ipython
227
228
228 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
229 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
229 io.stdout = StreamProxy('stdout')
230 io.stdout = StreamProxy('stdout')
230 io.stderr = StreamProxy('stderr')
231 io.stderr = StreamProxy('stderr')
232
233 # Override paging, so we don't require user interaction during the tests.
234 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
235 print(strng)
236
237 page.orig_page = page.page
238 page.page = nopage
231
239
232 return _ip
240 return _ip
General Comments 0
You need to be logged in to leave comments. Login now