Skip to content

Commit ffa404c

Browse files
author
Richard Jones
committed
merge from HEAD
1 parent a744fd1 commit ffa404c

File tree

7 files changed

+76
-76
lines changed

7 files changed

+76
-76
lines changed

CHANGES.txt

Lines changed: 7 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-
2004-??-?? 0.7.6
4+
2004-07-20 0.7.6
55
Fixed:
66
- rdbms backend full text search failure after import (sf bug 980314)
77
- rdbms backends not filtering correctly on link=None
@@ -16,6 +16,12 @@ Fixed:
1616
- document the STATIC_FILES config var
1717
- implement the HTTP HEAD command (sf bug 992544)
1818
- fix journal export of files to remove content from CSV files
19+
- API clarification. Previously, the anydbm/bsddb/metakit filter() methods
20+
had required exact matches to Multilink argument lists. The RDBMS
21+
backends treated Multilink matches like all other data types - matching
22+
any of the Multilink argument list is good enough. The latter behaviour
23+
is implemented across the board now.
24+
- fix metakit handling of filter on Link==None
1925

2026

2127
2004-06-24 0.7.5

doc/announcement.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ from Ka-Ping Yee in the Software Carpentry "Track" design competition.
1616
- fixed external password source example (sf bug 986601)
1717
- document the STATIC_FILES config var
1818
- implement the HTTP HEAD command (sf bug 992544)
19+
- fix journal export of files to remove content from CSV files
1920

2021
If you're upgrading from an older version of Roundup you *must* follow
2122
the "Software Upgrade" guidelines given in the maintenance documentation.

roundup/backends/back_anydbm.py

Lines changed: 4 additions & 13 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.146.2.14 2004-07-20 05:58:47 richard Exp $
18+
#$Id: back_anydbm.py,v 1.146.2.15 2004-07-20 23:27:02 richard Exp $
1919
'''This module defines a backend that saves the hyperdatabase in a
2020
database chosen by anydbm. It is guaranteed to always be available in python
2121
versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several
@@ -943,8 +943,6 @@ def create_inner(self, **propvalues):
943943
raise ValueError, 'key property "%s" is required'%key
944944
if isinstance(prop, Multilink):
945945
propvalues[key] = []
946-
else:
947-
propvalues[key] = None
948946

949947
# done
950948
self.db.addnode(self.classname, newid, propvalues)
@@ -1588,9 +1586,7 @@ def filter(self, search_matches, filterspec, sort=(None,None),
15881586
15891587
The filter must match all properties specificed - but if the
15901588
property value to match is a list, any one of the values in the
1591-
list may match for that property to match. Unless the property
1592-
is a Multilink, in which case the item's property list must
1593-
match the filterspec list.
1589+
list may match for that property to match.
15941590
"""
15951591
if __debug__:
15961592
start_t = time.time()
@@ -1718,10 +1714,9 @@ def filter(self, search_matches, filterspec, sort=(None,None),
17181714
# othewise, make sure this node has each of the
17191715
# required values
17201716
for want in v:
1721-
if want not in nv:
1717+
if want in nv:
1718+
match = True
17221719
break
1723-
else:
1724-
match = True
17251720
elif t == STRING:
17261721
if nv is None:
17271722
nv = ''
@@ -2108,10 +2103,6 @@ def create(self, **propvalues):
21082103
# do the database create
21092104
newid = self.create_inner(**propvalues)
21102105

2111-
# and index!
2112-
self.db.indexer.add_text((self.classname, newid, 'content'), content,
2113-
mime_type)
2114-
21152106
# fire reactors
21162107
self.fireReactors('create', newid, None)
21172108

roundup/backends/back_metakit.py

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: back_metakit.py,v 1.70.2.7 2004-07-20 05:58:47 richard Exp $
1+
# $Id: back_metakit.py,v 1.70.2.8 2004-07-20 23:27:02 richard Exp $
22
'''Metakit backend for Roundup, originally by Gordon McMillan.
33
44
Known Current Bugs:
@@ -84,6 +84,9 @@ def __init__(self, config, journaltag=None):
8484
self.indexer = Indexer(self.config.DATABASE, self._db)
8585
self.security = security.Security(self)
8686

87+
self.stats = {'cache_hits': 0, 'cache_misses': 0, 'get_items': 0,
88+
'filtering': 0}
89+
8790
os.umask(0002)
8891

8992
def post_init(self):
@@ -1189,10 +1192,8 @@ def filter(self, search_matches, filterspec, sort=(None,None),
11891192
property value to match is a list, any one of the values in the
11901193
list may match for that property to match.
11911194
'''
1192-
# search_matches is None or a set (dict of {nodeid: {propname:[nodeid,...]}})
1193-
# filterspec is a dict {propname:value}
1194-
# sort and group are (dir, prop) where dir is '+', '-' or None
1195-
# and prop is a prop name or None
1195+
if __debug__:
1196+
start_t = time.time()
11961197

11971198
timezone = self.db.getUserTimezone()
11981199

@@ -1227,10 +1228,14 @@ def filter(self, search_matches, filterspec, sort=(None,None),
12271228
# transform keys to ids
12281229
u = []
12291230
for item in value:
1230-
try:
1231-
item = int(item)
1232-
except (TypeError, ValueError):
1233-
item = int(self.db.getclass(prop.classname).lookup(item))
1231+
if item is None:
1232+
item = -1
1233+
else:
1234+
try:
1235+
item = int(item)
1236+
except (TypeError, ValueError):
1237+
linkcl = self.db.getclass(prop.classname)
1238+
item = int(linkcl.lookup(item))
12341239
if item == -1:
12351240
item = 0
12361241
u.append(item)
@@ -1300,29 +1305,25 @@ def filter(self, search_matches, filterspec, sort=(None,None),
13001305
else:
13011306
where[propname] = str(value)
13021307
v = self.getview()
1303-
#print "filter start at %s" % time.time()
13041308
if where:
13051309
where_higherbound = where.copy()
13061310
where_higherbound.update(wherehigh)
13071311
v = v.select(where, where_higherbound)
1308-
#print "filter where at %s" % time.time()
13091312

13101313
if mlcriteria:
13111314
# multilink - if any of the nodeids required by the
13121315
# filterspec aren't in this node's property, then skip it
13131316
def ff(row, ml=mlcriteria):
13141317
for propname, values in ml.items():
13151318
sv = getattr(row, propname)
1316-
if not values and sv:
1317-
return 0
1319+
if not values and not sv:
1320+
return 1
13181321
for id in values:
1319-
if sv.find(fid=id) == -1:
1320-
return 0
1321-
return 1
1322+
if sv.find(fid=id) != -1:
1323+
return 1
1324+
return 0
13221325
iv = v.filter(ff)
13231326
v = v.remapwith(iv)
1324-
1325-
#print "filter mlcrit at %s" % time.time()
13261327

13271328
if orcriteria:
13281329
def ff(row, crit=orcriteria):
@@ -1335,7 +1336,6 @@ def ff(row, crit=orcriteria):
13351336
iv = v.filter(ff)
13361337
v = v.remapwith(iv)
13371338

1338-
#print "filter orcrit at %s" % time.time()
13391339
if regexes:
13401340
def ff(row, r=regexes):
13411341
for propname, regex in r.items():
@@ -1346,7 +1346,6 @@ def ff(row, r=regexes):
13461346

13471347
iv = v.filter(ff)
13481348
v = v.remapwith(iv)
1349-
#print "filter regexs at %s" % time.time()
13501349

13511350
if sort or group:
13521351
sortspec = []
@@ -1381,7 +1380,6 @@ def ff(row, r=regexes):
13811380
rev.append(prop)
13821381
sortspec.append(prop)
13831382
v = v.sortrev(sortspec, rev)[:] #XXX Metakit bug
1384-
#print "filter sort at %s" % time.time()
13851383

13861384
rslt = []
13871385
for row in v:
@@ -1391,6 +1389,10 @@ def ff(row, r=regexes):
13911389
rslt.append(id)
13921390
else:
13931391
rslt.append(id)
1392+
1393+
if __debug__:
1394+
self.db.stats['filtering'] += (time.time() - start_t)
1395+
13941396
return rslt
13951397

13961398
def hasnode(self, nodeid):

roundup/backends/rdbms_common.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# $Id: rdbms_common.py,v 1.98.2.18 2004-07-20 05:58:47 richard Exp $
1+
# $Id: rdbms_common.py,v 1.98.2.19 2004-07-20 23:27:02 richard Exp $
22
''' Relational database (SQL) backend common code.
33
44
Basics:
@@ -2268,7 +2268,6 @@ def filter(self, search_matches, filterspec, sort=(None,None),
22682268
cols = ','.join(cols)
22692269
loj = ' '.join(loj)
22702270
sql = 'select %s from %s %s %s%s'%(cols, frum, loj, where, order)
2271-
print sql
22722271
args = tuple(args)
22732272
if __debug__:
22742273
print >>hyperdb.DEBUG, 'filter', (self, sql, args)

setup.py

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
# BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
1717
# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
1818
#
19-
# $Id: setup.py,v 1.64.2.5 2004-06-24 07:59:55 richard Exp $
19+
# $Id: setup.py,v 1.64.2.6 2004-07-20 23:27:00 richard Exp $
2020

2121
from distutils.core import setup, Extension
2222
from distutils.util import get_platform
@@ -217,22 +217,21 @@ def main():
217217
If you're upgrading from an older version of Roundup you *must* follow
218218
the "Software Upgrade" guidelines given in the maintenance documentation.
219219
220-
0.7.5 is a bug fix release, including:
221-
222-
- force lookup of journal props in anydbm filtering
223-
- fixed lookup of "missing" Link values for new props in anydbm backend
224-
- allow list of values for id, Number and Boolean filtering in anydbm
225-
backend
226-
- fixed some more mysql 0.6->0.7 upgrade bugs (sf bug 950410)
227-
- fixed Boolean values in postgresql (sf bugs 972546 and 972600)
228-
- fixed -g arg to roundup-server (sf bug 973946)
229-
- better roundup-server usage string (sf bug 973352)
230-
- include "context" always, as documented (sf bug 965447)
231-
- fixed REMOTE_USER (external HTTP Basic auth) (sf bug 977309)
232-
- fixed roundup-admin "find" to use better value parsing
233-
- fixed RDBMS Class.find() to handle None value in multiple find
234-
- export now stores file "content" in separate files in export directory
235-
220+
This is a bug fix release, including:
221+
222+
- rdbms backend full text search failure after import (sf bug 980314)
223+
- rdbms backends not filtering correctly on link=None
224+
- fix anydbm journal import (sf bug 983166)
225+
- handle postgresql bug in SQL generation (sf bug 984591)
226+
- fix dates-from-Dates (sf bug 984604)
227+
- fix messageid generated when msgid is None for send_message (sf bug 987933)
228+
- make user permissions check more sane (fix search page for anonymous)
229+
- fixed RDBMS filter() for no matches from full-text search (sf bug 990778)
230+
- fixed DateHTMLProperty for invalid date entry (sf bug 986538)
231+
- fixed external password source example (sf bug 986601)
232+
- document the STATIC_FILES config var
233+
- implement the HTTP HEAD command (sf bug 992544)
234+
- fix journal export of files to remove content from CSV files
236235
''',
237236
author = "Richard Jones",
238237
author_email = "[email protected]",

test/db_test_base.py

Lines changed: 24 additions & 22 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: db_test_base.py,v 1.27.2.9 2004-07-03 23:08:44 richard Exp $
18+
# $Id: db_test_base.py,v 1.27.2.10 2004-07-20 23:27:02 richard Exp $
1919

2020
import unittest, os, shutil, errno, imp, sys, time, pprint
2121

@@ -691,6 +691,7 @@ def testFileClassReindexing(self):
691691
i1 = self.db.issue.create(files=[f1, f2])
692692
self.db.commit()
693693
d = self.db.indexer.search(['hello'], self.db.issue)
694+
self.assert_(d.has_key(i1))
694695
d[i1]['files'].sort()
695696
self.assertEquals(d, {i1: {'files': [f1, f2]}})
696697
self.assertEquals(self.db.indexer.search(['world'], self.db.issue),
@@ -836,11 +837,11 @@ def filteringSetup(self):
836837
for issue in (
837838
{'title': 'issue one', 'status': '2', 'assignedto': '1',
838839
'foo': date.Interval('1:10'), 'priority': '3',
839-
'deadline': date.Date('2003-01-01.00:00')},
840+
'deadline': date.Date('2003-02-16.22:50')},
840841
{'title': 'issue two', 'status': '1', 'assignedto': '2',
841842
'foo': date.Interval('1d'), 'priority': '3',
842-
'deadline': date.Date('2003-02-16.22:50')},
843-
{'title': 'issue three', 'status': '1', 'priority': '2',
843+
'deadline': date.Date('2003-01-01.00:00')},
844+
{'title': 'issue three', 'status': '1', 'priority': '2',
844845
'nosy': ['1','2'], 'deadline': date.Date('2003-02-18')},
845846
{'title': 'non four', 'status': '3',
846847
'foo': date.Interval('0:10'), 'priority': '2',
@@ -893,7 +894,7 @@ def testFilteringMultilink(self):
893894
ae(filt(None, {'nosy': '2'}, ('+','id'), (None,None)), ['3'])
894895
ae(filt(None, {'nosy': '-1'}, ('+','id'), (None,None)), ['1', '2'])
895896
ae(filt(None, {'nosy': ['1','2']}, ('+', 'status'),
896-
('-', 'activity')), ['4', '3'])
897+
('-', 'deadline')), ['4', '3'])
897898

898899
def testFilteringMany(self):
899900
ae, filt = self.filteringSetup()
@@ -903,20 +904,20 @@ def testFilteringMany(self):
903904
def testFilteringRange(self):
904905
ae, filt = self.filteringSetup()
905906
# Date ranges
906-
ae(filt(None, {'deadline': 'from 2003-02-10 to 2003-02-23'}), ['2','3'])
907-
ae(filt(None, {'deadline': '2003-02-10; 2003-02-23'}), ['2','3'])
908-
ae(filt(None, {'deadline': '; 2003-02-16'}), ['1'])
907+
ae(filt(None, {'deadline': 'from 2003-02-10 to 2003-02-23'}), ['1','3'])
908+
ae(filt(None, {'deadline': '2003-02-10; 2003-02-23'}), ['1','3'])
909+
ae(filt(None, {'deadline': '; 2003-02-16'}), ['2'])
909910
# Lets assume people won't invent a time machine, otherwise this test
910911
# may fail :)
911-
ae(filt(None, {'deadline': 'from 2003-02-16'}), ['2', '3', '4'])
912-
ae(filt(None, {'deadline': '2003-02-16;'}), ['2', '3', '4'])
912+
ae(filt(None, {'deadline': 'from 2003-02-16'}), ['1', '3', '4'])
913+
ae(filt(None, {'deadline': '2003-02-16;'}), ['1', '3', '4'])
913914
# year and month granularity
914915
ae(filt(None, {'deadline': '2002'}), [])
915916
ae(filt(None, {'deadline': '2003'}), ['1', '2', '3'])
916917
ae(filt(None, {'deadline': '2004'}), ['4'])
917-
ae(filt(None, {'deadline': '2003-02'}), ['2', '3'])
918+
ae(filt(None, {'deadline': '2003-02'}), ['1', '3'])
918919
ae(filt(None, {'deadline': '2003-03'}), [])
919-
ae(filt(None, {'deadline': '2003-02-16'}), ['2'])
920+
ae(filt(None, {'deadline': '2003-02-16'}), ['1'])
920921
ae(filt(None, {'deadline': '2003-02-17'}), [])
921922
# Interval ranges
922923
ae(filt(None, {'foo': 'from 0:50 to 2:00'}), ['1'])
@@ -945,32 +946,33 @@ def testFilteringMultilinkSort(self):
945946
ae(filt(None, {}, ('-','nosy'), (None,None)), ['3', '4', '1', '2'])
946947

947948
def testFilteringDateSort(self):
948-
# '1': '2003-01-01.00:00'
949-
# '2': '2003-02-16.22:50'
949+
# '1': '2003-02-16.22:50'
950+
# '2': '2003-01-01.00:00'
950951
# '3': '2003-02-18'
951952
# '4': '2004-03-08'
952953
ae, filt = self.filteringSetup()
953954
# ascending
954-
ae(filt(None, {}, ('+','deadline'), (None,None)), ['1', '2', '3', '4'])
955+
ae(filt(None, {}, ('+','deadline'), (None,None)), ['2', '1', '3', '4'])
955956
# descending
956-
ae(filt(None, {}, ('-','deadline'), (None,None)), ['4', '3', '2', '1'])
957+
ae(filt(None, {}, ('-','deadline'), (None,None)), ['4', '3', '1', '2'])
957958

958959
def testFilteringDateSortPriorityGroup(self):
959-
# '1': '2003-01-01.00:00' 1 => 2
960-
# '2': '2003-02-16.22:50' 3 => 1
960+
# '1': '2003-02-16.22:50' 1 => 2
961+
# '2': '2003-01-01.00:00' 3 => 1
961962
# '3': '2003-02-18' 2 => 3
962963
# '4': '2004-03-08' 1 => 2
963964
ae, filt = self.filteringSetup()
965+
964966
# ascending
965967
ae(filt(None, {}, ('+','deadline'), ('+','priority')),
966-
['2', '1', '4', '3'])
968+
['2', '1', '3', '4'])
967969
ae(filt(None, {}, ('-','deadline'), ('+','priority')),
968-
['2', '4', '1', '3'])
970+
['1', '2', '4', '3'])
969971
# descending
970972
ae(filt(None, {}, ('+','deadline'), ('-','priority')),
971-
['3', '1', '4', '2'])
973+
['3', '4', '2', '1'])
972974
ae(filt(None, {}, ('-','deadline'), ('-','priority')),
973-
['3', '4', '1', '2'])
975+
['4', '3', '1', '2'])
974976

975977
# XXX add sorting tests for other types
976978
# XXX test auditors and reactors

0 commit comments

Comments
 (0)