Skip to content

Commit 63eb54a

Browse files
author
Richard Jones
committed
Fix breakage caused by transaction changes.
Sorry for the huge checkin message - I was only intending to implement [SF#496356] but I found a number of places where things had been broken by transactions: . modified ROUNDUPDBSENDMAILDEBUG to be SENDMAILDEBUG and hold a filename for _all_ roundup-generated smtp messages to be sent to. . the transaction cache had broken the roundupdb.Class set() reactors . newly-created author users in the mailgw weren't being committed to the db Stuff that made it into CHANGES.txt (ie. the stuff I was actually working on when I found that stuff :): . [SF#496356] Use threading in messages . detectors were being registered multiple times . added tests for mailgw . much better attaching of erroneous messages in the mail gateway
1 parent 088775c commit 63eb54a

File tree

12 files changed

+497
-111
lines changed

12 files changed

+497
-111
lines changed

CHANGES.txt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
This file contains the changes to the Roundup system over time. The entries
22
are given with the most recent entry first.
33

4-
2001-12-?? - 0.3.1b1
4+
2001-12-?? - 0.4.0b1
55
Feature:
66
. Added INSTANCE_NAME to configuration - used in web and email to identify
77
the instance.
@@ -25,6 +25,11 @@ Feature:
2525
. Added a Zope frontend for roundup.
2626
. Centralised the python version check code, bumped version to 2.1.1 (really
2727
needs to be 2.1.2, but that isn't released yet :)
28+
. much better attaching of erroneous messages in the mail gateway
29+
. #496356 ] Use threading in messages
30+
This adds the tracking of messages by message-id and allows threading
31+
using in-reply-to. Most e-mail clients support threading using this
32+
feature, and we hope to add support for it to the web gateway.
2833

2934
Fixed:
3035
. Lots of bugs, thanks Roch� and others on the devel mailing list!
@@ -47,7 +52,12 @@ Fixed:
4752
. envelope-from is now set to the roundup-admin and not roundup itself so
4853
delivery reports aren't sent to roundup (thanks Patrick Ohly)
4954
. #495400 ] entering blanks
55+
Values with spaces are now accepted in roundup-admin - check the long help
56+
for details.
5057
. #496360 ] table width does not work
58+
. detectors were being registered multiple times
59+
. added tests for mailgw
60+
5161

5262
2001-11-23 - 0.3.0
5363
Feature:

MIGRATION.txt

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,54 @@
11
Migrating to newer versions of Roundup
22
======================================
33

4+
Please read each section carefully and edit your instance home files
5+
accordingly.
46

5-
Migrating from 0.2.x to 0.3.x
7+
This file contains information for users upgrading from:
8+
0.3.x -> 0.4.x
9+
0.2.x -> 0.3.x
10+
11+
12+
Migrating from 0.3.x to 0.4.x
613
=============================
714

8-
Please read each section carefully and edit your instance home files
9-
accordingly.
15+
Message-ID and In-Reply-To addition
16+
-----------------------------------
17+
0.4.0 adds the tracking of messages by message-id and allows threading
18+
using in-reply-to. Most e-mail clients support threading using this
19+
feature, and we hope to add support for it to the web gateway. If you
20+
have not edited the dbinit.py file in your instance home directory, you may
21+
simply copy the new dbinit.py file from the core code. If you used the
22+
classic schema, the interfaces file is in:
1023

24+
<roundup source>/roundup/templates/classic/dbinit.py
25+
26+
If you used the extended schema, the file is in:
27+
28+
<roundup source>/roundup/templates/extended/dbinit.pybinit.py needs updating from the original.
29+
30+
If you have modified your dbinit.py file, you may use encoded passwords:
31+
32+
1. Edit the dbinit.py file in your instance home directory. Find the lines
33+
which define the msg class:
34+
35+
msg = FileClass(db, "msg",
36+
author=Link("user"), recipients=Multilink("user"),
37+
date=Date(), summary=String(),
38+
files=Multilink("file"))
39+
40+
and add the messageid and inreplyto properties like so:
41+
42+
msg = FileClass(db, "msg",
43+
author=Link("user"), recipients=Multilink("user"),
44+
date=Date(), summary=String(),
45+
files=Multilink("file"),
46+
messageid=String(), inreplyto=String())
47+
48+
49+
50+
Migrating from 0.2.x to 0.3.x
51+
=============================
1152

1253
Cookie Authentication changes
1354
-----------------------------

roundup/backends/back_anydbm.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
#$Id: back_anydbm.py,v 1.20 2001-12-18 15:30:34 rochecompaan Exp $
18+
#$Id: back_anydbm.py,v 1.21 2002-01-02 02:31:38 richard Exp $
1919
'''
2020
This module defines a backend that saves the hyperdatabase in a database
2121
chosen by anydbm. It is guaranteed to always be available in python
@@ -187,23 +187,25 @@ def savenode(self, classname, nodeid, node):
187187
print 'savenode', (self, classname, nodeid, node)
188188
self.transactions.append((self._doSaveNode, (classname, nodeid, node)))
189189

190-
def getnode(self, classname, nodeid, db=None):
190+
def getnode(self, classname, nodeid, db=None, cache=1):
191191
''' get a node from the database
192192
'''
193193
if DEBUG:
194194
print 'getnode', (self, classname, nodeid, cldb)
195-
# try the cache
196-
cache = self.cache.setdefault(classname, {})
197-
if cache.has_key(nodeid):
198-
return cache[nodeid]
195+
if cache:
196+
# try the cache
197+
cache = self.cache.setdefault(classname, {})
198+
if cache.has_key(nodeid):
199+
return cache[nodeid]
199200

200201
# get from the database and save in the cache
201202
if db is None:
202203
db = self.getclassdb(classname)
203204
if not db.has_key(nodeid):
204-
raise IndexError, nodeid
205+
raise IndexError, "no such %s %s"%(classname, nodeid)
205206
res = marshal.loads(db[nodeid])
206-
cache[nodeid] = res
207+
if cache:
208+
cache[nodeid] = res
207209
return res
208210

209211
def hasnode(self, classname, nodeid, db=None):
@@ -402,6 +404,15 @@ def rollback(self):
402404

403405
#
404406
#$Log: not supported by cvs2svn $
407+
#Revision 1.20 2001/12/18 15:30:34 rochecompaan
408+
#Fixed bugs:
409+
# . Fixed file creation and retrieval in same transaction in anydbm
410+
# backend
411+
# . Cgi interface now renders new issue after issue creation
412+
# . Could not set issue status to resolved through cgi interface
413+
# . Mail gateway was changing status back to 'chatting' if status was
414+
# omitted as an argument
415+
#
405416
#Revision 1.19 2001/12/17 03:52:48 richard
406417
#Implemented file store rollback. As a bonus, the hyperdb is now capable of
407418
#storing more than one file per node - if a property name is supplied,

roundup/cgi_client.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: cgi_client.py,v 1.87 2001-12-23 23:18:49 richard Exp $
18+
# $Id: cgi_client.py,v 1.88 2002-01-02 02:31:38 richard Exp $
1919

2020
__doc__ = """
2121
WWW request handler (also used in the stand-alone server).
2222
"""
2323

2424
import os, cgi, pprint, StringIO, urlparse, re, traceback, mimetypes
25-
import binascii, Cookie, time
25+
import binascii, Cookie, time, random
2626

2727
import roundupdb, htmltemplate, date, hyperdb, password
2828
from roundup.i18n import _
@@ -456,11 +456,16 @@ def _handle_message(self):
456456
# don't generate a useless message
457457
return None, files
458458

459+
# handle the messageid
460+
# TODO: handle inreplyto
461+
messageid = "%s.%s.%s%s-%s"%(time.time(), random.random(),
462+
classname, nodeid, self.MAIL_DOMAIN)
463+
459464
# now create the message, attaching the files
460465
content = '\n'.join(m)
461466
message_id = self.db.msg.create(author=self.getuid(),
462467
recipients=[], date=date.Date('.'), summary=summary,
463-
content=content, files=files)
468+
content=content, files=files, messageid=messageid)
464469

465470
# update the messages property
466471
return message_id, files
@@ -1163,6 +1168,10 @@ def parsePropsFromForm(db, cl, form, nodeid=0):
11631168

11641169
#
11651170
# $Log: not supported by cvs2svn $
1171+
# Revision 1.87 2001/12/23 23:18:49 richard
1172+
# We already had an admin-specific section of the web heading, no need to add
1173+
# another one :)
1174+
#
11661175
# Revision 1.86 2001/12/20 15:43:01 rochecompaan
11671176
# Features added:
11681177
# . Multilink properties are now displayed as comma separated values in

roundup/hyperdb.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1616
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1717
#
18-
# $Id: hyperdb.py,v 1.43 2001-12-20 06:13:24 rochecompaan Exp $
18+
# $Id: hyperdb.py,v 1.44 2002-01-02 02:31:38 richard Exp $
1919

2020
__doc__ = """
2121
Hyperdatabase implementation, especially field types.
@@ -240,18 +240,23 @@ def create(self, **propvalues):
240240
self.db.addjournal(self.classname, newid, 'create', propvalues)
241241
return newid
242242

243-
def get(self, nodeid, propname, default=_marker):
243+
def get(self, nodeid, propname, default=_marker, cache=1):
244244
"""Get the value of a property on an existing node of this class.
245245
246246
'nodeid' must be the id of an existing node of this class or an
247247
IndexError is raised. 'propname' must be the name of a property
248248
of this class or a KeyError is raised.
249+
250+
'cache' indicates whether the transaction cache should be queried
251+
for the node. If the node has been modified and you need to
252+
determine what its values prior to modification are, you need to
253+
set cache=0.
249254
"""
250255
if propname == 'id':
251256
return nodeid
252257

253258
# get the node's dict
254-
d = self.db.getnode(self.classname, nodeid)
259+
d = self.db.getnode(self.classname, nodeid, cache=cache)
255260
if not d.has_key(propname) and default is not _marker:
256261
return default
257262

@@ -271,10 +276,18 @@ def get(self, nodeid, propname, default=_marker):
271276
return d[propname]
272277

273278
# XXX not in spec
274-
def getnode(self, nodeid):
275-
''' Return a convenience wrapper for the node
279+
def getnode(self, nodeid, cache=1):
280+
''' Return a convenience wrapper for the node.
281+
282+
'nodeid' must be the id of an existing node of this class or an
283+
IndexError is raised.
284+
285+
'cache' indicates whether the transaction cache should be queried
286+
for the node. If the node has been modified and you need to
287+
determine what its values prior to modification are, you need to
288+
set cache=0.
276289
'''
277-
return Node(self, nodeid)
290+
return Node(self, nodeid, cache=cache)
278291

279292
def set(self, nodeid, **propvalues):
280293
"""Modify a property on an existing node of this class.
@@ -824,36 +837,37 @@ def addprop(self, **properties):
824837
class Node:
825838
''' A convenience wrapper for the given node
826839
'''
827-
def __init__(self, cl, nodeid):
840+
def __init__(self, cl, nodeid, cache=1):
828841
self.__dict__['cl'] = cl
829842
self.__dict__['nodeid'] = nodeid
843+
self.cache = cache
830844
def keys(self, protected=1):
831845
return self.cl.getprops(protected=protected).keys()
832846
def values(self, protected=1):
833847
l = []
834848
for name in self.cl.getprops(protected=protected).keys():
835-
l.append(self.cl.get(self.nodeid, name))
849+
l.append(self.cl.get(self.nodeid, name, cache=self.cache))
836850
return l
837851
def items(self, protected=1):
838852
l = []
839853
for name in self.cl.getprops(protected=protected).keys():
840-
l.append((name, self.cl.get(self.nodeid, name)))
854+
l.append((name, self.cl.get(self.nodeid, name, cache=self.cache)))
841855
return l
842856
def has_key(self, name):
843857
return self.cl.getprops().has_key(name)
844858
def __getattr__(self, name):
845859
if self.__dict__.has_key(name):
846860
return self.__dict__[name]
847861
try:
848-
return self.cl.get(self.nodeid, name)
862+
return self.cl.get(self.nodeid, name, cache=self.cache)
849863
except KeyError, value:
850864
# we trap this but re-raise it as AttributeError - all other
851865
# exceptions should pass through untrapped
852866
pass
853867
# nope, no such attribute
854868
raise AttributeError, str(value)
855869
def __getitem__(self, name):
856-
return self.cl.get(self.nodeid, name)
870+
return self.cl.get(self.nodeid, name, cache=self.cache)
857871
def __setattr__(self, name, value):
858872
try:
859873
return self.cl.set(self.nodeid, **{name: value})
@@ -875,6 +889,16 @@ def Choice(name, *options):
875889

876890
#
877891
# $Log: not supported by cvs2svn $
892+
# Revision 1.43 2001/12/20 06:13:24 rochecompaan
893+
# Bugs fixed:
894+
# . Exception handling in hyperdb for strings-that-look-like numbers got
895+
# lost somewhere
896+
# . Internet Explorer submits full path for filename - we now strip away
897+
# the path
898+
# Features added:
899+
# . Link and multilink properties are now displayed sorted in the cgi
900+
# interface
901+
#
878902
# Revision 1.42 2001/12/16 10:53:37 richard
879903
# take a copy of the node dict so that the subsequent set
880904
# operation doesn't modify the oldvalues structure

0 commit comments

Comments
 (0)