Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Use standard IPython startup instead of embed #74

Open
wants to merge 2 commits into from

2 participants

@bendavis78

Fixes #73

@techniq
Collaborator

One reason I changed to use embed was it was part of the public API (init.py) and consistent across versions (after 0.10). I agree and understand the reason not to use it (especially coming from an IPython developer). A couple issues I see with the current pull request:

  • IPython 1.x moved the ipapp module from IPython.frontend.terminal to IPython.terminal so we need some more conditional logic to get TerminalIPythonApp imported
  • Issue #36 was opened wanting the default profile loaded. I saw in the Django issue that this goes back and forth, and ultimately in issue #36 the request was to have the confirm_ext = False. I really don't want to expose another argument in Shell()'s constructor so I think this should just always be set to False (I figure 95%+ would prefer this, if not 100% :) ) or expose it as a Flask config parameter (maybe a key like SCRIPT_IPYTHON_CONFIRM_EXIT) but I don't know at this point if it even needs to be exposed.
@bendavis78

Yeah as for #36 I agree there's no point to add an argument for confirm_ext, when a better way to do that would be via ipython config. The main thing should be to get user configuration loading correctly. I also realized my patch is broken as it doesn't seem to pull in the user context, so I need to figure that out as well. I'll see if I can add conditional support for the various versions also.

@techniq
Collaborator

I just got a chance to look to see how Django is handling this and see that IPython 1.x now has a public API IPython.start_ipython() which looks like what we should be using moving forward (in case it's namespace moves again).
https://github.com/django/django/blob/master/django/core/management/commands/shell.py

It also seems like you're doing a lot with the TerminalIPythonApp and TerminalInteractiveShell instances. Is all this needed / is there a cleaning way?

@bendavis78

Unfortunately start_ipython() doesn't take user_ns (yet). See my stackoverflow question here: http://stackoverflow.com/questions/18318257/how-can-i-start-an-ipython-application-instance-while-passing-a-custom-user-ns-a/18345717#18345717

Ideally ipython should be using TerminalIPythonApp. Unfortunately this is the best way I've found to do it while still supporting a custom user_ns and banner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
Showing with 30 additions and 10 deletions.
  1. +30 −10 flask_script/commands.py
View
40 flask_script/commands.py
@@ -230,6 +230,35 @@ def get_context(self):
"""
return self.make_context()
+ def ipython(self, context):
+ try:
+ # 0.10.x
+ from IPython.Shell import IPShellEmbed
+ ipshell = IPShellEmbed(banner=self.banner)
+ ipshell(global_ns=dict(), local_ns=context)
+ except ImportError:
+ # 0.12+
+ try:
+ from IPython.terminal import ipapp
+ except ImportError:
+ from IPython.frontend.terminal import ipapp
+ app = ipapp.TerminalIPythonApp.instance()
+ shell = ipapp.TerminalInteractiveShell.instance(
+ parent=app,
+ display_banner=False,
+ profile_dir=app.profile_dir,
+ ipython_dir=app.ipython_dir,
+ user_ns=context,
+ banner1=self.banner)
+ shell.configurables.append(app)
+ app.shell = shell
+ # shell has already been initialized, so we have to monkeypatch
+ # app.init_shell() to act as no-op
+ app.init_shell = lambda: None
+ app.initialize(argv=[])
+ app.start()
+
+
def run(self, no_ipython, no_bpython):
"""
Runs the shell. If no_bpython is False or use_bpython is True, then
@@ -249,17 +278,8 @@ def run(self, no_ipython, no_bpython):
pass
if not no_ipython:
- # Try IPython
try:
- try:
- # 0.10.x
- from IPython.Shell import IPShellEmbed
- ipshell = IPShellEmbed(banner=self.banner)
- ipshell(global_ns=dict(), local_ns=context)
- except ImportError:
- # 0.12+
- from IPython import embed
- embed(banner1=self.banner, user_ns=context)
+ self.ipython(context)
return
except ImportError:
pass
Something went wrong with that request. Please try again.