11
11
import subprocess
12
12
import sys
13
13
import tempfile
14
+ from tempfile import TemporaryDirectory
14
15
import weakref
15
16
16
17
from PIL import Image
@@ -208,7 +209,6 @@ class LatexManager:
208
209
determining the metrics of text elements. The LaTeX environment can be
209
210
modified by setting fonts and/or a custom preamble in `.rcParams`.
210
211
"""
211
- _unclean_instances = weakref .WeakSet ()
212
212
213
213
@staticmethod
214
214
def _build_latex_header ():
@@ -245,12 +245,6 @@ def _get_cached_or_new(cls):
245
245
def _get_cached_or_new_impl (cls , header ): # Helper for _get_cached_or_new.
246
246
return cls ()
247
247
248
- @staticmethod
249
- def _cleanup_remaining_instances ():
250
- unclean_instances = list (LatexManager ._unclean_instances )
251
- for latex_manager in unclean_instances :
252
- latex_manager ._cleanup ()
253
-
254
248
def _stdin_writeln (self , s ):
255
249
if self .latex is None :
256
250
self ._setup_latex_process ()
@@ -276,13 +270,10 @@ def _expect_prompt(self):
276
270
return self ._expect ("\n *" )
277
271
278
272
def __init__ (self ):
279
- # store references for __del__
280
- self ._os_path = os .path
281
- self ._shutil = shutil
282
-
283
- # create a tmp directory for running latex, remember to cleanup
284
- self .tmpdir = tempfile .mkdtemp (prefix = "mpl_pgf_lm_" )
285
- LatexManager ._unclean_instances .add (self )
273
+ # create a tmp directory for running latex, register it for deletion
274
+ self ._tmpdir = TemporaryDirectory ()
275
+ self .tmpdir = self ._tmpdir .name
276
+ self ._finalize_tmpdir = weakref .finalize (self , self ._tmpdir .cleanup )
286
277
287
278
# test the LaTeX setup to ensure a clean startup of the subprocess
288
279
self .texcommand = mpl .rcParams ["pgf.texsystem" ]
@@ -311,11 +302,21 @@ def __init__(self):
311
302
self .str_cache = {} # cache for strings already processed
312
303
313
304
def _setup_latex_process (self ):
314
- # open LaTeX process for real work
305
+ # Open LaTeX process for real work; register it for deletion. On
306
+ # Windows, we must ensure that the subprocess has quit before being
307
+ # able to delete the tmpdir in which it runs; in order to do so, we
308
+ # must first `kill()` it, and then `communicate()` with it.
315
309
self .latex = subprocess .Popen (
316
310
[self .texcommand , "-halt-on-error" ],
317
311
stdin = subprocess .PIPE , stdout = subprocess .PIPE ,
318
312
encoding = "utf-8" , cwd = self .tmpdir )
313
+
314
+ def finalize_latex (latex ):
315
+ latex .kill ()
316
+ latex .communicate ()
317
+
318
+ self ._finalize_latex = weakref .finalize (
319
+ self , finalize_latex , self .latex )
319
320
# write header with 'pgf_backend_query_start' token
320
321
self ._stdin_writeln (self ._build_latex_header ())
321
322
# read all lines until our 'pgf_backend_query_start' token appears
@@ -326,23 +327,6 @@ def _setup_latex_process(self):
326
327
def latex_stdin_utf8 (self ):
327
328
return self .latex .stdin
328
329
329
- def _cleanup (self ):
330
- if not self ._os_path .isdir (self .tmpdir ):
331
- return
332
- try :
333
- self .latex .communicate ()
334
- except Exception :
335
- pass
336
- try :
337
- self ._shutil .rmtree (self .tmpdir )
338
- LatexManager ._unclean_instances .discard (self )
339
- except Exception :
340
- sys .stderr .write ("error deleting tmp directory %s\n " % self .tmpdir )
341
-
342
- def __del__ (self ):
343
- _log .debug ("deleting LatexManager" )
344
- self ._cleanup ()
345
-
346
330
def get_width_height_descent (self , text , prop ):
347
331
"""
348
332
Get the width, total height and descent for a text typeset by the
@@ -779,15 +763,20 @@ class GraphicsContextPgf(GraphicsContextBase):
779
763
780
764
781
765
class TmpDirCleaner :
782
- remaining_tmpdirs = set ()
766
+ _remaining_tmpdirs = set ()
767
+
768
+ @cbook ._classproperty
769
+ def remaining_tmpdirs (cls ):
770
+ return cls ._remaining_tmpdirs
783
771
784
772
@staticmethod
785
773
def add (tmpdir ):
786
- TmpDirCleaner .remaining_tmpdirs .add (tmpdir )
774
+ TmpDirCleaner ._remaining_tmpdirs .add (tmpdir )
787
775
788
776
@staticmethod
777
+ @atexit .register
789
778
def cleanup_remaining_tmpdirs ():
790
- for tmpdir in TmpDirCleaner .remaining_tmpdirs :
779
+ for tmpdir in TmpDirCleaner ._remaining_tmpdirs :
791
780
error_message = "error deleting tmp directory {}" .format (tmpdir )
792
781
shutil .rmtree (
793
782
tmpdir ,
@@ -979,14 +968,6 @@ class _BackendPgf(_Backend):
979
968
FigureCanvas = FigureCanvasPgf
980
969
981
970
982
- def _cleanup_all ():
983
- LatexManager ._cleanup_remaining_instances ()
984
- TmpDirCleaner .cleanup_remaining_tmpdirs ()
985
-
986
-
987
- atexit .register (_cleanup_all )
988
-
989
-
990
971
class PdfPages :
991
972
"""
992
973
A multi-page PDF file using the pgf backend
0 commit comments