Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit37afee2

Browse files
committed
Use QuickLook instead of gs and inkscape on MacOS
qlmanage is built into MacOS since 10.5 and is faster to call thaneither of the alternatives
1 parentd8db93f commit37afee2

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

‎INSTALL.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@ To run the test suite:
5555
directories from the source distribution.
5656
* install test dependencies: `pytest<https://pypi.org/project/pytest>`_,
5757
MiKTeX, GhostScript, ffmpeg, avconv, ImageMagick, and `Inkscape
58-
<https://inkscape.org/>`_.
58+
<https://inkscape.org/>`_. On MacOS, GhostScript and Inkscape are not
59+
needed.
5960
* run ``python -mpytest``.
6061

6162
Third-party distributions of Matplotlib
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Image comparisons use QuickLook on MacOS
2+
----------------------------------------
3+
4+
Previously, you had to install Inkscape and GhostScript to convert the
5+
svg and pdf files generated by the test suite into bitmap files. Now,
6+
we use MacOS's built-in QuickLook instead.

‎lib/matplotlib/__init__.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,8 +268,8 @@ def _get_executable_info(name):
268268
----------
269269
name : str
270270
The executable to query. The following values are currently supported:
271-
"dvipng", "gs", "inkscape", "magick", "pdftops". This list is subject
272-
to change without notice.
271+
"dvipng", "gs", "inkscape", "magick", "pdftops", "qlmanage". This list
272+
is subjectto change without notice.
273273
274274
Returns
275275
-------
@@ -378,6 +378,17 @@ def impl(args, regex, min_ver=None, ignore_exit_code=False):
378378
f"You have pdftops version{info.version} but the minimum "
379379
f"version supported by Matplotlib is 3.0")
380380
returninfo
381+
elifname=="qlmanage":
382+
try:
383+
subprocess.check_call(
384+
["qlmanage","-h"],
385+
stdout=subprocess.DEVNULL,
386+
stderr=subprocess.DEVNULL
387+
)
388+
exceptsubprocess.CalledProcessError:
389+
raiseExecutableNotFoundError()
390+
return_ExecInfo("qlmanage","")
391+
381392
else:
382393
raiseValueError("Unknown executable: {!r}".format(name))
383394

‎lib/matplotlib/testing/compare.py

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ def get_cache_dir():
3636
returnstr(cache_dir)
3737

3838

39-
defget_file_hash(path,block_size=2**20):
39+
defget_file_hash(path,block_size=2**20,converter=None):
4040
md5=hashlib.md5()
4141
withopen(path,'rb')asfd:
4242
whileTrue:
@@ -45,11 +45,13 @@ def get_file_hash(path, block_size=2 ** 20):
4545
break
4646
md5.update(data)
4747

48-
ifPath(path).suffix=='.pdf':
49-
md5.update(str(mpl._get_executable_info("gs").version)
48+
ifconverterisnotNone:
49+
md5.update(str(converter._version).encode('utf-8'))
50+
elifPath(path).suffix=='.pdf':
51+
md5.update(str(mpl._get_executable_info("gs")._version)
5052
.encode('utf-8'))
5153
elifPath(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
returnmd5.hexdigest()
@@ -118,7 +120,34 @@ def _read_until(self, terminator):
118120
returnbytes(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='qlmanage'
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","-f8","-o",self._tmpdir.name,copied],
138+
stdout=subprocess.DEVNULL,
139+
stderr=subprocess.DEVNULL
140+
)
141+
(self._tmppath/ (orig.name+".png")).rename(dest)
142+
exceptExceptionase:
143+
raise_ConverterError(e)
144+
145+
121146
class_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
ifnotself._proc:
124153
self._proc=subprocess.Popen(
@@ -157,8 +186,12 @@ def encode_and_escape(name):
157186

158187

159188
class_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>"ifold_inkscapeelseb"> "
163196
ifnothasattr(self,"_tmpdir"):
164197
self._tmpdir=TemporaryDirectory()
@@ -226,18 +259,26 @@ def __del__(self):
226259

227260

228261
def_update_converter():
262+
try:
263+
mpl._get_executable_info("qlmanage")
264+
exceptmpl.ExecutableNotFoundError:
265+
pass
266+
else:
267+
converter['pdf']=converter['svg']=_QLConverter()
229268
try:
230269
mpl._get_executable_info("gs")
231270
exceptmpl.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
exceptmpl.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
ifnotnewpath.exists()ornewpath.stat().st_mtime<path.stat().st_mtime:
285326
cache_dir=Path(get_cache_dir())ifcacheelseNone
327+
cvt=converter[path.suffix[1:]]
286328

287329
ifcache_dirisnotNone:
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
ifcached_path.exists():
291333
shutil.copyfile(cached_path,newpath)
292334
returnstr(newpath)
293335

294-
converter[path.suffix[1:]](path,newpath)
336+
cvt(path,newpath)
295337

296338
ifcache_dirisnotNone:
297339
shutil.copyfile(newpath,cached_path)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp