From 9c5dd1b39ee2fce86611bc478f28b1c6d4c9b8e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Sat, 19 Mar 2022 23:58:36 +0100 Subject: [PATCH 1/4] simplify conformation dialogue coding in CLI commands for deletion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Höning --- flexmeasures/cli/data_delete.py | 37 ++++++++------------------------- 1 file changed, 9 insertions(+), 28 deletions(-) diff --git a/flexmeasures/cli/data_delete.py b/flexmeasures/cli/data_delete.py index b422b6fb3..124603345 100644 --- a/flexmeasures/cli/data_delete.py +++ b/flexmeasures/cli/data_delete.py @@ -11,7 +11,6 @@ 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.services.users import find_user_by_email, delete_user @@ -113,25 +112,6 @@ def delete_user_and_data(email: str, force: bool): app.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("structure") @with_appcontext @click.option( @@ -140,14 +120,13 @@ 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 {app.db.engine}?", + abort=True, + ) from flexmeasures.data.scripts.data_gen import depopulate_structure depopulate_structure(app.db) @@ -169,7 +148,9 @@ 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 {app.db.engine}?", abort=True + ) from flexmeasures.data.scripts.data_gen import depopulate_measurements depopulate_measurements(app.db, sensor_id) @@ -191,7 +172,7 @@ 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 {app.db.engine}?", abort=True) from flexmeasures.data.scripts.data_gen import depopulate_prognoses depopulate_prognoses(app.db, sensor_id) From 4bf2a5e746cff2f140ba0dbb69072d211fd6c2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Sun, 20 Mar 2022 00:13:59 +0100 Subject: [PATCH 2/4] add command: flexmeasures delete asset MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Höning --- flexmeasures/cli/data_delete.py | 39 ++++++++++++++++++++--------- flexmeasures/data/services/users.py | 2 -- 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/flexmeasures/cli/data_delete.py b/flexmeasures/cli/data_delete.py index 124603345..0b5572a46 100644 --- a/flexmeasures/cli/data_delete.py +++ b/flexmeasures/cli/data_delete.py @@ -11,6 +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.schemas.generic_assets import GenericAssetIdField from flexmeasures.data.services.users import find_user_by_email, delete_user @@ -96,20 +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() + + +@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 their 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") @@ -124,12 +141,12 @@ def delete_structure(force): """ if not force: click.confirm( - f"Sure to delete all asset(type)s, sources, roles and users from {app.db.engine}?", + 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") @@ -148,12 +165,10 @@ def delete_measurements( ): """Delete measurements (ex-post beliefs, i.e. with belief_horizon <= 0).""" if not force: - click.confirm( - f"Sure to delete all measurements from {app.db.engine}?", abort=True - ) + 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") @@ -172,10 +187,10 @@ def delete_prognoses( ): """Delete forecasts and schedules (ex-ante beliefs, i.e. with belief_horizon > 0).""" if not force: - click.confirm(f"Sure to delete all prognoses from {app.db.engine}?", abort=True) + 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") diff --git a/flexmeasures/data/services/users.py b/flexmeasures/data/services/users.py index d4a134dd7..8cf9ed2da 100644 --- a/flexmeasures/data/services/users.py +++ b/flexmeasures/data/services/users.py @@ -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! From 90d70a0ebcc307c8a8b2112e46cae6c4474db538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Sun, 20 Mar 2022 00:33:55 +0100 Subject: [PATCH 3/4] document the command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Höning --- documentation/changelog.rst | 1 + documentation/cli/commands.rst | 1 + flexmeasures/cli/data_delete.py | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/documentation/changelog.rst b/documentation/changelog.rst index b4b62a79b..77fcad4e3 100644 --- a/documentation/changelog.rst +++ b/documentation/changelog.rst @@ -17,6 +17,7 @@ New features * Add a CLI command for showing time series data [see `PR #379 `_] * Add CLI command for attaching annotations to assets: ``flexmeasures add holidays`` adds public holidays [see `PR #343 `_] * Add CLI command for resampling existing sensor data to new resolution [see `PR #360 `_] +* Add CLI command to delete an asset, with its sensors and data. [see `PR #395 `_] * Add CLI command to edit/add an attribute on an asset or sensor. [see `PR #380 `_] * Add CLI command to add a toy account for tutorials and trying things [see `PR #368 `_] * Add CLI command to create a charging schedule [see `PR #372 `_] diff --git a/documentation/cli/commands.rst b/documentation/cli/commands.rst index 64d3bd124..cde6382e5 100644 --- a/documentation/cli/commands.rst +++ b/documentation/cli/commands.rst @@ -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). diff --git a/flexmeasures/cli/data_delete.py b/flexmeasures/cli/data_delete.py index 0b5572a46..708387661 100644 --- a/flexmeasures/cli/data_delete.py +++ b/flexmeasures/cli/data_delete.py @@ -120,7 +120,7 @@ def delete_a_user(email: str, force: bool): ) def delete_asset_and_data(asset: GenericAsset, force: bool): """ - Delete an asset & also their sensors and data. + Delete an asset & also its sensors and data. """ if not force: prompt = f"Delete {asset}, including all its sensors and data?" From b911092f32d9b8599076be4a2821df4c6b227c05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20H=C3=B6ning?= Date: Mon, 21 Mar 2022 19:50:14 +0100 Subject: [PATCH 4/4] adjust another debugging statement MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Nicolas Höning --- flexmeasures/cli/data_delete.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flexmeasures/cli/data_delete.py b/flexmeasures/cli/data_delete.py index 708387661..0a65d6a7d 100644 --- a/flexmeasures/cli/data_delete.py +++ b/flexmeasures/cli/data_delete.py @@ -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