forked from sphinx-doc/sphinx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
imgconverter.py
90 lines (79 loc) · 3.48 KB
/
imgconverter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""Image converter extension for Sphinx"""
import subprocess
import sys
from subprocess import PIPE, CalledProcessError
from typing import Any, Dict
import sphinx
from sphinx.application import Sphinx
from sphinx.errors import ExtensionError
from sphinx.locale import __
from sphinx.transforms.post_transforms.images import ImageConverter
from sphinx.util import logging
logger = logging.getLogger(__name__)
class ImagemagickConverter(ImageConverter):
conversion_rules = [
('image/svg+xml', 'image/png'),
('image/gif', 'image/png'),
('application/pdf', 'image/png'),
('application/illustrator', 'image/png'),
]
def is_available(self) -> bool:
"""Confirms the converter is available or not."""
try:
args = [self.config.image_converter, '-version']
logger.debug('Invoking %r ...', args)
subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
return True
except OSError as exc:
logger.warning(__(
"Unable to run the image conversion command %r. "
"'sphinx.ext.imgconverter' requires ImageMagick by default. "
"Ensure it is installed, or set the 'image_converter' option "
"to a custom conversion command.\n\n"
"Traceback: %s"
), self.config.image_converter, exc)
return False
except CalledProcessError as exc:
logger.warning(__('convert exited with error:\n'
'[stderr]\n%r\n[stdout]\n%r'),
exc.stderr, exc.stdout)
return False
def convert(self, _from: str, _to: str) -> bool:
"""Converts the image to expected one."""
try:
# append an index 0 to source filename to pick up the first frame
# (or first page) of image (ex. Animation GIF, PDF)
_from += '[0]'
args = ([self.config.image_converter] +
self.config.image_converter_args +
[_from, _to])
logger.debug('Invoking %r ...', args)
subprocess.run(args, stdout=PIPE, stderr=PIPE, check=True)
return True
except OSError:
logger.warning(__('convert command %r cannot be run, '
'check the image_converter setting'),
self.config.image_converter)
return False
except CalledProcessError as exc:
raise ExtensionError(__('convert exited with error:\n'
'[stderr]\n%r\n[stdout]\n%r') %
(exc.stderr, exc.stdout)) from exc
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(ImagemagickConverter)
if sys.platform == 'win32':
# On Windows, we use Imagemagik v7 by default to avoid the trouble for
# convert.exe bundled with Windows.
app.add_config_value('image_converter', 'magick', 'env')
app.add_config_value('image_converter_args', ['convert'], 'env')
else:
# On other platform, we use Imagemagick v6 by default. Especially,
# Debian/Ubuntu are still based of v6. So we can't use "magick" command
# for these platforms.
app.add_config_value('image_converter', 'convert', 'env')
app.add_config_value('image_converter_args', [], 'env')
return {
'version': sphinx.__display_version__,
'parallel_read_safe': True,
'parallel_write_safe': True,
}