Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/matplotlib/__init__.py : 40%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2This is an object-oriented plotting library.
4A procedural interface is provided by the companion pyplot module,
5which may be imported directly, e.g.::
7 import matplotlib.pyplot as plt
9or using ipython::
11 ipython
13at your terminal, followed by::
15 In [1]: %matplotlib
16 In [2]: import matplotlib.pyplot as plt
18at the ipython shell prompt.
20For the most part, direct use of the object-oriented library is
21encouraged when programming; pyplot is primarily for working
22interactively. The
23exceptions are the pyplot commands :func:`~matplotlib.pyplot.figure`,
24:func:`~matplotlib.pyplot.subplot`,
25:func:`~matplotlib.pyplot.subplots`, and
26:func:`~pyplot.savefig`, which can greatly simplify scripting.
28Modules include:
30 :mod:`matplotlib.axes`
31 defines the :class:`~matplotlib.axes.Axes` class. Most pyplot
32 commands are wrappers for :class:`~matplotlib.axes.Axes`
33 methods. The axes module is the highest level of OO access to
34 the library.
36 :mod:`matplotlib.figure`
37 defines the :class:`~matplotlib.figure.Figure` class.
39 :mod:`matplotlib.artist`
40 defines the :class:`~matplotlib.artist.Artist` base class for
41 all classes that draw things.
43 :mod:`matplotlib.lines`
44 defines the :class:`~matplotlib.lines.Line2D` class for
45 drawing lines and markers
47 :mod:`matplotlib.patches`
48 defines classes for drawing polygons
50 :mod:`matplotlib.text`
51 defines the :class:`~matplotlib.text.Text`,
52 :class:`~matplotlib.text.TextWithDash`, and
53 :class:`~matplotlib.text.Annotate` classes
55 :mod:`matplotlib.image`
56 defines the :class:`~matplotlib.image.AxesImage` and
57 :class:`~matplotlib.image.FigureImage` classes
59 :mod:`matplotlib.collections`
60 classes for efficient drawing of groups of lines or polygons
62 :mod:`matplotlib.colors`
63 classes for interpreting color specifications and for making
64 colormaps
66 :mod:`matplotlib.cm`
67 colormaps and the :class:`~matplotlib.image.ScalarMappable`
68 mixin class for providing color mapping functionality to other
69 classes
71 :mod:`matplotlib.ticker`
72 classes for calculating tick mark locations and for formatting
73 tick labels
75 :mod:`matplotlib.backends`
76 a subpackage with modules for various gui libraries and output
77 formats
79The base matplotlib namespace includes:
81 :data:`~matplotlib.rcParams`
82 a global dictionary of default configuration settings. It is
83 initialized by code which may be overridden by a matplotlibrc
84 file.
86 :func:`~matplotlib.rc`
87 a function for setting groups of rcParams values
89 :func:`~matplotlib.use`
90 a function for setting the matplotlib backend. If used, this
91 function must be called immediately after importing matplotlib
92 for the first time. In particular, it must be called
93 **before** importing pyplot (if pyplot is imported).
95matplotlib was initially written by John D. Hunter (1968-2012) and is now
96developed and maintained by a host of others.
98Occasionally the internal documentation (python docstrings) will refer
99to MATLAB®, a registered trademark of The MathWorks, Inc.
101"""
102# NOTE: This file must remain Python 2 compatible for the foreseeable future,
103# to ensure that we error out properly for existing editable installs.
105import sys
106if sys.version_info < (3, 5): # noqa: E402
107 raise ImportError("""
108Matplotlib 3.0+ does not support Python 2.x, 3.0, 3.1, 3.2, 3.3, or 3.4.
109Beginning with Matplotlib 3.0, Python 3.5 and above is required.
111See Matplotlib `INSTALL.rst` file for more information:
113 https://github.com/matplotlib/matplotlib/blob/master/INSTALL.rst
115""")
117import atexit
118from collections import namedtuple
119from collections.abc import MutableMapping
120import contextlib
121from distutils.version import LooseVersion
122import functools
123import importlib
124import inspect
125from inspect import Parameter
126import locale
127import logging
128import os
129from pathlib import Path
130import pprint
131import re
132import shutil
133import subprocess
134import tempfile
135import warnings
137# cbook must import matplotlib only within function
138# definitions, so it is safe to import from it here.
139from . import cbook, rcsetup
140from matplotlib.cbook import (
141 MatplotlibDeprecationWarning, dedent, get_label, sanitize_sequence)
142from matplotlib.cbook import mplDeprecation # deprecated
143from matplotlib.rcsetup import defaultParams, validate_backend, cycler
145import numpy
147# Get the version from the _version.py versioneer file. For a git checkout,
148# this is computed based on the number of commits since the last tag.
149from ._version import get_versions
150__version__ = str(get_versions()['version'])
151del get_versions
153_log = logging.getLogger(__name__)
155__bibtex__ = r"""@Article{Hunter:2007,
156 Author = {Hunter, J. D.},
157 Title = {Matplotlib: A 2D graphics environment},
158 Journal = {Computing in Science \& Engineering},
159 Volume = {9},
160 Number = {3},
161 Pages = {90--95},
162 abstract = {Matplotlib is a 2D graphics package used for Python
163 for application development, interactive scripting, and
164 publication-quality image generation across user
165 interfaces and operating systems.},
166 publisher = {IEEE COMPUTER SOC},
167 year = 2007
168}"""
171@cbook.deprecated("3.2")
172def compare_versions(a, b):
173 "Return whether version *a* is greater than or equal to version *b*."
174 if isinstance(a, bytes):
175 cbook.warn_deprecated(
176 "3.0", message="compare_versions arguments should be strs.")
177 a = a.decode('ascii')
178 if isinstance(b, bytes):
179 cbook.warn_deprecated(
180 "3.0", message="compare_versions arguments should be strs.")
181 b = b.decode('ascii')
182 if a:
183 return LooseVersion(a) >= LooseVersion(b)
184 else:
185 return False
188def _check_versions():
190 # Quickfix to ensure Microsoft Visual C++ redistributable
191 # DLLs are loaded before importing kiwisolver
192 from . import ft2font
194 for modname, minver in [
195 ("cycler", "0.10"),
196 ("dateutil", "2.1"),
197 ("kiwisolver", "1.0.1"),
198 ("numpy", "1.11"),
199 ("pyparsing", "2.0.1"),
200 ]:
201 module = importlib.import_module(modname)
202 if LooseVersion(module.__version__) < minver:
203 raise ImportError("Matplotlib requires {}>={}; you have {}"
204 .format(modname, minver, module.__version__))
207_check_versions()
210if not hasattr(sys, 'argv'): # for modpython
211 sys.argv = ['modpython']
214# The decorator ensures this always returns the same handler (and it is only
215# attached once).
216@functools.lru_cache()
217def _ensure_handler():
218 """
219 The first time this function is called, attach a `StreamHandler` using the
220 same format as `logging.basicConfig` to the Matplotlib root logger.
222 Return this handler every time this function is called.
223 """
224 handler = logging.StreamHandler()
225 handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
226 _log.addHandler(handler)
227 return handler
230def set_loglevel(level):
231 """
232 Sets the Matplotlib's root logger and root logger handler level, creating
233 the handler if it does not exist yet.
235 Typically, one should call ``set_loglevel("info")`` or
236 ``set_loglevel("debug")`` to get additional debugging information.
238 Parameters
239 ----------
240 level : {"notset", "debug", "info", "warning", "error", "critical"}
241 The log level of the handler.
243 Notes
244 -----
245 The first time this function is called, an additional handler is attached
246 to Matplotlib's root handler; this handler is reused every time and this
247 function simply manipulates the logger and handler's level.
248 """
249 _log.setLevel(level.upper())
250 _ensure_handler().setLevel(level.upper())
253def _logged_cached(fmt, func=None):
254 """
255 Decorator that logs a function's return value, and memoizes that value.
257 After ::
259 @_logged_cached(fmt)
260 def func(): ...
262 the first call to *func* will log its return value at the DEBUG level using
263 %-format string *fmt*, and memoize it; later calls to *func* will directly
264 return that value.
265 """
266 if func is None: # Return the actual decorator.
267 return functools.partial(_logged_cached, fmt)
269 called = False
270 ret = None
272 @functools.wraps(func)
273 def wrapper(**kwargs):
274 nonlocal called, ret
275 if not called:
276 ret = func(**kwargs)
277 called = True
278 _log.debug(fmt, ret)
279 return ret
281 return wrapper
284_ExecInfo = namedtuple("_ExecInfo", "executable version")
287class ExecutableNotFoundError(FileNotFoundError):
288 """
289 Error raised when an executable that Matplotlib optionally
290 depends on can't be found.
291 """
292 pass
295@functools.lru_cache()
296def _get_executable_info(name):
297 """
298 Get the version of some executable that Matplotlib optionally depends on.
300 .. warning:
301 The list of executables that this function supports is set according to
302 Matplotlib's internal needs, and may change without notice.
304 Parameters
305 ----------
306 name : str
307 The executable to query. The following values are currently supported:
308 "dvipng", "gs", "inkscape", "magick", "pdftops". This list is subject
309 to change without notice.
311 Returns
312 -------
313 If the executable is found, a namedtuple with fields ``executable`` (`str`)
314 and ``version`` (`distutils.version.LooseVersion`, or ``None`` if the
315 version cannot be determined).
317 Raises
318 ------
319 ExecutableNotFoundError
320 If the executable is not found or older than the oldest version
321 supported by Matplotlib.
322 ValueError
323 If the executable is not one that we know how to query.
324 """
326 def impl(args, regex, min_ver=None, ignore_exit_code=False):
327 # Execute the subprocess specified by args; capture stdout and stderr.
328 # Search for a regex match in the output; if the match succeeds, the
329 # first group of the match is the version.
330 # Return an _ExecInfo if the executable exists, and has a version of
331 # at least min_ver (if set); else, raise ExecutableNotFoundError.
332 try:
333 output = subprocess.check_output(
334 args, stderr=subprocess.STDOUT,
335 universal_newlines=True, errors="replace")
336 except subprocess.CalledProcessError as _cpe:
337 if ignore_exit_code:
338 output = _cpe.output
339 else:
340 raise ExecutableNotFoundError(str(_cpe)) from _cpe
341 except OSError as _ose:
342 raise ExecutableNotFoundError(str(_ose)) from _ose
343 match = re.search(regex, output)
344 if match:
345 version = LooseVersion(match.group(1))
346 if min_ver is not None and version < min_ver:
347 raise ExecutableNotFoundError(
348 f"You have {args[0]} version {version} but the minimum "
349 f"version supported by Matplotlib is {min_ver}")
350 return _ExecInfo(args[0], version)
351 else:
352 raise ExecutableNotFoundError(
353 f"Failed to determine the version of {args[0]} from "
354 f"{' '.join(args)}, which output {output}")
356 if name == "dvipng":
357 return impl(["dvipng", "-version"], "(?m)^dvipng(?: .*)? (.+)", "1.6")
358 elif name == "gs":
359 execs = (["gswin32c", "gswin64c", "mgs", "gs"] # "mgs" for miktex.
360 if sys.platform == "win32" else
361 ["gs"])
362 for e in execs:
363 try:
364 return impl([e, "--version"], "(.*)", "9")
365 except ExecutableNotFoundError:
366 pass
367 message = "Failed to find a Ghostscript installation"
368 raise ExecutableNotFoundError(message)
369 elif name == "inkscape":
370 info = impl(["inkscape", "-V"], "^Inkscape ([^ ]*)")
371 if info and info.version >= "1.0":
372 raise ExecutableNotFoundError(
373 f"You have Inkscape version {info.version} but Matplotlib "
374 f"only supports Inkscape<1.0")
375 return info
376 elif name == "magick":
377 path = None
378 if sys.platform == "win32":
379 # Check the registry to avoid confusing ImageMagick's convert with
380 # Windows's builtin convert.exe.
381 import winreg
382 binpath = ""
383 for flag in [0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY]:
384 try:
385 with winreg.OpenKeyEx(
386 winreg.HKEY_LOCAL_MACHINE,
387 r"Software\Imagemagick\Current",
388 0, winreg.KEY_QUERY_VALUE | flag) as hkey:
389 binpath = winreg.QueryValueEx(hkey, "BinPath")[0]
390 except OSError:
391 pass
392 if binpath:
393 for name in ["convert.exe", "magick.exe"]:
394 candidate = Path(binpath, name)
395 if candidate.exists():
396 path = str(candidate)
397 break
398 else:
399 path = "convert"
400 if path is None:
401 raise ExecutableNotFoundError(
402 "Failed to find an ImageMagick installation")
403 return impl([path, "--version"], r"^Version: ImageMagick (\S*)")
404 elif name == "pdftops":
405 info = impl(["pdftops", "-v"], "^pdftops version (.*)",
406 ignore_exit_code=True)
407 if info and not ("3.0" <= info.version
408 # poppler version numbers.
409 or "0.9" <= info.version <= "1.0"):
410 raise ExecutableNotFoundError(
411 f"You have pdftops version {info.version} but the minimum "
412 f"version supported by Matplotlib is 3.0")
413 return info
414 else:
415 raise ValueError("Unknown executable: {!r}".format(name))
418@cbook.deprecated("3.1")
419def checkdep_dvipng():
420 try:
421 s = subprocess.Popen(['dvipng', '-version'],
422 stdout=subprocess.PIPE,
423 stderr=subprocess.PIPE)
424 stdout, stderr = s.communicate()
425 line = stdout.decode('ascii').split('\n')[1]
426 v = line.split()[-1]
427 return v
428 except (IndexError, ValueError, OSError):
429 return None
432@cbook.deprecated("3.1")
433def checkdep_ghostscript():
434 if checkdep_ghostscript.executable is None:
435 if sys.platform == 'win32':
436 # mgs is the name in miktex
437 gs_execs = ['gswin32c', 'gswin64c', 'mgs', 'gs']
438 else:
439 gs_execs = ['gs']
440 for gs_exec in gs_execs:
441 try:
442 s = subprocess.Popen(
443 [gs_exec, '--version'], stdout=subprocess.PIPE,
444 stderr=subprocess.PIPE)
445 stdout, stderr = s.communicate()
446 if s.returncode == 0:
447 v = stdout[:-1].decode('ascii')
448 if compare_versions(v, '9.0'):
449 checkdep_ghostscript.executable = gs_exec
450 checkdep_ghostscript.version = v
451 except (IndexError, ValueError, OSError):
452 pass
453 return checkdep_ghostscript.executable, checkdep_ghostscript.version
454checkdep_ghostscript.executable = None
455checkdep_ghostscript.version = None
458@cbook.deprecated("3.1")
459def checkdep_pdftops():
460 try:
461 s = subprocess.Popen(['pdftops', '-v'], stdout=subprocess.PIPE,
462 stderr=subprocess.PIPE)
463 stdout, stderr = s.communicate()
464 lines = stderr.decode('ascii').split('\n')
465 for line in lines:
466 if 'version' in line:
467 v = line.split()[-1]
468 return v
469 except (IndexError, ValueError, UnboundLocalError, OSError):
470 return None
473@cbook.deprecated("3.1")
474def checkdep_inkscape():
475 if checkdep_inkscape.version is None:
476 try:
477 s = subprocess.Popen(['inkscape', '-V'],
478 stdout=subprocess.PIPE,
479 stderr=subprocess.PIPE)
480 stdout, stderr = s.communicate()
481 lines = stdout.decode('ascii').split('\n')
482 for line in lines:
483 if 'Inkscape' in line:
484 v = line.split()[1]
485 break
486 checkdep_inkscape.version = v
487 except (IndexError, ValueError, UnboundLocalError, OSError):
488 pass
489 return checkdep_inkscape.version
490checkdep_inkscape.version = None
493@cbook.deprecated("3.2")
494def checkdep_ps_distiller(s):
495 if not s:
496 return False
497 try:
498 _get_executable_info("gs")
499 except ExecutableNotFoundError:
500 _log.warning(
501 "Setting rcParams['ps.usedistiller'] requires ghostscript.")
502 return False
503 if s == "xpdf":
504 try:
505 _get_executable_info("pdftops")
506 except ExecutableNotFoundError:
507 _log.warning(
508 "Setting rcParams['ps.usedistiller'] to 'xpdf' requires xpdf.")
509 return False
510 return s
513def checkdep_usetex(s):
514 if not s:
515 return False
516 if not shutil.which("tex"):
517 _log.warning("usetex mode requires TeX.")
518 return False
519 try:
520 _get_executable_info("dvipng")
521 except ExecutableNotFoundError:
522 _log.warning("usetex mode requires dvipng.")
523 return False
524 try:
525 _get_executable_info("gs")
526 except ExecutableNotFoundError:
527 _log.warning("usetex mode requires ghostscript.")
528 return False
529 return True
532@cbook.deprecated("3.2", alternative="os.path.expanduser('~')")
533@_logged_cached('$HOME=%s')
534def get_home():
535 """
536 Return the user's home directory.
538 If the user's home directory cannot be found, return None.
539 """
540 try:
541 return str(Path.home())
542 except Exception:
543 return None
546def _create_tmp_config_or_cache_dir():
547 """
548 If the config or cache directory cannot be created, create a temporary one.
549 """
550 configdir = os.environ['MPLCONFIGDIR'] = (
551 tempfile.mkdtemp(prefix='matplotlib-'))
552 atexit.register(shutil.rmtree, configdir)
553 return configdir
556def _get_xdg_config_dir():
557 """
558 Return the XDG configuration directory, according to the `XDG
559 base directory spec
560 <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
561 """
562 return os.environ.get('XDG_CONFIG_HOME') or str(Path.home() / ".config")
565def _get_xdg_cache_dir():
566 """
567 Return the XDG cache directory, according to the `XDG
568 base directory spec
569 <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
570 """
571 return os.environ.get('XDG_CACHE_HOME') or str(Path.home() / ".cache")
574def _get_config_or_cache_dir(xdg_base):
575 configdir = os.environ.get('MPLCONFIGDIR')
576 if configdir:
577 configdir = Path(configdir).resolve()
578 elif sys.platform.startswith(('linux', 'freebsd')) and xdg_base:
579 configdir = Path(xdg_base, "matplotlib")
580 else:
581 configdir = Path.home() / ".matplotlib"
582 try:
583 configdir.mkdir(parents=True, exist_ok=True)
584 except OSError:
585 pass
586 else:
587 if os.access(str(configdir), os.W_OK) and configdir.is_dir():
588 return str(configdir)
589 return _create_tmp_config_or_cache_dir()
592@_logged_cached('CONFIGDIR=%s')
593def get_configdir():
594 """
595 Return the string representing the configuration directory.
597 The directory is chosen as follows:
599 1. If the MPLCONFIGDIR environment variable is supplied, choose that.
600 2a. On Linux, follow the XDG specification and look first in
601 `$XDG_CONFIG_HOME`, if defined, or `$HOME/.config`.
602 2b. On other platforms, choose `$HOME/.matplotlib`.
603 3. If the chosen directory exists and is writable, use that as the
604 configuration directory.
605 4. If possible, create a temporary directory, and use it as the
606 configuration directory.
607 5. A writable directory could not be found or created; return None.
608 """
609 return _get_config_or_cache_dir(_get_xdg_config_dir())
612@_logged_cached('CACHEDIR=%s')
613def get_cachedir():
614 """
615 Return the location of the cache directory.
617 The procedure used to find the directory is the same as for
618 _get_config_dir, except using `$XDG_CACHE_HOME`/`~/.cache` instead.
619 """
620 return _get_config_or_cache_dir(_get_xdg_cache_dir())
623@_logged_cached('matplotlib data path: %s')
624def get_data_path(*, _from_rc=None):
625 """Return the path to Matplotlib data."""
626 if _from_rc is not None:
627 cbook.warn_deprecated(
628 "3.2",
629 message=("Setting the datapath via matplotlibrc is "
630 "deprecated %(since)s and will be removed in %(removal)s. "
631 ""),
632 removal='3.3')
633 path = Path(_from_rc)
634 if path.is_dir():
635 defaultParams['datapath'][0] = str(path)
636 return str(path)
637 else:
638 warnings.warn(f"You passed datapath: {_from_rc!r} in your "
639 f"matplotribrc file ({matplotlib_fname()}). "
640 "However this path does not exist, falling back "
641 "to standard paths.")
643 return _get_data_path()
646@_logged_cached('(private) matplotlib data path: %s')
647def _get_data_path():
648 if 'MATPLOTLIBDATA' in os.environ:
649 path = os.environ['MATPLOTLIBDATA']
650 if not os.path.isdir(path):
651 raise RuntimeError('Path in environment MATPLOTLIBDATA not a '
652 'directory')
653 cbook.warn_deprecated(
654 "3.1", name="MATPLOTLIBDATA", obj_type="environment variable")
655 return path
657 path = Path(__file__).with_name("mpl-data")
658 if path.is_dir():
659 defaultParams['datapath'][0] = str(path)
660 return str(path)
662 cbook.warn_deprecated(
663 "3.2", message="Matplotlib installs where the data is not in the "
664 "mpl-data subdirectory of the package are deprecated since %(since)s "
665 "and support for them will be removed %(removal)s.")
667 def get_candidate_paths():
668 # setuptools' namespace_packages may hijack this init file
669 # so need to try something known to be in Matplotlib, not basemap.
670 import matplotlib.afm
671 yield Path(matplotlib.afm.__file__).with_name('mpl-data')
672 # py2exe zips pure python, so still need special check.
673 if getattr(sys, 'frozen', None):
674 yield Path(sys.executable).with_name('mpl-data')
675 # Try again assuming we need to step up one more directory.
676 yield Path(sys.executable).parent.with_name('mpl-data')
677 # Try again assuming sys.path[0] is a dir not a exe.
678 yield Path(sys.path[0]) / 'mpl-data'
680 for path in get_candidate_paths():
681 if path.is_dir():
682 defaultParams['datapath'][0] = str(path)
683 return str(path)
685 raise RuntimeError('Could not find the matplotlib data files')
688@cbook.deprecated("3.1")
689def get_py2exe_datafiles():
690 data_path = Path(get_data_path())
691 d = {}
692 for path in filter(Path.is_file, data_path.glob("**/*")):
693 (d.setdefault(str(path.parent.relative_to(data_path.parent)), [])
694 .append(str(path)))
695 return list(d.items())
698def matplotlib_fname():
699 """
700 Get the location of the config file.
702 The file location is determined in the following order
704 - ``$PWD/matplotlibrc``
705 - ``$MATPLOTLIBRC`` if it is not a directory
706 - ``$MATPLOTLIBRC/matplotlibrc``
707 - ``$MPLCONFIGDIR/matplotlibrc``
708 - On Linux,
709 - ``$XDG_CONFIG_HOME/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
710 is defined)
711 - or ``$HOME/.config/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
712 is not defined)
713 - On other platforms,
714 - ``$HOME/.matplotlib/matplotlibrc`` if ``$HOME`` is defined
715 - Lastly, it looks in ``$MATPLOTLIBDATA/matplotlibrc``, which should always
716 exist.
717 """
719 def gen_candidates():
720 yield os.path.join(os.getcwd(), 'matplotlibrc')
721 try:
722 matplotlibrc = os.environ['MATPLOTLIBRC']
723 except KeyError:
724 pass
725 else:
726 yield matplotlibrc
727 yield os.path.join(matplotlibrc, 'matplotlibrc')
728 yield os.path.join(get_configdir(), 'matplotlibrc')
729 yield os.path.join(_get_data_path(), 'matplotlibrc')
731 for fname in gen_candidates():
732 if os.path.exists(fname) and not os.path.isdir(fname):
733 return fname
735 raise RuntimeError("Could not find matplotlibrc file; your Matplotlib "
736 "install is broken")
739# rcParams deprecated and automatically mapped to another key.
740# Values are tuples of (version, new_name, f_old2new, f_new2old).
741_deprecated_map = {}
743# rcParams deprecated; some can manually be mapped to another key.
744# Values are tuples of (version, new_name_or_None).
745_deprecated_ignore_map = {
746 'pgf.debug': ('3.0', None),
747}
749# rcParams deprecated; can use None to suppress warnings; remain actually
750# listed in the rcParams (not included in _all_deprecated).
751# Values are tuples of (version,)
752_deprecated_remain_as_none = {
753 'text.latex.unicode': ('3.0',),
754 'savefig.frameon': ('3.1',),
755 'verbose.fileo': ('3.1',),
756 'verbose.level': ('3.1',),
757 'datapath': ('3.2.1',),
758}
761_all_deprecated = {*_deprecated_map, *_deprecated_ignore_map}
764class RcParams(MutableMapping, dict):
765 """
766 A dictionary object including validation.
768 Validating functions are defined and associated with rc parameters in
769 :mod:`matplotlib.rcsetup`.
771 See Also
772 --------
773 :ref:`customizing-with-matplotlibrc-files`
774 """
776 validate = {key: converter
777 for key, (default, converter) in defaultParams.items()
778 if key not in _all_deprecated}
780 # validate values on the way in
781 def __init__(self, *args, **kwargs):
782 self.update(*args, **kwargs)
784 def __setitem__(self, key, val):
785 try:
786 if key in _deprecated_map:
787 version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
788 cbook.warn_deprecated(
789 version, name=key, obj_type="rcparam", alternative=alt_key)
790 key = alt_key
791 val = alt_val(val)
792 elif key in _deprecated_remain_as_none and val is not None:
793 version, = _deprecated_remain_as_none[key]
794 cbook.warn_deprecated(
795 version, name=key, obj_type="rcparam")
796 elif key in _deprecated_ignore_map:
797 version, alt_key = _deprecated_ignore_map[key]
798 cbook.warn_deprecated(
799 version, name=key, obj_type="rcparam", alternative=alt_key)
800 return
801 elif key == 'backend':
802 if val is rcsetup._auto_backend_sentinel:
803 if 'backend' in self:
804 return
805 try:
806 cval = self.validate[key](val)
807 except ValueError as ve:
808 raise ValueError("Key %s: %s" % (key, str(ve)))
809 dict.__setitem__(self, key, cval)
810 except KeyError:
811 raise KeyError(
812 f"{key} is not a valid rc parameter (see rcParams.keys() for "
813 f"a list of valid parameters)")
815 def __getitem__(self, key):
816 if key in _deprecated_map:
817 version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
818 cbook.warn_deprecated(
819 version, name=key, obj_type="rcparam", alternative=alt_key)
820 return inverse_alt(dict.__getitem__(self, alt_key))
822 elif key in _deprecated_ignore_map:
823 version, alt_key = _deprecated_ignore_map[key]
824 cbook.warn_deprecated(
825 version, name=key, obj_type="rcparam", alternative=alt_key)
826 return dict.__getitem__(self, alt_key) if alt_key else None
828 elif key == "backend":
829 val = dict.__getitem__(self, key)
830 if val is rcsetup._auto_backend_sentinel:
831 from matplotlib import pyplot as plt
832 plt.switch_backend(rcsetup._auto_backend_sentinel)
834 return dict.__getitem__(self, key)
836 def __repr__(self):
837 class_name = self.__class__.__name__
838 indent = len(class_name) + 1
839 with cbook._suppress_matplotlib_deprecation_warning():
840 repr_split = pprint.pformat(dict(self), indent=1,
841 width=80 - indent).split('\n')
842 repr_indented = ('\n' + ' ' * indent).join(repr_split)
843 return '{}({})'.format(class_name, repr_indented)
845 def __str__(self):
846 return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items())))
848 def __iter__(self):
849 """Yield sorted list of keys."""
850 with cbook._suppress_matplotlib_deprecation_warning():
851 yield from sorted(dict.__iter__(self))
853 def __len__(self):
854 return dict.__len__(self)
856 def find_all(self, pattern):
857 """
858 Return the subset of this RcParams dictionary whose keys match,
859 using :func:`re.search`, the given ``pattern``.
861 .. note::
863 Changes to the returned dictionary are *not* propagated to
864 the parent RcParams dictionary.
866 """
867 pattern_re = re.compile(pattern)
868 return RcParams((key, value)
869 for key, value in self.items()
870 if pattern_re.search(key))
872 def copy(self):
873 return {k: dict.__getitem__(self, k) for k in self}
876def rc_params(fail_on_error=False):
877 """Construct a `RcParams` instance from the default Matplotlib rc file."""
878 return rc_params_from_file(matplotlib_fname(), fail_on_error)
881URL_REGEX = re.compile(r'^http://|^https://|^ftp://|^file:')
884def is_url(filename):
885 """Return True if string is an http, ftp, or file URL path."""
886 return URL_REGEX.match(filename) is not None
889@contextlib.contextmanager
890def _open_file_or_url(fname):
891 if not isinstance(fname, Path) and is_url(fname):
892 import urllib.request
893 with urllib.request.urlopen(fname) as f:
894 yield (line.decode('utf-8') for line in f)
895 else:
896 fname = os.path.expanduser(fname)
897 encoding = locale.getpreferredencoding(do_setlocale=False)
898 if encoding is None:
899 encoding = "utf-8"
900 with open(fname, encoding=encoding) as f:
901 yield f
904def _rc_params_in_file(fname, fail_on_error=False):
905 """
906 Construct a `RcParams` instance from file *fname*.
908 Unlike `rc_params_from_file`, the configuration class only contains the
909 parameters specified in the file (i.e. default values are not filled in).
910 """
911 _error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
913 rc_temp = {}
914 with _open_file_or_url(fname) as fd:
915 try:
916 for line_no, line in enumerate(fd, 1):
917 strippedline = line.split('#', 1)[0].strip()
918 if not strippedline:
919 continue
920 tup = strippedline.split(':', 1)
921 if len(tup) != 2:
922 error_details = _error_details_fmt % (line_no, line, fname)
923 _log.warning('Illegal %s', error_details)
924 continue
925 key, val = tup
926 key = key.strip()
927 val = val.strip()
928 if key in rc_temp:
929 _log.warning('Duplicate key in file %r line #%d.',
930 fname, line_no)
931 rc_temp[key] = (val, line, line_no)
932 except UnicodeDecodeError:
933 _log.warning('Cannot decode configuration file %s with encoding '
934 '%s, check LANG and LC_* variables.',
935 fname,
936 locale.getpreferredencoding(do_setlocale=False)
937 or 'utf-8 (default)')
938 raise
940 config = RcParams()
942 for key, (val, line, line_no) in rc_temp.items():
943 if key in defaultParams:
944 if fail_on_error:
945 config[key] = val # try to convert to proper type or raise
946 else:
947 try:
948 config[key] = val # try to convert to proper type or skip
949 except Exception as msg:
950 error_details = _error_details_fmt % (line_no, line, fname)
951 _log.warning('Bad val %r on %s\n\t%s',
952 val, error_details, msg)
953 elif key in _deprecated_ignore_map:
954 version, alt_key = _deprecated_ignore_map[key]
955 cbook.warn_deprecated(
956 version, name=key, alternative=alt_key,
957 addendum="Please update your matplotlibrc.")
958 else:
959 version = 'master' if '.post' in __version__ else f'v{__version__}'
960 print(f"""
961Bad key "{key}" on line {line_no} in
962{fname}.
963You probably need to get an updated matplotlibrc file from
964https://github.com/matplotlib/matplotlib/blob/{version}/matplotlibrc.template
965or from the matplotlib source distribution""", file=sys.stderr)
966 return config
969def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
970 """
971 Construct a `RcParams` from file *fname*.
973 Parameters
974 ----------
975 fname : str or path-like
976 Name of file parsed for Matplotlib settings.
977 fail_on_error : bool
978 If True, raise an error when the parser fails to convert a parameter.
979 use_default_template : bool
980 If True, initialize with default parameters before updating with those
981 in the given file. If False, the configuration class only contains the
982 parameters specified in the file. (Useful for updating dicts.)
983 """
984 config_from_file = _rc_params_in_file(fname, fail_on_error)
986 if not use_default_template:
987 return config_from_file
989 iter_params = defaultParams.items()
990 with cbook._suppress_matplotlib_deprecation_warning():
991 config = RcParams([(key, default) for key, (default, _) in iter_params
992 if key not in _all_deprecated])
993 config.update(config_from_file)
995 with cbook._suppress_matplotlib_deprecation_warning():
996 if config['datapath'] is None:
997 config['datapath'] = _get_data_path()
998 else:
999 config['datapath'] = get_data_path(_from_rc=config['datapath'])
1001 if "".join(config['text.latex.preamble']):
1002 _log.info("""
1003*****************************************************************
1004You have the following UNSUPPORTED LaTeX preamble customizations:
1005%s
1006Please do not ask for support with these customizations active.
1007*****************************************************************
1008""", '\n'.join(config['text.latex.preamble']))
1009 _log.debug('loaded rc file %s', fname)
1011 return config
1014# this is the instance used by the matplotlib classes
1015rcParams = rc_params()
1018with cbook._suppress_matplotlib_deprecation_warning():
1019 rcParamsOrig = RcParams(rcParams.copy())
1020 rcParamsDefault = RcParams([(key, default) for key, (default, converter) in
1021 defaultParams.items()
1022 if key not in _all_deprecated])
1024if rcParams['axes.formatter.use_locale']:
1025 locale.setlocale(locale.LC_ALL, '')
1028def rc(group, **kwargs):
1029 """
1030 Set the current rc params. *group* is the grouping for the rc, e.g.,
1031 for ``lines.linewidth`` the group is ``lines``, for
1032 ``axes.facecolor``, the group is ``axes``, and so on. Group may
1033 also be a list or tuple of group names, e.g., (*xtick*, *ytick*).
1034 *kwargs* is a dictionary attribute name/value pairs, e.g.,::
1036 rc('lines', linewidth=2, color='r')
1038 sets the current rc params and is equivalent to::
1040 rcParams['lines.linewidth'] = 2
1041 rcParams['lines.color'] = 'r'
1043 The following aliases are available to save typing for interactive users:
1045 ===== =================
1046 Alias Property
1047 ===== =================
1048 'lw' 'linewidth'
1049 'ls' 'linestyle'
1050 'c' 'color'
1051 'fc' 'facecolor'
1052 'ec' 'edgecolor'
1053 'mew' 'markeredgewidth'
1054 'aa' 'antialiased'
1055 ===== =================
1057 Thus you could abbreviate the above rc command as::
1059 rc('lines', lw=2, c='r')
1061 Note you can use python's kwargs dictionary facility to store
1062 dictionaries of default parameters. e.g., you can customize the
1063 font rc as follows::
1065 font = {'family' : 'monospace',
1066 'weight' : 'bold',
1067 'size' : 'larger'}
1068 rc('font', **font) # pass in the font dict as kwargs
1070 This enables you to easily switch between several configurations. Use
1071 ``matplotlib.style.use('default')`` or :func:`~matplotlib.rcdefaults` to
1072 restore the default rc params after changes.
1074 Notes
1075 -----
1076 Similar functionality is available by using the normal dict interface, i.e.
1077 ``rcParams.update({"lines.linewidth": 2, ...})`` (but ``rcParams.update``
1078 does not support abbreviations or grouping).
1079 """
1081 aliases = {
1082 'lw': 'linewidth',
1083 'ls': 'linestyle',
1084 'c': 'color',
1085 'fc': 'facecolor',
1086 'ec': 'edgecolor',
1087 'mew': 'markeredgewidth',
1088 'aa': 'antialiased',
1089 }
1091 if isinstance(group, str):
1092 group = (group,)
1093 for g in group:
1094 for k, v in kwargs.items():
1095 name = aliases.get(k) or k
1096 key = '%s.%s' % (g, name)
1097 try:
1098 rcParams[key] = v
1099 except KeyError:
1100 raise KeyError(('Unrecognized key "%s" for group "%s" and '
1101 'name "%s"') % (key, g, name))
1104def rcdefaults():
1105 """
1106 Restore the rc params from Matplotlib's internal default style.
1108 Style-blacklisted rc params (defined in
1109 `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
1111 See Also
1112 --------
1113 rc_file_defaults
1114 Restore the rc params from the rc file originally loaded by Matplotlib.
1115 matplotlib.style.use :
1116 Use a specific style file. Call ``style.use('default')`` to restore
1117 the default style.
1118 """
1119 # Deprecation warnings were already handled when creating rcParamsDefault,
1120 # no need to reemit them here.
1121 with cbook._suppress_matplotlib_deprecation_warning():
1122 from .style.core import STYLE_BLACKLIST
1123 rcParams.clear()
1124 rcParams.update({k: v for k, v in rcParamsDefault.items()
1125 if k not in STYLE_BLACKLIST})
1128def rc_file_defaults():
1129 """
1130 Restore the rc params from the original rc file loaded by Matplotlib.
1132 Style-blacklisted rc params (defined in
1133 `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
1134 """
1135 # Deprecation warnings were already handled when creating rcParamsOrig, no
1136 # need to reemit them here.
1137 with cbook._suppress_matplotlib_deprecation_warning():
1138 from .style.core import STYLE_BLACKLIST
1139 rcParams.update({k: rcParamsOrig[k] for k in rcParamsOrig
1140 if k not in STYLE_BLACKLIST})
1143def rc_file(fname, *, use_default_template=True):
1144 """
1145 Update rc params from file.
1147 Style-blacklisted rc params (defined in
1148 `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
1150 Parameters
1151 ----------
1152 fname : str
1153 Name of file parsed for matplotlib settings.
1155 use_default_template : bool
1156 If True, initialize with default parameters before updating with those
1157 in the given file. If False, the current configuration persists
1158 and only the parameters specified in the file are updated.
1159 """
1160 # Deprecation warnings were already handled in rc_params_from_file, no need
1161 # to reemit them here.
1162 with cbook._suppress_matplotlib_deprecation_warning():
1163 from .style.core import STYLE_BLACKLIST
1164 rc_from_file = rc_params_from_file(
1165 fname, use_default_template=use_default_template)
1166 rcParams.update({k: rc_from_file[k] for k in rc_from_file
1167 if k not in STYLE_BLACKLIST})
1170class rc_context:
1171 """
1172 Return a context manager for managing rc settings.
1174 This allows one to do::
1176 with mpl.rc_context(fname='screen.rc'):
1177 plt.plot(x, a) # uses 'screen.rc'
1178 with mpl.rc_context(fname='print.rc'):
1179 plt.plot(x, b) # uses 'print.rc'
1180 plt.plot(x, c) # uses 'screen.rc'
1182 A dictionary can also be passed to the context manager::
1184 with mpl.rc_context(rc={'text.usetex': True}, fname='screen.rc'):
1185 plt.plot(x, a)
1187 The 'rc' dictionary takes precedence over the settings loaded from
1188 'fname'. Passing a dictionary only is also valid. For example a
1189 common usage is::
1191 with mpl.rc_context(rc={'interactive': False}):
1192 fig, ax = plt.subplots()
1193 ax.plot(range(3), range(3))
1194 fig.savefig('A.png', format='png')
1195 plt.close(fig)
1196 """
1197 # While it may seem natural to implement rc_context using
1198 # contextlib.contextmanager, that would entail always calling the finally:
1199 # clause of the contextmanager (which restores the original rcs) including
1200 # during garbage collection; as a result, something like `plt.xkcd();
1201 # gc.collect()` would result in the style being lost (as `xkcd()` is
1202 # implemented on top of rc_context, and nothing is holding onto context
1203 # manager except possibly circular references.
1205 def __init__(self, rc=None, fname=None):
1206 self._orig = rcParams.copy()
1207 try:
1208 if fname:
1209 rc_file(fname)
1210 if rc:
1211 rcParams.update(rc)
1212 except Exception:
1213 self.__fallback()
1214 raise
1216 def __fallback(self):
1217 # If anything goes wrong, revert to the original rcs.
1218 updated_backend = self._orig['backend']
1219 dict.update(rcParams, self._orig)
1220 # except for the backend. If the context block triggered resolving
1221 # the auto backend resolution keep that value around
1222 if self._orig['backend'] is rcsetup._auto_backend_sentinel:
1223 rcParams['backend'] = updated_backend
1225 def __enter__(self):
1226 return self
1228 def __exit__(self, exc_type, exc_value, exc_tb):
1229 self.__fallback()
1232@cbook._rename_parameter("3.1", "arg", "backend")
1233@cbook._delete_parameter("3.1", "warn")
1234def use(backend, warn=False, force=True):
1235 """
1236 Select the backend used for rendering and GUI integration.
1238 Parameters
1239 ----------
1240 backend : str
1241 The backend to switch to. This can either be one of the standard
1242 backend names, which are case-insensitive:
1244 - interactive backends:
1245 GTK3Agg, GTK3Cairo, MacOSX, nbAgg,
1246 Qt4Agg, Qt4Cairo, Qt5Agg, Qt5Cairo,
1247 TkAgg, TkCairo, WebAgg, WX, WXAgg, WXCairo
1249 - non-interactive backends:
1250 agg, cairo, pdf, pgf, ps, svg, template
1252 or a string of the form: ``module://my.module.name``.
1254 warn : bool, optional, default: False
1255 If True and not *force*, emit a warning if a failure-to-switch
1256 `ImportError` has been suppressed. This parameter is deprecated.
1258 force : bool, optional, default: True
1259 If True (the default), raise an `ImportError` if the backend cannot be
1260 set up (either because it fails to import, or because an incompatible
1261 GUI interactive framework is already running); if False, ignore the
1262 failure.
1264 See Also
1265 --------
1266 :ref:`backends`
1267 matplotlib.get_backend
1268 """
1269 name = validate_backend(backend)
1270 if dict.__getitem__(rcParams, 'backend') == name:
1271 # Nothing to do if the requested backend is already set
1272 pass
1273 else:
1274 # Update both rcParams and rcDefaults so restoring the defaults later
1275 # with rcdefaults won't change the backend. This is a bit of overkill
1276 # as 'backend' is already in style.core.STYLE_BLACKLIST, but better to
1277 # be safe.
1278 rcParams['backend'] = rcParamsDefault['backend'] = name
1279 try:
1280 from matplotlib import pyplot as plt
1281 plt.switch_backend(name)
1282 except ImportError as exc:
1283 if force:
1284 raise
1285 if warn:
1286 cbook._warn_external(
1287 f"Failed to switch backend to {backend}: {exc}")
1290if os.environ.get('MPLBACKEND'):
1291 rcParams['backend'] = os.environ.get('MPLBACKEND')
1294def get_backend():
1295 """
1296 Return the name of the current backend.
1298 See Also
1299 --------
1300 matplotlib.use
1301 """
1302 return rcParams['backend']
1305def interactive(b):
1306 """
1307 Set whether to redraw after every plotting command (e.g. `.pyplot.xlabel`).
1308 """
1309 rcParams['interactive'] = b
1312def is_interactive():
1313 """Return whether to redraw after every plotting command."""
1314 return rcParams['interactive']
1317@cbook.deprecated("3.1", alternative="rcParams['tk.window_focus']")
1318def tk_window_focus():
1319 """
1320 Return true if focus maintenance under TkAgg on win32 is on.
1322 This currently works only for python.exe and IPython.exe.
1323 Both IDLE and Pythonwin.exe fail badly when tk_window_focus is on.
1324 """
1325 if rcParams['backend'] != 'TkAgg':
1326 return False
1327 return rcParams['tk.window_focus']
1330default_test_modules = [
1331 'matplotlib.tests',
1332 'mpl_toolkits.tests',
1333]
1336def _init_tests():
1337 # The version of FreeType to install locally for running the
1338 # tests. This must match the value in `setupext.py`
1339 LOCAL_FREETYPE_VERSION = '2.6.1'
1341 from matplotlib import ft2font
1342 if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
1343 ft2font.__freetype_build_type__ != 'local'):
1344 _log.warning(
1345 "Matplotlib is not built with the correct FreeType version to run "
1346 "tests. Set local_freetype=True in setup.cfg and rebuild. "
1347 "Expect many image comparison failures below. "
1348 "Expected freetype version {0}. "
1349 "Found freetype version {1}. "
1350 "Freetype build type is {2}local".format(
1351 LOCAL_FREETYPE_VERSION,
1352 ft2font.__freetype_version__,
1353 "" if ft2font.__freetype_build_type__ == 'local' else "not "))
1355 try:
1356 import pytest
1357 except ImportError:
1358 print("matplotlib.test requires pytest to run.")
1359 raise
1362@cbook._delete_parameter("3.2", "switch_backend_warn")
1363def test(verbosity=None, coverage=False, switch_backend_warn=True,
1364 recursionlimit=0, **kwargs):
1365 """Run the matplotlib test suite."""
1366 _init_tests()
1367 if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')):
1368 raise ImportError("Matplotlib test data is not installed")
1370 old_backend = get_backend()
1371 old_recursionlimit = sys.getrecursionlimit()
1372 try:
1373 use('agg')
1374 if recursionlimit:
1375 sys.setrecursionlimit(recursionlimit)
1376 import pytest
1378 args = kwargs.pop('argv', [])
1379 provide_default_modules = True
1380 use_pyargs = True
1381 for arg in args:
1382 if any(arg.startswith(module_path)
1383 for module_path in default_test_modules):
1384 provide_default_modules = False
1385 break
1386 if os.path.exists(arg):
1387 provide_default_modules = False
1388 use_pyargs = False
1389 break
1390 if use_pyargs:
1391 args += ['--pyargs']
1392 if provide_default_modules:
1393 args += default_test_modules
1395 if coverage:
1396 args += ['--cov']
1398 if verbosity:
1399 args += ['-' + 'v' * verbosity]
1401 retcode = pytest.main(args, **kwargs)
1402 finally:
1403 if old_backend.lower() != 'agg':
1404 use(old_backend)
1405 if recursionlimit:
1406 sys.setrecursionlimit(old_recursionlimit)
1408 return retcode
1411test.__test__ = False # pytest: this function is not a test
1414def _replacer(data, value):
1415 """
1416 Either returns ``data[value]`` or passes ``data`` back, converts either to
1417 a sequence.
1418 """
1419 try:
1420 # if key isn't a string don't bother
1421 if isinstance(value, str):
1422 # try to use __getitem__
1423 value = data[value]
1424 except Exception:
1425 # key does not exist, silently fall back to key
1426 pass
1427 return sanitize_sequence(value)
1430def _label_from_arg(y, default_name):
1431 try:
1432 return y.name
1433 except AttributeError:
1434 if isinstance(default_name, str):
1435 return default_name
1436 return None
1439_DATA_DOC_TITLE = """
1441Notes
1442-----
1443"""
1445_DATA_DOC_APPENDIX = """
1447.. note::
1448 In addition to the above described arguments, this function can take a
1449 **data** keyword argument. If such a **data** argument is given, the
1450 following arguments are replaced by **data[<arg>]**:
1452 {replaced}
1454 Objects passed as **data** must support item access (``data[<arg>]``) and
1455 membership test (``<arg> in data``).
1456"""
1459def _add_data_doc(docstring, replace_names):
1460 """Add documentation for a *data* field to the given docstring.
1462 Parameters
1463 ----------
1464 docstring : str
1465 The input docstring.
1466 replace_names : list of str or None
1467 The list of parameter names which arguments should be replaced by
1468 ``data[name]`` (if ``data[name]`` does not throw an exception). If
1469 None, replacement is attempted for all arguments.
1471 Returns
1472 -------
1473 The augmented docstring.
1474 """
1475 docstring = inspect.cleandoc(docstring) if docstring is not None else ""
1476 repl = ("* All positional and all keyword arguments."
1477 if replace_names is None else
1478 ""
1479 if len(replace_names) == 0 else
1480 "* All arguments with the following names: {}.".format(
1481 ", ".join(map(repr, sorted(replace_names)))))
1482 addendum = _DATA_DOC_APPENDIX.format(replaced=repl)
1483 if _DATA_DOC_TITLE not in docstring:
1484 addendum = _DATA_DOC_TITLE + addendum
1485 return docstring + addendum
1488def _preprocess_data(func=None, *, replace_names=None, label_namer=None):
1489 """
1490 A decorator to add a 'data' kwarg to a function.
1492 When applied::
1494 @_preprocess_data()
1495 def func(ax, *args, **kwargs): ...
1497 the signature is modified to ``decorated(ax, *args, data=None, **kwargs)``
1498 with the following behavior:
1500 - if called with ``data=None``, forward the other arguments to ``func``;
1501 - otherwise, *data* must be a mapping; for any argument passed in as a
1502 string ``name``, replace the argument by ``data[name]`` (if this does not
1503 throw an exception), then forward the arguments to ``func``.
1505 In either case, any argument that is a `MappingView` is also converted to a
1506 list.
1508 Parameters
1509 ----------
1510 replace_names : list of str or None, optional, default: None
1511 The list of parameter names for which lookup into *data* should be
1512 attempted. If None, replacement is attempted for all arguments.
1513 label_namer : str, optional, default: None
1514 If set e.g. to "namer" (which must be a kwarg in the function's
1515 signature -- not as ``**kwargs``), if the *namer* argument passed in is
1516 a (string) key of *data* and no *label* kwarg is passed, then use the
1517 (string) value of the *namer* as *label*. ::
1519 @_preprocess_data(label_namer="foo")
1520 def func(foo, label=None): ...
1522 func("key", data={"key": value})
1523 # is equivalent to
1524 func.__wrapped__(value, label="key")
1525 """
1527 if func is None: # Return the actual decorator.
1528 return functools.partial(
1529 _preprocess_data,
1530 replace_names=replace_names, label_namer=label_namer)
1532 sig = inspect.signature(func)
1533 varargs_name = None
1534 varkwargs_name = None
1535 arg_names = []
1536 params = list(sig.parameters.values())
1537 for p in params:
1538 if p.kind is Parameter.VAR_POSITIONAL:
1539 varargs_name = p.name
1540 elif p.kind is Parameter.VAR_KEYWORD:
1541 varkwargs_name = p.name
1542 else:
1543 arg_names.append(p.name)
1544 data_param = Parameter("data", Parameter.KEYWORD_ONLY, default=None)
1545 if varkwargs_name:
1546 params.insert(-1, data_param)
1547 else:
1548 params.append(data_param)
1549 new_sig = sig.replace(parameters=params)
1550 arg_names = arg_names[1:] # remove the first "ax" / self arg
1552 if replace_names is not None:
1553 replace_names = set(replace_names)
1555 assert (replace_names or set()) <= set(arg_names) or varkwargs_name, (
1556 "Matplotlib internal error: invalid replace_names ({!r}) for {!r}"
1557 .format(replace_names, func.__name__))
1558 assert label_namer is None or label_namer in arg_names, (
1559 "Matplotlib internal error: invalid label_namer ({!r}) for {!r}"
1560 .format(label_namer, func.__name__))
1562 @functools.wraps(func)
1563 def inner(ax, *args, data=None, **kwargs):
1564 if data is None:
1565 return func(ax, *map(sanitize_sequence, args), **kwargs)
1567 bound = new_sig.bind(ax, *args, **kwargs)
1568 auto_label = (bound.arguments.get(label_namer)
1569 or bound.kwargs.get(label_namer))
1571 for k, v in bound.arguments.items():
1572 if k == varkwargs_name:
1573 for k1, v1 in v.items():
1574 if replace_names is None or k1 in replace_names:
1575 v[k1] = _replacer(data, v1)
1576 elif k == varargs_name:
1577 if replace_names is None:
1578 bound.arguments[k] = tuple(_replacer(data, v1) for v1 in v)
1579 else:
1580 if replace_names is None or k in replace_names:
1581 bound.arguments[k] = _replacer(data, v)
1583 new_args = bound.args
1584 new_kwargs = bound.kwargs
1586 args_and_kwargs = {**bound.arguments, **bound.kwargs}
1587 if label_namer and "label" not in args_and_kwargs:
1588 new_kwargs["label"] = _label_from_arg(
1589 args_and_kwargs.get(label_namer), auto_label)
1591 return func(*new_args, **new_kwargs)
1593 inner.__doc__ = _add_data_doc(inner.__doc__, replace_names)
1594 inner.__signature__ = new_sig
1595 return inner
1598_log.debug('matplotlib version %s', __version__)
1599_log.debug('interactive is %s', is_interactive())
1600_log.debug('platform is %s', sys.platform)
1601_log.debug('loaded modules: %s', list(sys.modules))