Zachciało mi się dzisiaj wygodnego powiadamiania o poczcie. Evolution udostępnia od jakiegoś czasu powiadomienia za pomocą interfejsu D-BUS, Python ma binding dla D-BUSa, czemu więc nie napisać appletu, który by słuchał tych powiadomień?

Szybko przekonałem się, że łatwo nie będzie, bo Evolution nie posiada dla interfejsu powiadomień nazwy kanonicznej. Znaczy to mniej-więcej tyle, że D-BUS przydziela mu przy każdym włączeniu programu losową nazwę postaci :X.Y (podobnie, jak X11 numeruje swoje sesje i ekrany). Nazwa oczywiście zmienia się z każdym restartem Evo.

I tu pojawia się problem: binding Pythona pozwala bardzo wygodnie obsługiwać typowe przypadki użycia D-BUSa. Innymi słowy, wszystko byłoby pięknie, gdyby dało się zrobić tak:

#!/usr/bin/python
import gtk
import dbus
import gnomeapplet
import sys

class evoNotify:
	def handleNewMail(self, int, sig, srv, pth, msg):
		self.label.set_label('new mail')
		print('test')

	def handleReadingMail(self, int, sig, srv, pth, msg):
		self.label.set_label('read mail')
		print('test')

	def __init__(self, applet):
		label = gtk.Label('test')
		self.label = label
		bus = dbus.SessionBus()
		evolution = bus.get_service(':1.0')
		ifc = evolution.get_object('/org/gnome/evolution/mail/newmail',
				'org.gnome.evolution.mail.dbus.Signal')

		applet.iface = ifc

		applet.iface.connect_to_signal('MessageReading',
				self.handleReadingMail)
		
		applet.iface.connect_to_signal('NewMail',
				self.handleNewMail)
	
		applet.add(self.label)

		applet.show_all()

def appletFactory(applet, iid):
	evoNotify(applet)
	return gtk.TRUE

gnomeapplet.bonobo_factory('OAFIID:GNOME_evoMailApplet_Factory',
		gnomeapplet.Applet.__gtype__,
		'evoMailApplet', '0.1', appletFactory)

gtk.main()

Ale nie można, bo niby skąd znać wcześniej unikalny numerek serwisu przyznany przez demona? W C można to prosto obejść, tam można posłużyć się add_match i wyłapywać wiadomości po filtrach, niezależnie od nadawców (mam wszelkie powody, żeby założyć, że właśnie tak działa dbus-monitor, ale nie chce mi się teraz sprawdzać), w Pythonie nie można, bo nie jest eksportowana taka metoda.

Póki co, oznacza to śmierć projektu. Przynajmniej do czasu, kiedy naprawione zostaną pythonowe wrappery, bo w C pisać tego nie zamierzam.