Skip to content

Commit

Permalink
CLI command to delete an asset (#395)
Browse files Browse the repository at this point in the history
* simplify conformation dialogue coding in CLI commands for deletion

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

* add command: flexmeasures delete asset

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

* document the command

Signed-off-by: Nicolas Höning <nicolas@seita.nl>

* adjust another debugging statement

Signed-off-by: Nicolas Höning <nicolas@seita.nl>
  • Loading branch information
nhoening committed Mar 21, 2022
1 parent 7cf25e4 commit f24c82d
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 36 deletions.
1 change: 1 addition & 0 deletions documentation/changelog.rst
Expand Up @@ -17,6 +17,7 @@ New features
* Add a CLI command for showing time series data [see `PR #379 <http://www.github.com/FlexMeasures/flexmeasures/pull/379>`_]
* Add CLI command for attaching annotations to assets: ``flexmeasures add holidays`` adds public holidays [see `PR #343 <http://www.github.com/FlexMeasures/flexmeasures/pull/343>`_]
* Add CLI command for resampling existing sensor data to new resolution [see `PR #360 <http://www.github.com/FlexMeasures/flexmeasures/pull/360>`_]
* Add CLI command to delete an asset, with its sensors and data. [see `PR #395 <http://www.github.com/FlexMeasures/flexmeasures/pull/395>`_]
* Add CLI command to edit/add an attribute on an asset or sensor. [see `PR #380 <http://www.github.com/FlexMeasures/flexmeasures/pull/380>`_]
* Add CLI command to add a toy account for tutorials and trying things [see `PR #368 <http://www.github.com/FlexMeasures/flexmeasures/pull/368>`_]
* Add CLI command to create a charging schedule [see `PR #372 <http://www.github.com/FlexMeasures/flexmeasures/pull/372>`_]
Expand Down
1 change: 1 addition & 0 deletions documentation/cli/commands.rst
Expand Up @@ -72,6 +72,7 @@ of which some are referred to in this documentation.
``flexmeasures delete account-role`` Delete a tenant account role.
``flexmeasures delete account`` Delete a tenant account & also their users (with assets and power measurements).
``flexmeasures delete user`` Delete a user & also their assets and power measurements.
``flexmeasures delete asset`` Delete an asset & also its sensors and data.
``flexmeasures delete sensor`` Delete a sensor and all beliefs about it.
``flexmeasures delete measurements`` Delete measurements (with horizon <= 0).
``flexmeasures delete prognoses`` Delete forecasts and schedules (forecasts > 0).
Expand Down
64 changes: 30 additions & 34 deletions flexmeasures/cli/data_delete.py
Expand Up @@ -11,7 +11,7 @@
from flexmeasures.data.models.user import Account, AccountRole, RolesAccounts, User
from flexmeasures.data.models.generic_assets import GenericAsset
from flexmeasures.data.models.time_series import Sensor, TimedBelief
from flexmeasures.data.scripts.data_gen import get_affected_classes
from flexmeasures.data.schemas.generic_assets import GenericAssetIdField
from flexmeasures.data.services.users import find_user_by_email, delete_user


Expand Down Expand Up @@ -72,7 +72,7 @@ def delete_account(id: int, force: bool):
)
click.confirm(prompt, abort=True)
for user in account.users:
print(f"Deleting user {user} (and assets & data) ...")
print(f"Deleting user {user} ...")
delete_user(user)
for role_account_association in RolesAccounts.query.filter_by(
account_id=account.id
Expand All @@ -97,39 +97,36 @@ def delete_account(id: int, force: bool):
@click.option(
"--force/--no-force", default=False, help="Skip warning about consequences."
)
def delete_user_and_data(email: str, force: bool):
def delete_a_user(email: str, force: bool):
"""
Delete a user & also their assets and data.
"""
if not force:
# TODO: later, when assets belong to accounts, remove this.
prompt = f"Delete user '{email}', including all their assets and data?"
prompt = f"Delete user '{email}'?"
click.confirm(prompt, abort=True)
the_user = find_user_by_email(email)
if the_user is None:
print(f"Could not find user with email address '{email}' ...")
return
delete_user(the_user)
app.db.session.commit()
db.session.commit()


def confirm_deletion(
structure: bool = False,
data: bool = False,
is_by_id: bool = False,
):
affected_classes = get_affected_classes(structure, data)
prompt = "This deletes all %s entries from %s.\nDo you want to continue?" % (
" and ".join(
", ".join(
[affected_class.__tablename__ for affected_class in affected_classes]
).rsplit(", ", 1)
),
app.db.engine,
)
if is_by_id:
prompt = prompt.replace(" all ", " ")
click.confirm(prompt, abort=True)
@fm_delete_data.command("asset")
@with_appcontext
@click.option("--id", "asset", type=GenericAssetIdField())
@click.option(
"--force/--no-force", default=False, help="Skip warning about consequences."
)
def delete_asset_and_data(asset: GenericAsset, force: bool):
"""
Delete an asset & also its sensors and data.
"""
if not force:
prompt = f"Delete {asset}, including all its sensors and data?"
click.confirm(prompt, abort=True)
db.session.delete(asset)
db.session.commit()


@fm_delete_data.command("structure")
Expand All @@ -140,17 +137,16 @@ def confirm_deletion(
def delete_structure(force):
"""
Delete all structural (non time-series) data like assets (types),
markets (types) and weather sensors (types) and users.
TODO: This could in our future data model (currently in development) be replaced by
`flexmeasures delete generic-asset-type`, `flexmeasures delete generic-asset`
and so on.
sources, roles and users.
"""
if not force:
confirm_deletion(structure=True)
click.confirm(
f"Sure to delete all asset(type)s, sources, roles and users from {db.engine}?",
abort=True,
)
from flexmeasures.data.scripts.data_gen import depopulate_structure

depopulate_structure(app.db)
depopulate_structure(db)


@fm_delete_data.command("measurements")
Expand All @@ -169,10 +165,10 @@ def delete_measurements(
):
"""Delete measurements (ex-post beliefs, i.e. with belief_horizon <= 0)."""
if not force:
confirm_deletion(data=True, is_by_id=sensor_id is not None)
click.confirm(f"Sure to delete all measurements from {db.engine}?", abort=True)
from flexmeasures.data.scripts.data_gen import depopulate_measurements

depopulate_measurements(app.db, sensor_id)
depopulate_measurements(db, sensor_id)


@fm_delete_data.command("prognoses")
Expand All @@ -191,10 +187,10 @@ def delete_prognoses(
):
"""Delete forecasts and schedules (ex-ante beliefs, i.e. with belief_horizon > 0)."""
if not force:
confirm_deletion(data=True, is_by_id=sensor_id is not None)
click.confirm(f"Sure to delete all prognoses from {db.engine}?", abort=True)
from flexmeasures.data.scripts.data_gen import depopulate_prognoses

depopulate_prognoses(app.db, sensor_id)
depopulate_prognoses(db, sensor_id)


@fm_delete_data.command("unchanged-beliefs")
Expand Down
2 changes: 0 additions & 2 deletions flexmeasures/data/services/users.py
Expand Up @@ -200,8 +200,6 @@ def delete_user(user: User):
"""
Delete the user (and also his assets and power measurements!).
The deletion cascades to the user's assets (sensors), and from there to the beliefs which reference these assets (sensors).
Deleting oneself is not allowed.
Remember to commit the session after calling this function!
Expand Down

0 comments on commit f24c82d

Please sign in to comment.