About Louie and lib.pubsub

Stani's Python Editor spe.stani.be at gmail.com
Fri Jun 22 02:41:47 PDT 2007


Hi Bill,

I wrote a wrapper some time ago which appareantly makes pubsub behave
like what you are looking for in Louie. From this module you only need
to import the mixin 'Receiver' and the instance 'send'. You need to do
two steps: register any object with Receiver (e.g. with the name 'test')
and afterwards to subscribe the methods (e.g. the method 'write').
Afterwards you can send a notification by unifying the name of the
receiver and the method name with an underscore (e.g. 'test_write' ->
'send.test_write'). The only limitation is that you can not use dots.
(However after some hacking that could be a possibility as well.) In
this way there is no need for a message anymore and you can pass
arguments and/or keyword options.
In my applications I just copy pubsub.py locally and include events.py
as I also want that my application can work as a console application
without a gui. If you want to see a full application using my events
module, you can browse the trunk code of:
http://launchpad.net/phatch

You'll need bazaar to download it locally. Events.py is in phatch/core

Stani
--
http://pythonide.stani.be

wxPython-dev-digest-help at lists.wxwidgets.org schreef:
> Onderwerp:
> About Louie and lib.pubsub
> Van:
> "Bill Baxter" <wbaxter at gmail.com>
> Datum:
> Fri, 22 Jun 2007 11:59:56 +0900
> Aan:
> wxpython-dev at lists.wxwidgets.org
> =

> Aan:
> wxpython-dev at lists.wxwidgets.org
> =

> =

> I posted something about this to the Louie mailing list, but since there
> have been all of 5 messages there since last year, I didn't really expect=
 a
> reply, and indeed didn't get one.
> =

> So at the risk of being off-topic I'm repeating myself here since this is
> the place I heard about Louie.
> =

> Here's my quick comparison of how Louie measures up to wx.lib.pubsub:
> =

> - on the plus side you can hook up arbitrary methods as callbacks, unlike
> wx.lib.pubsub where your callback always has to take a single Message
> parameter.  With Louie, if you have a method sitting around that takes a
> 'value' parameter, you can hook up some notification to it directly rather
> than having to write an adapter that takes a Message, extracts the
> msg.data.value and then calls the function you really wanted to call.   I=
'm
> sure there's a cost you have to pay for this though.   You can also just
> use
> positional arguments.  So with louie you can do:
> =

>   louie.send('value_changed", sender, new_value)
> =

> and it can directly call a callback method like
> =

>   def setDisplay(self, display):
>        self.text =3D str(display)
> =

> whereas with pubsub you'd have to make another method to call the
> setDisplay
> one, something like:
> =

>   def onValueChanged(self, message):
>        self.setDisplay(message.data['new_value'])
> =

> It's just an extra two-liner, but still it's kind of an annoyance for
> someone used to Qt's way where signals can usually be hooked up to existi=
ng
> slots that are just setters.  Maybe you can lambda it down to a one-liner,
> but it's still a little extra work.
> =

> =

> - on the minus side Louie uses a single global dispatcher.  In that respe=
ct
> wx.lib.pubsub is nicer, since you can create multiple
> dispatchers/Publishers
> with pubsub.  This was a deal-breaker for me.  If you have a app that
> creates two main document frames, it makes no sense for there to be a
> single
> dispatcher that processes all the signals in both frames.  The dispatcher
> for events related to one document should really belong to that document,
> and not be global.   Having said that, it doesn't look like it would be
> terribly hard to fix Louie to make the dispatcher a class.
> =

> - also on the minus side, like I said, I posted a message to the Louie
> mailing list and got no response.  Seems like the project is pretty dead =
at
> this time.
> =

> --bb
> =


-------------- next part --------------
"""(c)2007 www.stani.be
License: GPLv2 or later
The aim of this library is to abstract pubsub."""

from lib.pubsub import ALL_TOPICS, Publisher

#---Send
class SendListener:
    def __init__(self,topic=3DALL_TOPICS):
        self.topic  =3D topic
        =

    def __call__(self, *args, **keyw):
        data    =3D (args,keyw) #pack (see ReceiveListener.__call__)
        return Publisher().sendMessage(self.topic,data)
    =

class Sender:
    def __getattr__(self,topic):
        return SendListener(topic)
    =

send    =3D Sender()

#---Receive
def subscribe(method,obj):
    Publisher().subscribe(method,getattr(obj,method))
    =

class ReceiveListener:
    def __init__(self,obj,method):
        self.method =3D getattr(obj,method)
        =

    def __call__(self,message):
        args, keyw  =3D message.data #unpack (see SendListener.__call__)
        return self.method(*args, **keyw)
    =

class Receiver:
    def __init__(self,name):
        self._pubsub_name           =3D name
        self._listeners             =3D []
        =

    def subscribe(self,method):
        """Subscribe with some class magic.
        Example: self.subscribe('error') -> subscribe('frame.error')
        Afterwars you can call it with send.frame_error()"""
        listener  =3D ReceiveListener(self,method)
        self._listeners.append(listener)
        Publisher().subscribe(listener,'%s_%s'%(self._pubsub_name,method))
        =

    def unsubscribe(self,method):
        """Subscribe with some class magic.
        Example: self.subscribe('error') -> subscribe('frame.error')"""
        listener  =3D ReceiveListener(self,method)
        self._listeners.remove(listener)
        Publisher().unsubscribe(listener,'%s_%s'%(self._pubsub_name,method))
        =

    def unsubscribe_all(self):
        for listener in self._listeners:
            Publisher().unsubscribe(listener)
        self._listeners =3D []
        =

def test():
    import sys
    =

    class Test(Receiver):
        def __init__(self):
            #register an instance
            Receiver.__init__(self,'test')
            #register the method send.test_write -> self.write
            self.subscribe('write')
            self.phrase =3D 'planet'
            =

        def write(self,phrase,error):
            sys.stdout.write(phrase+'\n')
            sys.stderr.write(error)
            self.phrase =3D phrase
            =

    demo    =3D Test()
    phrase  =3D 'hello world'
    send.test_write(phrase,error=3D'(No error.)')
    assert demo.phrase  =3D=3D phrase =

            =

if __name__ =3D=3D '__main__':
    test()


More information about the wxpython-dev mailing list