Note that there are some explanatory texts on larger screens.

plurals
  1. POPython observable implementation that supports multi-channel subscribers
    text
    copied!<p>In a twisted application I have a series of resource controller/manager classes that interact via the Observable pattern. Generally most observers will subscribe to a specific channel (ex. "foo.bar.entity2") but there are a few cases where I'd like to know about all event in a specific channel (ex. "foo.*" ) so I wrote something like the following:</p> <pre><code> from collections import defaultdict class SimplePubSub(object): def __init__(self): self.subjects = defaultdict(list) def subscribe(self, subject, callbackstr): """ for brevity, callbackstr would be a valid Python function or bound method but here is just a string """ self.subjects[subject].append(callbackstr) def fire(self, subject): """ Again for brevity, fire would have *args, **kwargs or some other additional message arguments but not here """ if subject in self.subjects: print "Firing callback %s" % subject for callback in self.subjects[subject]: print "callback %s" % callback pubSub = SimplePubSub() pubSub.subscribe('foo.bar', "foo.bar1") pubSub.subscribe('foo.foo', "foo.foo1") pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") #Find everything that starts with foo #say foo.bar is fired firedSubject = "foo.bar" pubSub.fire(firedSubject) #outputs #&gt;&gt;Firing callback foo.bar #&gt;&gt;callback foo.bar1 #but let's say I want to add a callback for everything undr foo.ich class GlobalPubSub(SimplePubSub): def __init__(self): self.globals = defaultdict(list) super(GlobalPubSub, self).__init__() def subscribe(self, subject, callback): if subject.find("*") &gt; -1: #assumes global suscriptions would be like subject.foo.* and we want to catch all subject.foo's self.globals[subject[:-2]].append(callback) else: super(GlobalPubSub, self).subscribe(subject, callback) def fire(self, subject): super(GlobalPubSub, self).fire(subject) if self.globals: for key in self.globals.iterkeys(): if subject.startswith(key): for callback in self.globals[key]: print "global callback says", callback print "Now with global subscriptions" print pubSub = GlobalPubSub() pubSub.subscribe('foo.bar', "foo.bar1") pubSub.subscribe('foo.foo', "foo.foo1") pubSub.subscribe('foo.ich.tier1', "foo.ich.tier3_1") pubSub.subscribe('foo.ich.tier2', "foo.ich.tier2_1") pubSub.subscribe('foo.ich.tier3', "foo.ich.tier2_1") pubSub.subscribe("foo.ich.*", "All the ichs, all the time!") #Find everything that starts with foo.ich firedSubject = "foo.ich.tier2" pubSub.fire(firedSubject) #outputs #&gt;&gt;Firing callback foo.bar #&gt;&gt;callback foo.bar1 #&gt;&gt;Now with global subscriptions # #&gt;&gt;Firing callback foo.ich.tier2 #&gt;&gt;callback foo.ich.tier2_1 #&gt;&gt;global callback says All the ichs, all the time! </code></pre> <p>Is this as good as it gets without resorting to some sort of exotic construct ( tries for example )? I'm looking for an affirmation that I'm on the right track or a better alternative suggestion on a global subscription handler that's pure python ( no external libraries or services ).</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload