diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py index 2d3369c..18a6570 100644 --- a/IPython/core/interactiveshell.py +++ b/IPython/core/interactiveshell.py @@ -439,11 +439,13 @@ class InteractiveShell(Configurable, Magic): self.object_info_string_level) def init_io(self): - import IPython.utils.io + # This will just use sys.stdout and sys.stderr. If you want to + # override sys.stdout and sys.stderr themselves, you need to do that + # *before* instantiating this class, because Term holds onto + # references to the underlying streams. if sys.platform == 'win32' and self.has_readline: - Term = io.IOTerm( - cout=self.readline._outputfile,cerr=self.readline._outputfile - ) + Term = io.IOTerm(cout=self.readline._outputfile, + cerr=self.readline._outputfile) else: Term = io.IOTerm() io.Term = Term @@ -1483,9 +1485,7 @@ class InteractiveShell(Configurable, Magic): Subclasses may override this method to put the traceback on a different place, like a side channel. """ - # FIXME: this should use the proper write channels, but our test suite - # relies on it coming out of stdout... - print >> sys.stdout, self.InteractiveTB.stb2text(stb) + print >> io.Term.cout, self.InteractiveTB.stb2text(stb) def showsyntaxerror(self, filename=None): """Display the syntax error that just occurred. diff --git a/IPython/testing/globalipapp.py b/IPython/testing/globalipapp.py index 1439ed7..35cad38 100644 --- a/IPython/testing/globalipapp.py +++ b/IPython/testing/globalipapp.py @@ -5,11 +5,11 @@ modifications IPython makes to system behavior don't send the doctest machinery into a fit. This code should be considered a gross hack, but it gets the job done. """ - from __future__ import absolute_import +from __future__ import print_function #----------------------------------------------------------------------------- -# Copyright (C) 2009 The IPython Development Team +# Copyright (C) 2009-2010 The IPython Development Team # # Distributed under the terms of the BSD License. The full license is in # the file COPYING, distributed as part of this software. @@ -19,13 +19,17 @@ from __future__ import absolute_import # Imports #----------------------------------------------------------------------------- +# stdlib import __builtin__ -import commands import os import sys +from types import MethodType +# our own from . import tools +from IPython.frontend.terminal.interactiveshell import TerminalInteractiveShell + #----------------------------------------------------------------------------- # Functions #----------------------------------------------------------------------------- @@ -53,12 +57,9 @@ def _run_ns_sync(self,arg_s,runner=None): This is strictly needed for running doctests that call %run. """ - #print >> sys.stderr, 'in run_ns_sync', arg_s # dbg - - _ip = get_ipython() + #print('in run_ns_sync', arg_s, file=sys.stderr) # dbg finder = py_file_finder(arg_s) - out = _ip.magic_run_ori(arg_s,runner,finder) - return out + return get_ipython().magic_run_ori(arg_s, runner, finder) class ipnsdict(dict): @@ -104,6 +105,25 @@ def get_ipython(): return start_ipython() +# A couple of methods to override those in the running IPython to interact +# better with doctest (doctest captures on raw stdout, so we need to direct +# various types of output there otherwise it will miss them). + +def xsys(self, cmd): + """Replace the default system call with a capturing one for doctest. + """ + # We use getoutput, but we need to strip it because pexpect captures + # the trailing newline differently from commands.getoutput + print(self.getoutput(cmd).rstrip(), end='', file=sys.stdout) + sys.stdout.flush() + + +def _showtraceback(self, etype, evalue, stb): + """Print the traceback purely on stdout for doctest to capture it. + """ + print(self.InteractiveTB.stb2text(stb), file=sys.stdout) + + def start_ipython(): """Start a global IPython shell, which we need for IPython-specific syntax. """ @@ -113,19 +133,7 @@ def start_ipython(): if hasattr(start_ipython, 'already_called'): return start_ipython.already_called = True - - from IPython.frontend.terminal import interactiveshell - def xsys(cmd): - """Execute a command and print its output. - - This is just a convenience function to replace the IPython system call - with one that is more doctest-friendly. - """ - cmd = _ip.var_expand(cmd,depth=1) - sys.stdout.write(commands.getoutput(cmd)) - sys.stdout.flush() - # Store certain global objects that IPython modifies _displayhook = sys.displayhook _excepthook = sys.excepthook @@ -135,10 +143,10 @@ def start_ipython(): config = tools.default_config() # Create and initialize our test-friendly IPython instance. - shell = interactiveshell.TerminalInteractiveShell.instance( - config=config, - user_ns=ipnsdict(), user_global_ns={} - ) + shell = TerminalInteractiveShell.instance(config=config, + user_ns=ipnsdict(), + user_global_ns={} + ) # A few more tweaks needed for playing nicely with doctests... @@ -149,7 +157,11 @@ def start_ipython(): # Modify the IPython system call with one that uses getoutput, so that we # can capture subcommands and print them to Python's stdout, otherwise the # doctest machinery would miss them. - shell.system = xsys + shell.system = MethodType(xsys, shell, TerminalInteractiveShell) + + + shell._showtraceback = MethodType(_showtraceback, shell, + TerminalInteractiveShell) # IPython is ready, now clean up some global state... diff --git a/IPython/zmq/zmqshell.py b/IPython/zmq/zmqshell.py index fde5194..f0362df 100644 --- a/IPython/zmq/zmqshell.py +++ b/IPython/zmq/zmqshell.py @@ -27,6 +27,7 @@ from IPython.core.interactiveshell import ( from IPython.core.displayhook import DisplayHook from IPython.core.macro import Macro from IPython.core.payloadpage import install_payload_page +from IPython.utils import io from IPython.utils.path import get_py_filename from IPython.utils.text import StringTypes from IPython.utils.traitlets import Instance, Type, Dict @@ -77,15 +78,6 @@ class ZMQInteractiveShell(InteractiveShell): displayhook_class = Type(ZMQDisplayHook) - def init_io(self): - # This will just use sys.stdout and sys.stderr. If you want to - # override sys.stdout and sys.stderr themselves, you need to do that - # *before* instantiating this class, because Term holds onto - # references to the underlying streams. - import IPython.utils.io - Term = IPython.utils.io.IOTerm() - IPython.utils.io.Term = Term - def magic_doctest_mode(self,parameter_s=''): """Toggle doctest mode on and off.