Mercurial > p > roundup > code
changeset 2604:b3ea6bad36b7 maint-0.7
merge from HEAD
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Tue, 20 Jul 2004 23:27:02 +0000 |
| parents | 3fefdbfa6141 |
| children | b1bf4aee5def |
| files | CHANGES.txt doc/announcement.txt roundup/backends/back_anydbm.py roundup/backends/back_metakit.py roundup/backends/rdbms_common.py setup.py test/db_test_base.py |
| diffstat | 7 files changed, 75 insertions(+), 75 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Tue Jul 20 06:00:07 2004 +0000 +++ b/CHANGES.txt Tue Jul 20 23:27:02 2004 +0000 @@ -1,7 +1,7 @@ This file contains the changes to the Roundup system over time. The entries are given with the most recent entry first. -2004-??-?? 0.7.6 +2004-07-20 0.7.6 Fixed: - rdbms backend full text search failure after import (sf bug 980314) - rdbms backends not filtering correctly on link=None @@ -16,6 +16,12 @@ - document the STATIC_FILES config var - implement the HTTP HEAD command (sf bug 992544) - fix journal export of files to remove content from CSV files +- API clarification. Previously, the anydbm/bsddb/metakit filter() methods + had required exact matches to Multilink argument lists. The RDBMS + backends treated Multilink matches like all other data types - matching + any of the Multilink argument list is good enough. The latter behaviour + is implemented across the board now. +- fix metakit handling of filter on Link==None 2004-06-24 0.7.5
--- a/doc/announcement.txt Tue Jul 20 06:00:07 2004 +0000 +++ b/doc/announcement.txt Tue Jul 20 23:27:02 2004 +0000 @@ -16,6 +16,7 @@ - fixed external password source example (sf bug 986601) - document the STATIC_FILES config var - implement the HTTP HEAD command (sf bug 992544) +- fix journal export of files to remove content from CSV files If you're upgrading from an older version of Roundup you *must* follow the "Software Upgrade" guidelines given in the maintenance documentation.
--- a/roundup/backends/back_anydbm.py Tue Jul 20 06:00:07 2004 +0000 +++ b/roundup/backends/back_anydbm.py Tue Jul 20 23:27:02 2004 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -#$Id: back_anydbm.py,v 1.146.2.14 2004-07-20 05:58:47 richard Exp $ +#$Id: back_anydbm.py,v 1.146.2.15 2004-07-20 23:27:02 richard Exp $ '''This module defines a backend that saves the hyperdatabase in a database chosen by anydbm. It is guaranteed to always be available in python versions >2.1.1 (the dumbdbm fallback in 2.1.1 and earlier has several @@ -943,8 +943,6 @@ raise ValueError, 'key property "%s" is required'%key if isinstance(prop, Multilink): propvalues[key] = [] - else: - propvalues[key] = None # done self.db.addnode(self.classname, newid, propvalues) @@ -1588,9 +1586,7 @@ The filter must match all properties specificed - but if the property value to match is a list, any one of the values in the - list may match for that property to match. Unless the property - is a Multilink, in which case the item's property list must - match the filterspec list. + list may match for that property to match. """ if __debug__: start_t = time.time() @@ -1718,10 +1714,9 @@ # othewise, make sure this node has each of the # required values for want in v: - if want not in nv: + if want in nv: + match = True break - else: - match = True elif t == STRING: if nv is None: nv = '' @@ -2108,10 +2103,6 @@ # do the database create newid = self.create_inner(**propvalues) - # and index! - self.db.indexer.add_text((self.classname, newid, 'content'), content, - mime_type) - # fire reactors self.fireReactors('create', newid, None)
--- a/roundup/backends/back_metakit.py Tue Jul 20 06:00:07 2004 +0000 +++ b/roundup/backends/back_metakit.py Tue Jul 20 23:27:02 2004 +0000 @@ -1,4 +1,4 @@ -# $Id: back_metakit.py,v 1.70.2.7 2004-07-20 05:58:47 richard Exp $ +# $Id: back_metakit.py,v 1.70.2.8 2004-07-20 23:27:02 richard Exp $ '''Metakit backend for Roundup, originally by Gordon McMillan. Known Current Bugs: @@ -84,6 +84,9 @@ self.indexer = Indexer(self.config.DATABASE, self._db) self.security = security.Security(self) + self.stats = {'cache_hits': 0, 'cache_misses': 0, 'get_items': 0, + 'filtering': 0} + os.umask(0002) def post_init(self): @@ -1189,10 +1192,8 @@ property value to match is a list, any one of the values in the list may match for that property to match. ''' - # search_matches is None or a set (dict of {nodeid: {propname:[nodeid,...]}}) - # filterspec is a dict {propname:value} - # sort and group are (dir, prop) where dir is '+', '-' or None - # and prop is a prop name or None + if __debug__: + start_t = time.time() timezone = self.db.getUserTimezone() @@ -1227,10 +1228,14 @@ # transform keys to ids u = [] for item in value: - try: - item = int(item) - except (TypeError, ValueError): - item = int(self.db.getclass(prop.classname).lookup(item)) + if item is None: + item = -1 + else: + try: + item = int(item) + except (TypeError, ValueError): + linkcl = self.db.getclass(prop.classname) + item = int(linkcl.lookup(item)) if item == -1: item = 0 u.append(item) @@ -1300,12 +1305,10 @@ else: where[propname] = str(value) v = self.getview() - #print "filter start at %s" % time.time() if where: where_higherbound = where.copy() where_higherbound.update(wherehigh) v = v.select(where, where_higherbound) - #print "filter where at %s" % time.time() if mlcriteria: # multilink - if any of the nodeids required by the @@ -1313,16 +1316,14 @@ def ff(row, ml=mlcriteria): for propname, values in ml.items(): sv = getattr(row, propname) - if not values and sv: - return 0 + if not values and not sv: + return 1 for id in values: - if sv.find(fid=id) == -1: - return 0 - return 1 + if sv.find(fid=id) != -1: + return 1 + return 0 iv = v.filter(ff) v = v.remapwith(iv) - - #print "filter mlcrit at %s" % time.time() if orcriteria: def ff(row, crit=orcriteria): @@ -1335,7 +1336,6 @@ iv = v.filter(ff) v = v.remapwith(iv) - #print "filter orcrit at %s" % time.time() if regexes: def ff(row, r=regexes): for propname, regex in r.items(): @@ -1346,7 +1346,6 @@ iv = v.filter(ff) v = v.remapwith(iv) - #print "filter regexs at %s" % time.time() if sort or group: sortspec = [] @@ -1381,7 +1380,6 @@ rev.append(prop) sortspec.append(prop) v = v.sortrev(sortspec, rev)[:] #XXX Metakit bug - #print "filter sort at %s" % time.time() rslt = [] for row in v: @@ -1391,6 +1389,10 @@ rslt.append(id) else: rslt.append(id) + + if __debug__: + self.db.stats['filtering'] += (time.time() - start_t) + return rslt def hasnode(self, nodeid):
--- a/roundup/backends/rdbms_common.py Tue Jul 20 06:00:07 2004 +0000 +++ b/roundup/backends/rdbms_common.py Tue Jul 20 23:27:02 2004 +0000 @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.98.2.18 2004-07-20 05:58:47 richard Exp $ +# $Id: rdbms_common.py,v 1.98.2.19 2004-07-20 23:27:02 richard Exp $ ''' Relational database (SQL) backend common code. Basics: @@ -2268,7 +2268,6 @@ cols = ','.join(cols) loj = ' '.join(loj) sql = 'select %s from %s %s %s%s'%(cols, frum, loj, where, order) - print sql args = tuple(args) if __debug__: print >>hyperdb.DEBUG, 'filter', (self, sql, args)
--- a/setup.py Tue Jul 20 06:00:07 2004 +0000 +++ b/setup.py Tue Jul 20 23:27:02 2004 +0000 @@ -16,7 +16,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: setup.py,v 1.64.2.5 2004-06-24 07:59:55 richard Exp $ +# $Id: setup.py,v 1.64.2.6 2004-07-20 23:27:00 richard Exp $ from distutils.core import setup, Extension from distutils.util import get_platform @@ -217,22 +217,21 @@ If you're upgrading from an older version of Roundup you *must* follow the "Software Upgrade" guidelines given in the maintenance documentation. -0.7.5 is a bug fix release, including: +This is a bug fix release, including: -- force lookup of journal props in anydbm filtering -- fixed lookup of "missing" Link values for new props in anydbm backend -- allow list of values for id, Number and Boolean filtering in anydbm - backend -- fixed some more mysql 0.6->0.7 upgrade bugs (sf bug 950410) -- fixed Boolean values in postgresql (sf bugs 972546 and 972600) -- fixed -g arg to roundup-server (sf bug 973946) -- better roundup-server usage string (sf bug 973352) -- include "context" always, as documented (sf bug 965447) -- fixed REMOTE_USER (external HTTP Basic auth) (sf bug 977309) -- fixed roundup-admin "find" to use better value parsing -- fixed RDBMS Class.find() to handle None value in multiple find -- export now stores file "content" in separate files in export directory - +- rdbms backend full text search failure after import (sf bug 980314) +- rdbms backends not filtering correctly on link=None +- fix anydbm journal import (sf bug 983166) +- handle postgresql bug in SQL generation (sf bug 984591) +- fix dates-from-Dates (sf bug 984604) +- fix messageid generated when msgid is None for send_message (sf bug 987933) +- make user permissions check more sane (fix search page for anonymous) +- fixed RDBMS filter() for no matches from full-text search (sf bug 990778) +- fixed DateHTMLProperty for invalid date entry (sf bug 986538) +- fixed external password source example (sf bug 986601) +- document the STATIC_FILES config var +- implement the HTTP HEAD command (sf bug 992544) +- fix journal export of files to remove content from CSV files ''', author = "Richard Jones", author_email = "richard@users.sourceforge.net",
--- a/test/db_test_base.py Tue Jul 20 06:00:07 2004 +0000 +++ b/test/db_test_base.py Tue Jul 20 23:27:02 2004 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: db_test_base.py,v 1.27.2.9 2004-07-03 23:08:44 richard Exp $ +# $Id: db_test_base.py,v 1.27.2.10 2004-07-20 23:27:02 richard Exp $ import unittest, os, shutil, errno, imp, sys, time, pprint @@ -691,6 +691,7 @@ i1 = self.db.issue.create(files=[f1, f2]) self.db.commit() d = self.db.indexer.search(['hello'], self.db.issue) + self.assert_(d.has_key(i1)) d[i1]['files'].sort() self.assertEquals(d, {i1: {'files': [f1, f2]}}) self.assertEquals(self.db.indexer.search(['world'], self.db.issue), @@ -836,11 +837,11 @@ for issue in ( {'title': 'issue one', 'status': '2', 'assignedto': '1', 'foo': date.Interval('1:10'), 'priority': '3', - 'deadline': date.Date('2003-01-01.00:00')}, + 'deadline': date.Date('2003-02-16.22:50')}, {'title': 'issue two', 'status': '1', 'assignedto': '2', 'foo': date.Interval('1d'), 'priority': '3', - 'deadline': date.Date('2003-02-16.22:50')}, - {'title': 'issue three', 'status': '1', 'priority': '2', + 'deadline': date.Date('2003-01-01.00:00')}, + {'title': 'issue three', 'status': '1', 'priority': '2', 'nosy': ['1','2'], 'deadline': date.Date('2003-02-18')}, {'title': 'non four', 'status': '3', 'foo': date.Interval('0:10'), 'priority': '2', @@ -893,7 +894,7 @@ ae(filt(None, {'nosy': '2'}, ('+','id'), (None,None)), ['3']) ae(filt(None, {'nosy': '-1'}, ('+','id'), (None,None)), ['1', '2']) ae(filt(None, {'nosy': ['1','2']}, ('+', 'status'), - ('-', 'activity')), ['4', '3']) + ('-', 'deadline')), ['4', '3']) def testFilteringMany(self): ae, filt = self.filteringSetup() @@ -903,20 +904,20 @@ def testFilteringRange(self): ae, filt = self.filteringSetup() # Date ranges - ae(filt(None, {'deadline': 'from 2003-02-10 to 2003-02-23'}), ['2','3']) - ae(filt(None, {'deadline': '2003-02-10; 2003-02-23'}), ['2','3']) - ae(filt(None, {'deadline': '; 2003-02-16'}), ['1']) + ae(filt(None, {'deadline': 'from 2003-02-10 to 2003-02-23'}), ['1','3']) + ae(filt(None, {'deadline': '2003-02-10; 2003-02-23'}), ['1','3']) + ae(filt(None, {'deadline': '; 2003-02-16'}), ['2']) # Lets assume people won't invent a time machine, otherwise this test # may fail :) - ae(filt(None, {'deadline': 'from 2003-02-16'}), ['2', '3', '4']) - ae(filt(None, {'deadline': '2003-02-16;'}), ['2', '3', '4']) + ae(filt(None, {'deadline': 'from 2003-02-16'}), ['1', '3', '4']) + ae(filt(None, {'deadline': '2003-02-16;'}), ['1', '3', '4']) # year and month granularity ae(filt(None, {'deadline': '2002'}), []) ae(filt(None, {'deadline': '2003'}), ['1', '2', '3']) ae(filt(None, {'deadline': '2004'}), ['4']) - ae(filt(None, {'deadline': '2003-02'}), ['2', '3']) + ae(filt(None, {'deadline': '2003-02'}), ['1', '3']) ae(filt(None, {'deadline': '2003-03'}), []) - ae(filt(None, {'deadline': '2003-02-16'}), ['2']) + ae(filt(None, {'deadline': '2003-02-16'}), ['1']) ae(filt(None, {'deadline': '2003-02-17'}), []) # Interval ranges ae(filt(None, {'foo': 'from 0:50 to 2:00'}), ['1']) @@ -945,32 +946,33 @@ ae(filt(None, {}, ('-','nosy'), (None,None)), ['3', '4', '1', '2']) def testFilteringDateSort(self): - # '1': '2003-01-01.00:00' - # '2': '2003-02-16.22:50' + # '1': '2003-02-16.22:50' + # '2': '2003-01-01.00:00' # '3': '2003-02-18' # '4': '2004-03-08' ae, filt = self.filteringSetup() # ascending - ae(filt(None, {}, ('+','deadline'), (None,None)), ['1', '2', '3', '4']) + ae(filt(None, {}, ('+','deadline'), (None,None)), ['2', '1', '3', '4']) # descending - ae(filt(None, {}, ('-','deadline'), (None,None)), ['4', '3', '2', '1']) + ae(filt(None, {}, ('-','deadline'), (None,None)), ['4', '3', '1', '2']) def testFilteringDateSortPriorityGroup(self): - # '1': '2003-01-01.00:00' 1 => 2 - # '2': '2003-02-16.22:50' 3 => 1 + # '1': '2003-02-16.22:50' 1 => 2 + # '2': '2003-01-01.00:00' 3 => 1 # '3': '2003-02-18' 2 => 3 # '4': '2004-03-08' 1 => 2 ae, filt = self.filteringSetup() + # ascending ae(filt(None, {}, ('+','deadline'), ('+','priority')), - ['2', '1', '4', '3']) + ['2', '1', '3', '4']) ae(filt(None, {}, ('-','deadline'), ('+','priority')), - ['2', '4', '1', '3']) + ['1', '2', '4', '3']) # descending ae(filt(None, {}, ('+','deadline'), ('-','priority')), - ['3', '1', '4', '2']) + ['3', '4', '2', '1']) ae(filt(None, {}, ('-','deadline'), ('-','priority')), - ['3', '4', '1', '2']) + ['4', '3', '1', '2']) # XXX add sorting tests for other types # XXX test auditors and reactors
