web/hosts/issues/detectors ciabot.py,1.1,1.2

Nathaniel Smith <[email protected]> Sun, 01 Jun 2003 22:12:38 -0500
Newsgroups gmane.comp.video.fresco.cvs
Message-ID <[email protected]>
Update of /cvs/fresco/web/hosts/issues/detectors
In directory purcel:/tmp/cvs-serv3904

Modified Files:
	ciabot.py 
Log Message:
Commit working version of ciabot detector.


Index: ciabot.py
===================================================================
RCS file: /cvs/fresco/web/hosts/issues/detectors/ciabot.py,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- ciabot.py	2 Jun 2003 01:21:04 -0000	1.1
+++ ciabot.py	2 Jun 2003 03:12:34 -0000	1.2
@@ -1,4 +1,5 @@
 from roundup import roundupdb, hyperdb
+from __future__ import nested_scopes
 
 ADDRESSES = ["[email protected]"]
 SUBJECT = "Announce Fresco"
@@ -14,34 +15,40 @@
         self.event = event
         self.cls = cls
     def __call__(self, db, cl, nodeid, oldvalues):
-        def name(id):
-            if id == -1: return "nobody"
-            return db.user.get(id, "username")
+        def username(nid):
+            if nid is None: return "nobody"
+            return db.user.get(nid, "username")
         args = {}
+        #args["dbg"] = (repr(have_inited) + "," + str(id(self)) + "," +
+        #               self.event + "," + self.cls + " ")
+        args["dbg"] = ""
         args["class"] = self.cls
         args["id"] = nodeid
         args["url"] = BASEURL + self.cls + nodeid
         args["title"] = cl.get(nodeid, "title")
-        args["user"] = name(db.getuid())
+        args["user"] = username(db.getuid())
 
         if self.event == "create":
-            self.message("%(user)s created %(id)s: "
-                         + "%(title)s  (see %(url)s )" % args)
+            self.message(db, ("%(dbg)s%(user)s created %(class)s%(id)s: "
+                              + "%(title)s (see %(url)s)") % args)
 
         elif self.event == "retire":
-            self.message("%(user)s retired %(id)s (%(title)s)" % args)
+            self.message(db, "%(dbg)s%(user)s retired %(class)s%(id)s (%(title)s)"
+                             % args)
 
         else:  # self.event == "set"
-            def modified(key):
-                return oldvalues.has_key(key)
             mods = oldvalues.copy()
-            def noted(key):
-                del mods[key]
+            # modified() has the evil side effect of assuming that if you call
+            # it, then you don't want the key to show up in the "also
+            # modified" list.
+            def modified(key):
+                if oldvalues.has_key(key):
+                    del mods[key]
+                    return oldvalues[key] != cl.get(nodeid, key)
+                else:
+                    return 0
 
-            interesting_fields = ("messages", "title", "files", "superseder",
-                                  "assignedto", "topics", "status",
-                                  "priority", "resolution", "dependson")
-            msgstr = "%(user)s modified %(id)s"
+            msgstr = "%(dbg)s%(user)s modified %(class)s%(id)s"
             if modified("title"):
                 noted("title")
                 args["oldtitle"] = oldvalues["title"]
@@ -51,80 +58,84 @@
 
             notes = []
             if modified("messages"):
-                noted("messages")
                 notes.append("added message")
             if modified("files"):
-                noted("files")
                 notes.append("added file")
             if modified("assignedto"):
-                noted("assignedto")
-                if self.event == "task":
-                    addedids = listminus(cls.get(nodeid, "assignedto"),
+                if self.cls == "task":
+                    addedids = listminus(cl.get(nodeid, "assignedto"),
                                          oldvalues["assignedto"])
-                    added = map(name, addedids)
+                    added = map(username, addedids)
                     removedids = listminus(oldvalues["assignedto"],
-                                           cls.get(nodeid, "assignedto"))
-                    removed = map(name, removedids)
+                                           cl.get(nodeid, "assignedto"))
+                    removed = map(username, removedids)
                     if added: notes.append("assigned to: " + ", ".join(added))
                     if removed: notes.append("unassigned from: "
                                              + ", ".join(removed))
                 else:
                     notes.append("assigned to %s (was %s)"
-                                 % (name(cls.get(nodeid, "assignedto")),
-                                    name(oldvalues["assignedto"])))
+                                 % (username(cl.get(nodeid, "assignedto")),
+                                    username(oldvalues["assignedto"])))
+            def nametuple(cls, key):
+                def fetch(nid):
+                    if nid is None: return "no selection"
+                    else: return cls.get(nid, "name")
+                return (fetch(oldvalues[key]), fetch(cl.get(nodeid, key)))
             if modified("status"):
-                noted("status")
                 notes.append("Status: %s -> %s"
-                             % (db.status.get(oldvalues["status"]),
-                                db.status.get(cl.get(nodeid, "status"))))
+                             % nametuple(db.status, "status"))
             if modified("resolution"):
-                noted("resolution")
                 notes.append("Resolution: %s -> %s"
-                             % (db.resolution.get(oldvalues["resolution"]),
-                                db.resolution.get(cl.get(nodeid,
-                                                         "resolution"))))
+                             % nametuple(db.resolution, "resolution"))
+            if modified("result"):
+                notes.append("Result: %s -> %s"
+                             % nametuple(db.resolution, "result"))
             if modified("priority"):
-                noted("priority")
                 notes.append("Priority: %s -> %s"
-                             % (db.priority.get(oldvalues["priority"]),
-                                db.priority.get(cl.get(nodeid, "priority"))))
+                             % nametuple(db.priority, "priority"))
+            if modified("severity"):
+                notes.append("Severity: %s -> %s"
+                             % nametuple(db.priority, "severity"))
             if modified("release_date"):
-                noted("release_date")
                 notes.append("Release date: %s -> %s"
                              % (oldvalues["release_date"],
                                 cl.get(nodeid, "release_date")))
+            (addedbugs, removedbugs) = ([], [])
             if modified("bugs"):
-                noted("bugs")
-                addedbugs = listminus(cls.get(nodeid, "bugs"),
+                addedbugs = listminus(cl.get(nodeid, "bugs"),
                                       oldvalues["bugs"])
                 removedbugs = listminus(oldvalues["bugs"],
-                                        cls.get(nodeid, "bugs"))
+                                        cl.get(nodeid, "bugs"))
+            (addedtasks, removedtasks) = ([], [])
             if modified("tasks"):
-                noted("tasks")
-                addedtasks = listminus(cls.get(nodeid, "tasks"),
+                addedtasks = listminus(cl.get(nodeid, "tasks"),
                                       oldvalues["tasks"])
                 removedtasks = listminus(oldvalues["tasks"],
-                                        cls.get(nodeid, "tasks"))
+                                        cl.get(nodeid, "tasks"))
             # milestone specific attributes
             if addedtasks or addedbugs:
-                tlist = [BASEURL + "task" + id for id in addedtasks]
-                blist = [BASEURL + "bug" + id for id in addedbugs]
+                tlist = [BASEURL + "task" + nid for nid in addedtasks]
+                blist = [BASEURL + "bug" + nid for nid in addedbugs]
                 notes.append("Added: " + ", ".join(blist + tlist))
             if removedtasks or removedbugs:
-                tlist = [BASEURL + "task" + id for id in removedtasks]
-                blist = [BASEURL + "bug" + id for id in removedbugs]
+                tlist = [BASEURL + "task" + nid for nid in removedtasks]
+                blist = [BASEURL + "bug" + nid for nid in removedbugs]
                 notes.append("Removed: " + ", ".join(blist + tlist))
 
-            noted("activity")
-            notes.append("Also modified: " + ", ".join(mods.keys()))
+            del mods["activity"]
+            for key in mods.keys():  # we don't want to use an iter her
+                if mods[key] == cl.get(nodeid, key):
+                    del mods[key]
+            if mods:
+                notes.append("Also modified: " + ", ".join(mods.keys()))
 
             if notes:
                 msgstr += ": " + ", ".join(notes)
 
-            msgstr += 
-            self.message(msgstr % args)
+            msgstr += " (%(url)s)"
+            self.message(db, msgstr % args)
             
-    def message(body):
+    def message(self, db, body):
         lines = []
         while len(body) > MAXLINELENGTH:
             i = MAXLINELENGTH
@@ -150,7 +161,13 @@
         smtp = smtplib.SMTP(db.config.MAILHOST)
         smtp.sendmail(db.config.ADMIN_EMAIL, ADDRESSES, message.getvalue())
 
+# For some reason, we have to actually check this, or else we end setting up
+# multiple reactors on the same event.  It appears that roundup initializes
+# two databases, and calls init() twice for each of them?  very odd.
+have_inited = []
 def init(db):
+    if db in have_inited: return
+    have_inited.append(db)
     for event in ("create", "set", "retire"):
         for cls in ("bug", "task", "milestone"):
             db.getclass(cls).react(event, Notifier(event, cls))