From d63f61ca2fd50c6d5445ca5663e3d1011c4223ac Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Sun, 7 Jun 2020 22:03:56 +0200 Subject: [PATCH 1/2] Added handler for emit event --- sample_lego.py | 8 +++++++- thingsdb/model/thing.py | 17 +++++++++++++++++ thingsdb/util/__init__.py | 1 + thingsdb/util/event.py | 12 ++++++++++++ thingsdb/version.py | 2 +- 5 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 thingsdb/util/event.py diff --git a/sample_lego.py b/sample_lego.py index 5cefdab..9d19477 100644 --- a/sample_lego.py +++ b/sample_lego.py @@ -1,6 +1,7 @@ import asyncio from thingsdb.client import Client from thingsdb.model import Collection, Thing, ThingStrict, Enum +from thingsdb.util import event class Color(Enum): @@ -21,6 +22,11 @@ def on_init(self, *args, **kwars): color value: {self.color.value} ''') + @event('new-color') + def on_new_color(self, color): + print(f'brick with id {self.id()} as a new color: {color}') + + class Lego(Collection): bricks = '[Brick]', Brick @@ -41,7 +47,7 @@ async def example(): await lego.load(client) # ... now the collection will be watched for 100 seconds - await asyncio.sleep(100) + await asyncio.sleep(300) finally: client.close() diff --git a/thingsdb/model/thing.py b/thingsdb/model/thing.py index bbd7473..0110308 100644 --- a/thingsdb/model/thing.py +++ b/thingsdb/model/thing.py @@ -43,6 +43,7 @@ class Thing(ThingHash): # will be created. A Collection instance will have `False` as default. __AS_TYPE__ = True + _ev_handlers = dict() _props = dict() _type_name = None # Only set when __AS_TYPE__ is True _visited = 0 # For build, 0=not visited, 1=new_type, 2=set_type, 3=build @@ -54,6 +55,7 @@ def __init__(self, collection, id: int): collection._register(self) def __init_subclass__(cls): + cls._ev_handlers = {} cls._props = {} items = { k: v for k, v in cls.__dict__.items() if not k.startswith('__')} @@ -63,6 +65,9 @@ def __init_subclass__(cls): if isinstance(val, tuple): prop = cls._props[key] = Prop(*val) delattr(cls, key) + elif callable(val) and hasattr(val, '_ev'): + cls._ev_handlers[val._ev] = val + if cls.__AS_TYPE__: cls._type_name = getattr(cls, '__TYPE_NAME__', cls.__name__) @@ -105,6 +110,14 @@ def on_update(self, event, jobs): def on_delete(self): self._collection._things.pop(self.id()) + def on_event(self, ev, *args): + cls = self.__class__ + fun = cls._ev_handlers.get(ev) + if fun is None: + logging.debug(f'no event handler for {ev} on {cls.__name__}') + return + fun(self, *args) + def on_stop(self): logging.warning(f'stopped watching thing {self}') @@ -148,6 +161,9 @@ def _job_del(self, k): except AttributeError: pass + def _job_event(self, data): + self.on_event(*data) + def _job_remove(self, pair): cls = self.__class__ (k, v), = pair.items() @@ -270,6 +286,7 @@ def _job_set_type(self, data): # Thing jobs 'add': _job_add, 'del': _job_del, + 'event': _job_event, 'remove': _job_remove, 'set': _job_set, 'splice': _job_splice, diff --git a/thingsdb/util/__init__.py b/thingsdb/util/__init__.py index 242bd77..bd83d21 100644 --- a/thingsdb/util/__init__.py +++ b/thingsdb/util/__init__.py @@ -1,2 +1,3 @@ from .convert import convert from .fmt import fmt +from .event import event \ No newline at end of file diff --git a/thingsdb/util/event.py b/thingsdb/util/event.py new file mode 100644 index 0000000..b870027 --- /dev/null +++ b/thingsdb/util/event.py @@ -0,0 +1,12 @@ +"""Decorator for handleing events.""" + +def event(ev): + + def _event(fun): + def wrapper(self, *args): + fun(self, *args) + + wrapper._ev = ev + return wrapper + + return _event diff --git a/thingsdb/version.py b/thingsdb/version.py index a68d2bd..02f8497 100644 --- a/thingsdb/version.py +++ b/thingsdb/version.py @@ -1 +1 @@ -__version__ = '0.6.3' +__version__ = '0.6.4' From 391de6b099e881ff75264a37b7b092b564036464 Mon Sep 17 00:00:00 2001 From: Jeroen van der Heijden Date: Mon, 8 Jun 2020 13:20:48 +0200 Subject: [PATCH 2/2] Added emit function --- sample_lego.py | 8 ++++++++ thingsdb/model/thing.py | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/sample_lego.py b/sample_lego.py index 9d19477..ed18ab5 100644 --- a/sample_lego.py +++ b/sample_lego.py @@ -47,6 +47,14 @@ async def example(): await lego.load(client) # ... now the collection will be watched for 100 seconds + while True: + await asyncio.sleep(3) + if lego and lego.bricks: + brick = lego.bricks[0] + await brick.emit('new-color', 'RED') + break + await lego.query('.bricks.push(Brick{});') + await asyncio.sleep(300) finally: diff --git a/thingsdb/model/thing.py b/thingsdb/model/thing.py index 0110308..5fbce30 100644 --- a/thingsdb/model/thing.py +++ b/thingsdb/model/thing.py @@ -94,6 +94,16 @@ def unwatch(self): collection = self._collection return collection._client.unwatch(self._id, scope=collection._scope) + def emit(self, event, *args): + data = {f'd{i}': v for i, v in enumerate(args)} + dstr = "".join((f", {k}" for k in data.keys())) + + return self._collection.query( + f'thing(id).emit(event{dstr});', + id=self._id, + event=event, + **data) + @checkevent def on_init(self, event, data): self._job_set(data)