##// END OF EJS Templates
Replace pager_page() instead of page() for test suite...
Thomas Kluyver -
Show More
@@ -1,176 +1,176 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-2011 The IPython Development Team
12 # Copyright (C) 2009-2011 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 os
23 import os
24 import sys
24 import sys
25
25
26 # our own
26 # our own
27 from . import tools
27 from . import tools
28
28
29 from IPython.core import page
29 from IPython.core import page
30 from IPython.utils import io
30 from IPython.utils import io
31 from IPython.utils import py3compat
31 from IPython.utils import py3compat
32 from IPython.utils.py3compat import builtin_mod
32 from IPython.utils.py3compat import builtin_mod
33 from IPython.terminal.interactiveshell import TerminalInteractiveShell
33 from IPython.terminal.interactiveshell import TerminalInteractiveShell
34
34
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36 # Functions
36 # Functions
37 #-----------------------------------------------------------------------------
37 #-----------------------------------------------------------------------------
38
38
39 class StreamProxy(io.IOStream):
39 class StreamProxy(io.IOStream):
40 """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*
41 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.
42
42
43 Parameters
43 Parameters
44 ----------
44 ----------
45 name : str
45 name : str
46 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
47 """
47 """
48
48
49 def __init__(self, name):
49 def __init__(self, name):
50 self.name=name
50 self.name=name
51
51
52 @property
52 @property
53 def stream(self):
53 def stream(self):
54 return getattr(sys, self.name)
54 return getattr(sys, self.name)
55
55
56 def flush(self):
56 def flush(self):
57 self.stream.flush()
57 self.stream.flush()
58
58
59 # 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
60 # 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
61 # with much less ugliness.
61 # with much less ugliness.
62
62
63 class py_file_finder(object):
63 class py_file_finder(object):
64 def __init__(self,test_filename):
64 def __init__(self,test_filename):
65 self.test_filename = test_filename
65 self.test_filename = test_filename
66
66
67 def __call__(self,name,win32=False):
67 def __call__(self,name,win32=False):
68 from IPython.utils.path import get_py_filename
68 from IPython.utils.path import get_py_filename
69 try:
69 try:
70 return get_py_filename(name,win32=win32)
70 return get_py_filename(name,win32=win32)
71 except IOError:
71 except IOError:
72 test_dir = os.path.dirname(self.test_filename)
72 test_dir = os.path.dirname(self.test_filename)
73 new_path = os.path.join(test_dir,name)
73 new_path = os.path.join(test_dir,name)
74 return get_py_filename(new_path,win32=win32)
74 return get_py_filename(new_path,win32=win32)
75
75
76
76
77 def _run_ns_sync(self,arg_s,runner=None):
77 def _run_ns_sync(self,arg_s,runner=None):
78 """Modified version of %run that syncs testing namespaces.
78 """Modified version of %run that syncs testing namespaces.
79
79
80 This is strictly needed for running doctests that call %run.
80 This is strictly needed for running doctests that call %run.
81 """
81 """
82 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
82 #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg
83 finder = py_file_finder(arg_s)
83 finder = py_file_finder(arg_s)
84 return get_ipython().magic_run_ori(arg_s, runner, finder)
84 return get_ipython().magic_run_ori(arg_s, runner, finder)
85
85
86
86
87 def get_ipython():
87 def get_ipython():
88 # This will get replaced by the real thing once we start IPython below
88 # This will get replaced by the real thing once we start IPython below
89 return start_ipython()
89 return start_ipython()
90
90
91
91
92 # A couple of methods to override those in the running IPython to interact
92 # A couple of methods to override those in the running IPython to interact
93 # better with doctest (doctest captures on raw stdout, so we need to direct
93 # better with doctest (doctest captures on raw stdout, so we need to direct
94 # various types of output there otherwise it will miss them).
94 # various types of output there otherwise it will miss them).
95
95
96 def xsys(self, cmd):
96 def xsys(self, cmd):
97 """Replace the default system call with a capturing one for doctest.
97 """Replace the default system call with a capturing one for doctest.
98 """
98 """
99 # We use getoutput, but we need to strip it because pexpect captures
99 # We use getoutput, but we need to strip it because pexpect captures
100 # the trailing newline differently from commands.getoutput
100 # the trailing newline differently from commands.getoutput
101 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout)
101 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout)
102 sys.stdout.flush()
102 sys.stdout.flush()
103
103
104
104
105 def _showtraceback(self, etype, evalue, stb):
105 def _showtraceback(self, etype, evalue, stb):
106 """Print the traceback purely on stdout for doctest to capture it.
106 """Print the traceback purely on stdout for doctest to capture it.
107 """
107 """
108 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
108 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
109
109
110
110
111 def start_ipython():
111 def start_ipython():
112 """Start a global IPython shell, which we need for IPython-specific syntax.
112 """Start a global IPython shell, which we need for IPython-specific syntax.
113 """
113 """
114 global get_ipython
114 global get_ipython
115
115
116 # This function should only ever run once!
116 # This function should only ever run once!
117 if hasattr(start_ipython, 'already_called'):
117 if hasattr(start_ipython, 'already_called'):
118 return
118 return
119 start_ipython.already_called = True
119 start_ipython.already_called = True
120
120
121 # Store certain global objects that IPython modifies
121 # Store certain global objects that IPython modifies
122 _displayhook = sys.displayhook
122 _displayhook = sys.displayhook
123 _excepthook = sys.excepthook
123 _excepthook = sys.excepthook
124 _main = sys.modules.get('__main__')
124 _main = sys.modules.get('__main__')
125
125
126 # Create custom argv and namespaces for our IPython to be test-friendly
126 # Create custom argv and namespaces for our IPython to be test-friendly
127 config = tools.default_config()
127 config = tools.default_config()
128
128
129 # Create and initialize our test-friendly IPython instance.
129 # Create and initialize our test-friendly IPython instance.
130 shell = TerminalInteractiveShell.instance(config=config,
130 shell = TerminalInteractiveShell.instance(config=config,
131 )
131 )
132
132
133 # A few more tweaks needed for playing nicely with doctests...
133 # A few more tweaks needed for playing nicely with doctests...
134
134
135 # remove history file
135 # remove history file
136 shell.tempfiles.append(config.HistoryManager.hist_file)
136 shell.tempfiles.append(config.HistoryManager.hist_file)
137
137
138 # These traps are normally only active for interactive use, set them
138 # These traps are normally only active for interactive use, set them
139 # permanently since we'll be mocking interactive sessions.
139 # permanently since we'll be mocking interactive sessions.
140 shell.builtin_trap.activate()
140 shell.builtin_trap.activate()
141
141
142 # Modify the IPython system call with one that uses getoutput, so that we
142 # Modify the IPython system call with one that uses getoutput, so that we
143 # can capture subcommands and print them to Python's stdout, otherwise the
143 # can capture subcommands and print them to Python's stdout, otherwise the
144 # doctest machinery would miss them.
144 # doctest machinery would miss them.
145 shell.system = py3compat.MethodType(xsys, shell)
145 shell.system = py3compat.MethodType(xsys, shell)
146
146
147 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
147 shell._showtraceback = py3compat.MethodType(_showtraceback, shell)
148
148
149 # IPython is ready, now clean up some global state...
149 # IPython is ready, now clean up some global state...
150
150
151 # Deactivate the various python system hooks added by ipython for
151 # Deactivate the various python system hooks added by ipython for
152 # interactive convenience so we don't confuse the doctest system
152 # interactive convenience so we don't confuse the doctest system
153 sys.modules['__main__'] = _main
153 sys.modules['__main__'] = _main
154 sys.displayhook = _displayhook
154 sys.displayhook = _displayhook
155 sys.excepthook = _excepthook
155 sys.excepthook = _excepthook
156
156
157 # So that ipython magics and aliases can be doctested (they work by making
157 # So that ipython magics and aliases can be doctested (they work by making
158 # a call into a global _ip object). Also make the top-level get_ipython
158 # a call into a global _ip object). Also make the top-level get_ipython
159 # now return this without recursively calling here again.
159 # now return this without recursively calling here again.
160 _ip = shell
160 _ip = shell
161 get_ipython = _ip.get_ipython
161 get_ipython = _ip.get_ipython
162 builtin_mod._ip = _ip
162 builtin_mod._ip = _ip
163 builtin_mod.get_ipython = get_ipython
163 builtin_mod.get_ipython = get_ipython
164
164
165 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
165 # To avoid extra IPython messages during testing, suppress io.stdout/stderr
166 io.stdout = StreamProxy('stdout')
166 io.stdout = StreamProxy('stdout')
167 io.stderr = StreamProxy('stderr')
167 io.stderr = StreamProxy('stderr')
168
168
169 # Override paging, so we don't require user interaction during the tests.
169 # Override paging, so we don't require user interaction during the tests.
170 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
170 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
171 print(strng)
171 print(strng)
172
172
173 page.orig_page = page.page
173 page.orig_page = page.pager_page
174 page.page = nopage
174 page.pager_page = nopage
175
175
176 return _ip
176 return _ip
General Comments 0
You need to be logged in to leave comments. Login now