You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			1580 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Python
		
	
			
		
		
	
	
			1580 lines
		
	
	
		
			54 KiB
		
	
	
	
		
			Python
		
	
"""
 | 
						|
An object-oriented plotting library.
 | 
						|
 | 
						|
A procedural interface is provided by the companion pyplot module,
 | 
						|
which may be imported directly, e.g.::
 | 
						|
 | 
						|
    import matplotlib.pyplot as plt
 | 
						|
 | 
						|
or using ipython::
 | 
						|
 | 
						|
    ipython
 | 
						|
 | 
						|
at your terminal, followed by::
 | 
						|
 | 
						|
    In [1]: %matplotlib
 | 
						|
    In [2]: import matplotlib.pyplot as plt
 | 
						|
 | 
						|
at the ipython shell prompt.
 | 
						|
 | 
						|
For the most part, direct use of the explicit object-oriented library is
 | 
						|
encouraged when programming; the implicit pyplot interface is primarily for
 | 
						|
working interactively. The exceptions to this suggestion are the pyplot
 | 
						|
functions `.pyplot.figure`, `.pyplot.subplot`, `.pyplot.subplots`, and
 | 
						|
`.pyplot.savefig`, which can greatly simplify scripting.  See
 | 
						|
:ref:`api_interfaces` for an explanation of the tradeoffs between the implicit
 | 
						|
and explicit interfaces.
 | 
						|
 | 
						|
Modules include:
 | 
						|
 | 
						|
:mod:`matplotlib.axes`
 | 
						|
    The `~.axes.Axes` class.  Most pyplot functions are wrappers for
 | 
						|
    `~.axes.Axes` methods.  The axes module is the highest level of OO
 | 
						|
    access to the library.
 | 
						|
 | 
						|
:mod:`matplotlib.figure`
 | 
						|
    The `.Figure` class.
 | 
						|
 | 
						|
:mod:`matplotlib.artist`
 | 
						|
    The `.Artist` base class for all classes that draw things.
 | 
						|
 | 
						|
:mod:`matplotlib.lines`
 | 
						|
    The `.Line2D` class for drawing lines and markers.
 | 
						|
 | 
						|
:mod:`matplotlib.patches`
 | 
						|
    Classes for drawing polygons.
 | 
						|
 | 
						|
:mod:`matplotlib.text`
 | 
						|
    The `.Text` and `.Annotation` classes.
 | 
						|
 | 
						|
:mod:`matplotlib.image`
 | 
						|
    The `.AxesImage` and `.FigureImage` classes.
 | 
						|
 | 
						|
:mod:`matplotlib.collections`
 | 
						|
    Classes for efficient drawing of groups of lines or polygons.
 | 
						|
 | 
						|
:mod:`matplotlib.colors`
 | 
						|
    Color specifications and making colormaps.
 | 
						|
 | 
						|
:mod:`matplotlib.cm`
 | 
						|
    Colormaps, and the `.ScalarMappable` mixin class for providing color
 | 
						|
    mapping functionality to other classes.
 | 
						|
 | 
						|
:mod:`matplotlib.ticker`
 | 
						|
    Calculation of tick mark locations and formatting of tick labels.
 | 
						|
 | 
						|
:mod:`matplotlib.backends`
 | 
						|
    A subpackage with modules for various GUI libraries and output formats.
 | 
						|
 | 
						|
The base matplotlib namespace includes:
 | 
						|
 | 
						|
`~matplotlib.rcParams`
 | 
						|
    Default configuration settings; their defaults may be overridden using
 | 
						|
    a :file:`matplotlibrc` file.
 | 
						|
 | 
						|
`~matplotlib.use`
 | 
						|
    Setting the Matplotlib backend.  This should be called before any
 | 
						|
    figure is created, because it is not possible to switch between
 | 
						|
    different GUI backends after that.
 | 
						|
 | 
						|
The following environment variables can be used to customize the behavior:
 | 
						|
 | 
						|
:envvar:`MPLBACKEND`
 | 
						|
    This optional variable can be set to choose the Matplotlib backend. See
 | 
						|
    :ref:`what-is-a-backend`.
 | 
						|
 | 
						|
:envvar:`MPLCONFIGDIR`
 | 
						|
    This is the directory used to store user customizations to
 | 
						|
    Matplotlib, as well as some caches to improve performance. If
 | 
						|
    :envvar:`MPLCONFIGDIR` is not defined, :file:`{HOME}/.config/matplotlib`
 | 
						|
    and :file:`{HOME}/.cache/matplotlib` are used on Linux, and
 | 
						|
    :file:`{HOME}/.matplotlib` on other platforms, if they are
 | 
						|
    writable. Otherwise, the Python standard library's `tempfile.gettempdir`
 | 
						|
    is used to find a base directory in which the :file:`matplotlib`
 | 
						|
    subdirectory is created.
 | 
						|
 | 
						|
Matplotlib was initially written by John D. Hunter (1968-2012) and is now
 | 
						|
developed and maintained by a host of others.
 | 
						|
 | 
						|
Occasionally the internal documentation (python docstrings) will refer
 | 
						|
to MATLAB®, a registered trademark of The MathWorks, Inc.
 | 
						|
 | 
						|
"""
 | 
						|
 | 
						|
__all__ = [
 | 
						|
    "__bibtex__",
 | 
						|
    "__version__",
 | 
						|
    "__version_info__",
 | 
						|
    "set_loglevel",
 | 
						|
    "ExecutableNotFoundError",
 | 
						|
    "get_configdir",
 | 
						|
    "get_cachedir",
 | 
						|
    "get_data_path",
 | 
						|
    "matplotlib_fname",
 | 
						|
    "MatplotlibDeprecationWarning",
 | 
						|
    "RcParams",
 | 
						|
    "rc_params",
 | 
						|
    "rc_params_from_file",
 | 
						|
    "rcParamsDefault",
 | 
						|
    "rcParams",
 | 
						|
    "rcParamsOrig",
 | 
						|
    "defaultParams",
 | 
						|
    "rc",
 | 
						|
    "rcdefaults",
 | 
						|
    "rc_file_defaults",
 | 
						|
    "rc_file",
 | 
						|
    "rc_context",
 | 
						|
    "use",
 | 
						|
    "get_backend",
 | 
						|
    "interactive",
 | 
						|
    "is_interactive",
 | 
						|
    "colormaps",
 | 
						|
    "multivar_colormaps",
 | 
						|
    "bivar_colormaps",
 | 
						|
    "color_sequences",
 | 
						|
]
 | 
						|
 | 
						|
 | 
						|
import atexit
 | 
						|
from collections import namedtuple
 | 
						|
from collections.abc import MutableMapping
 | 
						|
import contextlib
 | 
						|
import functools
 | 
						|
import importlib
 | 
						|
import inspect
 | 
						|
from inspect import Parameter
 | 
						|
import locale
 | 
						|
import logging
 | 
						|
import os
 | 
						|
from pathlib import Path
 | 
						|
import pprint
 | 
						|
import re
 | 
						|
import shutil
 | 
						|
import subprocess
 | 
						|
import sys
 | 
						|
import tempfile
 | 
						|
 | 
						|
from packaging.version import parse as parse_version
 | 
						|
 | 
						|
# cbook must import matplotlib only within function
 | 
						|
# definitions, so it is safe to import from it here.
 | 
						|
from . import _api, _version, cbook, _docstring, rcsetup
 | 
						|
from matplotlib._api import MatplotlibDeprecationWarning
 | 
						|
from matplotlib.rcsetup import cycler  # noqa: F401
 | 
						|
 | 
						|
 | 
						|
_log = logging.getLogger(__name__)
 | 
						|
 | 
						|
__bibtex__ = r"""@Article{Hunter:2007,
 | 
						|
  Author    = {Hunter, J. D.},
 | 
						|
  Title     = {Matplotlib: A 2D graphics environment},
 | 
						|
  Journal   = {Computing in Science \& Engineering},
 | 
						|
  Volume    = {9},
 | 
						|
  Number    = {3},
 | 
						|
  Pages     = {90--95},
 | 
						|
  abstract  = {Matplotlib is a 2D graphics package used for Python
 | 
						|
  for application development, interactive scripting, and
 | 
						|
  publication-quality image generation across user
 | 
						|
  interfaces and operating systems.},
 | 
						|
  publisher = {IEEE COMPUTER SOC},
 | 
						|
  year      = 2007
 | 
						|
}"""
 | 
						|
 | 
						|
# modelled after sys.version_info
 | 
						|
_VersionInfo = namedtuple('_VersionInfo',
 | 
						|
                          'major, minor, micro, releaselevel, serial')
 | 
						|
 | 
						|
 | 
						|
def _parse_to_version_info(version_str):
 | 
						|
    """
 | 
						|
    Parse a version string to a namedtuple analogous to sys.version_info.
 | 
						|
 | 
						|
    See:
 | 
						|
    https://packaging.pypa.io/en/latest/version.html#packaging.version.parse
 | 
						|
    https://docs.python.org/3/library/sys.html#sys.version_info
 | 
						|
    """
 | 
						|
    v = parse_version(version_str)
 | 
						|
    if v.pre is None and v.post is None and v.dev is None:
 | 
						|
        return _VersionInfo(v.major, v.minor, v.micro, 'final', 0)
 | 
						|
    elif v.dev is not None:
 | 
						|
        return _VersionInfo(v.major, v.minor, v.micro, 'alpha', v.dev)
 | 
						|
    elif v.pre is not None:
 | 
						|
        releaselevel = {
 | 
						|
            'a': 'alpha',
 | 
						|
            'b': 'beta',
 | 
						|
            'rc': 'candidate'}.get(v.pre[0], 'alpha')
 | 
						|
        return _VersionInfo(v.major, v.minor, v.micro, releaselevel, v.pre[1])
 | 
						|
    else:
 | 
						|
        # fallback for v.post: guess-next-dev scheme from setuptools_scm
 | 
						|
        return _VersionInfo(v.major, v.minor, v.micro + 1, 'alpha', v.post)
 | 
						|
 | 
						|
 | 
						|
def _get_version():
 | 
						|
    """Return the version string used for __version__."""
 | 
						|
    # Only shell out to a git subprocess if really needed, i.e. when we are in
 | 
						|
    # a matplotlib git repo but not in a shallow clone, such as those used by
 | 
						|
    # CI, as the latter would trigger a warning from setuptools_scm.
 | 
						|
    root = Path(__file__).resolve().parents[2]
 | 
						|
    if ((root / ".matplotlib-repo").exists()
 | 
						|
            and (root / ".git").exists()
 | 
						|
            and not (root / ".git/shallow").exists()):
 | 
						|
        try:
 | 
						|
            import setuptools_scm
 | 
						|
        except ImportError:
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            return setuptools_scm.get_version(
 | 
						|
                root=root,
 | 
						|
                dist_name="matplotlib",
 | 
						|
                version_scheme="release-branch-semver",
 | 
						|
                local_scheme="node-and-date",
 | 
						|
                fallback_version=_version.version,
 | 
						|
            )
 | 
						|
    # Get the version from the _version.py file if not in repo or setuptools_scm is
 | 
						|
    # unavailable.
 | 
						|
    return _version.version
 | 
						|
 | 
						|
 | 
						|
@_api.caching_module_getattr
 | 
						|
class __getattr__:
 | 
						|
    __version__ = property(lambda self: _get_version())
 | 
						|
    __version_info__ = property(
 | 
						|
        lambda self: _parse_to_version_info(self.__version__))
 | 
						|
 | 
						|
 | 
						|
def _check_versions():
 | 
						|
 | 
						|
    # Quickfix to ensure Microsoft Visual C++ redistributable
 | 
						|
    # DLLs are loaded before importing kiwisolver
 | 
						|
    from . import ft2font  # noqa: F401
 | 
						|
 | 
						|
    for modname, minver in [
 | 
						|
            ("cycler", "0.10"),
 | 
						|
            ("dateutil", "2.7"),
 | 
						|
            ("kiwisolver", "1.3.1"),
 | 
						|
            ("numpy", "1.23"),
 | 
						|
            ("pyparsing", "2.3.1"),
 | 
						|
    ]:
 | 
						|
        module = importlib.import_module(modname)
 | 
						|
        if parse_version(module.__version__) < parse_version(minver):
 | 
						|
            raise ImportError(f"Matplotlib requires {modname}>={minver}; "
 | 
						|
                              f"you have {module.__version__}")
 | 
						|
 | 
						|
 | 
						|
_check_versions()
 | 
						|
 | 
						|
 | 
						|
# The decorator ensures this always returns the same handler (and it is only
 | 
						|
# attached once).
 | 
						|
@functools.cache
 | 
						|
def _ensure_handler():
 | 
						|
    """
 | 
						|
    The first time this function is called, attach a `StreamHandler` using the
 | 
						|
    same format as `logging.basicConfig` to the Matplotlib root logger.
 | 
						|
 | 
						|
    Return this handler every time this function is called.
 | 
						|
    """
 | 
						|
    handler = logging.StreamHandler()
 | 
						|
    handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
 | 
						|
    _log.addHandler(handler)
 | 
						|
    return handler
 | 
						|
 | 
						|
 | 
						|
def set_loglevel(level):
 | 
						|
    """
 | 
						|
    Configure Matplotlib's logging levels.
 | 
						|
 | 
						|
    Matplotlib uses the standard library `logging` framework under the root
 | 
						|
    logger 'matplotlib'.  This is a helper function to:
 | 
						|
 | 
						|
    - set Matplotlib's root logger level
 | 
						|
    - set the root logger handler's level, creating the handler
 | 
						|
      if it does not exist yet
 | 
						|
 | 
						|
    Typically, one should call ``set_loglevel("info")`` or
 | 
						|
    ``set_loglevel("debug")`` to get additional debugging information.
 | 
						|
 | 
						|
    Users or applications that are installing their own logging handlers
 | 
						|
    may want to directly manipulate ``logging.getLogger('matplotlib')`` rather
 | 
						|
    than use this function.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    level : {"notset", "debug", "info", "warning", "error", "critical"}
 | 
						|
        The log level of the handler.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    The first time this function is called, an additional handler is attached
 | 
						|
    to Matplotlib's root handler; this handler is reused every time and this
 | 
						|
    function simply manipulates the logger and handler's level.
 | 
						|
 | 
						|
    """
 | 
						|
    _log.setLevel(level.upper())
 | 
						|
    _ensure_handler().setLevel(level.upper())
 | 
						|
 | 
						|
 | 
						|
def _logged_cached(fmt, func=None):
 | 
						|
    """
 | 
						|
    Decorator that logs a function's return value, and memoizes that value.
 | 
						|
 | 
						|
    After ::
 | 
						|
 | 
						|
        @_logged_cached(fmt)
 | 
						|
        def func(): ...
 | 
						|
 | 
						|
    the first call to *func* will log its return value at the DEBUG level using
 | 
						|
    %-format string *fmt*, and memoize it; later calls to *func* will directly
 | 
						|
    return that value.
 | 
						|
    """
 | 
						|
    if func is None:  # Return the actual decorator.
 | 
						|
        return functools.partial(_logged_cached, fmt)
 | 
						|
 | 
						|
    called = False
 | 
						|
    ret = None
 | 
						|
 | 
						|
    @functools.wraps(func)
 | 
						|
    def wrapper(**kwargs):
 | 
						|
        nonlocal called, ret
 | 
						|
        if not called:
 | 
						|
            ret = func(**kwargs)
 | 
						|
            called = True
 | 
						|
            _log.debug(fmt, ret)
 | 
						|
        return ret
 | 
						|
 | 
						|
    return wrapper
 | 
						|
 | 
						|
 | 
						|
_ExecInfo = namedtuple("_ExecInfo", "executable raw_version version")
 | 
						|
 | 
						|
 | 
						|
class ExecutableNotFoundError(FileNotFoundError):
 | 
						|
    """
 | 
						|
    Error raised when an executable that Matplotlib optionally
 | 
						|
    depends on can't be found.
 | 
						|
    """
 | 
						|
    pass
 | 
						|
 | 
						|
 | 
						|
@functools.cache
 | 
						|
def _get_executable_info(name):
 | 
						|
    """
 | 
						|
    Get the version of some executable that Matplotlib optionally depends on.
 | 
						|
 | 
						|
    .. warning::
 | 
						|
       The list of executables that this function supports is set according to
 | 
						|
       Matplotlib's internal needs, and may change without notice.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    name : str
 | 
						|
        The executable to query.  The following values are currently supported:
 | 
						|
        "dvipng", "gs", "inkscape", "magick", "pdftocairo", "pdftops".  This
 | 
						|
        list is subject to change without notice.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    tuple
 | 
						|
        A namedtuple with fields ``executable`` (`str`) and ``version``
 | 
						|
        (`packaging.Version`, or ``None`` if the version cannot be determined).
 | 
						|
 | 
						|
    Raises
 | 
						|
    ------
 | 
						|
    ExecutableNotFoundError
 | 
						|
        If the executable is not found or older than the oldest version
 | 
						|
        supported by Matplotlib.  For debugging purposes, it is also
 | 
						|
        possible to "hide" an executable from Matplotlib by adding it to the
 | 
						|
        :envvar:`_MPLHIDEEXECUTABLES` environment variable (a comma-separated
 | 
						|
        list), which must be set prior to any calls to this function.
 | 
						|
    ValueError
 | 
						|
        If the executable is not one that we know how to query.
 | 
						|
    """
 | 
						|
 | 
						|
    def impl(args, regex, min_ver=None, ignore_exit_code=False):
 | 
						|
        # Execute the subprocess specified by args; capture stdout and stderr.
 | 
						|
        # Search for a regex match in the output; if the match succeeds, the
 | 
						|
        # first group of the match is the version.
 | 
						|
        # Return an _ExecInfo if the executable exists, and has a version of
 | 
						|
        # at least min_ver (if set); else, raise ExecutableNotFoundError.
 | 
						|
        try:
 | 
						|
            output = subprocess.check_output(
 | 
						|
                args, stderr=subprocess.STDOUT,
 | 
						|
                text=True, errors="replace", timeout=30)
 | 
						|
        except subprocess.CalledProcessError as _cpe:
 | 
						|
            if ignore_exit_code:
 | 
						|
                output = _cpe.output
 | 
						|
            else:
 | 
						|
                raise ExecutableNotFoundError(str(_cpe)) from _cpe
 | 
						|
        except subprocess.TimeoutExpired as _te:
 | 
						|
            msg = f"Timed out running {cbook._pformat_subprocess(args)}"
 | 
						|
            raise ExecutableNotFoundError(msg) from _te
 | 
						|
        except OSError as _ose:
 | 
						|
            raise ExecutableNotFoundError(str(_ose)) from _ose
 | 
						|
        match = re.search(regex, output)
 | 
						|
        if match:
 | 
						|
            raw_version = match.group(1)
 | 
						|
            version = parse_version(raw_version)
 | 
						|
            if min_ver is not None and version < parse_version(min_ver):
 | 
						|
                raise ExecutableNotFoundError(
 | 
						|
                    f"You have {args[0]} version {version} but the minimum "
 | 
						|
                    f"version supported by Matplotlib is {min_ver}")
 | 
						|
            return _ExecInfo(args[0], raw_version, version)
 | 
						|
        else:
 | 
						|
            raise ExecutableNotFoundError(
 | 
						|
                f"Failed to determine the version of {args[0]} from "
 | 
						|
                f"{' '.join(args)}, which output {output}")
 | 
						|
 | 
						|
    if name in os.environ.get("_MPLHIDEEXECUTABLES", "").split(","):
 | 
						|
        raise ExecutableNotFoundError(f"{name} was hidden")
 | 
						|
 | 
						|
    if name == "dvipng":
 | 
						|
        return impl(["dvipng", "-version"], "(?m)^dvipng(?: .*)? (.+)", "1.6")
 | 
						|
    elif name == "gs":
 | 
						|
        execs = (["gswin32c", "gswin64c", "mgs", "gs"]  # "mgs" for miktex.
 | 
						|
                 if sys.platform == "win32" else
 | 
						|
                 ["gs"])
 | 
						|
        for e in execs:
 | 
						|
            try:
 | 
						|
                return impl([e, "--version"], "(.*)", "9")
 | 
						|
            except ExecutableNotFoundError:
 | 
						|
                pass
 | 
						|
        message = "Failed to find a Ghostscript installation"
 | 
						|
        raise ExecutableNotFoundError(message)
 | 
						|
    elif name == "inkscape":
 | 
						|
        try:
 | 
						|
            # Try headless option first (needed for Inkscape version < 1.0):
 | 
						|
            return impl(["inkscape", "--without-gui", "-V"],
 | 
						|
                        "Inkscape ([^ ]*)")
 | 
						|
        except ExecutableNotFoundError:
 | 
						|
            pass  # Suppress exception chaining.
 | 
						|
        # If --without-gui is not accepted, we may be using Inkscape >= 1.0 so
 | 
						|
        # try without it:
 | 
						|
        return impl(["inkscape", "-V"], "Inkscape ([^ ]*)")
 | 
						|
    elif name == "magick":
 | 
						|
        if sys.platform == "win32":
 | 
						|
            # Check the registry to avoid confusing ImageMagick's convert with
 | 
						|
            # Windows's builtin convert.exe.
 | 
						|
            import winreg
 | 
						|
            binpath = ""
 | 
						|
            for flag in [0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY]:
 | 
						|
                try:
 | 
						|
                    with winreg.OpenKeyEx(
 | 
						|
                            winreg.HKEY_LOCAL_MACHINE,
 | 
						|
                            r"Software\Imagemagick\Current",
 | 
						|
                            0, winreg.KEY_QUERY_VALUE | flag) as hkey:
 | 
						|
                        binpath = winreg.QueryValueEx(hkey, "BinPath")[0]
 | 
						|
                except OSError:
 | 
						|
                    pass
 | 
						|
            path = None
 | 
						|
            if binpath:
 | 
						|
                for name in ["convert.exe", "magick.exe"]:
 | 
						|
                    candidate = Path(binpath, name)
 | 
						|
                    if candidate.exists():
 | 
						|
                        path = str(candidate)
 | 
						|
                        break
 | 
						|
            if path is None:
 | 
						|
                raise ExecutableNotFoundError(
 | 
						|
                    "Failed to find an ImageMagick installation")
 | 
						|
        else:
 | 
						|
            path = "convert"
 | 
						|
        info = impl([path, "--version"], r"^Version: ImageMagick (\S*)")
 | 
						|
        if info.raw_version == "7.0.10-34":
 | 
						|
            # https://github.com/ImageMagick/ImageMagick/issues/2720
 | 
						|
            raise ExecutableNotFoundError(
 | 
						|
                f"You have ImageMagick {info.version}, which is unsupported")
 | 
						|
        return info
 | 
						|
    elif name == "pdftocairo":
 | 
						|
        return impl(["pdftocairo", "-v"], "pdftocairo version (.*)")
 | 
						|
    elif name == "pdftops":
 | 
						|
        info = impl(["pdftops", "-v"], "^pdftops version (.*)",
 | 
						|
                    ignore_exit_code=True)
 | 
						|
        if info and not (
 | 
						|
                3 <= info.version.major or
 | 
						|
                # poppler version numbers.
 | 
						|
                parse_version("0.9") <= info.version < parse_version("1.0")):
 | 
						|
            raise ExecutableNotFoundError(
 | 
						|
                f"You have pdftops version {info.version} but the minimum "
 | 
						|
                f"version supported by Matplotlib is 3.0")
 | 
						|
        return info
 | 
						|
    else:
 | 
						|
        raise ValueError(f"Unknown executable: {name!r}")
 | 
						|
 | 
						|
 | 
						|
def _get_xdg_config_dir():
 | 
						|
    """
 | 
						|
    Return the XDG configuration directory, according to the XDG base
 | 
						|
    directory spec:
 | 
						|
 | 
						|
    https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
 | 
						|
    """
 | 
						|
    return os.environ.get('XDG_CONFIG_HOME') or str(Path.home() / ".config")
 | 
						|
 | 
						|
 | 
						|
def _get_xdg_cache_dir():
 | 
						|
    """
 | 
						|
    Return the XDG cache directory, according to the XDG base directory spec:
 | 
						|
 | 
						|
    https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
 | 
						|
    """
 | 
						|
    return os.environ.get('XDG_CACHE_HOME') or str(Path.home() / ".cache")
 | 
						|
 | 
						|
 | 
						|
def _get_config_or_cache_dir(xdg_base_getter):
 | 
						|
    configdir = os.environ.get('MPLCONFIGDIR')
 | 
						|
    if configdir:
 | 
						|
        configdir = Path(configdir)
 | 
						|
    elif sys.platform.startswith(('linux', 'freebsd')):
 | 
						|
        # Only call _xdg_base_getter here so that MPLCONFIGDIR is tried first,
 | 
						|
        # as _xdg_base_getter can throw.
 | 
						|
        configdir = Path(xdg_base_getter(), "matplotlib")
 | 
						|
    else:
 | 
						|
        configdir = Path.home() / ".matplotlib"
 | 
						|
    # Resolve the path to handle potential issues with inaccessible symlinks.
 | 
						|
    configdir = configdir.resolve()
 | 
						|
    try:
 | 
						|
        configdir.mkdir(parents=True, exist_ok=True)
 | 
						|
    except OSError as exc:
 | 
						|
        _log.warning("mkdir -p failed for path %s: %s", configdir, exc)
 | 
						|
    else:
 | 
						|
        if os.access(str(configdir), os.W_OK) and configdir.is_dir():
 | 
						|
            return str(configdir)
 | 
						|
        _log.warning("%s is not a writable directory", configdir)
 | 
						|
    # If the config or cache directory cannot be created or is not a writable
 | 
						|
    # directory, create a temporary one.
 | 
						|
    try:
 | 
						|
        tmpdir = tempfile.mkdtemp(prefix="matplotlib-")
 | 
						|
    except OSError as exc:
 | 
						|
        raise OSError(
 | 
						|
            f"Matplotlib requires access to a writable cache directory, but there "
 | 
						|
            f"was an issue with the default path ({configdir}), and a temporary "
 | 
						|
            f"directory could not be created; set the MPLCONFIGDIR environment "
 | 
						|
            f"variable to a writable directory") from exc
 | 
						|
    os.environ["MPLCONFIGDIR"] = tmpdir
 | 
						|
    atexit.register(shutil.rmtree, tmpdir)
 | 
						|
    _log.warning(
 | 
						|
        "Matplotlib created a temporary cache directory at %s because there was "
 | 
						|
        "an issue with the default path (%s); it is highly recommended to set the "
 | 
						|
        "MPLCONFIGDIR environment variable to a writable directory, in particular to "
 | 
						|
        "speed up the import of Matplotlib and to better support multiprocessing.",
 | 
						|
        tmpdir, configdir)
 | 
						|
    return tmpdir
 | 
						|
 | 
						|
 | 
						|
@_logged_cached('CONFIGDIR=%s')
 | 
						|
def get_configdir():
 | 
						|
    """
 | 
						|
    Return the string path of the configuration directory.
 | 
						|
 | 
						|
    The directory is chosen as follows:
 | 
						|
 | 
						|
    1. If the MPLCONFIGDIR environment variable is supplied, choose that.
 | 
						|
    2. On Linux, follow the XDG specification and look first in
 | 
						|
       ``$XDG_CONFIG_HOME``, if defined, or ``$HOME/.config``.  On other
 | 
						|
       platforms, choose ``$HOME/.matplotlib``.
 | 
						|
    3. If the chosen directory exists and is writable, use that as the
 | 
						|
       configuration directory.
 | 
						|
    4. Else, create a temporary directory, and use it as the configuration
 | 
						|
       directory.
 | 
						|
    """
 | 
						|
    return _get_config_or_cache_dir(_get_xdg_config_dir)
 | 
						|
 | 
						|
 | 
						|
@_logged_cached('CACHEDIR=%s')
 | 
						|
def get_cachedir():
 | 
						|
    """
 | 
						|
    Return the string path of the cache directory.
 | 
						|
 | 
						|
    The procedure used to find the directory is the same as for
 | 
						|
    `get_configdir`, except using ``$XDG_CACHE_HOME``/``$HOME/.cache`` instead.
 | 
						|
    """
 | 
						|
    return _get_config_or_cache_dir(_get_xdg_cache_dir)
 | 
						|
 | 
						|
 | 
						|
@_logged_cached('matplotlib data path: %s')
 | 
						|
def get_data_path():
 | 
						|
    """Return the path to Matplotlib data."""
 | 
						|
    return str(Path(__file__).with_name("mpl-data"))
 | 
						|
 | 
						|
 | 
						|
def matplotlib_fname():
 | 
						|
    """
 | 
						|
    Get the location of the config file.
 | 
						|
 | 
						|
    The file location is determined in the following order
 | 
						|
 | 
						|
    - ``$PWD/matplotlibrc``
 | 
						|
    - ``$MATPLOTLIBRC`` if it is not a directory
 | 
						|
    - ``$MATPLOTLIBRC/matplotlibrc``
 | 
						|
    - ``$MPLCONFIGDIR/matplotlibrc``
 | 
						|
    - On Linux,
 | 
						|
        - ``$XDG_CONFIG_HOME/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
 | 
						|
          is defined)
 | 
						|
        - or ``$HOME/.config/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
 | 
						|
          is not defined)
 | 
						|
    - On other platforms,
 | 
						|
      - ``$HOME/.matplotlib/matplotlibrc`` if ``$HOME`` is defined
 | 
						|
    - Lastly, it looks in ``$MATPLOTLIBDATA/matplotlibrc``, which should always
 | 
						|
      exist.
 | 
						|
    """
 | 
						|
 | 
						|
    def gen_candidates():
 | 
						|
        # rely on down-stream code to make absolute.  This protects us
 | 
						|
        # from having to directly get the current working directory
 | 
						|
        # which can fail if the user has ended up with a cwd that is
 | 
						|
        # non-existent.
 | 
						|
        yield 'matplotlibrc'
 | 
						|
        try:
 | 
						|
            matplotlibrc = os.environ['MATPLOTLIBRC']
 | 
						|
        except KeyError:
 | 
						|
            pass
 | 
						|
        else:
 | 
						|
            yield matplotlibrc
 | 
						|
            yield os.path.join(matplotlibrc, 'matplotlibrc')
 | 
						|
        yield os.path.join(get_configdir(), 'matplotlibrc')
 | 
						|
        yield os.path.join(get_data_path(), 'matplotlibrc')
 | 
						|
 | 
						|
    for fname in gen_candidates():
 | 
						|
        if os.path.exists(fname) and not os.path.isdir(fname):
 | 
						|
            return fname
 | 
						|
 | 
						|
    raise RuntimeError("Could not find matplotlibrc file; your Matplotlib "
 | 
						|
                       "install is broken")
 | 
						|
 | 
						|
 | 
						|
# rcParams deprecated and automatically mapped to another key.
 | 
						|
# Values are tuples of (version, new_name, f_old2new, f_new2old).
 | 
						|
_deprecated_map = {}
 | 
						|
# rcParams deprecated; some can manually be mapped to another key.
 | 
						|
# Values are tuples of (version, new_name_or_None).
 | 
						|
_deprecated_ignore_map = {}
 | 
						|
# rcParams deprecated; can use None to suppress warnings; remain actually
 | 
						|
# listed in the rcParams.
 | 
						|
# Values are tuples of (version,)
 | 
						|
_deprecated_remain_as_none = {}
 | 
						|
 | 
						|
 | 
						|
@_docstring.Substitution(
 | 
						|
    "\n".join(map("- {}".format, sorted(rcsetup._validators, key=str.lower)))
 | 
						|
)
 | 
						|
class RcParams(MutableMapping, dict):
 | 
						|
    """
 | 
						|
    A dict-like key-value store for config parameters, including validation.
 | 
						|
 | 
						|
    Validating functions are defined and associated with rc parameters in
 | 
						|
    :mod:`matplotlib.rcsetup`.
 | 
						|
 | 
						|
    The list of rcParams is:
 | 
						|
 | 
						|
    %s
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    :ref:`customizing-with-matplotlibrc-files`
 | 
						|
    """
 | 
						|
 | 
						|
    validate = rcsetup._validators
 | 
						|
 | 
						|
    # validate values on the way in
 | 
						|
    def __init__(self, *args, **kwargs):
 | 
						|
        self.update(*args, **kwargs)
 | 
						|
 | 
						|
    def _set(self, key, val):
 | 
						|
        """
 | 
						|
        Directly write data bypassing deprecation and validation logic.
 | 
						|
 | 
						|
        Notes
 | 
						|
        -----
 | 
						|
        As end user or downstream library you almost always should use
 | 
						|
        ``rcParams[key] = val`` and not ``_set()``.
 | 
						|
 | 
						|
        There are only very few special cases that need direct data access.
 | 
						|
        These cases previously used ``dict.__setitem__(rcParams, key, val)``,
 | 
						|
        which is now deprecated and replaced by ``rcParams._set(key, val)``.
 | 
						|
 | 
						|
        Even though private, we guarantee API stability for ``rcParams._set``,
 | 
						|
        i.e. it is subject to Matplotlib's API and deprecation policy.
 | 
						|
 | 
						|
        :meta public:
 | 
						|
        """
 | 
						|
        dict.__setitem__(self, key, val)
 | 
						|
 | 
						|
    def _get(self, key):
 | 
						|
        """
 | 
						|
        Directly read data bypassing deprecation, backend and validation
 | 
						|
        logic.
 | 
						|
 | 
						|
        Notes
 | 
						|
        -----
 | 
						|
        As end user or downstream library you almost always should use
 | 
						|
        ``val = rcParams[key]`` and not ``_get()``.
 | 
						|
 | 
						|
        There are only very few special cases that need direct data access.
 | 
						|
        These cases previously used ``dict.__getitem__(rcParams, key, val)``,
 | 
						|
        which is now deprecated and replaced by ``rcParams._get(key)``.
 | 
						|
 | 
						|
        Even though private, we guarantee API stability for ``rcParams._get``,
 | 
						|
        i.e. it is subject to Matplotlib's API and deprecation policy.
 | 
						|
 | 
						|
        :meta public:
 | 
						|
        """
 | 
						|
        return dict.__getitem__(self, key)
 | 
						|
 | 
						|
    def _update_raw(self, other_params):
 | 
						|
        """
 | 
						|
        Directly update the data from *other_params*, bypassing deprecation,
 | 
						|
        backend and validation logic on both sides.
 | 
						|
 | 
						|
        This ``rcParams._update_raw(params)`` replaces the previous pattern
 | 
						|
        ``dict.update(rcParams, params)``.
 | 
						|
 | 
						|
        Parameters
 | 
						|
        ----------
 | 
						|
        other_params : dict or `.RcParams`
 | 
						|
            The input mapping from which to update.
 | 
						|
        """
 | 
						|
        if isinstance(other_params, RcParams):
 | 
						|
            other_params = dict.items(other_params)
 | 
						|
        dict.update(self, other_params)
 | 
						|
 | 
						|
    def _ensure_has_backend(self):
 | 
						|
        """
 | 
						|
        Ensure that a "backend" entry exists.
 | 
						|
 | 
						|
        Normally, the default matplotlibrc file contains *no* entry for "backend" (the
 | 
						|
        corresponding line starts with ##, not #; we fill in _auto_backend_sentinel
 | 
						|
        in that case.  However, packagers can set a different default backend
 | 
						|
        (resulting in a normal `#backend: foo` line) in which case we should *not*
 | 
						|
        fill in _auto_backend_sentinel.
 | 
						|
        """
 | 
						|
        dict.setdefault(self, "backend", rcsetup._auto_backend_sentinel)
 | 
						|
 | 
						|
    def __setitem__(self, key, val):
 | 
						|
        try:
 | 
						|
            if key in _deprecated_map:
 | 
						|
                version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
 | 
						|
                _api.warn_deprecated(
 | 
						|
                    version, name=key, obj_type="rcparam", alternative=alt_key)
 | 
						|
                key = alt_key
 | 
						|
                val = alt_val(val)
 | 
						|
            elif key in _deprecated_remain_as_none and val is not None:
 | 
						|
                version, = _deprecated_remain_as_none[key]
 | 
						|
                _api.warn_deprecated(version, name=key, obj_type="rcparam")
 | 
						|
            elif key in _deprecated_ignore_map:
 | 
						|
                version, alt_key = _deprecated_ignore_map[key]
 | 
						|
                _api.warn_deprecated(
 | 
						|
                    version, name=key, obj_type="rcparam", alternative=alt_key)
 | 
						|
                return
 | 
						|
            elif key == 'backend':
 | 
						|
                if val is rcsetup._auto_backend_sentinel:
 | 
						|
                    if 'backend' in self:
 | 
						|
                        return
 | 
						|
            try:
 | 
						|
                cval = self.validate[key](val)
 | 
						|
            except ValueError as ve:
 | 
						|
                raise ValueError(f"Key {key}: {ve}") from None
 | 
						|
            self._set(key, cval)
 | 
						|
        except KeyError as err:
 | 
						|
            raise KeyError(
 | 
						|
                f"{key} is not a valid rc parameter (see rcParams.keys() for "
 | 
						|
                f"a list of valid parameters)") from err
 | 
						|
 | 
						|
    def __getitem__(self, key):
 | 
						|
        if key in _deprecated_map:
 | 
						|
            version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
 | 
						|
            _api.warn_deprecated(
 | 
						|
                version, name=key, obj_type="rcparam", alternative=alt_key)
 | 
						|
            return inverse_alt(self._get(alt_key))
 | 
						|
 | 
						|
        elif key in _deprecated_ignore_map:
 | 
						|
            version, alt_key = _deprecated_ignore_map[key]
 | 
						|
            _api.warn_deprecated(
 | 
						|
                version, name=key, obj_type="rcparam", alternative=alt_key)
 | 
						|
            return self._get(alt_key) if alt_key else None
 | 
						|
 | 
						|
        # In theory, this should only ever be used after the global rcParams
 | 
						|
        # has been set up, but better be safe e.g. in presence of breakpoints.
 | 
						|
        elif key == "backend" and self is globals().get("rcParams"):
 | 
						|
            val = self._get(key)
 | 
						|
            if val is rcsetup._auto_backend_sentinel:
 | 
						|
                from matplotlib import pyplot as plt
 | 
						|
                plt.switch_backend(rcsetup._auto_backend_sentinel)
 | 
						|
 | 
						|
        return self._get(key)
 | 
						|
 | 
						|
    def _get_backend_or_none(self):
 | 
						|
        """Get the requested backend, if any, without triggering resolution."""
 | 
						|
        backend = self._get("backend")
 | 
						|
        return None if backend is rcsetup._auto_backend_sentinel else backend
 | 
						|
 | 
						|
    def __repr__(self):
 | 
						|
        class_name = self.__class__.__name__
 | 
						|
        indent = len(class_name) + 1
 | 
						|
        with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
            repr_split = pprint.pformat(dict(self), indent=1,
 | 
						|
                                        width=80 - indent).split('\n')
 | 
						|
        repr_indented = ('\n' + ' ' * indent).join(repr_split)
 | 
						|
        return f'{class_name}({repr_indented})'
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items())))
 | 
						|
 | 
						|
    def __iter__(self):
 | 
						|
        """Yield sorted list of keys."""
 | 
						|
        with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
            yield from sorted(dict.__iter__(self))
 | 
						|
 | 
						|
    def __len__(self):
 | 
						|
        return dict.__len__(self)
 | 
						|
 | 
						|
    def find_all(self, pattern):
 | 
						|
        """
 | 
						|
        Return the subset of this RcParams dictionary whose keys match,
 | 
						|
        using :func:`re.search`, the given ``pattern``.
 | 
						|
 | 
						|
        .. note::
 | 
						|
 | 
						|
            Changes to the returned dictionary are *not* propagated to
 | 
						|
            the parent RcParams dictionary.
 | 
						|
 | 
						|
        """
 | 
						|
        pattern_re = re.compile(pattern)
 | 
						|
        return RcParams((key, value)
 | 
						|
                        for key, value in self.items()
 | 
						|
                        if pattern_re.search(key))
 | 
						|
 | 
						|
    def copy(self):
 | 
						|
        """Copy this RcParams instance."""
 | 
						|
        rccopy = RcParams()
 | 
						|
        for k in self:  # Skip deprecations and revalidation.
 | 
						|
            rccopy._set(k, self._get(k))
 | 
						|
        return rccopy
 | 
						|
 | 
						|
 | 
						|
def rc_params(fail_on_error=False):
 | 
						|
    """Construct a `RcParams` instance from the default Matplotlib rc file."""
 | 
						|
    return rc_params_from_file(matplotlib_fname(), fail_on_error)
 | 
						|
 | 
						|
 | 
						|
@functools.cache
 | 
						|
def _get_ssl_context():
 | 
						|
    try:
 | 
						|
        import certifi
 | 
						|
    except ImportError:
 | 
						|
        _log.debug("Could not import certifi.")
 | 
						|
        return None
 | 
						|
    import ssl
 | 
						|
    return ssl.create_default_context(cafile=certifi.where())
 | 
						|
 | 
						|
 | 
						|
@contextlib.contextmanager
 | 
						|
def _open_file_or_url(fname):
 | 
						|
    if (isinstance(fname, str)
 | 
						|
            and fname.startswith(('http://', 'https://', 'ftp://', 'file:'))):
 | 
						|
        import urllib.request
 | 
						|
        ssl_ctx = _get_ssl_context()
 | 
						|
        if ssl_ctx is None:
 | 
						|
            _log.debug(
 | 
						|
                "Could not get certifi ssl context, https may not work."
 | 
						|
            )
 | 
						|
        with urllib.request.urlopen(fname, context=ssl_ctx) as f:
 | 
						|
            yield (line.decode('utf-8') for line in f)
 | 
						|
    else:
 | 
						|
        fname = os.path.expanduser(fname)
 | 
						|
        with open(fname, encoding='utf-8') as f:
 | 
						|
            yield f
 | 
						|
 | 
						|
 | 
						|
def _rc_params_in_file(fname, transform=lambda x: x, fail_on_error=False):
 | 
						|
    """
 | 
						|
    Construct a `RcParams` instance from file *fname*.
 | 
						|
 | 
						|
    Unlike `rc_params_from_file`, the configuration class only contains the
 | 
						|
    parameters specified in the file (i.e. default values are not filled in).
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    fname : path-like
 | 
						|
        The loaded file.
 | 
						|
    transform : callable, default: the identity function
 | 
						|
        A function called on each individual line of the file to transform it,
 | 
						|
        before further parsing.
 | 
						|
    fail_on_error : bool, default: False
 | 
						|
        Whether invalid entries should result in an exception or a warning.
 | 
						|
    """
 | 
						|
    import matplotlib as mpl
 | 
						|
    rc_temp = {}
 | 
						|
    with _open_file_or_url(fname) as fd:
 | 
						|
        try:
 | 
						|
            for line_no, line in enumerate(fd, 1):
 | 
						|
                line = transform(line)
 | 
						|
                strippedline = cbook._strip_comment(line)
 | 
						|
                if not strippedline:
 | 
						|
                    continue
 | 
						|
                tup = strippedline.split(':', 1)
 | 
						|
                if len(tup) != 2:
 | 
						|
                    _log.warning('Missing colon in file %r, line %d (%r)',
 | 
						|
                                 fname, line_no, line.rstrip('\n'))
 | 
						|
                    continue
 | 
						|
                key, val = tup
 | 
						|
                key = key.strip()
 | 
						|
                val = val.strip()
 | 
						|
                if val.startswith('"') and val.endswith('"'):
 | 
						|
                    val = val[1:-1]  # strip double quotes
 | 
						|
                if key in rc_temp:
 | 
						|
                    _log.warning('Duplicate key in file %r, line %d (%r)',
 | 
						|
                                 fname, line_no, line.rstrip('\n'))
 | 
						|
                rc_temp[key] = (val, line, line_no)
 | 
						|
        except UnicodeDecodeError:
 | 
						|
            _log.warning('Cannot decode configuration file %r as utf-8.',
 | 
						|
                         fname)
 | 
						|
            raise
 | 
						|
 | 
						|
    config = RcParams()
 | 
						|
 | 
						|
    for key, (val, line, line_no) in rc_temp.items():
 | 
						|
        if key in rcsetup._validators:
 | 
						|
            if fail_on_error:
 | 
						|
                config[key] = val  # try to convert to proper type or raise
 | 
						|
            else:
 | 
						|
                try:
 | 
						|
                    config[key] = val  # try to convert to proper type or skip
 | 
						|
                except Exception as msg:
 | 
						|
                    _log.warning('Bad value in file %r, line %d (%r): %s',
 | 
						|
                                 fname, line_no, line.rstrip('\n'), msg)
 | 
						|
        elif key in _deprecated_ignore_map:
 | 
						|
            version, alt_key = _deprecated_ignore_map[key]
 | 
						|
            _api.warn_deprecated(
 | 
						|
                version, name=key, alternative=alt_key, obj_type='rcparam',
 | 
						|
                addendum="Please update your matplotlibrc.")
 | 
						|
        else:
 | 
						|
            # __version__ must be looked up as an attribute to trigger the
 | 
						|
            # module-level __getattr__.
 | 
						|
            version = ('main' if '.post' in mpl.__version__
 | 
						|
                       else f'v{mpl.__version__}')
 | 
						|
            _log.warning("""
 | 
						|
Bad key %(key)s in file %(fname)s, line %(line_no)s (%(line)r)
 | 
						|
You probably need to get an updated matplotlibrc file from
 | 
						|
https://github.com/matplotlib/matplotlib/blob/%(version)s/lib/matplotlib/mpl-data/matplotlibrc
 | 
						|
or from the matplotlib source distribution""",
 | 
						|
                         dict(key=key, fname=fname, line_no=line_no,
 | 
						|
                              line=line.rstrip('\n'), version=version))
 | 
						|
    return config
 | 
						|
 | 
						|
 | 
						|
def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
 | 
						|
    """
 | 
						|
    Construct a `RcParams` from file *fname*.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    fname : str or path-like
 | 
						|
        A file with Matplotlib rc settings.
 | 
						|
    fail_on_error : bool
 | 
						|
        If True, raise an error when the parser fails to convert a parameter.
 | 
						|
    use_default_template : bool
 | 
						|
        If True, initialize with default parameters before updating with those
 | 
						|
        in the given file. If False, the configuration class only contains the
 | 
						|
        parameters specified in the file. (Useful for updating dicts.)
 | 
						|
    """
 | 
						|
    config_from_file = _rc_params_in_file(fname, fail_on_error=fail_on_error)
 | 
						|
 | 
						|
    if not use_default_template:
 | 
						|
        return config_from_file
 | 
						|
 | 
						|
    with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
        config = RcParams({**rcParamsDefault, **config_from_file})
 | 
						|
 | 
						|
    if "".join(config['text.latex.preamble']):
 | 
						|
        _log.info("""
 | 
						|
*****************************************************************
 | 
						|
You have the following UNSUPPORTED LaTeX preamble customizations:
 | 
						|
%s
 | 
						|
Please do not ask for support with these customizations active.
 | 
						|
*****************************************************************
 | 
						|
""", '\n'.join(config['text.latex.preamble']))
 | 
						|
    _log.debug('loaded rc file %s', fname)
 | 
						|
 | 
						|
    return config
 | 
						|
 | 
						|
 | 
						|
rcParamsDefault = _rc_params_in_file(
 | 
						|
    cbook._get_data_path("matplotlibrc"),
 | 
						|
    # Strip leading comment.
 | 
						|
    transform=lambda line: line[1:] if line.startswith("#") else line,
 | 
						|
    fail_on_error=True)
 | 
						|
rcParamsDefault._update_raw(rcsetup._hardcoded_defaults)
 | 
						|
rcParamsDefault._ensure_has_backend()
 | 
						|
 | 
						|
rcParams = RcParams()  # The global instance.
 | 
						|
rcParams._update_raw(rcParamsDefault)
 | 
						|
rcParams._update_raw(_rc_params_in_file(matplotlib_fname()))
 | 
						|
rcParamsOrig = rcParams.copy()
 | 
						|
with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
    # This also checks that all rcParams are indeed listed in the template.
 | 
						|
    # Assigning to rcsetup.defaultParams is left only for backcompat.
 | 
						|
    defaultParams = rcsetup.defaultParams = {
 | 
						|
        # We want to resolve deprecated rcParams, but not backend...
 | 
						|
        key: [(rcsetup._auto_backend_sentinel if key == "backend" else
 | 
						|
               rcParamsDefault[key]),
 | 
						|
              validator]
 | 
						|
        for key, validator in rcsetup._validators.items()}
 | 
						|
if rcParams['axes.formatter.use_locale']:
 | 
						|
    locale.setlocale(locale.LC_ALL, '')
 | 
						|
 | 
						|
 | 
						|
def rc(group, **kwargs):
 | 
						|
    """
 | 
						|
    Set the current `.rcParams`.  *group* is the grouping for the rc, e.g.,
 | 
						|
    for ``lines.linewidth`` the group is ``lines``, for
 | 
						|
    ``axes.facecolor``, the group is ``axes``, and so on.  Group may
 | 
						|
    also be a list or tuple of group names, e.g., (*xtick*, *ytick*).
 | 
						|
    *kwargs* is a dictionary attribute name/value pairs, e.g.,::
 | 
						|
 | 
						|
      rc('lines', linewidth=2, color='r')
 | 
						|
 | 
						|
    sets the current `.rcParams` and is equivalent to::
 | 
						|
 | 
						|
      rcParams['lines.linewidth'] = 2
 | 
						|
      rcParams['lines.color'] = 'r'
 | 
						|
 | 
						|
    The following aliases are available to save typing for interactive users:
 | 
						|
 | 
						|
    =====   =================
 | 
						|
    Alias   Property
 | 
						|
    =====   =================
 | 
						|
    'lw'    'linewidth'
 | 
						|
    'ls'    'linestyle'
 | 
						|
    'c'     'color'
 | 
						|
    'fc'    'facecolor'
 | 
						|
    'ec'    'edgecolor'
 | 
						|
    'mew'   'markeredgewidth'
 | 
						|
    'aa'    'antialiased'
 | 
						|
    =====   =================
 | 
						|
 | 
						|
    Thus you could abbreviate the above call as::
 | 
						|
 | 
						|
          rc('lines', lw=2, c='r')
 | 
						|
 | 
						|
    Note you can use python's kwargs dictionary facility to store
 | 
						|
    dictionaries of default parameters.  e.g., you can customize the
 | 
						|
    font rc as follows::
 | 
						|
 | 
						|
      font = {'family' : 'monospace',
 | 
						|
              'weight' : 'bold',
 | 
						|
              'size'   : 'larger'}
 | 
						|
      rc('font', **font)  # pass in the font dict as kwargs
 | 
						|
 | 
						|
    This enables you to easily switch between several configurations.  Use
 | 
						|
    ``matplotlib.style.use('default')`` or :func:`~matplotlib.rcdefaults` to
 | 
						|
    restore the default `.rcParams` after changes.
 | 
						|
 | 
						|
    Notes
 | 
						|
    -----
 | 
						|
    Similar functionality is available by using the normal dict interface, i.e.
 | 
						|
    ``rcParams.update({"lines.linewidth": 2, ...})`` (but ``rcParams.update``
 | 
						|
    does not support abbreviations or grouping).
 | 
						|
    """
 | 
						|
 | 
						|
    aliases = {
 | 
						|
        'lw':  'linewidth',
 | 
						|
        'ls':  'linestyle',
 | 
						|
        'c':   'color',
 | 
						|
        'fc':  'facecolor',
 | 
						|
        'ec':  'edgecolor',
 | 
						|
        'mew': 'markeredgewidth',
 | 
						|
        'aa':  'antialiased',
 | 
						|
        }
 | 
						|
 | 
						|
    if isinstance(group, str):
 | 
						|
        group = (group,)
 | 
						|
    for g in group:
 | 
						|
        for k, v in kwargs.items():
 | 
						|
            name = aliases.get(k) or k
 | 
						|
            key = f'{g}.{name}'
 | 
						|
            try:
 | 
						|
                rcParams[key] = v
 | 
						|
            except KeyError as err:
 | 
						|
                raise KeyError(('Unrecognized key "%s" for group "%s" and '
 | 
						|
                                'name "%s"') % (key, g, name)) from err
 | 
						|
 | 
						|
 | 
						|
def rcdefaults():
 | 
						|
    """
 | 
						|
    Restore the `.rcParams` from Matplotlib's internal default style.
 | 
						|
 | 
						|
    Style-blacklisted `.rcParams` (defined in
 | 
						|
    ``matplotlib.style.core.STYLE_BLACKLIST``) are not updated.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    matplotlib.rc_file_defaults
 | 
						|
        Restore the `.rcParams` from the rc file originally loaded by
 | 
						|
        Matplotlib.
 | 
						|
    matplotlib.style.use
 | 
						|
        Use a specific style file.  Call ``style.use('default')`` to restore
 | 
						|
        the default style.
 | 
						|
    """
 | 
						|
    # Deprecation warnings were already handled when creating rcParamsDefault,
 | 
						|
    # no need to reemit them here.
 | 
						|
    with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
        from .style.core import STYLE_BLACKLIST
 | 
						|
        rcParams.clear()
 | 
						|
        rcParams.update({k: v for k, v in rcParamsDefault.items()
 | 
						|
                         if k not in STYLE_BLACKLIST})
 | 
						|
 | 
						|
 | 
						|
def rc_file_defaults():
 | 
						|
    """
 | 
						|
    Restore the `.rcParams` from the original rc file loaded by Matplotlib.
 | 
						|
 | 
						|
    Style-blacklisted `.rcParams` (defined in
 | 
						|
    ``matplotlib.style.core.STYLE_BLACKLIST``) are not updated.
 | 
						|
    """
 | 
						|
    # Deprecation warnings were already handled when creating rcParamsOrig, no
 | 
						|
    # need to reemit them here.
 | 
						|
    with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
        from .style.core import STYLE_BLACKLIST
 | 
						|
        rcParams.update({k: rcParamsOrig[k] for k in rcParamsOrig
 | 
						|
                         if k not in STYLE_BLACKLIST})
 | 
						|
 | 
						|
 | 
						|
def rc_file(fname, *, use_default_template=True):
 | 
						|
    """
 | 
						|
    Update `.rcParams` from file.
 | 
						|
 | 
						|
    Style-blacklisted `.rcParams` (defined in
 | 
						|
    ``matplotlib.style.core.STYLE_BLACKLIST``) are not updated.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    fname : str or path-like
 | 
						|
        A file with Matplotlib rc settings.
 | 
						|
 | 
						|
    use_default_template : bool
 | 
						|
        If True, initialize with default parameters before updating with those
 | 
						|
        in the given file. If False, the current configuration persists
 | 
						|
        and only the parameters specified in the file are updated.
 | 
						|
    """
 | 
						|
    # Deprecation warnings were already handled in rc_params_from_file, no need
 | 
						|
    # to reemit them here.
 | 
						|
    with _api.suppress_matplotlib_deprecation_warning():
 | 
						|
        from .style.core import STYLE_BLACKLIST
 | 
						|
        rc_from_file = rc_params_from_file(
 | 
						|
            fname, use_default_template=use_default_template)
 | 
						|
        rcParams.update({k: rc_from_file[k] for k in rc_from_file
 | 
						|
                         if k not in STYLE_BLACKLIST})
 | 
						|
 | 
						|
 | 
						|
@contextlib.contextmanager
 | 
						|
def rc_context(rc=None, fname=None):
 | 
						|
    """
 | 
						|
    Return a context manager for temporarily changing rcParams.
 | 
						|
 | 
						|
    The :rc:`backend` will not be reset by the context manager.
 | 
						|
 | 
						|
    rcParams changed both through the context manager invocation and
 | 
						|
    in the body of the context will be reset on context exit.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    rc : dict
 | 
						|
        The rcParams to temporarily set.
 | 
						|
    fname : str or path-like
 | 
						|
        A file with Matplotlib rc settings. If both *fname* and *rc* are given,
 | 
						|
        settings from *rc* take precedence.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    :ref:`customizing-with-matplotlibrc-files`
 | 
						|
 | 
						|
    Examples
 | 
						|
    --------
 | 
						|
    Passing explicit values via a dict::
 | 
						|
 | 
						|
        with mpl.rc_context({'interactive': False}):
 | 
						|
            fig, ax = plt.subplots()
 | 
						|
            ax.plot(range(3), range(3))
 | 
						|
            fig.savefig('example.png')
 | 
						|
            plt.close(fig)
 | 
						|
 | 
						|
    Loading settings from a file::
 | 
						|
 | 
						|
         with mpl.rc_context(fname='print.rc'):
 | 
						|
             plt.plot(x, y)  # uses 'print.rc'
 | 
						|
 | 
						|
    Setting in the context body::
 | 
						|
 | 
						|
        with mpl.rc_context():
 | 
						|
            # will be reset
 | 
						|
            mpl.rcParams['lines.linewidth'] = 5
 | 
						|
            plt.plot(x, y)
 | 
						|
 | 
						|
    """
 | 
						|
    orig = dict(rcParams.copy())
 | 
						|
    del orig['backend']
 | 
						|
    try:
 | 
						|
        if fname:
 | 
						|
            rc_file(fname)
 | 
						|
        if rc:
 | 
						|
            rcParams.update(rc)
 | 
						|
        yield
 | 
						|
    finally:
 | 
						|
        rcParams._update_raw(orig)  # Revert to the original rcs.
 | 
						|
 | 
						|
 | 
						|
def use(backend, *, force=True):
 | 
						|
    """
 | 
						|
    Select the backend used for rendering and GUI integration.
 | 
						|
 | 
						|
    If pyplot is already imported, `~matplotlib.pyplot.switch_backend` is used
 | 
						|
    and if the new backend is different than the current backend, all Figures
 | 
						|
    will be closed.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    backend : str
 | 
						|
        The backend to switch to.  This can either be one of the standard
 | 
						|
        backend names, which are case-insensitive:
 | 
						|
 | 
						|
        - interactive backends:
 | 
						|
          GTK3Agg, GTK3Cairo, GTK4Agg, GTK4Cairo, MacOSX, nbAgg, notebook, QtAgg,
 | 
						|
          QtCairo, TkAgg, TkCairo, WebAgg, WX, WXAgg, WXCairo, Qt5Agg, Qt5Cairo
 | 
						|
 | 
						|
        - non-interactive backends:
 | 
						|
          agg, cairo, pdf, pgf, ps, svg, template
 | 
						|
 | 
						|
        or a string of the form: ``module://my.module.name``.
 | 
						|
 | 
						|
        notebook is a synonym for nbAgg.
 | 
						|
 | 
						|
        Switching to an interactive backend is not possible if an unrelated
 | 
						|
        event loop has already been started (e.g., switching to GTK3Agg if a
 | 
						|
        TkAgg window has already been opened).  Switching to a non-interactive
 | 
						|
        backend is always possible.
 | 
						|
 | 
						|
    force : bool, default: True
 | 
						|
        If True (the default), raise an `ImportError` if the backend cannot be
 | 
						|
        set up (either because it fails to import, or because an incompatible
 | 
						|
        GUI interactive framework is already running); if False, silently
 | 
						|
        ignore the failure.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    :ref:`backends`
 | 
						|
    matplotlib.get_backend
 | 
						|
    matplotlib.pyplot.switch_backend
 | 
						|
 | 
						|
    """
 | 
						|
    name = rcsetup.validate_backend(backend)
 | 
						|
    # don't (prematurely) resolve the "auto" backend setting
 | 
						|
    if rcParams._get_backend_or_none() == name:
 | 
						|
        # Nothing to do if the requested backend is already set
 | 
						|
        pass
 | 
						|
    else:
 | 
						|
        # if pyplot is not already imported, do not import it.  Doing
 | 
						|
        # so may trigger a `plt.switch_backend` to the _default_ backend
 | 
						|
        # before we get a chance to change to the one the user just requested
 | 
						|
        plt = sys.modules.get('matplotlib.pyplot')
 | 
						|
        # if pyplot is imported, then try to change backends
 | 
						|
        if plt is not None:
 | 
						|
            try:
 | 
						|
                # we need this import check here to re-raise if the
 | 
						|
                # user does not have the libraries to support their
 | 
						|
                # chosen backend installed.
 | 
						|
                plt.switch_backend(name)
 | 
						|
            except ImportError:
 | 
						|
                if force:
 | 
						|
                    raise
 | 
						|
        # if we have not imported pyplot, then we can set the rcParam
 | 
						|
        # value which will be respected when the user finally imports
 | 
						|
        # pyplot
 | 
						|
        else:
 | 
						|
            rcParams['backend'] = backend
 | 
						|
    # if the user has asked for a given backend, do not helpfully
 | 
						|
    # fallback
 | 
						|
    rcParams['backend_fallback'] = False
 | 
						|
 | 
						|
 | 
						|
if os.environ.get('MPLBACKEND'):
 | 
						|
    rcParams['backend'] = os.environ.get('MPLBACKEND')
 | 
						|
 | 
						|
 | 
						|
def get_backend(*, auto_select=True):
 | 
						|
    """
 | 
						|
    Return the name of the current backend.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    auto_select : bool, default: True
 | 
						|
        Whether to trigger backend resolution if no backend has been
 | 
						|
        selected so far. If True, this ensures that a valid backend
 | 
						|
        is returned. If False, this returns None if no backend has been
 | 
						|
        selected so far.
 | 
						|
 | 
						|
        .. versionadded:: 3.10
 | 
						|
 | 
						|
        .. admonition:: Provisional
 | 
						|
 | 
						|
           The *auto_select* flag is provisional. It may be changed or removed
 | 
						|
           without prior warning.
 | 
						|
 | 
						|
    See Also
 | 
						|
    --------
 | 
						|
    matplotlib.use
 | 
						|
    """
 | 
						|
    if auto_select:
 | 
						|
        return rcParams['backend']
 | 
						|
    else:
 | 
						|
        backend = rcParams._get('backend')
 | 
						|
        if backend is rcsetup._auto_backend_sentinel:
 | 
						|
            return None
 | 
						|
        else:
 | 
						|
            return backend
 | 
						|
 | 
						|
 | 
						|
def interactive(b):
 | 
						|
    """
 | 
						|
    Set whether to redraw after every plotting command (e.g. `.pyplot.xlabel`).
 | 
						|
    """
 | 
						|
    rcParams['interactive'] = b
 | 
						|
 | 
						|
 | 
						|
def is_interactive():
 | 
						|
    """
 | 
						|
    Return whether to redraw after every plotting command.
 | 
						|
 | 
						|
    .. note::
 | 
						|
 | 
						|
        This function is only intended for use in backends. End users should
 | 
						|
        use `.pyplot.isinteractive` instead.
 | 
						|
    """
 | 
						|
    return rcParams['interactive']
 | 
						|
 | 
						|
 | 
						|
def _val_or_rc(val, rc_name):
 | 
						|
    """
 | 
						|
    If *val* is None, return ``mpl.rcParams[rc_name]``, otherwise return val.
 | 
						|
    """
 | 
						|
    return val if val is not None else rcParams[rc_name]
 | 
						|
 | 
						|
 | 
						|
def _init_tests():
 | 
						|
    # The version of FreeType to install locally for running the tests. This must match
 | 
						|
    # the value in `meson.build`.
 | 
						|
    LOCAL_FREETYPE_VERSION = '2.6.1'
 | 
						|
 | 
						|
    from matplotlib import ft2font
 | 
						|
    if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
 | 
						|
            ft2font.__freetype_build_type__ != 'local'):
 | 
						|
        _log.warning(
 | 
						|
            "Matplotlib is not built with the correct FreeType version to run tests.  "
 | 
						|
            "Rebuild without setting system-freetype=true in Meson setup options.  "
 | 
						|
            "Expect many image comparison failures below.  "
 | 
						|
            "Expected freetype version %s.  "
 | 
						|
            "Found freetype version %s.  "
 | 
						|
            "Freetype build type is %slocal.",
 | 
						|
            LOCAL_FREETYPE_VERSION,
 | 
						|
            ft2font.__freetype_version__,
 | 
						|
            "" if ft2font.__freetype_build_type__ == 'local' else "not ")
 | 
						|
 | 
						|
 | 
						|
def _replacer(data, value):
 | 
						|
    """
 | 
						|
    Either returns ``data[value]`` or passes ``data`` back, converts either to
 | 
						|
    a sequence.
 | 
						|
    """
 | 
						|
    try:
 | 
						|
        # if key isn't a string don't bother
 | 
						|
        if isinstance(value, str):
 | 
						|
            # try to use __getitem__
 | 
						|
            value = data[value]
 | 
						|
    except Exception:
 | 
						|
        # key does not exist, silently fall back to key
 | 
						|
        pass
 | 
						|
    return cbook.sanitize_sequence(value)
 | 
						|
 | 
						|
 | 
						|
def _label_from_arg(y, default_name):
 | 
						|
    try:
 | 
						|
        return y.name
 | 
						|
    except AttributeError:
 | 
						|
        if isinstance(default_name, str):
 | 
						|
            return default_name
 | 
						|
    return None
 | 
						|
 | 
						|
 | 
						|
def _add_data_doc(docstring, replace_names):
 | 
						|
    """
 | 
						|
    Add documentation for a *data* field to the given docstring.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    docstring : str
 | 
						|
        The input docstring.
 | 
						|
    replace_names : list of str or None
 | 
						|
        The list of parameter names which arguments should be replaced by
 | 
						|
        ``data[name]`` (if ``data[name]`` does not throw an exception).  If
 | 
						|
        None, replacement is attempted for all arguments.
 | 
						|
 | 
						|
    Returns
 | 
						|
    -------
 | 
						|
    str
 | 
						|
        The augmented docstring.
 | 
						|
    """
 | 
						|
    if (docstring is None
 | 
						|
            or replace_names is not None and len(replace_names) == 0):
 | 
						|
        return docstring
 | 
						|
    docstring = inspect.cleandoc(docstring)
 | 
						|
 | 
						|
    data_doc = ("""\
 | 
						|
    If given, all parameters also accept a string ``s``, which is
 | 
						|
    interpreted as ``data[s]`` if ``s`` is a key in ``data``."""
 | 
						|
                if replace_names is None else f"""\
 | 
						|
    If given, the following parameters also accept a string ``s``, which is
 | 
						|
    interpreted as ``data[s]`` if ``s`` is a key in ``data``:
 | 
						|
 | 
						|
    {', '.join(map('*{}*'.format, replace_names))}""")
 | 
						|
    # using string replacement instead of formatting has the advantages
 | 
						|
    # 1) simpler indent handling
 | 
						|
    # 2) prevent problems with formatting characters '{', '%' in the docstring
 | 
						|
    if _log.level <= logging.DEBUG:
 | 
						|
        # test_data_parameter_replacement() tests against these log messages
 | 
						|
        # make sure to keep message and test in sync
 | 
						|
        if "data : indexable object, optional" not in docstring:
 | 
						|
            _log.debug("data parameter docstring error: no data parameter")
 | 
						|
        if 'DATA_PARAMETER_PLACEHOLDER' not in docstring:
 | 
						|
            _log.debug("data parameter docstring error: missing placeholder")
 | 
						|
    return docstring.replace('    DATA_PARAMETER_PLACEHOLDER', data_doc)
 | 
						|
 | 
						|
 | 
						|
def _preprocess_data(func=None, *, replace_names=None, label_namer=None):
 | 
						|
    """
 | 
						|
    A decorator to add a 'data' kwarg to a function.
 | 
						|
 | 
						|
    When applied::
 | 
						|
 | 
						|
        @_preprocess_data()
 | 
						|
        def func(ax, *args, **kwargs): ...
 | 
						|
 | 
						|
    the signature is modified to ``decorated(ax, *args, data=None, **kwargs)``
 | 
						|
    with the following behavior:
 | 
						|
 | 
						|
    - if called with ``data=None``, forward the other arguments to ``func``;
 | 
						|
    - otherwise, *data* must be a mapping; for any argument passed in as a
 | 
						|
      string ``name``, replace the argument by ``data[name]`` (if this does not
 | 
						|
      throw an exception), then forward the arguments to ``func``.
 | 
						|
 | 
						|
    In either case, any argument that is a `MappingView` is also converted to a
 | 
						|
    list.
 | 
						|
 | 
						|
    Parameters
 | 
						|
    ----------
 | 
						|
    replace_names : list of str or None, default: None
 | 
						|
        The list of parameter names for which lookup into *data* should be
 | 
						|
        attempted. If None, replacement is attempted for all arguments.
 | 
						|
    label_namer : str, default: None
 | 
						|
        If set e.g. to "namer" (which must be a kwarg in the function's
 | 
						|
        signature -- not as ``**kwargs``), if the *namer* argument passed in is
 | 
						|
        a (string) key of *data* and no *label* kwarg is passed, then use the
 | 
						|
        (string) value of the *namer* as *label*. ::
 | 
						|
 | 
						|
            @_preprocess_data(label_namer="foo")
 | 
						|
            def func(foo, label=None): ...
 | 
						|
 | 
						|
            func("key", data={"key": value})
 | 
						|
            # is equivalent to
 | 
						|
            func.__wrapped__(value, label="key")
 | 
						|
    """
 | 
						|
 | 
						|
    if func is None:  # Return the actual decorator.
 | 
						|
        return functools.partial(
 | 
						|
            _preprocess_data,
 | 
						|
            replace_names=replace_names, label_namer=label_namer)
 | 
						|
 | 
						|
    sig = inspect.signature(func)
 | 
						|
    varargs_name = None
 | 
						|
    varkwargs_name = None
 | 
						|
    arg_names = []
 | 
						|
    params = list(sig.parameters.values())
 | 
						|
    for p in params:
 | 
						|
        if p.kind is Parameter.VAR_POSITIONAL:
 | 
						|
            varargs_name = p.name
 | 
						|
        elif p.kind is Parameter.VAR_KEYWORD:
 | 
						|
            varkwargs_name = p.name
 | 
						|
        else:
 | 
						|
            arg_names.append(p.name)
 | 
						|
    data_param = Parameter("data", Parameter.KEYWORD_ONLY, default=None)
 | 
						|
    if varkwargs_name:
 | 
						|
        params.insert(-1, data_param)
 | 
						|
    else:
 | 
						|
        params.append(data_param)
 | 
						|
    new_sig = sig.replace(parameters=params)
 | 
						|
    arg_names = arg_names[1:]  # remove the first "ax" / self arg
 | 
						|
 | 
						|
    assert {*arg_names}.issuperset(replace_names or []) or varkwargs_name, (
 | 
						|
        "Matplotlib internal error: invalid replace_names "
 | 
						|
        f"({replace_names!r}) for {func.__name__!r}")
 | 
						|
    assert label_namer is None or label_namer in arg_names, (
 | 
						|
        "Matplotlib internal error: invalid label_namer "
 | 
						|
        f"({label_namer!r}) for {func.__name__!r}")
 | 
						|
 | 
						|
    @functools.wraps(func)
 | 
						|
    def inner(ax, *args, data=None, **kwargs):
 | 
						|
        if data is None:
 | 
						|
            return func(
 | 
						|
                ax,
 | 
						|
                *map(cbook.sanitize_sequence, args),
 | 
						|
                **{k: cbook.sanitize_sequence(v) for k, v in kwargs.items()})
 | 
						|
 | 
						|
        bound = new_sig.bind(ax, *args, **kwargs)
 | 
						|
        auto_label = (bound.arguments.get(label_namer)
 | 
						|
                      or bound.kwargs.get(label_namer))
 | 
						|
 | 
						|
        for k, v in bound.arguments.items():
 | 
						|
            if k == varkwargs_name:
 | 
						|
                for k1, v1 in v.items():
 | 
						|
                    if replace_names is None or k1 in replace_names:
 | 
						|
                        v[k1] = _replacer(data, v1)
 | 
						|
            elif k == varargs_name:
 | 
						|
                if replace_names is None:
 | 
						|
                    bound.arguments[k] = tuple(_replacer(data, v1) for v1 in v)
 | 
						|
            else:
 | 
						|
                if replace_names is None or k in replace_names:
 | 
						|
                    bound.arguments[k] = _replacer(data, v)
 | 
						|
 | 
						|
        new_args = bound.args
 | 
						|
        new_kwargs = bound.kwargs
 | 
						|
 | 
						|
        args_and_kwargs = {**bound.arguments, **bound.kwargs}
 | 
						|
        if label_namer and "label" not in args_and_kwargs:
 | 
						|
            new_kwargs["label"] = _label_from_arg(
 | 
						|
                args_and_kwargs.get(label_namer), auto_label)
 | 
						|
 | 
						|
        return func(*new_args, **new_kwargs)
 | 
						|
 | 
						|
    inner.__doc__ = _add_data_doc(inner.__doc__, replace_names)
 | 
						|
    inner.__signature__ = new_sig
 | 
						|
    return inner
 | 
						|
 | 
						|
 | 
						|
_log.debug('interactive is %s', is_interactive())
 | 
						|
_log.debug('platform is %s', sys.platform)
 | 
						|
 | 
						|
 | 
						|
@_api.deprecated("3.10", alternative="matplotlib.cbook.sanitize_sequence")
 | 
						|
def sanitize_sequence(data):
 | 
						|
    return cbook.sanitize_sequence(data)
 | 
						|
 | 
						|
 | 
						|
@_api.deprecated("3.10", alternative="matplotlib.rcsetup.validate_backend")
 | 
						|
def validate_backend(s):
 | 
						|
    return rcsetup.validate_backend(s)
 | 
						|
 | 
						|
 | 
						|
# workaround: we must defer colormaps import to after loading rcParams, because
 | 
						|
# colormap creation depends on rcParams
 | 
						|
from matplotlib.cm import _colormaps as colormaps  # noqa: E402
 | 
						|
from matplotlib.cm import _multivar_colormaps as multivar_colormaps  # noqa: E402
 | 
						|
from matplotlib.cm import _bivar_colormaps as bivar_colormaps  # noqa: E402
 | 
						|
from matplotlib.colors import _color_sequences as color_sequences  # noqa: E402
 |