From f99a2008a2937ffbaa389f15243bbb62d1b707f7 2007-08-12 22:45:38 From: fperez Date: 2007-08-12 22:45:38 Subject: [PATCH] Fix doctest support: now running scripts that invoke the various doctest testing methods and functions from within IPython should work. --- diff --git a/IPython/Release.py b/IPython/Release.py index 4a67dbe..467ebb8 100644 --- a/IPython/Release.py +++ b/IPython/Release.py @@ -1,7 +1,7 @@ # -*- coding: utf-8 -*- """Release data for the IPython project. -$Id: Release.py 2446 2007-06-14 22:30:58Z vivainio $""" +$Id: Release.py 2602 2007-08-12 22:45:38Z fperez $""" #***************************************************************************** # Copyright (C) 2001-2006 Fernando Perez @@ -22,7 +22,7 @@ name = 'ipython' # because bdist_rpm does not accept dashes (an RPM) convention, and # bdist_deb does not accept underscores (a Debian convention). -revision = '2445' +revision = '2601' version = '0.8.2.svn.r' + revision.rstrip('M') diff --git a/IPython/genutils.py b/IPython/genutils.py index 50842d8..5dbbc7e 100644 --- a/IPython/genutils.py +++ b/IPython/genutils.py @@ -5,7 +5,7 @@ General purpose utilities. This is a grab-bag of stuff I find useful in most programs I write. Some of these things are also convenient when working at the command line. -$Id: genutils.py 2577 2007-08-02 23:50:02Z fperez $""" +$Id: genutils.py 2602 2007-08-12 22:45:38Z fperez $""" #***************************************************************************** # Copyright (C) 2001-2006 Fernando Perez. @@ -799,6 +799,30 @@ def flag_calls(func): return wrapper #---------------------------------------------------------------------------- +def dhook_wrap(func,*a,**k): + """Wrap a function call in a sys.displayhook controller. + + Returns a wrapper around func which calls func, with all its arguments and + keywords unmodified, using the default sys.displayhook. Since IPython + modifies sys.displayhook, it breaks the behavior of certain systems that + rely on the default behavior, notably doctest. + """ + + def f(*a,**k): + + dhook_s = sys.displayhook + sys.displayhook = sys.__displayhook__ + try: + out = func(*a,**k) + finally: + sys.displayhook = dhook_s + + return out + + f.__doc__ = func.__doc__ + return f + +#---------------------------------------------------------------------------- class HomeDirError(Error): pass diff --git a/IPython/iplib.py b/IPython/iplib.py index ded87c2..64a823d 100644 --- a/IPython/iplib.py +++ b/IPython/iplib.py @@ -6,7 +6,7 @@ Requires Python 2.3 or newer. This file contains all the classes and helper functions specific to IPython. -$Id: iplib.py 2596 2007-08-08 11:41:01Z vivainio $ +$Id: iplib.py 2602 2007-08-12 22:45:38Z fperez $ """ #***************************************************************************** @@ -41,6 +41,7 @@ import StringIO import bdb import cPickle as pickle import codeop +import doctest import exceptions import glob import inspect @@ -677,7 +678,15 @@ class InteractiveShell(object,Magic): # overwrite it. self.sys_displayhook = sys.displayhook sys.displayhook = self.outputcache - + + # Monkeypatch doctest so that its core test runner method is protected + # from IPython's modified displayhook. Doctest expects the default + # displayhook behavior deep down, so our modification breaks it + # completely. For this reason, a hard monkeypatch seems like a + # reasonable solution rather than asking users to manually use a + # different doctest runner when under IPython. + doctest.DocTestRunner.run = dhook_wrap(doctest.DocTestRunner.run) + # Set user colors (don't do it in the constructor above so that it # doesn't crash if colors option is invalid) self.magic_colors(rc.colors) diff --git a/doc/ChangeLog b/doc/ChangeLog index d6ac415..378c02a 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,3 +1,9 @@ +2007-08-12 Fernando Perez + + * IPython/iplib.py (InteractiveShell.post_config_initialization): + fix problems with doctests failing when run inside IPython due to + IPython's modifications of sys.displayhook. + 2007-8-9 Fernando Perez * IPython/ipapi.py (to_user_ns): update to accept a dict as well as diff --git a/doc/manual_base.lyx b/doc/manual_base.lyx index e1174b5..3f385cd 100644 --- a/doc/manual_base.lyx +++ b/doc/manual_base.lyx @@ -509,6 +509,21 @@ profile ') convenient for rapid interactive work. \end_layout +\begin_layout Itemize +Doctest support. + The special +\family typewriter +%doctest_mode +\family default + command toggles a mode that allows you to paste existing doctests (with + leading ` +\family typewriter +>>> +\family default +' prompts and whitespace) and uses doctest-compatible prompts and output, + so you can use IPython sessions as doctest code. +\end_layout + \begin_layout Subsection Portability and Python requirements \end_layout @@ -2646,6 +2661,31 @@ Use the IPython.demo.Demo class to load any Python script as an interactive for more. \end_layout +\begin_layout Itemize +Run your doctests from within IPython for development and debugging. + The special +\family typewriter +%doctest_mode +\family default + command toggles a mode where the prompt, output and exceptions display + matches as closely as possible that of the default Python interpreter. + In addition, this mode allows you to directly paste in code that contains + leading ` +\family typewriter +>>> +\family default +' prompts, even if they have extra leading whitespace (as is common in doctest + files). + This combined with the ` +\family typewriter +%history -t +\family default +n' call to see your translated history (with these extra prompts removed + and no line numbers) allows for an easy doctest workflow, where you can + go from doctest to interactive execution to pasting into valid Python code + as needed. +\end_layout + \begin_layout Subsection Source code handling tips \end_layout