Skip to content

Commit 3d1b29b

Browse files
tacaswellmeeseeksmachine
authored andcommitted
Backport PR #28541: MNT: be more careful about disk I/O failures when writing font cache
1 parent 80c96ef commit 3d1b29b

File tree

2 files changed

+27
-5
lines changed

2 files changed

+27
-5
lines changed

lib/matplotlib/font_manager.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -965,11 +965,11 @@ def json_dump(data, filename):
965965
This function temporarily locks the output file to prevent multiple
966966
processes from overwriting one another's output.
967967
"""
968-
with cbook._lock_path(filename), open(filename, 'w') as fh:
969-
try:
968+
try:
969+
with cbook._lock_path(filename), open(filename, 'w') as fh:
970970
json.dump(data, fh, cls=_JSONEncoder, indent=2)
971-
except OSError as e:
972-
_log.warning('Could not save font_manager cache %s', e)
971+
except OSError as e:
972+
_log.warning('Could not save font_manager cache %s', e)
973973

974974

975975
def json_load(filename):

lib/matplotlib/tests/test_font_manager.py

+23-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
json_dump, json_load, get_font, is_opentype_cff_font,
1717
MSUserFontDirectories, _get_fontconfig_fonts, ttfFontProperty)
1818
from matplotlib import cbook, ft2font, pyplot as plt, rc_context, figure as mfigure
19-
from matplotlib.testing import subprocess_run_helper
19+
from matplotlib.testing import subprocess_run_helper, subprocess_run_for_testing
2020

2121

2222
has_fclist = shutil.which('fc-list') is not None
@@ -280,6 +280,28 @@ def test_fontcache_thread_safe():
280280
subprocess_run_helper(_test_threading, timeout=10)
281281

282282

283+
def test_lockfilefailure(tmp_path):
284+
# The logic here:
285+
# 1. get a temp directory from pytest
286+
# 2. import matplotlib which makes sure it exists
287+
# 3. get the cache dir (where we check it is writable)
288+
# 4. make it not writable
289+
# 5. try to write into it via font manager
290+
proc = subprocess_run_for_testing(
291+
[
292+
sys.executable,
293+
"-c",
294+
"import matplotlib;"
295+
"import os;"
296+
"p = matplotlib.get_cachedir();"
297+
"os.chmod(p, 0o555);"
298+
"import matplotlib.font_manager;"
299+
],
300+
env={**os.environ, 'MPLCONFIGDIR': str(tmp_path)},
301+
check=True
302+
)
303+
304+
283305
def test_fontentry_dataclass():
284306
fontent = FontEntry(name='font-name')
285307

0 commit comments

Comments
 (0)