This notebook is part of my MESS Design Workshop PubSub {DRAFT}
For instruction to run, or see it as a slideshow, see: http://mess.softwarebetermaken.nl/en/latest/SoftwareCompetence/DesignWorkShops/PubSub/demo/index.html {Draft}
Notes (in slides-mode):
Some demos in python
Use it, by publishing to all
Both, the notebook & slides are downloadable
Topic
classclass Topic():
def __init__(self, name=None, initial_value=None):
self.name = "" if name is None else str(name)
self._callbacks = []
self._value = initial_value
def subscribe(self, callback):
if not callback in self._callbacks:
self._callbacks.append(callback)
def publish(self, value, force=False):
if force or self._value != value:
self._call_callbacks(value)
self._value = value
def _call_callbacks(self, new_value):
for cb in self._callbacks:
cb(new_value, self)
def __str__(self):
return "<<%s: '%s' at 0X%x>>" % (
self.__class__.__name__, self.name, id(self))
def demo(val, topic):
print("Demo:: Topic: %s has new value: %s" %(topic, val))
Note: You can ignore the dunder methods, Topic.__init__()
and Topic.__str__()
for now
demo
t1=Topic("demo 1")
t1.subscribe(demo)
t1.publish("HOI")
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: HOI
Using a Topic is trivial:
Once a topic is created and a callback is registerd, that function is called whenever a new value is pubished.
topic.publish(data)
kind of act as callback(data, topic)
, for all callbacks in a loop
force
)# Only a changed value will be published
t1.publish("AGAIN")
t1.publish("AGAIN")
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: AGAIN
# Unless we 'force' it
t1.publish("FORCE", force=True) # This force is needed, as it isn't "again" ...
t1.publish("FORCE", force=True)
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: FORCE Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: FORCE
# Unless we 'force' it
t1.publish("SMART", force=False) # You see ...
t1.publish("SMART", force=True)
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: SMART Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: SMART
This Topic
will not subscribe the same function again
t1.publish("I'm so smart")
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: I'm so smart
# `demo` is already registered above
t1.subscribe(demo) # will silently be ingnored
t1.publish("As I call demo only once")
Demo:: Topic: <<Topic: 'demo 1' at 0X1941ca82e88>> has new value: As I call demo only once
Now with multiple subscribers
t2
And subscribe all callbacks to the same t2
Topic ...
Then, all are executed as when publish()
is called (once).
It is so easy :-)
t2= Topic("demo2")
def demo_2(val, topic):
print("Demo 2:: Topic: %s has new value: %s" %(topic, val))
def demo_3(val, topic):
print("Demo 3:: Topic: %s has new value: %s" %(topic, val))
def demo_4(val, topic):
print("Demo 4:: Topic: %s has new value: %s" %(topic, val))
t2.subscribe(demo)
t2.subscribe(demo_2)
t2.subscribe(demo_3)
t2.subscribe(demo_4)
t2.publish("ALL")
Demo:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: ALL Demo 2:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: ALL Demo 3:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: ALL Demo 4:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: ALL
t2.publish("again")
Demo:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: again Demo 2:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: again Demo 3:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: again Demo 4:: Topic: <<Topic: 'demo2' at 0X1941ca89848>> has new value: again
Surely, we can add more subscribers, and publish more often ...
You can also subscribe methods, when you prefer an OO style. This works the same as with functions: just register the method.
t3
Notes:
self
).self._no
) to show (which of the) many instances are used.class Demo:
_stat_count=0
def __init__(self):
self._no = Demo._stat_count # make them unique
Demo._stat_count+=1
def demo(self, val, topic):
print("%s got '%s' from topic %s" %(
self, val, topic))
def __str__(self):
return "<<%s: ._no=%d at 0X%x>>" % (
self.__class__.__name__, self._no, id(self))
Note: Again, you may ignore the dunder methods, Demo.__init__()
and ``Demo.__str__()
o = Demo()
t3 = Topic("OO Demo")
t3.subscribe(o.demo)
t3.publish("class")
<<Demo: ._no=0 at 0X1941cadb588>> got 'class' from topic <<Topic: 'OO Demo' at 0X1941cad8348>>
You can mix-&-match all the several uses:
t4 = Topic("four-10-plys")
t4.subscribe(demo)
for x in range(10): # Quicly create/subscribe 10 Demo-instances
t4.subscribe(Demo().demo)
t4.subscribe(demo_4)
t4.subscribe(demo_3)
t4.subscribe(demo_2)
t4.publish('Yes')
Demo:: Topic: <<Topic: 'four-10-plys' at 0X1941ca98e48>> has new value: Yes <<Demo: ._no=1 at 0X1941ca71e08>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=2 at 0X1941ca71dc8>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=3 at 0X1941ca82488>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=4 at 0X1941ca82988>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=5 at 0X1941ca82288>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=6 at 0X1941cabf748>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=7 at 0X1941cabf608>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=8 at 0X1941cabf388>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=9 at 0X1941ca82108>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> <<Demo: ._no=10 at 0X1941cabf048>> got 'Yes' from topic <<Topic: 'four-10-plys' at 0X1941ca98e48>> Demo 4:: Topic: <<Topic: 'four-10-plys' at 0X1941ca98e48>> has new value: Yes Demo 3:: Topic: <<Topic: 'four-10-plys' at 0X1941ca98e48>> has new value: Yes Demo 2:: Topic: <<Topic: 'four-10-plys' at 0X1941ca98e48>> has new value: Yes
t42 = Topic()
t42.subscribe(demo)
t42.publish("fist")
Demo:: Topic: <<Topic: '' at 0X1941cabf4c8>> has new value: fist
# Now add subscribe another callback
t42. subscribe(demo_2)
t42.publish("more and more")
Demo:: Topic: <<Topic: '' at 0X1941cabf4c8>> has new value: more and more Demo 2:: Topic: <<Topic: '' at 0X1941cabf4c8>> has new value: more and more
Back to the main presentation
import datetime, pytz
print("These slides are generated at:", datetime.datetime.now(pytz.timezone('Europe/Amsterdam')))
#EoF
These slides are generated at: 2020-03-24 10:24:17.362544+01:00