How to use ipython's IPShellEmbed from within a running doctest
-
22-09-2019 - |
Question
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
Solution
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()