Example #1
0
def report(verbose, user, password, base_url, report_file, output_file, format,
           serialization_roundtrip, orca_server_url):
    """
    Make a report. See API documentation's POST reports section for
    REPORT_FILE requirements.
    """
    set_log_level(verbose)
    token = cli_access_token(user, password)
    with open(report_file) as f:
        metadata = json.load(f)
    session = APISession(token, base_url=base_url)
    report = session.process_report_dict(metadata)
    if orca_server_url is not None:
        import plotly.io as pio
        pio.orca.config.server_url = orca_server_url
    if serialization_roundtrip:
        with mock_raw_report_endpoints(base_url):
            session.create_report(report)
            reports.compute_report(token, 'no_id', base_url)
            full_report = session.get_report('no_id')
    else:
        data = reports.get_data_for_report(session, report)
        raw_report = reports.create_raw_report_from_data(report, data)
        full_report = report.replace(raw_report=raw_report, status='complete')
    # assumed dashboard url based on api url
    dash_url = base_url.replace('api', 'dashboard')
    if ((format == 'detect' and output_file.endswith('.html'))
            or format == 'html'):
        html_report = template.render_html(full_report,
                                           dash_url,
                                           with_timeseries=True,
                                           body_only=False)
        with open(output_file, 'w') as f:
            f.write(html_report)
    elif ((format == 'detect' and output_file.endswith('.pdf'))
          or format == 'pdf'):
        pdf_report = template.render_pdf(full_report, dash_url)
        with open(output_file, 'wb') as f:
            f.write(pdf_report)
    else:
        raise ValueError("Unable to detect format")
Example #2
0
    def get(self, uuid):
        try:
            self.set_metadata(uuid)
        except DataRequestException as e:
            errors = {'errors': e.errors}
            return ReportView().get(uuid, errors=errors)

        exclude_timeseries = 'exclude_timeseries' in request.args

        # don't do the work of making a report if the format is incorrect
        if self.format_ not in ('html', 'pdf'):
            raise ValueError(
                'Only html and pdf report downloads are currently supported')

        fname = self.metadata['report_parameters']['name'].replace(
                ' ', '_')
        report_object = build_report(self.metadata)
        # render to right format
        if self.format_ == 'html':
            bytes_out = render_html(
                report_object,
                request.url_root.rstrip('/'),
                with_timeseries=not exclude_timeseries, body_only=False
            ).encode('utf-8')
        elif self.format_ == 'pdf':
            bytes_out = render_pdf(
                report_object,
                request.url_root.rstrip('/'),
            )

        out = check_sign_zip(bytes_out, fname + f'.{self.format_}',
                             current_app.config['GPG_KEY_ID'],
                             current_app.config['GPG_PASSPHRASE_FILE'])
        return send_file(
            out,
            'application/zip',
            as_attachment=True,
            attachment_filename=fname + '.zip',
            add_etags=False)
Example #3
0
def test_render_pdf_process_error(report_with_raw, dash_url, mocker):
    mocker.patch('solarforecastarbiter.reports.template.subprocess.run',
                 side_effect=subprocess.CalledProcessError(
                     cmd='', returncode=1))
    with pytest.raises(subprocess.CalledProcessError):
        template.render_pdf(report_with_raw, dash_url)
Example #4
0
def test_render_pdf_not_settled(report_with_raw, dash_url):
    if shutil.which('pdflatex') is None:  # pragma: no cover
        pytest.skip('pdflatex must be on PATH to generate PDF reports')
    with pytest.raises(RuntimeError):
        template.render_pdf(report_with_raw, dash_url, 1)
Example #5
0
def test_render_pdf_special_chars(
        ac_power_observation_metadata, ac_power_forecast_metadata, dash_url,
        fail_pdf, preprocessing_result_types, report_metrics):
    if shutil.which('pdflatex') is None:  # pragma: no cover
        pytest.skip('pdflatex must be on PATH to generate PDF reports')
    quality_flag_filter = datamodel.QualityFlagFilter(
        (
            "USER FLAGGED",
        )
    )
    forecast = ac_power_forecast_metadata.replace(
        name="ac_power forecast (why,)  ()'-_,")
    observation = ac_power_observation_metadata.replace(
        name="ac_power observations  ()'-_,")
    fxobs = datamodel.ForecastObservation(forecast,
                                          observation)
    tz = 'America/Phoenix'
    start = pd.Timestamp('20190401 0000', tz=tz)
    end = pd.Timestamp('20190404 2359', tz=tz)
    report_params = datamodel.ReportParameters(
        name="NREL MIDC OASIS GHI Forecast Analysis  ()'-_,",
        start=start,
        end=end,
        object_pairs=(fxobs,),
        metrics=("mae", "rmse", "mbe", "s"),
        categories=("total", "date", "hour"),
        filters=(quality_flag_filter,)
    )
    report = datamodel.Report(
        report_id="56c67770-9832-11e9-a535-f4939feddd83",
        report_parameters=report_params
    )
    qflags = list(
        f.quality_flags for f in report.report_parameters.filters if
        isinstance(f, datamodel.QualityFlagFilter)
    )
    qflags = list(qflags[0])
    ser_index = pd.date_range(
        start, end,
        freq=to_offset(forecast.interval_length),
        name='timestamp')
    ser = pd.Series(
        np.repeat(100, len(ser_index)), name='value',
        index=ser_index)
    pfxobs = datamodel.ProcessedForecastObservation(
        forecast.name,
        fxobs,
        forecast.interval_value_type,
        forecast.interval_length,
        forecast.interval_label,
        valid_point_count=len(ser),
        validation_results=tuple(datamodel.ValidationResult(
            flag=f, count=0) for f in qflags),
        preprocessing_results=tuple(datamodel.PreprocessingResult(
            name=t, count=0) for t in preprocessing_result_types),
        forecast_values=ser,
        observation_values=ser
    )

    figs = datamodel.RawReportPlots(
        (
            datamodel.PlotlyReportFigure.from_dict(
                {
                    'name': 'mae tucson ac_power',
                    'spec': '{"data":[{"x":[1],"y":[1],"type":"bar"}]}',
                    'pdf': fail_pdf,
                    'figure_type': 'bar',
                    'category': 'total',
                    'metric': 'mae',
                    'figure_class': 'plotly',
                }
            ),), '4.5.3',
    )
    raw = datamodel.RawReport(
        generated_at=report.report_parameters.end,
        timezone=tz,
        plots=figs,
        metrics=report_metrics(report),
        processed_forecasts_observations=(pfxobs,),
        versions=(('test',  'test_with_underscore?'),),
        messages=(datamodel.ReportMessage(
            message="Failed to make metrics for ac_power forecast ()'-_,",
            step='', level='', function=''),))
    rr = report.replace(raw_report=raw)
    rendered = template.render_pdf(rr, dash_url)
    assert rendered.startswith(b'%PDF')
Example #6
0
def test_render_pdf(report_with_raw, dash_url):
    if shutil.which('pdflatex') is None:  # pragma: no cover
        pytest.skip('pdflatex must be on PATH to generate PDF reports')
    rendered = template.render_pdf(report_with_raw, dash_url)
    assert rendered.startswith(b'%PDF')