@@ -283,6 +283,14 @@ def wrapper():
283
283
_ExecInfo = namedtuple ("_ExecInfo" , "executable version" )
284
284
285
285
286
+ class ExecutableNotFoundError (FileNotFoundError ):
287
+ """
288
+ Error raised when an executable that Matplotlib optionally
289
+ depends on can't be found.
290
+ """
291
+ pass
292
+
293
+
286
294
@functools .lru_cache ()
287
295
def _get_executable_info (name ):
288
296
"""
@@ -307,7 +315,7 @@ def _get_executable_info(name):
307
315
308
316
Raises
309
317
------
310
- FileNotFoundError
318
+ ExecutableNotFoundError
311
319
If the executable is not found or older than the oldest version
312
320
supported by Matplotlib.
313
321
ValueError
@@ -319,25 +327,27 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
319
327
# Search for a regex match in the output; if the match succeeds, the
320
328
# first group of the match is the version.
321
329
# Return an _ExecInfo if the executable exists, and has a version of
322
- # at least min_ver (if set); else, raise FileNotFoundError .
330
+ # at least min_ver (if set); else, raise ExecutableNotFoundError .
323
331
try :
324
332
output = subprocess .check_output (
325
333
args , stderr = subprocess .STDOUT , universal_newlines = True )
326
334
except subprocess .CalledProcessError as _cpe :
327
335
if ignore_exit_code :
328
336
output = _cpe .output
329
337
else :
330
- raise _cpe
338
+ raise ExecutableNotFoundError (str (_cpe )) from _cpe
339
+ except FileNotFoundError as _fnf :
340
+ raise ExecutableNotFoundError (str (_fnf )) from _fnf
331
341
match = re .search (regex , output )
332
342
if match :
333
343
version = LooseVersion (match .group (1 ))
334
344
if min_ver is not None and version < min_ver :
335
- raise FileNotFoundError (
345
+ raise ExecutableNotFoundError (
336
346
f"You have { args [0 ]} version { version } but the minimum "
337
347
f"version supported by Matplotlib is { min_ver } ." )
338
348
return _ExecInfo (args [0 ], version )
339
349
else :
340
- raise FileNotFoundError (
350
+ raise ExecutableNotFoundError (
341
351
f"Failed to determine the version of { args [0 ]} from "
342
352
f"{ ' ' .join (args )} , which output { output } " )
343
353
@@ -350,9 +360,10 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
350
360
for e in execs :
351
361
try :
352
362
return impl ([e , "--version" ], "(.*)" , "9" )
353
- except FileNotFoundError :
363
+ except ExecutableNotFoundError :
354
364
pass
355
- raise FileNotFoundError ("Failed to find a Ghostscript installation" )
365
+ message = "Failed to find a Ghostscript installation"
366
+ raise ExecutableNotFoundError (message )
356
367
elif name == "inkscape" :
357
368
return impl (["inkscape" , "-V" ], "^Inkscape ([^ ]*)" )
358
369
elif name == "magick" :
@@ -380,7 +391,7 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
380
391
else :
381
392
path = "convert"
382
393
if path is None :
383
- raise FileNotFoundError (
394
+ raise ExecutableNotFoundError (
384
395
"Failed to find an ImageMagick installation" )
385
396
return impl ([path , "--version" ], r"^Version: ImageMagick (\S*)" )
386
397
elif name == "pdftops" :
@@ -389,7 +400,7 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
389
400
if info and not ("3.0" <= info .version
390
401
# poppler version numbers.
391
402
or "0.9" <= info .version <= "1.0" ):
392
- raise FileNotFoundError (
403
+ raise ExecutableNotFoundError (
393
404
f"You have pdftops version { info .version } but the minimum "
394
405
f"version supported by Matplotlib is 3.0." )
395
406
return info
@@ -478,14 +489,14 @@ def checkdep_ps_distiller(s):
478
489
return False
479
490
try :
480
491
_get_executable_info ("gs" )
481
- except FileNotFoundError :
492
+ except ExecutableNotFoundError :
482
493
_log .warning (
483
494
"Setting rcParams['ps.usedistiller'] requires ghostscript." )
484
495
return False
485
496
if s == "xpdf" :
486
497
try :
487
498
_get_executable_info ("pdftops" )
488
- except FileNotFoundError :
499
+ except ExecutableNotFoundError :
489
500
_log .warning (
490
501
"Setting rcParams['ps.usedistiller'] to 'xpdf' requires xpdf." )
491
502
return False
@@ -500,12 +511,12 @@ def checkdep_usetex(s):
500
511
return False
501
512
try :
502
513
_get_executable_info ("dvipng" )
503
- except FileNotFoundError :
514
+ except ExecutableNotFoundError :
504
515
_log .warning ("usetex mode requires dvipng." )
505
516
return False
506
517
try :
507
518
_get_executable_info ("gs" )
508
- except FileNotFoundError :
519
+ except ExecutableNotFoundError :
509
520
_log .warning ("usetex mode requires ghostscript." )
510
521
return False
511
522
return True
0 commit comments