##// END OF EJS Templates
Merge pull request #12645 from Carreau/str-path...
Matthias Bussonnier -
r26128:b9e1d67a merge
parent child Browse files
Show More
@@ -1,137 +1,139 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
8
9 # Copyright (c) IPython Development Team.
9 # Copyright (c) IPython Development Team.
10 # Distributed under the terms of the Modified BSD License.
10 # Distributed under the terms of the Modified BSD License.
11
11
12 import builtins as builtin_mod
12 import builtins as builtin_mod
13 import sys
13 import sys
14 import types
14 import types
15 import warnings
15 import warnings
16
16
17 from pathlib import Path
18
17 from . import tools
19 from . import tools
18
20
19 from IPython.core import page
21 from IPython.core import page
20 from IPython.utils import io
22 from IPython.utils import io
21 from IPython.terminal.interactiveshell import TerminalInteractiveShell
23 from IPython.terminal.interactiveshell import TerminalInteractiveShell
22
24
23
25
24 class StreamProxy(io.IOStream):
26 class StreamProxy(io.IOStream):
25 """Proxy for sys.stdout/err. This will request the stream *at call time*
27 """Proxy for sys.stdout/err. This will request the stream *at call time*
26 allowing for nose's Capture plugin's redirection of sys.stdout/err.
28 allowing for nose's Capture plugin's redirection of sys.stdout/err.
27
29
28 Parameters
30 Parameters
29 ----------
31 ----------
30 name : str
32 name : str
31 The name of the stream. This will be requested anew at every call
33 The name of the stream. This will be requested anew at every call
32 """
34 """
33
35
34 def __init__(self, name):
36 def __init__(self, name):
35 warnings.warn("StreamProxy is deprecated and unused as of IPython 5", DeprecationWarning,
37 warnings.warn("StreamProxy is deprecated and unused as of IPython 5", DeprecationWarning,
36 stacklevel=2,
38 stacklevel=2,
37 )
39 )
38 self.name=name
40 self.name=name
39
41
40 @property
42 @property
41 def stream(self):
43 def stream(self):
42 return getattr(sys, self.name)
44 return getattr(sys, self.name)
43
45
44 def flush(self):
46 def flush(self):
45 self.stream.flush()
47 self.stream.flush()
46
48
47
49
48 def get_ipython():
50 def get_ipython():
49 # This will get replaced by the real thing once we start IPython below
51 # This will get replaced by the real thing once we start IPython below
50 return start_ipython()
52 return start_ipython()
51
53
52
54
53 # A couple of methods to override those in the running IPython to interact
55 # A couple of methods to override those in the running IPython to interact
54 # better with doctest (doctest captures on raw stdout, so we need to direct
56 # better with doctest (doctest captures on raw stdout, so we need to direct
55 # various types of output there otherwise it will miss them).
57 # various types of output there otherwise it will miss them).
56
58
57 def xsys(self, cmd):
59 def xsys(self, cmd):
58 """Replace the default system call with a capturing one for doctest.
60 """Replace the default system call with a capturing one for doctest.
59 """
61 """
60 # We use getoutput, but we need to strip it because pexpect captures
62 # We use getoutput, but we need to strip it because pexpect captures
61 # the trailing newline differently from commands.getoutput
63 # the trailing newline differently from commands.getoutput
62 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout)
64 print(self.getoutput(cmd, split=False, depth=1).rstrip(), end='', file=sys.stdout)
63 sys.stdout.flush()
65 sys.stdout.flush()
64
66
65
67
66 def _showtraceback(self, etype, evalue, stb):
68 def _showtraceback(self, etype, evalue, stb):
67 """Print the traceback purely on stdout for doctest to capture it.
69 """Print the traceback purely on stdout for doctest to capture it.
68 """
70 """
69 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
71 print(self.InteractiveTB.stb2text(stb), file=sys.stdout)
70
72
71
73
72 def start_ipython():
74 def start_ipython():
73 """Start a global IPython shell, which we need for IPython-specific syntax.
75 """Start a global IPython shell, which we need for IPython-specific syntax.
74 """
76 """
75 global get_ipython
77 global get_ipython
76
78
77 # This function should only ever run once!
79 # This function should only ever run once!
78 if hasattr(start_ipython, 'already_called'):
80 if hasattr(start_ipython, 'already_called'):
79 return
81 return
80 start_ipython.already_called = True
82 start_ipython.already_called = True
81
83
82 # Store certain global objects that IPython modifies
84 # Store certain global objects that IPython modifies
83 _displayhook = sys.displayhook
85 _displayhook = sys.displayhook
84 _excepthook = sys.excepthook
86 _excepthook = sys.excepthook
85 _main = sys.modules.get('__main__')
87 _main = sys.modules.get('__main__')
86
88
87 # Create custom argv and namespaces for our IPython to be test-friendly
89 # Create custom argv and namespaces for our IPython to be test-friendly
88 config = tools.default_config()
90 config = tools.default_config()
89 config.TerminalInteractiveShell.simple_prompt = True
91 config.TerminalInteractiveShell.simple_prompt = True
90
92
91 # Create and initialize our test-friendly IPython instance.
93 # Create and initialize our test-friendly IPython instance.
92 shell = TerminalInteractiveShell.instance(config=config,
94 shell = TerminalInteractiveShell.instance(config=config,
93 )
95 )
94
96
95 # A few more tweaks needed for playing nicely with doctests...
97 # A few more tweaks needed for playing nicely with doctests...
96
98
97 # remove history file
99 # remove history file
98 shell.tempfiles.append(config.HistoryManager.hist_file)
100 shell.tempfiles.append(Path(config.HistoryManager.hist_file))
99
101
100 # These traps are normally only active for interactive use, set them
102 # These traps are normally only active for interactive use, set them
101 # permanently since we'll be mocking interactive sessions.
103 # permanently since we'll be mocking interactive sessions.
102 shell.builtin_trap.activate()
104 shell.builtin_trap.activate()
103
105
104 # Modify the IPython system call with one that uses getoutput, so that we
106 # Modify the IPython system call with one that uses getoutput, so that we
105 # can capture subcommands and print them to Python's stdout, otherwise the
107 # can capture subcommands and print them to Python's stdout, otherwise the
106 # doctest machinery would miss them.
108 # doctest machinery would miss them.
107 shell.system = types.MethodType(xsys, shell)
109 shell.system = types.MethodType(xsys, shell)
108
110
109 shell._showtraceback = types.MethodType(_showtraceback, shell)
111 shell._showtraceback = types.MethodType(_showtraceback, shell)
110
112
111 # IPython is ready, now clean up some global state...
113 # IPython is ready, now clean up some global state...
112
114
113 # Deactivate the various python system hooks added by ipython for
115 # Deactivate the various python system hooks added by ipython for
114 # interactive convenience so we don't confuse the doctest system
116 # interactive convenience so we don't confuse the doctest system
115 sys.modules['__main__'] = _main
117 sys.modules['__main__'] = _main
116 sys.displayhook = _displayhook
118 sys.displayhook = _displayhook
117 sys.excepthook = _excepthook
119 sys.excepthook = _excepthook
118
120
119 # So that ipython magics and aliases can be doctested (they work by making
121 # So that ipython magics and aliases can be doctested (they work by making
120 # a call into a global _ip object). Also make the top-level get_ipython
122 # a call into a global _ip object). Also make the top-level get_ipython
121 # now return this without recursively calling here again.
123 # now return this without recursively calling here again.
122 _ip = shell
124 _ip = shell
123 get_ipython = _ip.get_ipython
125 get_ipython = _ip.get_ipython
124 builtin_mod._ip = _ip
126 builtin_mod._ip = _ip
125 builtin_mod.ip = _ip
127 builtin_mod.ip = _ip
126 builtin_mod.get_ipython = get_ipython
128 builtin_mod.get_ipython = get_ipython
127
129
128 # Override paging, so we don't require user interaction during the tests.
130 # Override paging, so we don't require user interaction during the tests.
129 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
131 def nopage(strng, start=0, screen_lines=0, pager_cmd=None):
130 if isinstance(strng, dict):
132 if isinstance(strng, dict):
131 strng = strng.get('text/plain', '')
133 strng = strng.get('text/plain', '')
132 print(strng)
134 print(strng)
133
135
134 page.orig_page = page.pager_page
136 page.orig_page = page.pager_page
135 page.pager_page = nopage
137 page.pager_page = nopage
136
138
137 return _ip
139 return _ip
General Comments 0
You need to be logged in to leave comments. Login now