Skip to content

Commit

Permalink
642 add report cli command (#659)
Browse files Browse the repository at this point in the history
* Creating Reporter and PandasReporter classes with their corresponding report_config schemas.

Signed-off-by: victor <victor@seita.nl>

* Added Tibber Reporter.

Signed-off-by: victor <victor@seita.nl>

* - Fixing wong DA Price value.
- Renaming BWV and EB to english words.
- Simplifying calculation (pandas pipeline).
- Adding units to sensors.
- Changing units from EUR/kWh to EUR/MWh
- Adding assert to check maximum error
- deserialize_report_config -> deserialize_reporter_config
- Warning when a string starting with  `@` is used in the method query or eval.
- Making process_pandas_args, process_pandas_kwargs and apply_transformation private methods.

Signed-off-by: victor <victor@seita.nl>

* Updating VAT units.

Signed-off-by: victor <victor@seita.nl>

* - Attatching report to sensor
- Output type of compute is BeliefDataFrame
- Added a global input resolution to schem
- ISO datetime and timedeltas
- start, end and input_resolution are considered serialized when passed to the method compute
- assert to check that result resolution = sensor resolution

Signed-off-by: victor <victor@seita.nl>

* Fixing wrong arguments to search_beliefs method.

Signed-off-by: victor <victor@seita.nl>

* FIxing wrong type conversion logic.

Signed-off-by: victor <victor@seita.nl>

* Small reporter fixes (#647)

* No return value

Signed-off-by: F.N. Claessen <felix@seita.nl>

* typo

Signed-off-by: F.N. Claessen <felix@seita.nl>

* plural

Signed-off-by: F.N. Claessen <felix@seita.nl>

* indentation

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix return type annotations

Signed-off-by: F.N. Claessen <felix@seita.nl>

* format docstring example

Signed-off-by: F.N. Claessen <felix@seita.nl>

* add type annotations

Signed-off-by: F.N. Claessen <felix@seita.nl>

* predefine instance attributes

Signed-off-by: F.N. Claessen <felix@seita.nl>

* remove redundant variable

Signed-off-by: F.N. Claessen <felix@seita.nl>

* grammar

Signed-off-by: F.N. Claessen <felix@seita.nl>

* support aliases

Signed-off-by: F.N. Claessen <felix@seita.nl>

* grammar/typos

Signed-off-by: F.N. Claessen <felix@seita.nl>

* test exact match

Signed-off-by: F.N. Claessen <felix@seita.nl>

---------

Signed-off-by: F.N. Claessen <felix@seita.nl>

* Add superclass to Reporter that will be common to all three data generator classes: Reporter, Scheduler, Forecaster.

Signed-off-by: victor <victor@seita.nl>

* Add start, end, resolution, beliefs_after and beliefs_before to the `compute` method signature.

Signed-off-by: victor <victor@seita.nl>

* Add FLEXMEASURES_DEFAULT_DATASOURCE config to be the feault datasource for data generators.

Signed-off-by: victor <victor@seita.nl>

* Fixing wrong input type.

Signed-off-by: victor <victor@seita.nl>

* Rename DataGenerator class to DataGeneratorMixin

Signed-off-by: victor <victor@seita.nl>

* Reduce logging level from warning to debug.

Signed-off-by: victor <victor@seita.nl>

* Register Reporter to the app context.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Allowing to use BeliefsDataFrame specific method in the schema.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Fixed wrong method. TODO: test with a plugin.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Using module name instead of the module object.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* use belief_time instead of beliefs_before and beliefs_after (#652)

Signed-off-by: F.N. Claessen <felix@seita.nl>

* Fixing example.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Fixing grammar.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Require at least 1 input sensor for the tb_query_config.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Bug fix: compute function was overriding the variables to the default value (None)

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Changing end to get 24h and fix assert condition to detect NaN.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Adding belief time variable to schema.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Avoid deserializing multiple times.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Add command flexmeasures add report.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Add scope="module" to avoid recreating objects in DB.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Skip tests and fixtures in GitHub.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style(cli): state that --last-X can be used instead of start or end.

* style(cli): add three dots after message

* style(cli): add CLI message to show that the computation is running.

* style(cli): add type hint for reporter and result.

* style(cli.utils): renaming function.
style(cli.utils): changing return type.
style(cli.utils): improving docstring.
style(cli.utils): using utils functions.
style(cli.data_add): moving validation of inputs to CLI function.

* style(cli.data_add): replace --save-to-database with --dry-run.

* feat(cli.data_add): default start to the latest time the reporter sensor has data and end to datetime.now().

* fix: setting a right default value for the timezone.

* style: using click parameter File instead of Path.

* style: add comments

* fix: remove time paramters (start, end, ...) from the Reporter class attributes.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: print success at the end.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: add test for get_timerange_from_flag and fix some bugs

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: move fixtures to the file conftest

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: add docstring to the fixture setup_dummy_data

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: typo

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: check for the right values

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: delete redundant test

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: improve docstring

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: improving docstring.

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: removing "In"s

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: change comments from triple quotes to block style

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: add a more informative test check

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: add comment

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Small fixes from reviewing the report cli command (#685)

* style: help texts

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: capitalization

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: punctuation

Signed-off-by: F.N. Claessen <felix@seita.nl>

* feature: warn in case of empty report

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: save result rather than reporter

Signed-off-by: F.N. Claessen <felix@seita.nl>

* feature: more informative error message for mismatching event resolutions of report results

Signed-off-by: F.N. Claessen <felix@seita.nl>

* feature: print out report in case of --dry-run

Signed-off-by: F.N. Claessen <felix@seita.nl>

* black

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: spacing

Signed-off-by: F.N. Claessen <felix@seita.nl>

---------

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: change dry_run default to False

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* test: update field name

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: use timezone in get_timerange_from_flag
fix: use get_timezone() for the default value

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: typo

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: week -> day

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* refactor: last_week -> last_7_days

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: add datasource to report

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: set reporter_class default value to ReporterClass

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: simplify reporter-config file param name

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: clarify help message

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: update repoter_config param click

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* test: update cli parameter names

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: fill missing indexes in beliefdataframes with default values

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: combine two lines into one

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* test: update tests to check with considering that BeliefDataframe is the output type

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: add data_source property to shared mixin

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: potential bug -> multiple data source creation

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: issubclass instead of isinstance

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* docs: clarify test_add_reporter docstring

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: add function to apply an offset chain

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: add start_offset and end_offset to add_report

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: add start and end offsets

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* docs: add entry for `flexmeasures add report`

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* feat: create the CLI command `flexmeasures show reporters` (#686)

* feat: create show reporter command

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: add hint to list reporters

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: add module name
style: print empty string when the author is missing

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: change column order

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* docs: add entry for PR #686

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* docs: add command flexmeasures show reporters

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

---------

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* docs: add entry to changelog

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* Small report cli fixes (#691)

* style: capitalize CSV

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: reporter is no longer a required parameter

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: required parameters on top

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: fix parameter name in docstring

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: avoid converting dt type

Signed-off-by: F.N. Claessen <felix@seita.nl>

* feature: add test case with timezone

Signed-off-by: F.N. Claessen <felix@seita.nl>

* feature: add test case for Pandas structure

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: type annotations

Signed-off-by: F.N. Claessen <felix@seita.nl>

* fix: use parameter 'end'

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: fix type annotation

Signed-off-by: F.N. Claessen <felix@seita.nl>

* style: justified indentation

Signed-off-by: F.N. Claessen <felix@seita.nl>

---------

Signed-off-by: F.N. Claessen <felix@seita.nl>

* docs: update PR number in the changelog

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: changing types

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* test: move fixture to conftest

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* fix: handle empty result

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* style: fix inaccurate message to the user

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

* refactor: remove last-X parameters

Signed-off-by: Victor Garcia Reolid <victor@seita.nl>

---------

Signed-off-by: victor <victor@seita.nl>
Signed-off-by: F.N. Claessen <felix@seita.nl>
Signed-off-by: Victor Garcia Reolid <victor@seita.nl>
Co-authored-by: Felix Claessen <30658763+Flix6x@users.noreply.github.com>
  • Loading branch information
victorgarcia98 and Flix6x committed May 29, 2023
1 parent fe4c3a9 commit cc40d37
Show file tree
Hide file tree
Showing 17 changed files with 921 additions and 102 deletions.
3 changes: 2 additions & 1 deletion documentation/changelog.rst
Expand Up @@ -10,7 +10,8 @@ New features
-------------

* Introduction of the classes `Reporter` and `PandasReporter` [see `PR #641 <https://www.github.com/FlexMeasures/flexmeasures/pull/641>`_]

* Add CLI command ``flexmeasures add report`` [see `PR #659 <https://www.github.com/FlexMeasures/flexmeasures/pull/659>`_]
* Add CLI command ``flexmeasures show reporters`` [see `PR #686 <https://www.github.com/FlexMeasures/flexmeasures/pull/686>`_]

Bugfixes
-----------
Expand Down
2 changes: 2 additions & 0 deletions documentation/cli/commands.rst
Expand Up @@ -39,6 +39,7 @@ of which some are referred to in this documentation.
``flexmeasures add holidays`` Add holiday annotations to accounts and/or assets.
``flexmeasures add annotation`` Add annotation to accounts, assets and/or sensors.
``flexmeasures add toy-account`` Create a toy account, for tutorials and trying things.
``flexmeasures add report`` Create a report.
================================================= =======================================


Expand All @@ -53,6 +54,7 @@ of which some are referred to in this documentation.
``flexmeasures show roles`` List available account- and user roles.
``flexmeasures show data-sources`` List available data sources.
``flexmeasures show beliefs`` Plot time series data.
``flexmeasures show reporters`` List available reporters.
================================================= =======================================


Expand Down
259 changes: 250 additions & 9 deletions flexmeasures/cli/data_add.py
Expand Up @@ -2,7 +2,10 @@
from __future__ import annotations

from datetime import datetime, timedelta
from typing import Optional, Type
import json
from pathlib import Path
from io import TextIOBase

from marshmallow import validate
import pandas as pd
Expand All @@ -12,6 +15,7 @@
import click
import getpass
from sqlalchemy.exc import IntegrityError
from sqlalchemy import func
from timely_beliefs.sensors.func_store.knowledge_horizons import x_days_ago_at_y_oclock
import timely_beliefs as tb
import timely_beliefs.utils as tb_utils
Expand Down Expand Up @@ -58,8 +62,11 @@
)
from flexmeasures.data.services.utils import get_or_create_model
from flexmeasures.utils import flexmeasures_inflection
from flexmeasures.utils.time_utils import server_now
from flexmeasures.utils.time_utils import server_now, get_timezone, apply_offset_chain
from flexmeasures.utils.unit_utils import convert_units, ur
from flexmeasures.data.utils import save_to_db
from flexmeasures.data.models.reporting import Reporter
from timely_beliefs import BeliefsDataFrame


@click.group("add")
Expand Down Expand Up @@ -127,7 +134,7 @@ def new_account(name: str, roles: str):
@click.option(
"--timezone",
"timezone_optional",
help="timezone as string, e.g. 'UTC' or 'Europe/Amsterdam' (defaults to FLEXMEASURES_TIMEZONE config setting)",
help="Timezone as string, e.g. 'UTC' or 'Europe/Amsterdam' (defaults to FLEXMEASURES_TIMEZONE config setting)",
)
def new_user(
username: str,
Expand Down Expand Up @@ -190,7 +197,7 @@ def new_user(
@click.option(
"--timezone",
required=True,
help="timezone as string, e.g. 'UTC' or 'Europe/Amsterdam'",
help="Timezone as string, e.g. 'UTC' or 'Europe/Amsterdam'",
)
@click.option(
"--asset-id",
Expand Down Expand Up @@ -439,7 +446,7 @@ def add_source(name: str, model: str, version: str, source_type: str):
"--timezone",
required=False,
default=None,
help="timezone as string, e.g. 'UTC' or 'Europe/Amsterdam'",
help="Timezone as string, e.g. 'UTC' or 'Europe/Amsterdam'",
)
@click.option(
"--filter-column",
Expand All @@ -458,21 +465,21 @@ def add_source(name: str, model: str, version: str, source_type: str):
required=True,
type=str,
default=",",
help="[For csv files] Character to delimit columns per row, defaults to comma",
help="[For CSV files] Character to delimit columns per row, defaults to comma",
)
@click.option(
"--decimal",
required=False,
default=".",
type=str,
help="[For csv files] decimal character, e.g. '.' for 10.5",
help="[For CSV files] decimal character, e.g. '.' for 10.5",
)
@click.option(
"--thousands",
required=False,
default=None,
type=str,
help="[For csv files] thousands separator, e.g. '.' for 10.035,2",
help="[For CSV files] thousands separator, e.g. '.' for 10.035,2",
)
@click.option(
"--sheet_number",
Expand Down Expand Up @@ -505,9 +512,9 @@ def add_beliefs(
sheet_number: int | None = None,
**kwargs, # in-code calls to this CLI command can set additional kwargs for use in pandas.read_csv or pandas.read_excel
):
"""Add sensor data from a csv file (also accepts xls or xlsx).
"""Add sensor data from a CSV or Excel file.
To use default settings, structure your csv file as follows:
To use default settings, structure your CSV file as follows:
- One header line (will be ignored!)
- UTC datetimes in 1st column
Expand Down Expand Up @@ -1117,6 +1124,240 @@ def add_schedule_for_storage(
click.secho("New schedule is stored.", **MsgStyle.SUCCESS)


@fm_add_data.command("report")
@with_appcontext
@click.option(
"--sensor-id",
"sensor",
type=SensorIdField(),
required=True,
help="ID of the sensor used to save the report."
" If needed, use `flexmeasures add sensor` to create a new sensor first.",
)
@click.option(
"--reporter-config",
"reporter_config",
required=True,
type=click.File("r"),
help="Path to the JSON file with the reporter configuration.",
)
@click.option(
"--reporter",
"reporter_class",
default="PandasReporter",
type=click.STRING,
help="Reporter class registered in flexmeasures.data.models.reporting or in an available flexmeasures plugin."
" Use the command `flexmeasures show reporters` to list all the available reporters.",
)
@click.option(
"--start",
"start",
type=AwareDateTimeField(format="iso"),
required=False,
help="Report start time. `--start-offset` can be used instead. Follow up with a timezone-aware datetime in ISO 6801 format.",
)
@click.option(
"--start-offset",
"start_offset",
type=str,
required=False,
help="Report start offset time from now. Use multiple Pandas offset strings separated by commas, e.g: -3D,DB,1W. Use DB or HB to offset to the begin of the day or hour, respectively.",
)
@click.option(
"--end-offset",
"end_offset",
type=str,
required=False,
help="Report end offset time from now. Use multiple Pandas offset strings separated by commas, e.g: -3D,DB,1W. Use DB or HB to offset to the begin of the day or hour, respectively.",
)
@click.option(
"--end",
"end",
type=AwareDateTimeField(format="iso"),
required=False,
help="Report end time. `--end-offset` can be used instead. Follow up with a timezone-aware datetime in ISO 6801 format.",
)
@click.option(
"--resolution",
"resolution",
type=DurationField(format="iso"),
required=False,
help="Time resolution of the input time series to employ for the calculations. Follow up with a ISO 8601 duration string",
)
@click.option(
"--output-file",
"output_file",
required=False,
type=click.Path(),
help="Path to save the report to file. Will override any previous file contents."
" Use the `.csv` suffix to save the results as Comma Separated Values and `.xlsx` to export them as Excel sheets.",
)
@click.option(
"--timezone",
"timezone",
required=False,
default="UTC",
help="Timezone as string, e.g. 'UTC' or 'Europe/Amsterdam' (defaults to FLEXMEASURES_TIMEZONE config setting)",
)
@click.option(
"--dry-run",
"dry_run",
is_flag=True,
help="Add this flag to avoid saving the results to the database.",
)
def add_report( # noqa: C901
reporter_class: str,
sensor: Sensor,
reporter_config: TextIOBase,
start: Optional[datetime] = None,
end: Optional[datetime] = None,
start_offset: Optional[str] = None,
end_offset: Optional[str] = None,
resolution: Optional[timedelta] = None,
output_file: Optional[Path] = None,
dry_run: bool = False,
timezone: str | pytz.BaseTzInfo = get_timezone(),
):
"""
Create a new report using the Reporter class and save the results
to the database or export them as CSV or Excel file.
"""

# parse timezone into a BaseTzInfo object
if isinstance(timezone, str):
check_timezone(timezone)
timezone = pytz.timezone(zone=timezone)

now = timezone.localize(datetime.now())

# apply offsets, if provided
if start_offset is not None:
if start is None:
start = now
start = apply_offset_chain(start, start_offset)

if end_offset is not None:
if end is None:
end = now
end = apply_offset_chain(end, end_offset)

# the case of not getting --start or --start-offset
if start is None:
click.secho(
"Either --start or --start-offset should be provided."
" Trying to use the latest datapoint of the report sensor as the start time...",
**MsgStyle.WARN,
)
last_value_datetime = (
db.session.query(func.max(TimedBelief.event_start))
.filter(TimedBelief.sensor_id == sensor.id)
.one_or_none()
)

# If there's data saved to the reporter sensors
if last_value_datetime[0] is not None:
start = last_value_datetime[0]
else:
click.secho(
f"Could not find any data for the report sensor {sensor}.",
**MsgStyle.ERROR,
)
raise click.Abort()

# the case of not getting --end or --end-offset
if end is None:
click.secho(
"Either --end or --end-offset should be provided."
" Trying to use the current time as the end...",
**MsgStyle.WARN,
)
end = now

click.echo(f"Report scope:\n\tstart: {start}\n\tend: {end}")

click.echo(
f"Looking for the Reporter {reporter_class} among all the registered reporters...",
)

# get reporter class
ReporterClass: Type[Reporter] = app.reporters.get(reporter_class)

# check if it exists
if ReporterClass is None:
click.secho(
f"Reporter class `{reporter_class}` not available.",
**MsgStyle.ERROR,
)
raise click.Abort()

click.secho(f"Reporter {reporter_class} found.", **MsgStyle.SUCCESS)

reporter_config_raw = json.load(reporter_config)

# initialize reporter class with the reporter sensor and reporter config
reporter: Reporter = ReporterClass(
sensor=sensor, reporter_config_raw=reporter_config_raw
)

click.echo("Report computation is running...")

# compute the report
result: BeliefsDataFrame = reporter.compute(
start=start, end=end, input_resolution=resolution
)

if not result.empty:
click.secho("Report computation done.", **MsgStyle.SUCCESS)
else:
click.secho(
"Report computation done, but the report is empty.", **MsgStyle.WARN
)

# save the report it's not running in dry mode
if not dry_run:
click.echo("Saving report to the database...")
save_to_db(result)
db.session.commit()
click.secho(
"Success. The report has been saved to the database.",
**MsgStyle.SUCCESS,
)
else:
click.echo(
f"Not saving report to the database (because of --dry-run), but this is what I computed:\n{result}"
)

# if an output file path is provided, save the results
if output_file:
suffix = str(output_file).split(".")[-1] if "." in str(output_file) else ""

if suffix == "xlsx": # save to EXCEL
result.to_excel(output_file)
click.secho(
f"Success. The report has been exported as EXCEL to the file `{output_file}`",
**MsgStyle.SUCCESS,
)

elif suffix == "csv": # save to CSV
result.to_csv(output_file)
click.secho(
f"Success. The report has been exported as CSV to the file `{output_file}`",
**MsgStyle.SUCCESS,
)

else: # default output format: CSV.
click.secho(
f"File suffix not provided. Exporting results as CSV to file {output_file}",
**MsgStyle.WARN,
)
result.to_csv(output_file)
else:
click.secho(
"Success.",
**MsgStyle.SUCCESS,
)


@fm_add_data.command("toy-account")
@with_appcontext
@click.option(
Expand Down
24 changes: 24 additions & 0 deletions flexmeasures/cli/data_show.py
Expand Up @@ -376,4 +376,28 @@ def plot_beliefs(
click.secho("Data saved to file.", **MsgStyle.SUCCESS)


@fm_show_data.command("reporters")
@with_appcontext
def list_reporters():
"""
Show available reporters.
"""

click.echo("Reporters:\n")
click.echo(
tabulate(
[
(
reporter_name,
reporter_class.__version__,
reporter_class.__author__,
reporter_class.__module__,
)
for reporter_name, reporter_class in app.reporters.items()
],
headers=["name", "version", "author", "module"],
)
)


app.cli.add_command(fm_show_data)

0 comments on commit cc40d37

Please sign in to comment.