From 5753ae109231ea389578634cf3f5ab8ef207bd90 Mon Sep 17 00:00:00 2001 From: kedder Date: Sun, 20 Apr 2003 11:58:45 +0000 Subject: [PATCH] searching on ranges of intervals is implemented git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@1668 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 7 ++++--- doc/upgrading.txt | 21 ++++++++++++++++++++- doc/user_guide.txt | 4 +++- roundup/backends/back_anydbm.py | 20 ++++++++++++-------- roundup/backends/back_metakit.py | 32 +++++++++++++++++++++++++++----- roundup/backends/rdbms_common.py | 18 +++++++++++++++--- test/test_db.py | 8 +++++++- 7 files changed, 88 insertions(+), 22 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 2a93850..81cd0e5 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -47,8 +47,9 @@ Feature: - added Node.get() method - nicer page titles (sf feature 65197) - relaxed CVS importing (sf feature 693277) -- added support for searching on ranges of dates (see doc/user_guide.txt in - chapter "Searching Page" for details) (closes sf feature 700178) +- added support for searching on ranges of dates and intervals (see + doc/user_guide.txt in chapter "Searching Page" for details) (closes sf + feature 700178) - role names made case insensitive - added ability to restore retired nodes - more lenient date input and addition Interval input support (sf bug 677764) @@ -56,7 +57,7 @@ Feature: - implemented ability to search for multilink properties with no value - Class.find() may now find unset Links (sf bug 700620) - more flexibility in classhelp link labelling (sf feature 608204) -- added command-line functionality for roundup-adming (sf feature 687664) +- added command-line functionality for roundup-admin (sf feature 687664) - added nicer popup windows for topic, nosy, etc (has add/remove buttons) thanks Gus Gollings - HTML templating files now have a .html extension diff --git a/doc/upgrading.txt b/doc/upgrading.txt index a334470..742dabf 100644 --- a/doc/upgrading.txt +++ b/doc/upgrading.txt @@ -70,7 +70,7 @@ name:confirm -> :confirm:name timezone if he/she has provided timezone information. To make it possible some modification to tracker's schema and HTML templates are required. First you should add string property 'timezone' to user class in dbinit.py - like this: + like this:: user = Class(db, "user", username=String(), password=Password(), @@ -98,6 +98,25 @@ name:confirm -> :confirm:name However you are not forced to make these modifications. By default roundup will assume timezone=0 and will work as previous versions did. + +0.6.0 Notes for metakit backend users +------------------------------------- + +- Roundup 0.6.0 introduced searching on ranges of dates and intervals. To + support it, some modifications to interval storing routine were made. So if + your tracker uses metakit backend and your db schema contains intervals + property, searches on that property will not be accurate for db items that + was stored before roundup' upgrade. However all new records should be + searchable on intervals. + + It is possible to convert your database to new format: you can export and + import back all your data (consult "Migrating backends" in "Maintenance" + documentation). After this operation all your interval properties should + become searchable. + + Users of backends others than metakit should not worry about this issue. + + Migrating from 0.4.x to 0.5.0 ============================= diff --git a/doc/user_guide.txt b/doc/user_guide.txt index 42bb379..8d94530 100644 --- a/doc/user_guide.txt +++ b/doc/user_guide.txt @@ -2,7 +2,7 @@ User Guide ========== -:Version: $Revision: 1.19 $ +:Version: $Revision: 1.20 $ .. contents:: @@ -141,6 +141,8 @@ Interval properties XXX explain... +When searching on interval properties use the same syntax as for dates. + Web Interface ============= diff --git a/roundup/backends/back_anydbm.py b/roundup/backends/back_anydbm.py index bed71b8..670a0af 100644 --- a/roundup/backends/back_anydbm.py +++ b/roundup/backends/back_anydbm.py @@ -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.118 2003-03-26 11:19:28 richard Exp $ +#$Id: back_anydbm.py,v 1.119 2003-04-20 11:58:45 kedder 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 @@ -1639,6 +1639,7 @@ class Class(hyperdb.Class): MULTILINK = 1 STRING = 2 DATE = 3 + INTERVAL = 4 OTHER = 6 timezone = self.db.getUserTimezone() @@ -1695,18 +1696,21 @@ class Class(hyperdb.Class): l.append((DATE, k, date_rng)) except ValueError: # If range creation fails - ignore that search parameter - pass + pass + elif isinstance(propclass, Interval): + try: + intv_rng = Range(v, date.Interval) + l.append((INTERVAL, k, intv_rng)) + except ValueError: + # If range creation fails - ignore that search parameter + pass + elif isinstance(propclass, Boolean): if type(v) is type(''): bv = v.lower() in ('yes', 'true', 'on', '1') else: bv = v l.append((OTHER, k, bv)) - # kedder: dates are filtered by ranges - #elif isinstance(propclass, Date): - # l.append((OTHER, k, date.Date(v))) - elif isinstance(propclass, Interval): - l.append((OTHER, k, date.Interval(v))) elif isinstance(propclass, Number): l.append((OTHER, k, int(v))) else: @@ -1760,7 +1764,7 @@ class Class(hyperdb.Class): # RE search if node[k] is None or not v.search(node[k]): break - elif t == DATE: + elif t == DATE or t == INTERVAL: if node[k] is None: break if v.to_value: if not (v.from_value < node[k] and v.to_value > node[k]): diff --git a/roundup/backends/back_metakit.py b/roundup/backends/back_metakit.py index 16ac60c..7b94ac8 100755 --- a/roundup/backends/back_metakit.py +++ b/roundup/backends/back_metakit.py @@ -1,4 +1,4 @@ -# $Id: back_metakit.py,v 1.45 2003-03-26 10:44:00 richard Exp $ +# $Id: back_metakit.py,v 1.46 2003-04-20 11:58:45 kedder Exp $ ''' Metakit backend for Roundup, originally by Gordon McMillan. @@ -603,10 +603,11 @@ class Class: if value is None: setattr(row, key, '') else: - setattr(row, key, str(value)) + # kedder: we should store interval values serialized + setattr(row, key, value.serialise()) changes[key] = str(oldvalue) propvalues[key] = str(value) - + elif isinstance(prop, hyperdb.Number): if value is None: value = 0 @@ -963,6 +964,10 @@ class Class: if date_rng.from_value: t = date_rng.from_value.get_tuple() where[propname] = int(calendar.timegm(t)) + else: + # use minimum possible value to exclude items without + # 'prop' property + where[propname] = 0 if date_rng.to_value: t = date_rng.to_value.get_tuple() wherehigh[propname] = int(calendar.timegm(t)) @@ -972,7 +977,24 @@ class Class: # If range creation fails - ignore that search parameter pass elif isinstance(prop, hyperdb.Interval): - where[propname] = str(date.Interval(value)) + try: + # Try to filter on range of intervals + date_rng = Range(value, date.Interval) + if date_rng.from_value: + #t = date_rng.from_value.get_tuple() + where[propname] = date_rng.from_value.serialise() + else: + # use minimum possible value to exclude items without + # 'prop' property + where[propname] = '-99999999999999' + if date_rng.to_value: + #t = date_rng.to_value.get_tuple() + wherehigh[propname] = date_rng.to_value.serialise() + else: + wherehigh[propname] = None + except ValueError: + # If range creation fails - ignore that search parameter + pass elif isinstance(prop, hyperdb.Number): where[propname] = int(value) else: @@ -1187,7 +1209,7 @@ class Class: if isinstance(prop, hyperdb.Date): value = int(calendar.timegm(value)) elif isinstance(prop, hyperdb.Interval): - value = str(date.Interval(value)) + value = date.Interval(value).serialise() elif isinstance(prop, hyperdb.Number): value = int(value) elif isinstance(prop, hyperdb.Boolean): diff --git a/roundup/backends/rdbms_common.py b/roundup/backends/rdbms_common.py index ffc9391..454fe3e 100644 --- a/roundup/backends/rdbms_common.py +++ b/roundup/backends/rdbms_common.py @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.53 2003-04-08 06:41:48 richard Exp $ +# $Id: rdbms_common.py,v 1.54 2003-04-20 11:58:45 kedder Exp $ ''' Relational database (SQL) backend common code. Basics: @@ -1866,8 +1866,20 @@ class Class(hyperdb.Class): where.append('_%s in (%s)'%(k, s)) args = args + [date.Interval(x).serialise() for x in v] else: - where.append('_%s=%s'%(k, a)) - args.append(date.Interval(v).serialise()) + try: + # Try to filter on range of intervals + date_rng = Range(v, date.Interval) + if (date_rng.from_value): + where.append('_%s > %s'%(k, a)) + args.append(date_rng.from_value.serialise()) + if (date_rng.to_value): + where.append('_%s < %s'%(k, a)) + args.append(date_rng.to_value.serialise()) + except ValueError: + # If range creation fails - ignore that search parameter + pass + #where.append('_%s=%s'%(k, a)) + #args.append(date.Interval(v).serialise()) else: if isinstance(v, type([])): s = ','.join([a for x in v]) diff --git a/test/test_db.py b/test/test_db.py index 613b0c9..8d0a49e 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_db.py,v 1.84 2003-03-26 11:19:28 richard Exp $ +# $Id: test_db.py,v 1.85 2003-04-20 11:58:45 kedder Exp $ import unittest, os, shutil, time @@ -691,6 +691,7 @@ class anydbmDBTestCase(MyTestCase): def testFilteringRange(self): ae, filt = self.filteringSetup() + # Date ranges ae(filt(None, {'deadline': 'from 2003-02-10 to 2003-02-23'}), ['2']) ae(filt(None, {'deadline': '2003-02-10; 2003-02-23'}), ['2']) ae(filt(None, {'deadline': '; 2003-02-16'}), ['1']) @@ -698,6 +699,11 @@ class anydbmDBTestCase(MyTestCase): # may fail :) ae(filt(None, {'deadline': 'from 2003-02-16'}), ['2', '3']) ae(filt(None, {'deadline': '2003-02-16'}), ['2', '3']) + # Interval ranges + ae(filt(None, {'foo': 'from 0:50 to 2:00'}), ['1']) + ae(filt(None, {'foo': 'from 0:50 to 1d 2:00'}), ['1', '2']) + ae(filt(None, {'foo': 'from 5:50'}), ['2']) + ae(filt(None, {'foo': 'to 0:50'}), []) def testFilteringIntervalSort(self): ae, filt = self.filteringSetup() -- 2.30.2