@@ -43,6 +43,7 @@ class Thing(ThingHash):
4343 # will be created. A Collection instance will have `False` as default.
4444 __AS_TYPE__ = True
4545
46+ _ev_handlers = dict ()
4647 _props = dict ()
4748 _type_name = None # Only set when __AS_TYPE__ is True
4849 _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):
5455 collection ._register (self )
5556
5657 def __init_subclass__ (cls ):
58+ cls ._ev_handlers = {}
5759 cls ._props = {}
5860 items = {
5961 k : v for k , v in cls .__dict__ .items () if not k .startswith ('__' )}
@@ -63,6 +65,9 @@ def __init_subclass__(cls):
6365 if isinstance (val , tuple ):
6466 prop = cls ._props [key ] = Prop (* val )
6567 delattr (cls , key )
68+ elif callable (val ) and hasattr (val , '_ev' ):
69+ cls ._ev_handlers [val ._ev ] = val
70+
6671 if cls .__AS_TYPE__ :
6772 cls ._type_name = getattr (cls , '__TYPE_NAME__' , cls .__name__ )
6873
@@ -89,6 +94,16 @@ def unwatch(self):
8994 collection = self ._collection
9095 return collection ._client .unwatch (self ._id , scope = collection ._scope )
9196
97+ def emit (self , event , * args ):
98+ data = {f'd{ i } ' : v for i , v in enumerate (args )}
99+ dstr = "" .join ((f", { k } " for k in data .keys ()))
100+
101+ return self ._collection .query (
102+ f'thing(id).emit(event{ dstr } );' ,
103+ id = self ._id ,
104+ event = event ,
105+ ** data )
106+
92107 @checkevent
93108 def on_init (self , event , data ):
94109 self ._job_set (data )
@@ -105,6 +120,14 @@ def on_update(self, event, jobs):
105120 def on_delete (self ):
106121 self ._collection ._things .pop (self .id ())
107122
123+ def on_event (self , ev , * args ):
124+ cls = self .__class__
125+ fun = cls ._ev_handlers .get (ev )
126+ if fun is None :
127+ logging .debug (f'no event handler for { ev } on { cls .__name__ } ' )
128+ return
129+ fun (self , * args )
130+
108131 def on_stop (self ):
109132 logging .warning (f'stopped watching thing { self } ' )
110133
@@ -148,6 +171,9 @@ def _job_del(self, k):
148171 except AttributeError :
149172 pass
150173
174+ def _job_event (self , data ):
175+ self .on_event (* data )
176+
151177 def _job_remove (self , pair ):
152178 cls = self .__class__
153179 (k , v ), = pair .items ()
@@ -270,6 +296,7 @@ def _job_set_type(self, data):
270296 # Thing jobs
271297 'add' : _job_add ,
272298 'del' : _job_del ,
299+ 'event' : _job_event ,
273300 'remove' : _job_remove ,
274301 'set' : _job_set ,
275302 'splice' : _job_splice ,
0 commit comments