Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion sample_lego.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -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

Expand All @@ -41,7 +47,15 @@ async def example():
await lego.load(client)

# ... now the collection will be watched for 100 seconds
await asyncio.sleep(100)
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:
client.close()
Expand Down
27 changes: 27 additions & 0 deletions thingsdb/model/thing.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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('__')}
Expand All @@ -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__)

Expand All @@ -89,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)
Expand All @@ -105,6 +120,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}')

Expand Down Expand Up @@ -148,6 +171,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()
Expand Down Expand Up @@ -270,6 +296,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,
Expand Down
1 change: 1 addition & 0 deletions thingsdb/util/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
from .convert import convert
from .fmt import fmt
from .event import event
12 changes: 12 additions & 0 deletions thingsdb/util/event.py
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion thingsdb/version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.6.3'
__version__ = '0.6.4'