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