diff --git a/platypush/message/event/entities.py b/platypush/message/event/entities.py index 6b56100a7..4c475c588 100644 --- a/platypush/message/event/entities.py +++ b/platypush/message/event/entities.py @@ -1,19 +1,28 @@ +from abc import ABC from typing import Union from platypush.entities import Entity from platypush.message.event import Event -class EntityUpdateEvent(Event): - """ - This even is triggered whenever an entity of any type (a switch, a light, - a sensor, a media player etc.) updates its state. - """ - +class EntityEvent(Event, ABC): def __init__(self, entity: Union[Entity, dict], *args, **kwargs): if isinstance(entity, Entity): entity = entity.to_json() super().__init__(entity=entity, *args, **kwargs) +class EntityUpdateEvent(EntityEvent): + """ + This event is triggered whenever an entity of any type (a switch, a light, + a sensor, a media player etc.) updates its state. + """ + + +class EntityDeleteEvent(EntityEvent): + """ + This event is triggered whenever an entity is deleted. + """ + + # vim:sw=4:ts=4:et: diff --git a/platypush/plugins/entities/__init__.py b/platypush/plugins/entities/__init__.py index d2e2652ae..acf7a1205 100644 --- a/platypush/plugins/entities/__init__.py +++ b/platypush/plugins/entities/__init__.py @@ -7,7 +7,7 @@ from sqlalchemy.orm import make_transient from platypush.context import get_plugin, get_bus from platypush.entities import Entity, get_plugin_entity_registry, get_entities_registry -from platypush.message.event.entities import EntityUpdateEvent +from platypush.message.event.entities import EntityUpdateEvent, EntityDeleteEvent from platypush.plugins import Plugin, action @@ -168,6 +168,32 @@ class EntitiesPlugin(Plugin): assert entity, f'No such entity ID: {id}' return entity.run(action, *args, **kwargs) + @action + def delete(self, *entities: int): # type: ignore + """ + Delete a set of entity IDs. + + Note: this should only be done if the entity is no longer available or + the associated plugin has been disabled, otherwise the entities will be + re-created by the plugins on the next scan. + + :param entities: IDs of the entities to be removed. + :return: The payload of the deleted entities. + """ + with self._get_db().get_session() as session: + entities: Collection[Entity] = ( + session.query(Entity).filter(Entity.id.in_(entities)).all() + ) + for entity in entities: + session.delete(entity) + session.commit() + + for entity in entities: + make_transient(entity) + get_bus().post(EntityDeleteEvent(entity)) + + return entities + @action def rename(self, **entities: Mapping[str, str]): """