views:

58

answers:

1

I have an little script which logs users that login to my Pidgin/MSN account

#!/usr/bin/env python

def log_names(buddy):
    name = str(purple.PurpleBuddyGetName(buddy))
    account = purple.PurpleAccountGetUsername(purple.PurpleBuddyGetAccount(buddy))

    if account == u'[email protected]':

        try: log[name] += 1
        except KeyError: log[name] = 1
        log.sync()


import dbus, gobject, shelve
from dbus.mainloop.glib import DBusGMainLoop
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()

log = shelve.open('pidgin.log')

obj = bus.get_object('im.pidgin.purple.PurpleService',
                     '/im/pidgin/purple/PurpleObject')
purple = dbus.Interface(obj, 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(log_names,
                       dbus_interface='im.pidgin.purple.PurpleInterface',
                       signal_name='BuddySignedOn')

loop = gobject.MainLoop()
loop.run()

I wanna add a simple interactive console to this which allows me to query the data from the log object, but I'm stuck at how I would implement it

Do I use threads of some kind or am I able to use some sort of call back within gobject.MainLoop()?

+1  A: 

You should look in the direction of general GObject/GLib programming (this is where gobject.MainLoop() is coming from). You could use threads, you could use event callbacks, whatever. For example, this is a simple 'console' using event callbacks. Add this just before the loop.run():

import glib, sys, os, fcntl

class IODriver(object):
    def __init__(self, line_callback):
        self.buffer = ''
        self.line_callback = line_callback
        flags = fcntl.fcntl(sys.stdin.fileno(), fcntl.F_GETFL)
        flags |= os.O_NONBLOCK
        fcntl.fcntl(sys.stdin.fileno(), fcntl.F_SETFL, flags)
        glib.io_add_watch(sys.stdin, glib.IO_IN, self.io_callback)

    def io_callback(self, fd, condition):
        chunk = fd.read()
        for char in chunk:
            self.buffer += char
            if char == '\n':
                self.line_callback(self.buffer)
                self.buffer = ''

        return True

def line_entered(line):
    print "You have typed:", line.strip()

d = IODriver(line_entered)

If you are building a PyGTK application, you don't have to call the mainloop specially for the dbus, because it will use the main application's mainloop. There also other mainloops for other libraries available, for example dbus.mainloop.qt for PyQt4.

abbot