remove venv
This commit is contained in:
parent
056387013d
commit
0680c7594e
13999 changed files with 0 additions and 2895688 deletions
|
|
@ -1,414 +0,0 @@
|
|||
from enum import Enum
|
||||
import importlib
|
||||
|
||||
|
||||
class BackendFilter(Enum):
|
||||
"""
|
||||
Filter used with :meth:`~matplotlib.backends.registry.BackendRegistry.list_builtin`
|
||||
|
||||
.. versionadded:: 3.9
|
||||
"""
|
||||
INTERACTIVE = 0
|
||||
NON_INTERACTIVE = 1
|
||||
|
||||
|
||||
class BackendRegistry:
|
||||
"""
|
||||
Registry of backends available within Matplotlib.
|
||||
|
||||
This is the single source of truth for available backends.
|
||||
|
||||
All use of ``BackendRegistry`` should be via the singleton instance
|
||||
``backend_registry`` which can be imported from ``matplotlib.backends``.
|
||||
|
||||
Each backend has a name, a module name containing the backend code, and an
|
||||
optional GUI framework that must be running if the backend is interactive.
|
||||
There are three sources of backends: built-in (source code is within the
|
||||
Matplotlib repository), explicit ``module://some.backend`` syntax (backend is
|
||||
obtained by loading the module), or via an entry point (self-registering
|
||||
backend in an external package).
|
||||
|
||||
.. versionadded:: 3.9
|
||||
"""
|
||||
# Mapping of built-in backend name to GUI framework, or "headless" for no
|
||||
# GUI framework. Built-in backends are those which are included in the
|
||||
# Matplotlib repo. A backend with name 'name' is located in the module
|
||||
# f"matplotlib.backends.backend_{name.lower()}"
|
||||
_BUILTIN_BACKEND_TO_GUI_FRAMEWORK = {
|
||||
"gtk3agg": "gtk3",
|
||||
"gtk3cairo": "gtk3",
|
||||
"gtk4agg": "gtk4",
|
||||
"gtk4cairo": "gtk4",
|
||||
"macosx": "macosx",
|
||||
"nbagg": "nbagg",
|
||||
"notebook": "nbagg",
|
||||
"qtagg": "qt",
|
||||
"qtcairo": "qt",
|
||||
"qt5agg": "qt5",
|
||||
"qt5cairo": "qt5",
|
||||
"tkagg": "tk",
|
||||
"tkcairo": "tk",
|
||||
"webagg": "webagg",
|
||||
"wx": "wx",
|
||||
"wxagg": "wx",
|
||||
"wxcairo": "wx",
|
||||
"agg": "headless",
|
||||
"cairo": "headless",
|
||||
"pdf": "headless",
|
||||
"pgf": "headless",
|
||||
"ps": "headless",
|
||||
"svg": "headless",
|
||||
"template": "headless",
|
||||
}
|
||||
|
||||
# Reverse mapping of gui framework to preferred built-in backend.
|
||||
_GUI_FRAMEWORK_TO_BACKEND = {
|
||||
"gtk3": "gtk3agg",
|
||||
"gtk4": "gtk4agg",
|
||||
"headless": "agg",
|
||||
"macosx": "macosx",
|
||||
"qt": "qtagg",
|
||||
"qt5": "qt5agg",
|
||||
"qt6": "qtagg",
|
||||
"tk": "tkagg",
|
||||
"wx": "wxagg",
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
# Only load entry points when first needed.
|
||||
self._loaded_entry_points = False
|
||||
|
||||
# Mapping of non-built-in backend to GUI framework, added dynamically from
|
||||
# entry points and from matplotlib.use("module://some.backend") format.
|
||||
# New entries have an "unknown" GUI framework that is determined when first
|
||||
# needed by calling _get_gui_framework_by_loading.
|
||||
self._backend_to_gui_framework = {}
|
||||
|
||||
# Mapping of backend name to module name, where different from
|
||||
# f"matplotlib.backends.backend_{backend_name.lower()}". These are either
|
||||
# hardcoded for backward compatibility, or loaded from entry points or
|
||||
# "module://some.backend" syntax.
|
||||
self._name_to_module = {
|
||||
"notebook": "nbagg",
|
||||
}
|
||||
|
||||
def _backend_module_name(self, backend):
|
||||
if backend.startswith("module://"):
|
||||
return backend[9:]
|
||||
|
||||
# Return name of module containing the specified backend.
|
||||
# Does not check if the backend is valid, use is_valid_backend for that.
|
||||
backend = backend.lower()
|
||||
|
||||
# Check if have specific name to module mapping.
|
||||
backend = self._name_to_module.get(backend, backend)
|
||||
|
||||
return (backend[9:] if backend.startswith("module://")
|
||||
else f"matplotlib.backends.backend_{backend}")
|
||||
|
||||
def _clear(self):
|
||||
# Clear all dynamically-added data, used for testing only.
|
||||
self.__init__()
|
||||
|
||||
def _ensure_entry_points_loaded(self):
|
||||
# Load entry points, if they have not already been loaded.
|
||||
if not self._loaded_entry_points:
|
||||
entries = self._read_entry_points()
|
||||
self._validate_and_store_entry_points(entries)
|
||||
self._loaded_entry_points = True
|
||||
|
||||
def _get_gui_framework_by_loading(self, backend):
|
||||
# Determine GUI framework for a backend by loading its module and reading the
|
||||
# FigureCanvas.required_interactive_framework attribute.
|
||||
# Returns "headless" if there is no GUI framework.
|
||||
module = self.load_backend_module(backend)
|
||||
canvas_class = module.FigureCanvas
|
||||
return canvas_class.required_interactive_framework or "headless"
|
||||
|
||||
def _read_entry_points(self):
|
||||
# Read entry points of modules that self-advertise as Matplotlib backends.
|
||||
# Expects entry points like this one from matplotlib-inline (in pyproject.toml
|
||||
# format):
|
||||
# [project.entry-points."matplotlib.backend"]
|
||||
# inline = "matplotlib_inline.backend_inline"
|
||||
import importlib.metadata as im
|
||||
|
||||
entry_points = im.entry_points(group="matplotlib.backend")
|
||||
entries = [(entry.name, entry.value) for entry in entry_points]
|
||||
|
||||
# For backward compatibility, if matplotlib-inline and/or ipympl are installed
|
||||
# but too old to include entry points, create them. Do not import ipympl
|
||||
# directly as this calls matplotlib.use() whilst in this function.
|
||||
def backward_compatible_entry_points(
|
||||
entries, module_name, threshold_version, names, target):
|
||||
from matplotlib import _parse_to_version_info
|
||||
try:
|
||||
module_version = im.version(module_name)
|
||||
if _parse_to_version_info(module_version) < threshold_version:
|
||||
for name in names:
|
||||
entries.append((name, target))
|
||||
except im.PackageNotFoundError:
|
||||
pass
|
||||
|
||||
names = [entry[0] for entry in entries]
|
||||
if "inline" not in names:
|
||||
backward_compatible_entry_points(
|
||||
entries, "matplotlib_inline", (0, 1, 7), ["inline"],
|
||||
"matplotlib_inline.backend_inline")
|
||||
if "ipympl" not in names:
|
||||
backward_compatible_entry_points(
|
||||
entries, "ipympl", (0, 9, 4), ["ipympl", "widget"],
|
||||
"ipympl.backend_nbagg")
|
||||
|
||||
return entries
|
||||
|
||||
def _validate_and_store_entry_points(self, entries):
|
||||
# Validate and store entry points so that they can be used via matplotlib.use()
|
||||
# in the normal manner. Entry point names cannot be of module:// format, cannot
|
||||
# shadow a built-in backend name, and there cannot be multiple entry points
|
||||
# with the same name but different modules. Multiple entry points with the same
|
||||
# name and value are permitted (it can sometimes happen outside of our control,
|
||||
# see https://github.com/matplotlib/matplotlib/issues/28367).
|
||||
for name, module in set(entries):
|
||||
name = name.lower()
|
||||
if name.startswith("module://"):
|
||||
raise RuntimeError(
|
||||
f"Entry point name '{name}' cannot start with 'module://'")
|
||||
if name in self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK:
|
||||
raise RuntimeError(f"Entry point name '{name}' is a built-in backend")
|
||||
if name in self._backend_to_gui_framework:
|
||||
raise RuntimeError(f"Entry point name '{name}' duplicated")
|
||||
|
||||
self._name_to_module[name] = "module://" + module
|
||||
# Do not yet know backend GUI framework, determine it only when necessary.
|
||||
self._backend_to_gui_framework[name] = "unknown"
|
||||
|
||||
def backend_for_gui_framework(self, framework):
|
||||
"""
|
||||
Return the name of the backend corresponding to the specified GUI framework.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
framework : str
|
||||
GUI framework such as "qt".
|
||||
|
||||
Returns
|
||||
-------
|
||||
str or None
|
||||
Backend name or None if GUI framework not recognised.
|
||||
"""
|
||||
return self._GUI_FRAMEWORK_TO_BACKEND.get(framework.lower())
|
||||
|
||||
def is_valid_backend(self, backend):
|
||||
"""
|
||||
Return True if the backend name is valid, False otherwise.
|
||||
|
||||
A backend name is valid if it is one of the built-in backends or has been
|
||||
dynamically added via an entry point. Those beginning with ``module://`` are
|
||||
always considered valid and are added to the current list of all backends
|
||||
within this function.
|
||||
|
||||
Even if a name is valid, it may not be importable or usable. This can only be
|
||||
determined by loading and using the backend module.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
backend : str
|
||||
Name of backend.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if backend is valid, False otherwise.
|
||||
"""
|
||||
if not backend.startswith("module://"):
|
||||
backend = backend.lower()
|
||||
|
||||
# For backward compatibility, convert ipympl and matplotlib-inline long
|
||||
# module:// names to their shortened forms.
|
||||
backwards_compat = {
|
||||
"module://ipympl.backend_nbagg": "widget",
|
||||
"module://matplotlib_inline.backend_inline": "inline",
|
||||
}
|
||||
backend = backwards_compat.get(backend, backend)
|
||||
|
||||
if (backend in self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK or
|
||||
backend in self._backend_to_gui_framework):
|
||||
return True
|
||||
|
||||
if backend.startswith("module://"):
|
||||
self._backend_to_gui_framework[backend] = "unknown"
|
||||
return True
|
||||
|
||||
# Only load entry points if really need to and not already done so.
|
||||
self._ensure_entry_points_loaded()
|
||||
if backend in self._backend_to_gui_framework:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def list_all(self):
|
||||
"""
|
||||
Return list of all known backends.
|
||||
|
||||
These include built-in backends and those obtained at runtime either from entry
|
||||
points or explicit ``module://some.backend`` syntax.
|
||||
|
||||
Entry points will be loaded if they haven't been already.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of str
|
||||
Backend names.
|
||||
"""
|
||||
self._ensure_entry_points_loaded()
|
||||
return [*self.list_builtin(), *self._backend_to_gui_framework]
|
||||
|
||||
def list_builtin(self, filter_=None):
|
||||
"""
|
||||
Return list of backends that are built into Matplotlib.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filter_ : `~.BackendFilter`, optional
|
||||
Filter to apply to returned backends. For example, to return only
|
||||
non-interactive backends use `.BackendFilter.NON_INTERACTIVE`.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of str
|
||||
Backend names.
|
||||
"""
|
||||
if filter_ == BackendFilter.INTERACTIVE:
|
||||
return [k for k, v in self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK.items()
|
||||
if v != "headless"]
|
||||
elif filter_ == BackendFilter.NON_INTERACTIVE:
|
||||
return [k for k, v in self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK.items()
|
||||
if v == "headless"]
|
||||
|
||||
return [*self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK]
|
||||
|
||||
def list_gui_frameworks(self):
|
||||
"""
|
||||
Return list of GUI frameworks used by Matplotlib backends.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list of str
|
||||
GUI framework names.
|
||||
"""
|
||||
return [k for k in self._GUI_FRAMEWORK_TO_BACKEND if k != "headless"]
|
||||
|
||||
def load_backend_module(self, backend):
|
||||
"""
|
||||
Load and return the module containing the specified backend.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
backend : str
|
||||
Name of backend to load.
|
||||
|
||||
Returns
|
||||
-------
|
||||
Module
|
||||
Module containing backend.
|
||||
"""
|
||||
module_name = self._backend_module_name(backend)
|
||||
return importlib.import_module(module_name)
|
||||
|
||||
def resolve_backend(self, backend):
|
||||
"""
|
||||
Return the backend and GUI framework for the specified backend name.
|
||||
|
||||
If the GUI framework is not yet known then it will be determined by loading the
|
||||
backend module and checking the ``FigureCanvas.required_interactive_framework``
|
||||
attribute.
|
||||
|
||||
This function only loads entry points if they have not already been loaded and
|
||||
the backend is not built-in and not of ``module://some.backend`` format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
backend : str or None
|
||||
Name of backend, or None to use the default backend.
|
||||
|
||||
Returns
|
||||
-------
|
||||
backend : str
|
||||
The backend name.
|
||||
framework : str or None
|
||||
The GUI framework, which will be None for a backend that is non-interactive.
|
||||
"""
|
||||
if isinstance(backend, str):
|
||||
if not backend.startswith("module://"):
|
||||
backend = backend.lower()
|
||||
else: # Might be _auto_backend_sentinel or None
|
||||
# Use whatever is already running...
|
||||
from matplotlib import get_backend
|
||||
backend = get_backend()
|
||||
|
||||
# Is backend already known (built-in or dynamically loaded)?
|
||||
gui = (self._BUILTIN_BACKEND_TO_GUI_FRAMEWORK.get(backend) or
|
||||
self._backend_to_gui_framework.get(backend))
|
||||
|
||||
# Is backend "module://something"?
|
||||
if gui is None and isinstance(backend, str) and backend.startswith("module://"):
|
||||
gui = "unknown"
|
||||
|
||||
# Is backend a possible entry point?
|
||||
if gui is None and not self._loaded_entry_points:
|
||||
self._ensure_entry_points_loaded()
|
||||
gui = self._backend_to_gui_framework.get(backend)
|
||||
|
||||
# Backend known but not its gui framework.
|
||||
if gui == "unknown":
|
||||
gui = self._get_gui_framework_by_loading(backend)
|
||||
self._backend_to_gui_framework[backend] = gui
|
||||
|
||||
if gui is None:
|
||||
raise RuntimeError(f"'{backend}' is not a recognised backend name")
|
||||
|
||||
return backend, gui if gui != "headless" else None
|
||||
|
||||
def resolve_gui_or_backend(self, gui_or_backend):
|
||||
"""
|
||||
Return the backend and GUI framework for the specified string that may be
|
||||
either a GUI framework or a backend name, tested in that order.
|
||||
|
||||
This is for use with the IPython %matplotlib magic command which may be a GUI
|
||||
framework such as ``%matplotlib qt`` or a backend name such as
|
||||
``%matplotlib qtagg``.
|
||||
|
||||
This function only loads entry points if they have not already been loaded and
|
||||
the backend is not built-in and not of ``module://some.backend`` format.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
gui_or_backend : str or None
|
||||
Name of GUI framework or backend, or None to use the default backend.
|
||||
|
||||
Returns
|
||||
-------
|
||||
backend : str
|
||||
The backend name.
|
||||
framework : str or None
|
||||
The GUI framework, which will be None for a backend that is non-interactive.
|
||||
"""
|
||||
if not gui_or_backend.startswith("module://"):
|
||||
gui_or_backend = gui_or_backend.lower()
|
||||
|
||||
# First check if it is a gui loop name.
|
||||
backend = self.backend_for_gui_framework(gui_or_backend)
|
||||
if backend is not None:
|
||||
return backend, gui_or_backend if gui_or_backend != "headless" else None
|
||||
|
||||
# Then check if it is a backend name.
|
||||
try:
|
||||
return self.resolve_backend(gui_or_backend)
|
||||
except Exception: # KeyError ?
|
||||
raise RuntimeError(
|
||||
f"'{gui_or_backend}' is not a recognised GUI loop or backend name")
|
||||
|
||||
|
||||
# Singleton
|
||||
backend_registry = BackendRegistry()
|
||||
Loading…
Add table
Add a link
Reference in a new issue