From 25e08bc62c382d2d172b71ab115fcfb2a8680179 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 12 Nov 2001 22:01:07 +0000 Subject: [PATCH] Fixed issues with nosy reaction and author copies. git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@391 57a73879-2fb5-44c3-a270-3262357dd7e2 --- roundup-admin | 19 +++- roundup/hyperdb.py | 7 +- roundup/instance.py | 13 ++- roundup/mailgw.py | 11 +- roundup/roundupdb.py | 102 ++++++++++-------- .../classic/detectors/nosyreaction.py | 15 ++- .../extended/detectors/nosyreaction.py | 15 ++- 7 files changed, 123 insertions(+), 59 deletions(-) diff --git a/roundup-admin b/roundup-admin index a7f2be7..4065e33 100755 --- a/roundup-admin +++ b/roundup-admin @@ -16,7 +16,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundup-admin,v 1.43 2001-11-09 22:33:28 richard Exp $ +# $Id: roundup-admin,v 1.44 2001-11-12 22:01:06 richard Exp $ import sys if int(sys.version[0]) < 2: @@ -64,6 +64,7 @@ class AdminTool: for k in AdminTool.__dict__.keys(): if k[:5] == 'help_': self.help[k[5:]] = getattr(self, k) + self.db = None def usage(message=''): if message: message = 'Problem: '+message+'\n' @@ -799,11 +800,15 @@ Command help: self.instance_home = raw_input('Enter instance home: ').strip() # before we open the db, we may be doing an init - if command == 'init': - return self.do_init(self.instance_home, args) + if command == 'initialise': + return self.do_initialise(self.instance_home, args) # get the instance - instance = roundup.instance.open(self.instance_home) + try: + instance = roundup.instance.open(self.instance_home) + except ValueError, message: + print "Couldn't open instance: %s"%message + return 1 self.db = instance.open('admin') if len(args) < 2: @@ -872,7 +877,8 @@ Command help: self.interactive() else: ret = self.run_command(args) - self.db.close() + if self.db: + self.db.close() return ret @@ -882,6 +888,9 @@ if __name__ == '__main__': # # $Log: not supported by cvs2svn $ +# Revision 1.43 2001/11/09 22:33:28 richard +# More error handling fixes. +# # Revision 1.42 2001/11/09 10:11:08 richard # . roundup-admin now handles all hyperdb exceptions # diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py index 49a6db6..5a4e837 100644 --- a/roundup/hyperdb.py +++ b/roundup/hyperdb.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: hyperdb.py,v 1.30 2001-11-09 10:11:08 richard Exp $ +# $Id: hyperdb.py,v 1.31 2001-11-12 22:01:06 richard Exp $ # standard python modules import cPickle, re, string @@ -545,7 +545,7 @@ class Class: if node.has_key(self.db.RETIRED_FLAG): continue for key, value in requirements.items(): - if node[key].lower() != value: + if node[key] and node[key].lower() != value: break else: l.append(nodeid) @@ -849,6 +849,9 @@ def Choice(name, *options): # # $Log: not supported by cvs2svn $ +# Revision 1.30 2001/11/09 10:11:08 richard +# . roundup-admin now handles all hyperdb exceptions +# # Revision 1.29 2001/10/27 00:17:41 richard # Made Class.stringFind() do caseless matching. # diff --git a/roundup/instance.py b/roundup/instance.py index 77dbb26..59c56fb 100644 --- a/roundup/instance.py +++ b/roundup/instance.py @@ -15,13 +15,13 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: instance.py,v 1.3 2001-08-07 00:24:42 richard Exp $ +# $Id: instance.py,v 1.4 2001-11-12 22:01:06 richard Exp $ ''' Currently this module provides one function: open. This function opens an instance. ''' -import imp +import imp, os class Opener: def __init__(self): @@ -29,6 +29,12 @@ class Opener: self.instances = {} def open(self, instance_home): + '''Open the instance. + + Raise ValueError if the instance home doesn't exist. + ''' + if not os.path.exists(instance_home): + raise ValueError, 'no such directory: "%s"'%instance_home if self.instances.has_key(instance_home): return imp.load_package(self.instances[instance_home], instance_home) @@ -46,6 +52,9 @@ del opener # # $Log: not supported by cvs2svn $ +# Revision 1.3 2001/08/07 00:24:42 richard +# stupid typo +# # Revision 1.2 2001/08/07 00:15:51 richard # Added the copyright/license notice to (nearly) all files at request of # Bizar Software. diff --git a/roundup/mailgw.py b/roundup/mailgw.py index de3e1e1..17f62f7 100644 --- a/roundup/mailgw.py +++ b/roundup/mailgw.py @@ -72,7 +72,7 @@ are calling the create() method to create a new node). If an auditor raises an exception, the original message is bounced back to the sender with the explanatory message given in the exception. -$Id: mailgw.py,v 1.30 2001-11-09 22:33:28 richard Exp $ +$Id: mailgw.py,v 1.31 2001-11-12 22:01:06 richard Exp $ ''' @@ -138,7 +138,8 @@ class MailGW: if sendto: try: self.handle_message(message) - return + sendto = [sendto[0][1]] + m = ['Subject: Well, it seemed to work', '', 'hi, mum!'] except MailUsageError, value: # bounce the message back to the sender with the usage message fulldoc = '\n'.join(string.split(__doc__, '\n')[2:]) @@ -150,8 +151,7 @@ class MailGW: except: # bounce the message back to the sender with the error message sendto = [sendto[0][1]] - m = ['Subject: failed issue tracker submission'] - m.append('') + m = ['Subject: failed issue tracker submission', ''] # TODO as attachments? m.append('---- traceback of failure ----') s = cStringIO.StringIO() @@ -516,6 +516,9 @@ def parseContent(content, blank_line=re.compile(r'[\r\n]+\s*[\r\n]+'), # # $Log: not supported by cvs2svn $ +# Revision 1.30 2001/11/09 22:33:28 richard +# More error handling fixes. +# # Revision 1.29 2001/11/07 05:29:26 richard # Modified roundup-mailgw so it can read e-mails from a local mail spool # file. Truncates the spool file after parsing. diff --git a/roundup/roundupdb.py b/roundup/roundupdb.py index ab3e0f3..d0ef649 100644 --- a/roundup/roundupdb.py +++ b/roundup/roundupdb.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: roundupdb.py,v 1.16 2001-10-30 00:54:45 richard Exp $ +# $Id: roundupdb.py,v 1.17 2001-11-12 22:01:06 richard Exp $ import re, os, smtplib, socket @@ -31,6 +31,7 @@ def splitDesignator(designator, dre=re.compile(r'([^\d]+)(\d+)')): raise DesignatorError, '"%s" not a node designator'%designator return m.group(1), m.group(2) + class Database: def getuid(self): """Return the id of the "user" node associated with the user @@ -214,6 +215,12 @@ class FileClass(Class): d['content'] = hyperdb.String() return d +class MessageSendError(RuntimeError): + pass + +class DetectorError(RuntimeError): + pass + # XXX deviation from spec - was called ItemClass class IssueClass(Class): # configuration @@ -266,17 +273,18 @@ class IssueClass(Class): r = {} for recipid in recipients: r[recipid] = 1 + rlen = len(recipients) # figure the author's id, and indicate they've received the message authid = self.db.msg.get(msgid, 'author') - r[authid] = 1 - sendto = [] # ... but duplicate the message to the author as long as it's not # the anonymous user if (self.MESSAGES_TO_AUTHOR == 'yes' and self.db.user.get(authid, 'username') != 'anonymous'): - sendto.append(authid) + if not r.has_key(authid): + recipients.append(authid) + r[authid] = 1 # now figure the nosy people who weren't recipients nosy = self.get(nodeid, 'nosy') @@ -286,46 +294,50 @@ class IssueClass(Class): # do...) if self.db.user.get(nosyid, 'username') == 'anonymous': continue if not r.has_key(nosyid): - sendto.append(nosyid) recipients.append(nosyid) - if sendto: - # update the message's recipients list - self.db.msg.set(msgid, recipients=recipients) - - # send an email to the people who missed out - sendto = [self.db.user.get(i, 'address') for i in recipients] - cn = self.classname - title = self.get(nodeid, 'title') or '%s message copy'%cn - # figure author information - authname = self.db.user.get(authid, 'realname') - if not authname: - authname = self.db.user.get(authid, 'username') - authaddr = self.db.user.get(authid, 'address') - if authaddr: - authaddr = '<%s> '%authaddr - else: - authaddr = '' - # TODO attachments - m = ['Subject: [%s%s] %s'%(cn, nodeid, title)] - m.append('To: %s'%', '.join(sendto)) - m.append('From: %s'%self.ISSUE_TRACKER_EMAIL) - m.append('Reply-To: %s'%self.ISSUE_TRACKER_EMAIL) - m.append('') - # add author information - m.append("%s %sadded the comment:"%(authname, authaddr)) - m.append('') - # add the content - m.append(self.db.msg.get(msgid, 'content')) - # "list information" footer - m.append(self.email_footer(nodeid, msgid)) - try: - smtp = smtplib.SMTP(self.MAILHOST) - smtp.sendmail(self.ISSUE_TRACKER_EMAIL, sendto, '\n'.join(m)) - except socket.error, value: - return "Couldn't send confirmation email: mailhost %s"%value - except smtplib.SMTPException, value: - return "Couldn't send confirmation email: %s"%value + # no new recipients + if rlen == len(recipients): + return + + # update the message's recipients list + self.db.msg.set(msgid, recipients=recipients) + + # send an email to the people who missed out + sendto = [self.db.user.get(i, 'address') for i in recipients] + cn = self.classname + title = self.get(nodeid, 'title') or '%s message copy'%cn + # figure author information + authname = self.db.user.get(authid, 'realname') + if not authname: + authname = self.db.user.get(authid, 'username') + authaddr = self.db.user.get(authid, 'address') + if authaddr: + authaddr = '<%s> '%authaddr + else: + authaddr = '' + # TODO attachments + m = ['Subject: [%s%s] %s'%(cn, nodeid, title)] + m.append('To: %s'%', '.join(sendto)) + m.append('From: %s'%self.ISSUE_TRACKER_EMAIL) + m.append('Reply-To: %s'%self.ISSUE_TRACKER_EMAIL) + m.append('') + # add author information + m.append("%s %sadded the comment:"%(authname, authaddr)) + m.append('') + # add the content + m.append(self.db.msg.get(msgid, 'content')) + # "list information" footer + m.append(self.email_footer(nodeid, msgid)) + try: + smtp = smtplib.SMTP(self.MAILHOST) + smtp.sendmail(self.ISSUE_TRACKER_EMAIL, sendto, '\n'.join(m)) + except socket.error, value: + raise MessageSendError, \ + "Couldn't send confirmation email: mailhost %s"%value + except smtplib.SMTPException, value: + raise MessageSendError, \ + "Couldn't send confirmation email: %s"%value def email_footer(self, nodeid, msgid): ''' Add a footer to the e-mail with some useful information @@ -339,6 +351,12 @@ Roundup issue tracker # # $Log: not supported by cvs2svn $ +# Revision 1.16 2001/10/30 00:54:45 richard +# Features: +# . #467129 ] Lossage when username=e-mail-address +# . #473123 ] Change message generation for author +# . MailGW now moves 'resolved' to 'chatting' on receiving e-mail for an issue. +# # Revision 1.15 2001/10/23 01:00:18 richard # Re-enabled login and registration access after lopping them off via # disabling access for anonymous users. diff --git a/roundup/templates/classic/detectors/nosyreaction.py b/roundup/templates/classic/detectors/nosyreaction.py index df0651e..8762197 100644 --- a/roundup/templates/classic/detectors/nosyreaction.py +++ b/roundup/templates/classic/detectors/nosyreaction.py @@ -15,7 +15,9 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: nosyreaction.py,v 1.4 2001-10-30 00:54:45 richard Exp $ +#$Id: nosyreaction.py,v 1.5 2001-11-12 22:01:07 richard Exp $ + +from roundup import roundupdb def nosyreaction(db, cl, nodeid, oldvalues): ''' A standard detector is provided that watches for additions to the @@ -51,7 +53,10 @@ def nosyreaction(db, cl, nodeid, oldvalues): # send a copy to the nosy list for msgid in messages: - cl.sendmessage(nodeid, msgid) + try: + cl.sendmessage(nodeid, msgid) + except roundupdb.MessageSendError, message: + raise roundupdb.DetectorError, message # update the nosy list with the recipients from the new messages nosy = cl.get(nodeid, 'nosy') @@ -82,6 +87,12 @@ def init(db): # #$Log: not supported by cvs2svn $ +#Revision 1.4 2001/10/30 00:54:45 richard +#Features: +# . #467129 ] Lossage when username=e-mail-address +# . #473123 ] Change message generation for author +# . MailGW now moves 'resolved' to 'chatting' on receiving e-mail for an issue. +# #Revision 1.3 2001/08/07 00:24:43 richard #stupid typo # diff --git a/roundup/templates/extended/detectors/nosyreaction.py b/roundup/templates/extended/detectors/nosyreaction.py index 45e6cee..ea8f695 100644 --- a/roundup/templates/extended/detectors/nosyreaction.py +++ b/roundup/templates/extended/detectors/nosyreaction.py @@ -15,7 +15,9 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: nosyreaction.py,v 1.4 2001-10-30 00:54:45 richard Exp $ +#$Id: nosyreaction.py,v 1.5 2001-11-12 22:01:07 richard Exp $ + +from roundup import roundupdb def nosyreaction(db, cl, nodeid, oldvalues): ''' A standard detector is provided that watches for additions to the @@ -51,7 +53,10 @@ def nosyreaction(db, cl, nodeid, oldvalues): # send a copy to the nosy list for msgid in messages: - cl.sendmessage(nodeid, msgid) + try: + cl.sendmessage(nodeid, msgid) + except roundupdb.MessageSendError, message: + raise roundupdb.DetectorError, message # update the nosy list with the recipients from the new messages nosy = cl.get(nodeid, 'nosy') @@ -82,6 +87,12 @@ def init(db): # #$Log: not supported by cvs2svn $ +#Revision 1.4 2001/10/30 00:54:45 richard +#Features: +# . #467129 ] Lossage when username=e-mail-address +# . #473123 ] Change message generation for author +# . MailGW now moves 'resolved' to 'chatting' on receiving e-mail for an issue. +# #Revision 1.3 2001/08/07 00:24:43 richard #stupid typo # -- 2.30.2