From 694d69e00989d5eb154cfb93d1496dbba6878e8e Mon Sep 17 00:00:00 2001 From: Antony Lee Date: Fri, 13 Dec 2019 21:39:23 +0100 Subject: [PATCH] Warn if a temporary config/cache dir must be created. Paying the cost of regen'ing the font cache on every import seems a bit silly when one can just set MPLCONFIGDIR to a persistent directory. Moreover the tmpdir approach is brittle against forking; this is fixable but somewhat complex to do. --- lib/matplotlib/__init__.py | 24 +++++++++++++----------- lib/matplotlib/tests/test_matplotlib.py | 23 ++++++++++++++++++++++- 2 files changed, 35 insertions(+), 12 deletions(-) diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 0e8ff7938006..03837b3609ec 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -431,16 +431,6 @@ def get_home(): return None -def _create_tmp_config_or_cache_dir(): - """ - If the config or cache directory cannot be created, create a temporary one. - """ - configdir = os.environ['MPLCONFIGDIR'] = ( - tempfile.mkdtemp(prefix='matplotlib-')) - atexit.register(shutil.rmtree, configdir) - return configdir - - def _get_xdg_config_dir(): """ Return the XDG configuration directory, according to the `XDG @@ -474,7 +464,19 @@ def _get_config_or_cache_dir(xdg_base): else: if os.access(str(configdir), os.W_OK) and configdir.is_dir(): return str(configdir) - return _create_tmp_config_or_cache_dir() + # If the config or cache directory cannot be created or is not a writable + # directory, create a temporary one. + tmpdir = os.environ["MPLCONFIGDIR"] = \ + tempfile.mkdtemp(prefix="matplotlib-") + atexit.register(shutil.rmtree, tmpdir) + _log.warning( + "Matplotlib created a temporary config/cache directory at %s because " + "the default path (%s) is not a writable directory; 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.", + configdir, tmpdir) + return tmpdir @_logged_cached('CONFIGDIR=%s') diff --git a/lib/matplotlib/tests/test_matplotlib.py b/lib/matplotlib/tests/test_matplotlib.py index 3981e8009993..8bbbd2cff806 100644 --- a/lib/matplotlib/tests/test_matplotlib.py +++ b/lib/matplotlib/tests/test_matplotlib.py @@ -1,5 +1,26 @@ +import os +import subprocess +import sys + +import pytest + import matplotlib -import matplotlib.rcsetup + + +@pytest.mark.skipif( + os.name == "nt", reason="chmod() doesn't work as is on Windows") +def test_tmpconfigdir_warning(tmpdir): + """Test that a warning is emitted if a temporary configdir must be used.""" + mode = os.stat(tmpdir).st_mode + try: + os.chmod(tmpdir, 0) + proc = subprocess.run( + [sys.executable, "-c", "import matplotlib"], + env={**os.environ, "MPLCONFIGDIR": str(tmpdir)}, + stderr=subprocess.PIPE, universal_newlines=True, check=True) + assert "set the MPLCONFIGDIR" in proc.stderr + finally: + os.chmod(tmpdir, mode) def test_use_doc_standard_backends():