Skip to content

Commit

Permalink
Only import IPython upon use
Browse files Browse the repository at this point in the history
  • Loading branch information
inducer committed Jun 24, 2016
1 parent be0fd00 commit 05b5b4b
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 54 deletions.
6 changes: 3 additions & 3 deletions pudb/debugger.py
Expand Up @@ -1774,11 +1774,11 @@ def run_external_cmdline(w, size, key):
curframe = self.debugger.curframe

import pudb.shell as shell
if shell.HAVE_IPYTHON and CONFIG["shell"] == "ipython":
if CONFIG["shell"] == "ipython" and shell.have_ipython():
runner = shell.run_ipython_shell
elif shell.HAVE_BPYTHON and CONFIG["shell"] == "bpython":
elif CONFIG["shell"] == "bpython" and shell.HAVE_BPYTHON:
runner = shell.run_bpython_shell
elif shell.HAVE_PTPYTHON and CONFIG["shell"] == "ptpython":
elif CONFIG["shell"] == "ptpython" and shell.HAVE_PTPYTHON:
runner = shell.run_ptpython_shell
else:
runner = shell.run_classic_shell
Expand Down
118 changes: 67 additions & 51 deletions pudb/shell.py
@@ -1,23 +1,3 @@
try:
import IPython
# Access a property to verify module exists in case
# there's a demand loader wrapping module imports
# See https://github.com/inducer/pudb/issues/177
IPython.core
except (ImportError, ValueError):
# Old IPythons versions (0.12?) may fail to import with
# ValueError: fallback required, but not specified
# https://github.com/inducer/pudb/pull/135
HAVE_IPYTHON = False
else:
HAVE_IPYTHON = True


if HAVE_IPYTHON:
from IPython import version_info as IPYTHON_VERSION
else:
IPYTHON_VERSION = None

try:
import bpython # noqa
# Access a property to verify module exists in case
Expand Down Expand Up @@ -115,6 +95,37 @@ def run_bpython_shell(locals, globals, first_time):
bpython.cli.main(locals_=ns)


# {{{ ipython

def have_ipython():
# IPython has started being obnoxious on import, only import
# if absolutely needed.

# https://github.com/ipython/ipython/issues/9435

try:
import IPython
# Access a property to verify module exists in case
# there's a demand loader wrapping module imports
# See https://github.com/inducer/pudb/issues/177
IPython.core
except (ImportError, ValueError):
# Old IPythons versions (0.12?) may fail to import with
# ValueError: fallback required, but not specified
# https://github.com/inducer/pudb/pull/135
return False
else:
return True


def ipython_version():
if have_ipython():
from IPython import version_info
return version_info
else:
return None


def run_ipython_shell_v10(locals, globals, first_time):
'''IPython shell from IPython version 0.10'''
if first_time:
Expand All @@ -130,6 +141,26 @@ def run_ipython_shell_v10(locals, globals, first_time):
.mainloop(banner=banner)


def _update_ipython_ns(shell, locals, globals):
'''Update the IPython 0.11 namespace at every visit'''

shell.user_ns = locals.copy()

try:
shell.user_global_ns = globals
except AttributeError:
class DummyMod(object):
"A dummy module used for IPython's interactive namespace."
pass

user_module = DummyMod()
user_module.__dict__ = globals
shell.user_module = user_module

shell.init_user_ns()
shell.init_completer()


def run_ipython_shell_v11(locals, globals, first_time):
'''IPython shell from IPython version 0.11'''
if first_time:
Expand Down Expand Up @@ -158,49 +189,34 @@ def run_ipython_shell_v11(locals, globals, first_time):
# Save the originating namespace
old_locals = shell.user_ns
old_globals = shell.user_global_ns

# Update shell with current namespace
_update_ns(shell, locals, globals)
_update_ipython_ns(shell, locals, globals)

args = []
if IPYTHON_VERSION < (5, 0, 0):
if ipython_version() < (5, 0, 0):
args.append(banner)
else:
print(banner)
shell.mainloop(*args)

# Restore originating namespace
_update_ns(shell, old_locals, old_globals)
_update_ipython_ns(shell, old_locals, old_globals)


def run_ipython_shell(locals, globals, first_time):
import IPython
if have_ipython() and hasattr(IPython, 'Shell'):
return run_ipython_shell_v10(locals, globals, first_time)
else:
return run_ipython_shell_v11(locals, globals, first_time)

# }}}


def run_ptpython_shell(locals, globals, first_time):
## Use the default ptpython history:
# Use the default ptpython history
import os
history_filename = os.path.expanduser('~/.ptpython_history')
ptpython_embed(globals.copy(), locals.copy(),
history_filename=history_filename)


def _update_ns(shell, locals, globals):
'''Update the IPython 0.11 namespace at every visit'''

shell.user_ns = locals.copy()

try:
shell.user_global_ns = globals
except AttributeError:
class DummyMod(object):
"A dummy module used for IPython's interactive namespace."
pass

user_module = DummyMod()
user_module.__dict__ = globals
shell.user_module = user_module

shell.init_user_ns()
shell.init_completer()


# Set the proper ipython shell
if HAVE_IPYTHON and hasattr(IPython, 'Shell'):
run_ipython_shell = run_ipython_shell_v10
else:
run_ipython_shell = run_ipython_shell_v11

0 comments on commit 05b5b4b

Please sign in to comment.