Skip to content

Tell IPython the correct GUI event loop to use for all backends. #12637

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

Merged
merged 2 commits into from
Mar 13, 2019

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Oct 26, 2018

IPython currently uses a hard-coded table
(IPython.core.pylabtools.backend2gui) to know which event loop to use
for which backend. This approach fails for both the new builtin
cairo-based backends (which do not appear in the table), and for
third-party backends (e.g. mplcairo).

mplcairo has used some custom code to patch that table for a while;
reuse it to more generally use the new "required_interactive_framework"
attribute.

Note that this PR suggests that there should be a better way to go back
from the canvas class to the backend module (rather than looking for
sys.modules[cls.__module__].required_interactive_framework, which is a
bit hacky and could in theory fail if the canvas class is actually
defined in another submodule).

(Edits:
Actually the "hack" above "sort-of" fails for Qt4 in the sense that backend_qt4agg.FigureCanvas is actually the same class as backend_qt5agg.FigureCanvas, so trying to reach the required_interactive_framework that way will point to "qt5". But fortunately ipython maps both "qt4" and "qt5" to "qt", so we're fine...

Perhaps we can just mandate that the __module__ attribute of FigureCanvas subclasses must point to their actual backend module name. It's not as if requiring that the backend module name be stored in another attribute really helps.)

Fixes #10763.
attn @Carreau

PR Summary

PR Checklist

  • Has Pytest style unit tests
  • Code is Flake 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@tacaswell
Copy link
Member

This is probably the right way to do this, definitely need to negotiate with the IPython folks to make this a bit more of a documented interface.

@Carreau
Copy link
Contributor

Carreau commented Nov 4, 2018

I'm happy to get any patch in IPython that can help you. I suppose we should probably find a nice way to register new backends with IPython (entrypoints ?). I'm also limited in bandwidth since I'm not 100% jupyter-funded, so I'm happy to work on giving access to the repository/PYPI/.... etc if I become a blocking factor.

@anntzer
Copy link
Contributor Author

anntzer commented Nov 4, 2018

I suppose we should probably find a nice way to register new backends with IPython (entrypoints ?).

I don't think that really helps as Matplotlib's current policy is that any module can be a backend, as long as it defines the correct functions/classes/attributes.

I am reasonably happy with the solution in this PR (i.e., let the backend register itself to IPython's table when a canvas is about to be created (which is more or less the latest the registration can be done)). Alternatively, IPython could itself have the code that tries to read required_interactive_framework, but that seems worse: 1. it would need to update itself if the backend is switched, and 2. it would neither work with old versions of Matplotlib that didn't have that attribute, nor with old versions of IPython which, well, didn't do that; whereas the solution here "works" for all versions of IPython that have the "more-or-less public" :-) API that this touches.

IPython currently uses a hard-coded table
(IPython.core.pylabtools.backend2gui) to know which event loop to use
for which backend.  This approach fails for both the new builtin
cairo-based backends (which do not appear in the table), and for
third-party backends (e.g. mplcairo).

mplcairo has used some custom code to patch that table for a while;
reuse it to more generally use the new "required_interactive_framework"
attribute.

Note that this PR suggests that there should be a better way to go back
from the canvas class to the backend module (rather than looking for
`sys.modules[cls.__module__].required_interactive_framework`, which is a
bit hacky and could in theory fail if the canvas class is actually
defined in another submodule).
@anntzer
Copy link
Contributor Author

anntzer commented Feb 24, 2019

rebased

@tacaswell
Copy link
Member

I'm in favor of merging this as long as @Carreau does not tell is it is too hacky.

@jklymak
Copy link
Member

jklymak commented Mar 3, 2019

@Carreau did you have a minute to look at this?

@jklymak jklymak merged commit b15140a into matplotlib:master Mar 13, 2019
meeseeksmachine pushed a commit to meeseeksmachine/matplotlib that referenced this pull request Mar 13, 2019
@jklymak
Copy link
Member

jklymak commented Mar 13, 2019

@Carreau did not tell us it was too hacky. If it is, I imagine we can back it out....

@anntzer anntzer deleted the ipython-gui branch March 13, 2019 22:21
jklymak added a commit that referenced this pull request Mar 13, 2019
…637-on-v3.1.x

Backport PR #12637 on branch v3.1.x (Tell IPython the correct GUI event loop to use for all backends.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cairo in 2.2.0 not working for new backends
4 participants