| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -18,7 +18,9 @@ | |
| The object-oriented API is recommended for more complex plots. | ||
| """ | ||
|
|
||
| import importlib | ||
| import inspect | ||
| import logging | ||
| from numbers import Number | ||
| import re | ||
| import sys | ||
| Expand Down Expand Up | @@ -67,10 +69,13 @@ | |
| MaxNLocator | ||
| from matplotlib.backends import pylab_setup | ||
|
|
||
| _log = logging.getLogger(__name__) | ||
|
|
||
|
|
||
| ## Backend detection ## | ||
|
|
||
|
|
||
| # FIXME: Deprecate. | ||
| def _backend_selection(): | ||
| """ | ||
| If rcParams['backend_fallback'] is true, check to see if the | ||
| Expand Down Expand Up | @@ -110,8 +115,6 @@ def _backend_selection(): | |
| ## Global ## | ||
|
|
||
|
|
||
| _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup() | ||
|
|
||
| _IP_REGISTERED = None | ||
| _INSTALL_FIG_OBSERVER = False | ||
|
|
||
| Expand Down Expand Up | @@ -213,21 +216,61 @@ def findobj(o=None, match=None, include_self=True): | |
|
|
||
| def switch_backend(newbackend): | ||
| """ | ||
| Switch the default backend. This feature is **experimental**, and | ||
| is only expected to work switching to an image backend. e.g., if | ||
| you have a bunch of PostScript scripts that you want to run from | ||
| an interactive ipython session, you may want to switch to the PS | ||
| backend before running them to avoid having a bunch of GUI windows | ||
| popup. If you try to interactively switch from one GUI backend to | ||
| another, you will explode. | ||
| Close all open figures and set the Matplotlib backend. | ||
|
|
||
| The argument is case-insensitive. Switching to an interactive backend is | ||
| possible only if no event loop for another interactive backend has started. | ||
| Switching to and from non-interactive backends is always possible. | ||
|
|
||
| Calling this command will close all open windows. | ||
| Parameters | ||
| ---------- | ||
| newbackend : str or List[str] | ||
| The name of the backend to use. If a list of backends, they will be | ||
| tried in order until one successfully loads. | ||
| """ | ||
| close('all') | ||
|
|
||
| if not isinstance(newbackend, str): | ||
| for candidate in newbackend: | ||
| try: | ||
| _log.info("Trying to load backend %s.", candidate) | ||
| return switch_backend(candidate) | ||
| except ImportError as exc: | ||
| _log.info("Loading backend %s failed: %s", candidate, exc) | ||
| else: | ||
| raise ValueError("No suitable backend among {}".format(newbackend)) | ||
|
|
||
| backend_name = ( | ||
| newbackend[9:] if newbackend.startswith("module://") | ||
| else "matplotlib.backends.backend_{}".format(newbackend.lower())) | ||
|
|
||
| backend_mod = importlib.import_module(backend_name) | ||
| Backend = type( | ||
| "Backend", (matplotlib.backends._Backend,), vars(backend_mod)) | ||
| _log.info("Loaded backend %s version %s.", | ||
| newbackend, Backend.backend_version) | ||
|
|
||
| required_framework = Backend.required_interactive_framework | ||
| current_framework = \ | ||
| matplotlib.backends._get_running_interactive_framework() | ||
| if (current_framework and required_framework | ||
| and current_framework != required_framework): | ||
| raise ImportError( | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI am worried that by this point we are already broken (due to importing the underlying GUI wrappers which may over-write each other's PyOS_EventHook), but I don't see any way around that short of delaying all of the imports (which I am not sure we can do).
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityPyOS_InputHook should (hopefully) not be overwritten before the toolkit event loop actually starts; e.g. for PyQt: from PyQt5.QtWidgets import *
print(input("foo? "))
app = QApplication([])
print(input("foo? "))
even after the QApplication is created, input works fine; overwriting likely only occurs in app.exec_().
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityBut if you the import tk will the Qt windows still be responsive while waiting for user input?
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityYes (this can easily be checked by, well, doing it). I'd guess tk also only sets up the input hook when actually starting the event loop.
Sorry, something went wrong.
All reactions
|
||
| "Cannot load backend {!r} which requires the {!r} interactive " | ||
| "framework, as {!r} is currently running".format( | ||
| newbackend, required_framework, current_framework)) | ||
|
|
||
| rcParams["backend"] = newbackend | ||
|
|
||
| global _backend_mod, new_figure_manager, draw_if_interactive, _show | ||
| matplotlib.use(newbackend, warn=False, force=True) | ||
| from matplotlib.backends import pylab_setup | ||
| _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup() | ||
| _backend_mod = backend_mod | ||
| new_figure_manager = Backend.new_figure_manager | ||
| draw_if_interactive = Backend.draw_if_interactive | ||
| _show = Backend.show | ||
|
|
||
| # Need to keep a global reference to the backend for compatibility reasons. | ||
| # See https://github.com/matplotlib/matplotlib/issues/6092 | ||
| matplotlib.backends.backend = newbackend | ||
|
|
||
|
|
||
| def show(*args, **kw): | ||
| Expand Down Expand Up | @@ -2358,6 +2401,9 @@ def _autogen_docstring(base): | |
| # to determine if they should trigger a draw. | ||
| install_repl_displayhook() | ||
|
|
||
| # Set up the backend. | ||
| switch_backend(rcParams["backend"]) | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityThis step locks the backend in, @WeatherGod wants import matplotlib
matplotlib.use('qt5agg')
import matplotlib.pyplot
matplotlib.use('tkagg') # this does not warn or fail
plt.figure() # this makes a tk agg figure and actually does the backend import etc.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityNo it doesn't, because the QApplication isn't created until a figure is created. Indeed, your snippet works as expected.
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityI am apparently confused about the details of various hooks get installed or not.... 🐑
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityIn general nothing should happen until you create a widget; we then start the loop lazily.
Sorry, something went wrong.
All reactions
|
||
|
|
||
|
|
||
| ################# REMAINING CONTENT GENERATED BY boilerplate.py ############## | ||
|
|
||
| Expand Down | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| Expand Up | @@ -13,11 +13,13 @@ | |
| parameter set listed here should also be visited to the | ||
| :file:`matplotlibrc.template` in matplotlib's root source directory. | ||
| """ | ||
|
|
||
| from collections import Iterable, Mapping | ||
| from functools import reduce | ||
| import operator | ||
| import os | ||
| import re | ||
| import sys | ||
|
|
||
| from matplotlib import cbook | ||
| from matplotlib.cbook import ls_mapper | ||
| Expand Down Expand Up | @@ -245,10 +247,35 @@ def validate_fonttype(s): | |
|
|
||
|
|
||
| def validate_backend(s): | ||
| if s.startswith('module://'): | ||
| return s | ||
| candidates = _listify_validator( | ||
| lambda s: | ||
| s if s.startswith("module://") | ||
| else ValidateInStrings('backend', all_backends, ignorecase=True)(s))(s) | ||
| pyplot = sys.modules.get("matplotlib.pyplot") | ||
| if len(candidates) == 1: | ||
| backend, = candidates | ||
| if pyplot: | ||
| # This import needs to be delayed (below too) because it is not | ||
| # available at first import. | ||
| from matplotlib import rcParams | ||
| # Don't recurse. | ||
| old_backend = rcParams["backend"] | ||
| if old_backend == backend: | ||
| return backend | ||
| dict.__setitem__(rcParams, "backend", backend) | ||
| try: | ||
| pyplot.switch_backend(backend) | ||
| except Exception: | ||
| dict.__setitem__(rcParams, "backend", old_backend) | ||
|
Comment thread
Copy link
Copy Markdown
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityThis needs to be done like this to make sure we un-wind any changes that `switch_backend_ makes to the rcparams?
Sorry, something went wrong.
All reactions
Copy link
Copy Markdown
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityNo, because switch_backend will set rcParams["backend"] too (to keep things consistent), but we don't want this to recurse ad infinitum (so we pre-set the entry -- but undo that if at the end of the day the backend switch was unsuccessful). Really it's just a complication because of the existence of two entry points (setting rcParams["backend"] and switch_backend) to the same info; it would even be simpler if switch_backend itself was inlined into the validator (but then you have funky action at distance with the proper initialization of pyplot happening in some other module...).
Sorry, something went wrong.
All reactions
|
||
| raise | ||
| return backend | ||
| else: | ||
| return _validate_standard_backends(s) | ||
| if pyplot: | ||
| from matplotlib import rcParams | ||
| pyplot.switch_backend(candidates) # Actually resolves the backend. | ||
| return rcParams["backend"] | ||
| else: | ||
| return candidates | ||
|
|
||
|
|
||
| def validate_qt4(s): | ||
| Expand Down Expand Up | @@ -965,9 +992,13 @@ def _validate_linestyle(ls): | |
|
|
||
| # a map from key -> value, converter | ||
| defaultParams = { | ||
| 'backend': ['Agg', validate_backend], # agg is certainly | ||
| # present | ||
| 'backend_fallback': [True, validate_bool], # agg is certainly present | ||
| 'backend': [["macosx", | ||
| "qt5agg", "qt4agg", | ||
| "gtk3agg", "gtk3cairo", | ||
| "tkagg", | ||
| "wxagg", | ||
| "agg", "cairo"], validate_backend], | ||
| 'backend_fallback': [True, validate_bool], | ||
| 'backend.qt4': [None, validate_qt4], | ||
| 'backend.qt5': [None, validate_qt5], | ||
| 'webagg.port': [8988, validate_int], | ||
| Expand Down | ||
| Back | FazBrowse Home | New Git URL |
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low QualityBy ".pyplot has already been imported" do you mean matplotlib.use() hasn't been called? Does pyplot fundamentally have anything to do with this, other than its where 99% of us call matplotlib.use() implicitly?
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.