@@ -36,7 +36,7 @@ def get_cache_dir():
36
36
return str (cache_dir )
37
37
38
38
39
- def get_file_hash (path , block_size = 2 ** 20 ):
39
+ def get_file_hash (path , block_size = 2 ** 20 , converter = None ):
40
40
md5 = hashlib .md5 ()
41
41
with open (path , 'rb' ) as fd :
42
42
while True :
@@ -45,11 +45,13 @@ def get_file_hash(path, block_size=2 ** 20):
45
45
break
46
46
md5 .update (data )
47
47
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 )
50
52
.encode ('utf-8' ))
51
53
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 )
53
55
.encode ('utf-8' ))
54
56
55
57
return md5 .hexdigest ()
@@ -118,7 +120,34 @@ def _read_until(self, terminator):
118
120
return bytes (buf [:- len (terminator )])
119
121
120
122
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
+
121
146
class _GSConverter (_Converter ):
147
+ def __init__ (self ):
148
+ super ().__init__ ()
149
+ self ._version = mpl ._get_executable_info ("gs" ).version
150
+
122
151
def __call__ (self , orig , dest ):
123
152
if not self ._proc :
124
153
self ._proc = subprocess .Popen (
@@ -157,8 +186,12 @@ def encode_and_escape(name):
157
186
158
187
159
188
class _SVGConverter (_Converter ):
189
+ def __init__ (self ):
190
+ super ().__init__ ()
191
+ self ._version = mpl ._get_executable_info ("inkscape" ).version
192
+
160
193
def __call__ (self , orig , dest ):
161
- old_inkscape = mpl . _get_executable_info ( "inkscape" ). version < "1"
194
+ old_inkscape = self . _version < "1"
162
195
terminator = b"\n >" if old_inkscape else b"> "
163
196
if not hasattr (self , "_tmpdir" ):
164
197
self ._tmpdir = TemporaryDirectory ()
@@ -226,18 +259,26 @@ def __del__(self):
226
259
227
260
228
261
def _update_converter ():
262
+ try :
263
+ mpl ._get_executable_info ("qlmanage" )
264
+ except mpl .ExecutableNotFoundError :
265
+ pass
266
+ else :
267
+ converter ['pdf' ] = converter ['svg' ] = _QLConverter ()
229
268
try :
230
269
mpl ._get_executable_info ("gs" )
231
270
except mpl .ExecutableNotFoundError :
232
271
pass
233
272
else :
234
- converter ['pdf' ] = converter ['eps' ] = _GSConverter ()
273
+ conv = _GSConverter ()
274
+ converter .setdefault ('eps' , conv )
275
+ converter .setdefault ('pdf' , conv )
235
276
try :
236
277
mpl ._get_executable_info ("inkscape" )
237
278
except mpl .ExecutableNotFoundError :
238
279
pass
239
280
else :
240
- converter [ 'svg' ] = _SVGConverter ()
281
+ converter . setdefault ( 'svg' , _SVGConverter () )
241
282
242
283
243
284
#: A dictionary that maps filename extensions to functions which
@@ -283,15 +324,16 @@ def convert(filename, cache):
283
324
# is out of date.
284
325
if not newpath .exists () or newpath .stat ().st_mtime < path .stat ().st_mtime :
285
326
cache_dir = Path (get_cache_dir ()) if cache else None
327
+ cvt = converter [path .suffix [1 :]]
286
328
287
329
if cache_dir is not None :
288
- hash_value = get_file_hash (path )
330
+ hash_value = get_file_hash (path , converter = cvt )
289
331
cached_path = cache_dir / (hash_value + newpath .suffix )
290
332
if cached_path .exists ():
291
333
shutil .copyfile (cached_path , newpath )
292
334
return str (newpath )
293
335
294
- converter [ path . suffix [ 1 :]] (path , newpath )
336
+ cvt (path , newpath )
295
337
296
338
if cache_dir is not None :
297
339
shutil .copyfile (newpath , cached_path )
0 commit comments