-
Notifications
You must be signed in to change notification settings - Fork 567
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
2d6302d
commit 87dae45
Showing
10 changed files
with
179 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import tempfile, os | ||
|
||
from jupyter_core.paths import jupyter_path | ||
from traitlets import default | ||
|
||
from .html import HTMLExporter | ||
|
||
|
||
class QtExporter(HTMLExporter): | ||
|
||
paginate = None | ||
|
||
def __init__(self, *args, **kwargs): | ||
self.format = self.output_mimetype.split("/")[-1] | ||
super().__init__(*args, **kwargs) | ||
|
||
@default('file_extension') | ||
def _file_extension_default(self): | ||
return "." + self.format | ||
|
||
@default('template_name') | ||
def _template_name_default(self): | ||
return "qt" + self.format | ||
|
||
@default('template_data_paths') | ||
def _template_data_paths_default(self): | ||
return jupyter_path("nbconvert", "templates", "qt" + self.format) | ||
|
||
def _check_launch_reqs(self): | ||
try: | ||
from PyQt5.QtWidgets import QApplication | ||
from .qt_screenshot import QtScreenshot | ||
except ModuleNotFoundError as e: | ||
raise RuntimeError(f"PyQtWebEngine is not installed to support Qt {self.format.upper()} conversion. " | ||
f"Please install `nbconvert[qt{self.format}]` to enable.") from e | ||
return QApplication, QtScreenshot | ||
|
||
def run_pyqtwebengine(self, html): | ||
"""Run pyqtwebengine.""" | ||
|
||
ext = ".html" | ||
temp_file = tempfile.NamedTemporaryFile(suffix=ext, delete=False) | ||
filename = f"{temp_file.name[:-len(ext)]}.{self.format}" | ||
with temp_file: | ||
temp_file.write(html.encode('utf-8')) | ||
|
||
try: | ||
QApplication, QtScreenshot = self._check_launch_reqs() | ||
app = QApplication([""]) | ||
s = QtScreenshot(app) | ||
s.capture(f"file://{temp_file.name}", filename, self.paginate) | ||
finally: | ||
# Ensure the file is deleted even if pyqtwebengine raises an exception | ||
os.unlink(temp_file.name) | ||
data = b"" | ||
if os.path.exists(filename): | ||
with open(filename, "rb") as f: | ||
data = f.read() | ||
os.unlink(filename) | ||
return data | ||
|
||
def from_notebook_node(self, nb, resources=None, **kw): | ||
self._check_launch_reqs() | ||
html, resources = super().from_notebook_node( | ||
nb, resources=resources, **kw | ||
) | ||
|
||
self.log.info(f"Building {self.format.upper()}") | ||
data = self.run_pyqtwebengine(html) | ||
self.log.info(f"{self.format.upper()} successfully created") | ||
|
||
# convert output extension | ||
# the writer above required it to be html | ||
resources['output_extension'] = f".{self.format}" | ||
|
||
return data, resources |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
from PyQt5.QtWidgets import QApplication | ||
from PyQt5 import QtCore | ||
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings | ||
from PyQt5.QtGui import QPageLayout, QPageSize | ||
|
||
|
||
class QtScreenshot(QWebEngineView): | ||
|
||
def __init__(self, app): | ||
super().__init__() | ||
self.app = app | ||
|
||
def capture(self, url, output_file, paginate): | ||
self.output_file = output_file | ||
self.paginate = paginate | ||
self.load(QtCore.QUrl(url)) | ||
self.loadFinished.connect(self.on_loaded) | ||
# Create hidden view without scrollbars | ||
self.setAttribute(QtCore.Qt.WA_DontShowOnScreen) | ||
self.page().settings().setAttribute( | ||
QWebEngineSettings.ShowScrollBars, False) | ||
if output_file.endswith(".pdf"): | ||
self.export = self.export_pdf | ||
self.page().pdfPrintingFinished.connect(lambda *args: self.app.exit()) | ||
elif output_file.endswith(".png"): | ||
self.export = self.export_png | ||
else: | ||
raise RuntimeError(f"Export file extension not supported: {output_file}") | ||
self.show() | ||
self.app.exec() | ||
|
||
def on_loaded(self): | ||
self.size = self.page().contentsSize().toSize() | ||
self.resize(self.size) | ||
# Wait for resize | ||
QtCore.QTimer.singleShot(1000, self.export) | ||
|
||
def export_pdf(self): | ||
if self.paginate: | ||
page_size = QPageSize(QPageSize.A4) | ||
page_layout = QPageLayout(page_size, QPageLayout.Portrait, QtCore.QMarginsF()) | ||
else: | ||
factor = 0.75 | ||
page_size = QPageSize(QtCore.QSizeF(self.size.width() * factor, self.size.height() * factor), QPageSize.Point) | ||
page_layout = QPageLayout(page_size, QPageLayout.Portrait, QtCore.QMarginsF()) | ||
|
||
self.page().printToPdf(self.output_file, pageLayout=page_layout) | ||
|
||
def export_png(self): | ||
self.grab().save(self.output_file, b"PNG") | ||
self.app.quit() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
"""Export to PNG via a headless browser""" | ||
|
||
# Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||
|
||
from .qt_exporter import QtExporter | ||
|
||
|
||
class QtPNGExporter(QtExporter): | ||
"""Writer designed to write to PNG files. | ||
This inherits from :class:`HTMLExporter`. It creates the HTML using the | ||
template machinery, and then uses pyqtwebengine to create a png. | ||
""" | ||
export_from_notebook = "PNG via HTML" | ||
|
||
output_mimetype = "image/png" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
"""Tests for the qtpng preprocessor""" | ||
|
||
# Copyright (c) IPython Development Team. | ||
# Distributed under the terms of the Modified BSD License. | ||
|
||
from .base import ExportersTestsBase | ||
from ..qtpng import QtPNGExporter | ||
|
||
class TestQtPNGExporter(ExportersTestsBase): | ||
"""Contains test functions for qtpng.py""" | ||
|
||
exporter_class = QtPNGExporter | ||
|
||
def test_export(self): | ||
""" | ||
Can a TemplateExporter export something? | ||
""" | ||
(output, resources) = QtPNGExporter().from_filename(self._get_notebook()) | ||
assert len(output) > 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"base_template": "lab", | ||
"mimetypes": { | ||
"image/png": true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{%- extends 'lab/index.html.j2' -%} |