Skip to content

Commit

Permalink
Merge branch 'main' into docs/scheduling/linear_programming
Browse files Browse the repository at this point in the history
  • Loading branch information
victorgarcia98 committed Jul 20, 2023
2 parents e4b8ef4 + 9ab3a24 commit a62c97a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 2 deletions.
1 change: 1 addition & 0 deletions documentation/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ New features
* Make it a lot easier to read off the color legend on the asset page, especially when showing many sensors, as they will now be ordered from top to bottom in the same order as they appear in the chart (as defined in the ``sensors_to_show`` attribute), rather than alphabetically [see `PR #742 <https://www.github.com/FlexMeasures/flexmeasures/pull/742>`_]
* Having percentages within the [0, 100] domain is such a common use case that we now always include it in sensor charts with % units, making it easier to read off individual charts and also to compare across charts [see `PR #739 <https://www.github.com/FlexMeasures/flexmeasures/pull/739>`_]
* DataSource table now allows storing arbitrary attributes as a JSON (without content validation), similar to the Sensor and GenericAsset tables [see `PR #750 <https://www.github.com/FlexMeasures/flexmeasures/pull/750>`_]
* The CLI now allows to set lists and dicts as asset & sensor attributes (formerly only single values) [see `PR #762 <https://www.github.com/FlexMeasures/flexmeasures/pull/762>`_]

Bugfixes
-----------
Expand Down
43 changes: 41 additions & 2 deletions flexmeasures/cli/data_edit.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import pandas as pd
from flask import current_app as app
from flask.cli import with_appcontext
import json

from flexmeasures import Sensor
from flexmeasures.data import db
Expand Down Expand Up @@ -78,6 +79,20 @@ def fm_edit_data():
type=int,
help="Set the attribute to this integer value.",
)
@click.option(
"--list",
"attribute_list_value",
required=False,
type=str,
help="Set the attribute to this list value. Pass a string with a JSON-parse-able list representation, e.g. '[1,\"a\"]'.",
)
@click.option(
"--dict",
"attribute_dict_value",
required=False,
type=str,
help="Set the attribute to this dict value. Pass a string with a JSON-parse-able dict representation, e.g. '{1:\"a\"}'.",
)
@click.option(
"--null",
"attribute_null_value",
Expand All @@ -95,6 +110,8 @@ def edit_attribute(
attribute_bool_value: bool | None = None,
attribute_str_value: str | None = None,
attribute_int_value: int | None = None,
attribute_list_value: str | None = None,
attribute_dict_value: str | None = None,
):
"""Edit (or add) an asset attribute or sensor attribute."""

Expand All @@ -107,6 +124,8 @@ def edit_attribute(
attribute_bool_value=attribute_bool_value,
attribute_str_value=attribute_str_value,
attribute_int_value=attribute_int_value,
attribute_list_value=attribute_list_value,
attribute_dict_value=attribute_dict_value,
attribute_null_value=attribute_null_value,
)

Expand Down Expand Up @@ -211,13 +230,15 @@ def resample_sensor_data(
app.cli.add_command(fm_edit_data)


def parse_attribute_value(
def parse_attribute_value( # noqa: C901
attribute_null_value: bool,
attribute_float_value: float | None = None,
attribute_bool_value: bool | None = None,
attribute_str_value: str | None = None,
attribute_int_value: int | None = None,
) -> float | int | bool | str | None:
attribute_list_value: str | None = None,
attribute_dict_value: str | None = None,
) -> float | int | bool | str | list | dict | None:
"""Parse attribute value."""
if not single_true(
[attribute_null_value]
Expand All @@ -228,6 +249,8 @@ def parse_attribute_value(
attribute_bool_value,
attribute_str_value,
attribute_int_value,
attribute_list_value,
attribute_dict_value,
]
]
):
Expand All @@ -240,6 +263,22 @@ def parse_attribute_value(
return bool(attribute_bool_value)
elif attribute_int_value is not None:
return int(attribute_int_value)
elif attribute_list_value is not None:
try:
val = json.loads(attribute_list_value)
except json.decoder.JSONDecodeError as jde:
raise ValueError(f"Error parsing list value: {jde}")
if not isinstance(val, list):
raise ValueError(f"{val} is not a list.")
return val
elif attribute_dict_value is not None:
try:
val = json.loads(attribute_dict_value)
except json.decoder.JSONDecodeError as jde:
raise ValueError(f"Error parsing dict value: {jde}")
if not isinstance(val, dict):
raise ValueError(f"{val} is not a dict.")
return val
return attribute_str_value


Expand Down

0 comments on commit a62c97a

Please sign in to comment.