8000 Merge pull request #10596 from anntzer/filelock · matplotlib/matplotlib@8184e1f · GitHub
[go: up one dir, main page]

Skip to content

Commit 8184e1f

Browse files
authored
Merge pull request #10596 from anntzer/filelock
Switch to per-file locking.
2 parents cc127eb + e0283a9 commit 8184e1f

File tree

4 files changed

+46
-11
lines changed

4 files changed

+46
-11
lines changed

doc/api/next_api_changes/2018-02-15-AL-deprecations.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ The following functions and classes are deprecated:
1010

1111
- ``cbook.GetRealpathAndStat`` (which is only a helper for
1212
``get_realpath_and_stat``),
13+
- ``cbook.Locked``,
1314
- ``cbook.is_numlike`` (use ``isinstance(..., numbers.Number)`` instead),
1415
- ``mathtext.unichr_safe`` (use ``chr`` instead),
1516
- ``texmanager.dvipng_hack_alpha``,

lib/matplotlib/cbook/__init__.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import numbers
2525
import operator
2626
import os
27+
from pathlib import Path
2728
import re
2829
import sys
2930
import time
@@ -1941,6 +1942,7 @@ def get_label(y, default_name):
19411942
"""
19421943

19431944

1945+
@deprecated("3.0")
19441946
class Locked(object):
19451947
"""
19461948
Context manager to handle locks.
@@ -1996,6 +1998,40 @@ def __exit__(self, exc_type, exc_value, traceback):
19961998
pass
19971999

19982000

2001+
@contextlib.contextmanager
2002+
def _lock_path(path):
2003+
"""
2004+
Context manager for locking a path.
2005+
2006+
Usage::
2007+
2008+
with _lock_path(path):
2009+
...
2010+
2011+
Another thread or process that attempts to lock the same path will wait
2012+
until this context manager is exited.
2013+
2014+
The lock is implemented by creating a temporary file in the parent
2015+
directory, so that directory must exist and be writable.
2016+
"""
2017+
path = Path(path)
2018+
lock_path = path.with_name(path.name + ".matplotlib-lock")
2019+
retries = 50
2020+
sleeptime = 0.1
2021+
for _ in range(retries):
2022+
try:
2023+
with lock_path.open("xb"):
2024+
break
2025+
except FileExistsError:
2026+
time.sleep(sleeptime)
2027+
else:
2028+
raise TimeoutError(_lockstr.format(lock_path))
2029+
try:
2030+
yield
2031+
finally:
2032+
lock_path.unlink()
2033+
2034+
19992035
def _topmost_artist(
20002036
artists,
20012037
_cached_max=functools.partial(max, key=operator.attrgetter("zorder"))):

lib/matplotlib/font_manager.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1378,7 +1378,7 @@ def _rebuild():
13781378
fontManager = FontManager()
13791379

13801380
if _fmcache:
1381-
with cbook.Locked(cachedir):
1381+
with cbook._lock_path(_fmcache):
13821382
json_dump(fontManager, _fmcache)
13831383
_log.info("generated new fontManager")
13841384

@@ -1391,9 +1391,9 @@ def _rebuild():
13911391
else:
13921392
fontManager.default_size = None
13931393
_log.debug("Using fontManager instance from %s", _fmcache)
1394-
except cbook.Locked.TimeoutError:
1394+
except TimeoutError:
13951395
raise
1396-
except:
1396+
except Exception:
13971397
_rebuild()
13981398
else:
13991399
_rebuild()

lib/matplotlib/texmanager.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,22 @@
3636
import six
3737

3838
import copy
39+
import distutils.version
3940
import glob
4041
import hashlib
4142
import logging
4243
import os
4344
from pathlib import Path
45+
import re
4446
import shutil
4547
import subprocess
4648
import sys
4749
import warnings
4850

49-
import distutils.version
5051
import numpy as np
52+
5153
import matplotlib as mpl
52-
from matplotlib import rcParams
53-
from matplotlib._png import read_png
54-
from matplotlib.cbook import Locked
55-
import matplotlib.dviread as dviread
56-
import re
54+
from matplotlib import _png, cbook, dviread, rcParams
5755

5856
_log = logging.getLogger(__name__)
5957

@@ -338,7 +336,7 @@ def make_dvi(self, tex, fontsize):
338336
dvifile = '%s.dvi' % basefile
339337
if not os.path.exists(dvifile):
340338
texfile = self.make_tex(tex, fontsize)
341-
with Locked(self.texcache):
339+
with cbook._lock_path(texfile):
342340
self._run_checked_subprocess(
343341
["latex", "-interaction=nonstopmode", "--halt-on-error",
344342
texfile], tex)
@@ -434,7 +432,7 @@ def get_grey(self, tex, fontsize=None, dpi=None):
434432
alpha = self.grey_arrayd.get(key)
435433
if alpha is None:
436434
pngfile = self.make_png(tex, fontsize, dpi)
437-
X = read_png(os.path.join(self.texcache, pngfile))
435+
X = _png.read_png(os.path.join(self.texcache, pngfile))
438436
self.grey_arrayd[key] = alpha = X[:, :, -1]
439437
return alpha
440438

0 commit comments

Comments
 (0)
0