Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CLI command to delete an asset #395

Merged
merged 4 commits into from Mar 21, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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
62 changes: 29 additions & 33 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 @@ -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}'?"
nhoening marked this conversation as resolved.
Show resolved Hide resolved
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