Skip to content

Commit

Permalink
Kaleido (#765)
Browse files Browse the repository at this point in the history
* add plotly/kaleido requirements

* update github minimum env

* dont skip pdf rendering

* remove unused shutil import

* unset height when writing pdf plots

* flake8

* add missing assignment, flake8
  • Loading branch information
lboeman committed Dec 10, 2021
1 parent dde1c50 commit 1b99ad2
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 38 deletions.
4 changes: 2 additions & 2 deletions .github/Minimum
@@ -1,5 +1,5 @@
bokeh==1.4.0
numpy==1.18.2
pandas==1.0.3
plotly==4.5.0
pvlib==0.8.0
plotly==4.9.0
pvlib==0.8.0
3 changes: 2 additions & 1 deletion requirements.txt
Expand Up @@ -6,7 +6,7 @@ loky==2.9.0
netCDF4==1.5.3
numpy==1.18.2
pandas==1.0.3
plotly==4.5.3
plotly==4.9
psutil==5.7.0
pvlib==0.8.0
python-dateutil==2.8.1
Expand All @@ -20,3 +20,4 @@ selenium==3.141.0
matplotlib==3.2.2
jinja2==3.0.1
pytz==2021.1
kaleido==0.2.1
3 changes: 2 additions & 1 deletion setup.py
Expand Up @@ -17,9 +17,10 @@
'plotting': [
'bokeh>=1.4.0, <2',
'matplotlib',
'plotly>=4.5.0, <5',
'plotly>=4.9.0, <5',
'selenium<4',
'jinja2',
'kaleido'
],
'doc': ['sphinx<2.0', 'sphinx_rtd_theme']
}
Expand Down
14 changes: 13 additions & 1 deletion solarforecastarbiter/reports/figures/plotly_figures.py
Expand Up @@ -1164,8 +1164,16 @@ def output_pdf(fig):
pdfs. If orca is not installed, an pdf with an error message will be
returned.
"""
# If height is explicitly set on the plot, remove it before generating
# a pdf. Needs to be reset at the end of the function.
height = None
if fig.layout.height is not None:
height = fig.layout.pop('height')

try:
pdf = base64.a85encode(fig.to_image(format='pdf')).decode('utf-8')
pdf = base64.a85encode(
fig.to_image(format='pdf')
).decode('utf-8')
except Exception:
try:
name = fig.layout.title['text'][3:-4]
Expand All @@ -1174,6 +1182,10 @@ def output_pdf(fig):
logger.error('Could not generate PDF for figure %s', name)
# should have same text as fail SVG
pdf = fail_pdf

# replace height if removed
if height is not None:
fig.layout.height = height
return pdf


Expand Down
33 changes: 0 additions & 33 deletions solarforecastarbiter/reports/figures/tests/test_plotly_figures.py
@@ -1,6 +1,5 @@
import base64
import json
import shutil

import pytest

Expand Down Expand Up @@ -198,10 +197,6 @@ def test_raw_report_plots(no_stats_report):
def test_output_svg_with_plotly_figure(mocker):
logger = mocker.patch(
'solarforecastarbiter.reports.figures.plotly_figures.logger')
if shutil.which('orca') is None: # pragma: no cover
pytest.skip('orca must be on PATH to make SVGs')
if shutil.which('xvfb-run') is None: # pragma: no cover
pytest.skip('xvfb-run must be on PATH to make SVGs')
values = list(range(5))
fig = graph_objects.Figure(data=graph_objects.Scatter(x=values, y=values))
svg = figures.output_svg(fig)
Expand All @@ -213,10 +208,6 @@ def test_output_svg_with_plotly_figure(mocker):
def test_output_pdf_with_plotly_figure(mocker):
logger = mocker.patch(
'solarforecastarbiter.reports.figures.plotly_figures.logger')
if shutil.which('orca') is None: # pragma: no cover
pytest.skip('orca must be on PATH to make PDFs')
if shutil.which('xvfb-run') is None: # pragma: no cover
pytest.skip('xvfb-run must be on PATH to make PDFs')
values = list(range(5))
fig = graph_objects.Figure(data=graph_objects.Scatter(x=values, y=values))
pdf = figures.output_pdf(fig)
Expand All @@ -226,30 +217,6 @@ def test_output_pdf_with_plotly_figure(mocker):
assert not logger.error.called


def test_output_svg_with_plotly_figure_no_orca(mocker, remove_orca):
logger = mocker.patch(
'solarforecastarbiter.reports.figures.plotly_figures.logger')
values = list(range(5))
fig = graph_objects.Figure(data=graph_objects.Scatter(x=values, y=values))
svg = figures.output_svg(fig)
assert svg.startswith('<svg')
assert 'Unable' in svg
assert svg.endswith('</svg>')
assert logger.error.called


def test_output_pdf_with_plotly_figure_no_orca(mocker, remove_orca):
logger = mocker.patch(
'solarforecastarbiter.reports.figures.plotly_figures.logger')
values = list(range(5))
fig = graph_objects.Figure(data=graph_objects.Scatter(x=values, y=values))
pdf = figures.output_pdf(fig)
pdf_bytes = base64.a85decode(pdf)
assert pdf_bytes.startswith(b'%PDF-')
assert pdf_bytes.rstrip(b'\n').endswith(b'%%EOF')
assert logger.error.called


@pytest.fixture()
def metric_dataframe():
return pd.DataFrame({
Expand Down

0 comments on commit 1b99ad2

Please sign in to comment.