Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shaperilio/gui msg #14067

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
6 changes: 4 additions & 2 deletions IPython/core/interactiveshell.py
Expand Up @@ -3585,7 +3585,9 @@ def enable_matplotlib(self, gui=None):
make sense in all contexts, for example a terminal ipython can't
display figures inline.
"""
from matplotlib_inline.backend_inline import configure_inline_support
# NOTE: this import triggers `enable_gui('qt')` and occurs before the users' config (e.g.
# `--matplotlib=qt5`) is procssed.
# from matplotlib_inline.backend_inline import configure_inline_support
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removing this import (and the function call that requires it) prevents the unnecessary installation of a qt event loop hook, and as far as I can tell, has no negative effects - I still get inline figures in a Jupyter notebook, for example. I'll need someone with more expertise to chime in on this.


from IPython.core import pylabtools as pt
gui, backend = pt.find_gui_and_backend(gui, self.pylab_gui_select)
Expand All @@ -3601,7 +3603,7 @@ def enable_matplotlib(self, gui=None):
gui, backend = pt.find_gui_and_backend(self.pylab_gui_select)

pt.activate_matplotlib(backend)
configure_inline_support(self, backend)
# configure_inline_support(self, backend)

# Now we must activate the gui pylab wants to use, and fix %run to take
# plot updates into account
Expand Down
99 changes: 58 additions & 41 deletions IPython/terminal/interactiveshell.py
Expand Up @@ -907,55 +907,72 @@ def mainloop(self):
self._atexit_once()


_inputhook = None
_inputhook = None # The actual event loop hook function
def inputhook(self, context):
if self._inputhook is not None:
self._inputhook(context)

active_eventloop = None
active_eventloop = None # The name of the event loop hook, e.g. "qt5"
def enable_gui(self, gui=None):
if self._inputhook is None and gui is None:
print("No event loop hook running.")
return

if self._inputhook is not None and gui is not None:
print(
f"Shell is already running a gui event loop for {self.active_eventloop}. "
"Call with no arguments to disable the current loop."
)
return
if self._inputhook is not None and gui is None:
self.active_eventloop = self._inputhook = None

if gui and (gui not in {"inline", "webagg"}):
# This hook runs with each cycle of the `prompt_toolkit`'s event loop.
self.active_eventloop, self._inputhook = get_inputhook_name_and_func(gui)
# NOTE: these two variables should be in sync; `active_eventloop` is the name and
# `_inputhook` is the actual function.
assert (self.active_eventloop is None and self._inputhook is None) \
or (self.active_eventloop is not None and self._inputhook is not None)

if gui is None:
# Requesting to remove the event loop hook.
if self._inputhook is None:
print("No event loop hook running.")
return
else:
# Input hook currently exists; let's yank it.
self.active_eventloop = self._inputhook = None
if PTK3:
import asyncio
self.pt_loop = asyncio.new_event_loop()
print("GUI event loop hook disabled.")
return
else:
self.active_eventloop = self._inputhook = None

# For prompt_toolkit 3.0. We have to create an asyncio event loop with
# this inputhook.
if PTK3:
# Requesting an event loop hook.
import asyncio
from prompt_toolkit.eventloop import new_eventloop_with_inputhook

if gui == 'asyncio':
# When we integrate the asyncio event loop, run the UI in the
# same event loop as the rest of the code. don't use an actual
# input hook. (Asyncio is not made for nesting event loops.)
self.pt_loop = get_asyncio_loop()
print("Installed asyncio event loop hook.")

elif self._inputhook:
# If an inputhook was set, create a new asyncio event loop with
# this inputhook for the prompt.
self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
print(f"Installed {self.active_eventloop} event loop hook.")
if self._inputhook is None:
# No event loop hook currently installed.
if gui in {"inline", "webagg"}:
# There's no actual hook for these.
return
else:
self.active_eventloop, self._inputhook = get_inputhook_name_and_func(gui)
if PTK3:
from prompt_toolkit.eventloop import new_eventloop_with_inputhook
self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
print(f"Installed {self.active_eventloop} event loop hook.")
else:
# When there's no inputhook, run the prompt in a separate
# asyncio event loop.
self.pt_loop = asyncio.new_event_loop()
print("GUI event loop hook disabled.")
# An event loop hook is already installed.
if self.active_eventloop == gui:
# already installed; nothing to do.
return
elif self.active_eventloop.startswith('qt'):
if gui == 'qt':
# This means "requesting latest version". But you can't switch versions once
# you've chosen one, so we just accept this if the event loop hook is
# already *any* Qt version.
return
elif gui.startswith('qt'):
# Requesting a specific version of qt, but not the same version as the one
# installed last time. We run this code, which will let the Qt importing
# logic tell the user that the version cannot be switched. Effectively, we
# are re-hooking the same hook.
self.active_eventloop, self._inputhook = get_inputhook_name_and_func(gui)
if PTK3:
from prompt_toolkit.eventloop import new_eventloop_with_inputhook
self.pt_loop = new_eventloop_with_inputhook(self._inputhook)
# Still print this so it's clear what's happening.
print(f"Installed {self.active_eventloop} event loop hook.")
else:
# A hook is already installed, and the user is requesting a different one.
print(f"Shell is already running a gui event loop for {self.active_eventloop}. "
"Call with no arguments to disable the current loop.")
return

# Run !system commands directly, not through pipes, so terminal programs
# work correctly.
Expand Down
3 changes: 3 additions & 0 deletions shaperilio-reqs.txt
@@ -0,0 +1,3 @@
-e .
matplotlib
pyqt5