- icon_class should not be part of the backend model

- Interaction with entities should occur through the `entities.action`
  method, not by implementing native methods on each of the model
  objects
This commit is contained in:
Fabio Manganiello 2022-04-08 16:49:47 +02:00
parent 947b50b937
commit f52b556219
Signed by: blacklight
GPG Key ID: D90FBA7F76362774
5 changed files with 35 additions and 48 deletions

View File

@ -52,12 +52,6 @@ class Entity(Base):
'polymorphic_on': type, 'polymorphic_on': type,
} }
@property
def _meta(self) -> dict:
return {
'icon_class': 'fa-solid fa-circle-question',
}
@classmethod @classmethod
@property @property
def columns(cls) -> Tuple[ColumnProperty]: def columns(cls) -> Tuple[ColumnProperty]:
@ -73,13 +67,7 @@ class Entity(Base):
return val return val
def to_json(self) -> dict: def to_json(self) -> dict:
return { return {col.key: self._serialize_value(col) for col in self.columns}
**{col.key: self._serialize_value(col) for col in self.columns},
'meta': {
**self._meta,
**(self.meta or {}),
},
}
def get_plugin(self): def get_plugin(self):
from platypush.context import get_plugin from platypush.context import get_plugin
@ -88,6 +76,12 @@ class Entity(Base):
assert plugin, f'No such plugin: {plugin}' assert plugin, f'No such plugin: {plugin}'
return plugin return plugin
def run(self, action: str, *args, **kwargs):
plugin = self.get_plugin()
method = getattr(plugin, action, None)
assert method, f'No such action: {self.plugin}.{action}'
return method(self.external_id or self.name, *args, **kwargs)
# Inject the JSONAble mixin (Python goes nuts if done through # Inject the JSONAble mixin (Python goes nuts if done through
# standard multiple inheritance with an SQLAlchemy ORM class) # standard multiple inheritance with an SQLAlchemy ORM class)

View File

@ -11,10 +11,3 @@ class Device(Entity):
__mapper_args__ = { __mapper_args__ = {
'polymorphic_identity': __tablename__, 'polymorphic_identity': __tablename__,
} }
@property
def _meta(self):
return {
**super()._meta,
'icon_class': 'fa-solid fa-gear',
}

View File

@ -11,10 +11,3 @@ class Light(Device):
__mapper_args__ = { __mapper_args__ = {
'polymorphic_identity': __tablename__, 'polymorphic_identity': __tablename__,
} }
@property
def _meta(self):
return {
**super()._meta,
'icon_class': 'fa-solid fa-lightbulb',
}

View File

@ -12,19 +12,3 @@ class Switch(Device):
__mapper_args__ = { __mapper_args__ = {
'polymorphic_identity': __tablename__, 'polymorphic_identity': __tablename__,
} }
@property
def _meta(self):
return {
**super()._meta,
'icon_class': 'fa-solid fa-light-switch',
}
def on(self):
return self.get_plugin().on(self)
def off(self):
return self.get_plugin().off(self)
def toggle(self):
return self.get_plugin().toggle(self)

View File

@ -1,10 +1,10 @@
from queue import Queue, Empty from queue import Queue, Empty
from threading import Thread from threading import Thread
from time import time from time import time
from typing import Optional from typing import Optional, Any
from platypush.context import get_plugin from platypush.context import get_plugin
from platypush.entities import get_plugin_entity_registry, get_entities_registry from platypush.entities import Entity, get_plugin_entity_registry, get_entities_registry
from platypush.plugins import Plugin, action from platypush.plugins import Plugin, action
@ -17,6 +17,11 @@ class EntitiesPlugin(Plugin):
def __init__(self, **kwargs): def __init__(self, **kwargs):
super().__init__(**kwargs) super().__init__(**kwargs)
def _get_db(self):
db = get_plugin('db')
assert db
return db
@action @action
def get(self, type: str = 'entity', **filter): def get(self, type: str = 'entity', **filter):
""" """
@ -35,9 +40,7 @@ class EntitiesPlugin(Plugin):
entity_type entity_type
), f'No such entity type: {type}. Supported types: {list(all_types.keys())}' ), f'No such entity type: {type}. Supported types: {list(all_types.keys())}'
db = get_plugin('db') db = self._get_db()
assert db
with db.get_session() as session: with db.get_session() as session:
query = session.query(entity_type) query = session.query(entity_type)
if filter: if filter:
@ -127,5 +130,25 @@ class EntitiesPlugin(Plugin):
return self.get(**filter) return self.get(**filter)
@action
def execute(self, id: Any, action: str, *args, **kwargs):
"""
Execute an action on an entity (for example `on`/`off` on a switch, or `get`
on a sensor).
:param id: Entity ID (i.e. the entity's db primary key, not the plugin's external
or "logical" key)
:param action: Action that should be run. It should be a method implemented
by the entity's class.
:param args: Action's extra positional arguments.
:param kwargs: Action's extra named arguments.
"""
db = self._get_db()
with db.get_session() as session:
entity = session.query(Entity).filter_by(id=id).one_or_none()
assert entity, f'No such entity ID: {id}'
return entity.run(action, *args, **kwargs)
# vim:sw=4:ts=4:et: # vim:sw=4:ts=4:et: