hub/venv/lib/python3.7/site-packages/nbconvert/preprocessors/svg2pdf.py

111 lines
3.6 KiB
Python

"""Module containing a preprocessor that converts outputs in the notebook from
one format to another.
"""
# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.
import base64
import io
import os
import sys
import subprocess
from ipython_genutils.py3compat import cast_unicode_py2
from testpath.tempdir import TemporaryDirectory
from traitlets import Unicode, default
from .convertfigures import ConvertFiguresPreprocessor
if sys.version_info >= (3,3):
from shutil import which
get_inkscape_path = which('inkscape')
else:
get_inkscape_path = None
INKSCAPE_APP = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'
if sys.platform == "win32":
try:
import winreg
except ImportError:
import _winreg as winreg
class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):
"""
Converts all of the outputs in a notebook from SVG to PDF.
"""
@default('from_format')
def _from_format_default(self):
return 'image/svg+xml'
@default('to_format')
def _to_format_default(self):
return 'application/pdf'
command = Unicode(
help="""The command to use for converting SVG to PDF
This string is a template, which will be formatted with the keys
to_filename and from_filename.
The conversion call must read the SVG from {from_filename},
and write a PDF to {to_filename}.
""").tag(config=True)
@default('command')
def _command_default(self):
return self.inkscape + \
' --without-gui --export-pdf="{to_filename}" "{from_filename}"'
inkscape = Unicode(help="The path to Inkscape, if necessary").tag(config=True)
@default('inkscape')
def _inkscape_default(self):
if get_inkscape_path is not None:
return get_inkscape_path
if sys.platform == "darwin":
if os.path.isfile(INKSCAPE_APP):
return INKSCAPE_APP
if sys.platform == "win32":
wr_handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
try:
rkey = winreg.OpenKey(wr_handle, "SOFTWARE\\Classes\\inkscape.svg\\DefaultIcon")
inkscape = winreg.QueryValueEx(rkey, "")[0]
except FileNotFoundError:
raise FileNotFoundError("Inkscape executable not found")
return inkscape
return "inkscape"
def convert_figure(self, data_format, data):
"""
Convert a single SVG figure to PDF. Returns converted data.
"""
#Work in a temporary directory
with TemporaryDirectory() as tmpdir:
#Write fig to temp file
input_filename = os.path.join(tmpdir, 'figure.svg')
# SVG data is unicode text
with io.open(input_filename, 'w', encoding='utf8') as f:
f.write(cast_unicode_py2(data))
#Call conversion application
output_filename = os.path.join(tmpdir, 'figure.pdf')
shell = self.command.format(from_filename=input_filename,
to_filename=output_filename)
subprocess.call(shell, shell=True) #Shell=True okay since input is trusted.
#Read output from drive
# return value expects a filename
if os.path.isfile(output_filename):
with open(output_filename, 'rb') as f:
# PDF is a nb supported binary, data type, so base64 encode.
return base64.encodestring(f.read())
else:
raise TypeError("Inkscape svg to pdf conversion failed")