@@ -36,7 +36,7 @@ def get_cache_dir():
3636 return str (cache_dir )
3737
3838
39- def get_file_hash (path , block_size = 2 ** 20 ):
39+ def get_file_hash (path , block_size = 2 ** 20 , converter = None ):
4040 md5 = hashlib .md5 ()
4141 with open (path , 'rb' ) as fd :
4242 while True :
@@ -45,11 +45,13 @@ def get_file_hash(path, block_size=2 ** 20):
4545 break
4646 md5 .update (data )
4747
48- if Path (path ).suffix == '.pdf' :
49- md5 .update (str (mpl ._get_executable_info ("gs" ).version )
48+ if converter is not None :
49+ md5 .update (str (converter ._version ).encode ('utf-8' ))
50+ elif Path (path ).suffix == '.pdf' :
51+ md5 .update (str (mpl ._get_executable_info ("gs" )._version )
5052 .encode ('utf-8' ))
5153 elif Path (path ).suffix == '.svg' :
52- md5 .update (str (mpl ._get_executable_info ("inkscape" ).version )
54+ md5 .update (str (mpl ._get_executable_info ("inkscape" )._version )
5355 .encode ('utf-8' ))
5456
5557 return md5 .hexdigest ()
@@ -118,7 +120,34 @@ def _read_until(self, terminator):
118120 return bytes (buf [:- len (terminator )])
119121
120122
123+ class _QLConverter (_Converter ):
124+ def __init__ (self ):
125+ super ().__init__ ()
126+ self ._proc = None
127+ self ._tmpdir = TemporaryDirectory ()
128+ self ._tmppath = Path (self ._tmpdir .name )
129+ self ._version = mpl ._get_executable_info ("qlmanage" ).version
130+
131+ def __call__ (self , orig , dest ):
132+ try :
133+ # qlmanage does not follow symlinks so copy the file
134+ copied = str (self ._tmppath / orig .name )
135+ shutil .copy (orig , copied )
136+ subprocess .check_call (
137+ ["qlmanage" , "-t" , "-f4" , "-o" , self ._tmpdir .name , copied ],
138+ stdout = subprocess .DEVNULL ,
139+ stderr = subprocess .DEVNULL
140+ )
141+ (self ._tmppath / (orig .name + ".png" )).rename (dest )
142+ except Exception as e :
143+ raise _ConverterError (e )
144+
145+
121146class _GSConverter (_Converter ):
147+ def __init__ (self ):
148+ super ().__init__ ()
149+ self ._version = mpl ._get_executable_info ("gs" ).version
150+
122151 def __call__ (self , orig , dest ):
123152 if not self ._proc :
124153 self ._proc = subprocess .Popen (
@@ -157,8 +186,12 @@ def encode_and_escape(name):
157186
158187
159188class _SVGConverter (_Converter ):
189+ def __init__ (self ):
190+ super ().__init__ ()
191+ self ._version = mpl ._get_executable_info ("inkscape" ).version
192+
160193 def __call__ (self , orig , dest ):
161- old_inkscape = mpl . _get_executable_info ( "inkscape" ). version < "1"
194+ old_inkscape = self . _version < "1"
162195 terminator = b"\n >" if old_inkscape else b"> "
163196 if not hasattr (self , "_tmpdir" ):
164197 self ._tmpdir = TemporaryDirectory ()
@@ -226,18 +259,26 @@ def __del__(self):
226259
227260
228261def _update_converter ():
262+ try :
263+ mpl ._get_executable_info ("qlmanage" )
264+ except mpl .ExecutableNotFoundError :
265+ pass
266+ else :
267+ converter ['pdf' ] = converter ['svg' ] = _QLConverter ()
229268 try :
230269 mpl ._get_executable_info ("gs" )
231270 except mpl .ExecutableNotFoundError :
232271 pass
233272 else :
234- converter ['pdf' ] = converter ['eps' ] = _GSConverter ()
273+ conv = _GSConverter ()
274+ converter .setdefault ('eps' , conv )
275+ converter .setdefault ('pdf' , conv )
235276 try :
236277 mpl ._get_executable_info ("inkscape" )
237278 except mpl .ExecutableNotFoundError :
238279 pass
239280 else :
240- converter [ 'svg' ] = _SVGConverter ()
281+ converter . setdefault ( 'svg' , _SVGConverter () )
241282
242283
243284#: A dictionary that maps filename extensions to functions which
@@ -283,15 +324,16 @@ def convert(filename, cache):
283324 # is out of date.
284325 if not newpath .exists () or newpath .stat ().st_mtime < path .stat ().st_mtime :
285326 cache_dir = Path (get_cache_dir ()) if cache else None
327+ cvt = converter [path .suffix [1 :]]
286328
287329 if cache_dir is not None :
288- hash_value = get_file_hash (path )
330+ hash_value = get_file_hash (path , converter = cvt )
289331 cached_path = cache_dir / (hash_value + newpath .suffix )
290332 if cached_path .exists ():
291333 shutil .copyfile (cached_path , newpath )
292334 return str (newpath )
293335
294- converter [ path . suffix [ 1 :]] (path , newpath )
336+ cvt (path , newpath )
295337
296338 if cache_dir is not None :
297339 shutil .copyfile (newpath , cached_path )
0 commit comments