views:

179

answers:

1

Please help me get an embedded ipython console to run inside a doctest. The example code demonstrates the problem and will hang your terminal. On bash shell I type ctrl-Z and then kill %1 to break out and kill, since ctrl-C won't work.

def some_function():
    """
    >>> some_function()
    'someoutput'
    """
    # now try to drop into an ipython shell to help 
    # with development
    import IPython.Shell; IPython.Shell.IPShellEmbed(argv=[])()
    return 'someoutput'

if __name__ == '__main__':
    import doctest
    print "Running doctest . . ."
    doctest.testmod()

I like to use ipython to help write code. A common trick is to use ipython as a breakpoint in my code by calling IPython.Shell.IPShellEmbed. This trick works everywhere I've tried (inside a django manage.py runserver, unit tests), but it doesn't work within doctests. I think it has to do with doctest controlling stdin/stdout.

Thanks in advance for your help. - Philip

A: 

I emailed the ipython user group and got some help. There is now a support ticket to get this feature fixed in future versions of ipython. Here is a code snippet with a workaround:

import sys

from IPython.Shell import IPShellEmbed

class IPShellDoctest(IPShellEmbed):
   def __call__(self, *a, **kw):
       sys_stdout_saved = sys.stdout
       sys.stdout = sys.stderr
       try:
           IPShellEmbed.__call__(self, *a, **kw)
       finally:
           sys.stdout = sys_stdout_saved


def some_function():
  """
  >>> some_function()
  'someoutput'
  """
  # now try to drop into an ipython shell to help
  # with development
  IPShellDoctest()(local_ns=locals())
  return 'someoutput'

if __name__ == '__main__':
  import doctest
  print "Running doctest . . ."
  doctest.testmod()
Gattster
If you don't care about resetting stdout, you can skip the whole `IPShellDoctest` class and just manually set `sys.stdout = sys.stderr` before you call `IPShellEmbed`. Generally I have a `sys.exit()` in my code right after the `IPShellEmbed` anyway.
Gattster