[Buildbot-commits] buildbot/buildbot/changes mail.py, 1.23, 1.24 maildir.py, 1.8, 1.9 maildirgtk.py, 1.1, NONE maildirtwisted.py, 1.3, NONE
Brian Warner
warner at users.sourceforge.net
Tue Jan 23 21:04:34 UTC 2007
Update of /cvsroot/buildbot/buildbot/buildbot/changes
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv15423/buildbot/changes
Modified Files:
mail.py maildir.py
Removed Files:
maildirgtk.py maildirtwisted.py
Log Message:
[project @ clean up maildir usage, remove a use of reactor.iterate from tests]
Original author: warner at lothar.com
Date: 2007-01-23 21:02:10
Index: mail.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/mail.py,v
retrieving revision 1.23
retrieving revision 1.24
diff -u -d -r1.23 -r1.24
--- mail.py 11 Dec 2006 09:06:34 -0000 1.23
+++ mail.py 23 Jan 2007 21:04:32 -0000 1.24
@@ -6,8 +6,11 @@
import os, re
from rfc822 import Message
+from zope.interface import implements
from buildbot import util
-from buildbot.changes import base, changes, maildirtwisted
+from buildbot.interfaces import IChangeSource
+from buildbot.changes import changes
+from buildbot.changes.maildir import MaildirService
def parseFreshCVSMail(self, fd, prefix=None, sep="/"):
"""Parse mail sent by FreshCVS"""
@@ -294,16 +297,18 @@
-class MaildirSource(maildirtwisted.MaildirTwisted, base.ChangeSource):
+class MaildirSource(MaildirService, util.ComparableMixin):
"""This source will watch a maildir that is subscribed to a FreshCVS
change-announcement mailing list.
"""
- compare_attrs = ["basedir", "newdir", "pollinterval", "parser"]
+ implements(IChangeSource)
+
+ compare_attrs = ["basedir", "pollinterval", "parser"]
parser = None
name = None
def __init__(self, maildir, prefix=None, sep="/"):
- maildirtwisted.MaildirTwisted.__init__(self, maildir)
+ MaildirService.__init__(self, maildir)
self.prefix = prefix
self.sep = sep
Index: maildir.py
===================================================================
RCS file: /cvsroot/buildbot/buildbot/buildbot/changes/maildir.py,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- maildir.py 6 Sep 2006 00:41:54 -0000 1.8
+++ maildir.py 23 Jan 2007 21:04:32 -0000 1.9
@@ -3,80 +3,94 @@
# This is a class which watches a maildir for new messages. It uses the
# linux dirwatcher API (if available) to look for new files. The
# .messageReceived method is invoked with the filename of the new message,
-# relative to the 'new' directory of the maildir.
-
-# this is an abstract base class. It must be subclassed by something to
-# provide a delay function (which polls in the case that DNotify isn't
-# available) and a way to safely schedule code to run after a signal handler
-# has fired. See maildirgtk.py and maildirtwisted.py for forms that use the
-# event loops provided by Gtk+ and Twisted.
+# relative to the top of the maildir (so it will look like "new/blahblah").
+import os
+from twisted.python import log
+from twisted.application import service, internet
+from twisted.internet import reactor
+dnotify = None
try:
- from dnotify import DNotify
- have_dnotify = 1
+ import dnotify
except:
- have_dnotify = 0
-import os
+ # I'm not actually sure this log message gets recorded
+ log.msg("unable to import dnotify, so Maildir will use polling instead")
-class Maildir:
- """This is a class which watches a maildir for new messages. Once
- started, it will run its .messageReceived method when a message is
- available.
+class NoSuchMaildir(Exception):
+ pass
+
+class MaildirService(service.MultiService):
+ """I watch a maildir for new messages. I should be placed as the service
+ child of some MultiService instance. When running, I use the linux
+ dirwatcher API (if available) or poll for new files in the 'new'
+ subdirectory of my maildir path. When I discover a new message, I invoke
+ my .messageReceived() method with the short filename of the new message,
+ so the full name of the new file can be obtained with
+ os.path.join(maildir, 'new', filename). messageReceived() should be
+ overridden by a subclass to do something useful. I will not move or
+ delete the file on my own: the subclass's messageReceived() should
+ probably do that.
"""
+ pollinterval = 10 # only used if we don't have DNotify
+
def __init__(self, basedir=None):
"""Create the Maildir watcher. BASEDIR is the maildir directory (the
one which contains new/ and tmp/)
"""
+ service.MultiService.__init__(self)
self.basedir = basedir
self.files = []
- self.pollinterval = 10 # only used if we don't have DNotify
- self.running = 0
self.dnotify = None
def setBasedir(self, basedir):
+ # some users of MaildirService (scheduler.Try_Jobdir, in particular)
+ # don't know their basedir until setServiceParent, since it is
+ # relative to the buildmaster's basedir. So let them set it late. We
+ # don't actually need it until our own startService.
self.basedir = basedir
- def start(self):
- """You must run start to receive any messages."""
- assert self.basedir
+ def startService(self):
+ service.MultiService.startService(self)
self.newdir = os.path.join(self.basedir, "new")
- if self.running:
- return
- self.running = 1
if not os.path.isdir(self.basedir) or not os.path.isdir(self.newdir):
- raise "invalid maildir '%s'" % self.basedir
- # we must hold an fd open on the directory, so we can get notified
- # when it changes.
- global have_dnotify
- if have_dnotify:
- try:
- self.dnotify = DNotify(self.newdir, self.dnotify_callback,
- [DNotify.DN_CREATE])
- except (IOError, OverflowError):
- # IOError is probably linux<2.4.19, which doesn't support
- # dnotify. OverflowError will occur on some 64-bit machines
- # because of a python bug
- print "DNotify failed, falling back to polling"
- have_dnotify = 0
-
+ raise NoSuchMaildir("invalid maildir '%s'" % self.basedir)
+ try:
+ if dnotify:
+ # we must hold an fd open on the directory, so we can get
+ # notified when it changes.
+ self.dnotify = dnotify.DNotify(self.newdir,
+ self.dnotify_callback,
+ [dnotify.DNotify.DN_CREATE])
+ except (IOError, OverflowError):
+ # IOError is probably linux<2.4.19, which doesn't support
+ # dnotify. OverflowError will occur on some 64-bit machines
+ # because of a python bug
+ log.msg("DNotify failed, falling back to polling")
+ if not self.dnotify:
+ t = internet.TimerService(self.pollinterval, self.poll)
+ t.setServiceParent(self)
self.poll()
- def startTimeout(self):
- raise NotImplemented
- def stopTimeout(self):
- raise NotImplemented
def dnotify_callback(self):
- print "callback"
- self.poll()
- raise NotImplemented
-
- def stop(self):
+ log.msg("dnotify noticed something, now polling")
+
+ # give it a moment. I found that qmail had problems when the message
+ # was removed from the maildir instantly. It shouldn't, that's what
+ # maildirs are made for. I wasn't able to eyeball any reason for the
+ # problem, and safecat didn't behave the same way, but qmail reports
+ # "Temporary_error_on_maildir_delivery" (qmail-local.c:165,
+ # maildir_child() process exited with rc not in 0,2,3,4). Not sure
+ # why, and I'd have to hack qmail to investigate further, so it's
+ # easier to just wait a second before yanking the message out of new/
+
+ reactor.callLater(0.1, self.poll)
+
+
+ def stopService(self):
if self.dnotify:
self.dnotify.remove()
self.dnotify = None
- else:
- self.stopTimeout()
- self.running = 0
+ return service.MultiService.stopService(self)
def poll(self):
assert self.basedir
@@ -94,22 +108,10 @@
for n in newfiles:
# TODO: consider catching exceptions in messageReceived
self.messageReceived(n)
- if not have_dnotify:
- self.startTimeout()
def messageReceived(self, filename):
- """Called when a new file is noticed. Override it in subclasses.
- Will receive path relative to maildir/new."""
- print filename
-
+ """Called when a new file is noticed. Will call
+ self.parent.messageReceived() with a path relative to maildir/new.
+ Should probably be overridden in subclasses."""
+ self.parent.messageReceived(filename)
-def test1():
- m = Maildir("ddir")
- m.start()
- import signal
- while 1:
- signal.pause()
-
-if __name__ == '__main__':
- test1()
-
--- maildirgtk.py DELETED ---
--- maildirtwisted.py DELETED ---
More information about the Commits
mailing list