Mercurial > p > roundup > code
changeset 1599:cc96bf971b33
extended date syntax to make range searches even more useful
| author | Andrey Lebedev <kedder@users.sourceforge.net> |
|---|---|
| date | Tue, 22 Apr 2003 20:53:55 +0000 |
| parents | b3263567b8c6 |
| children | 2047425bf7e7 |
| files | CHANGES.txt doc/user_guide.txt roundup/backends/back_anydbm.py roundup/backends/rdbms_common.py roundup/date.py test/test_dates.py test/test_db.py |
| diffstat | 7 files changed, 67 insertions(+), 46 deletions(-) [+] |
line wrap: on
line diff
--- a/CHANGES.txt Mon Apr 21 22:38:48 2003 +0000 +++ b/CHANGES.txt Tue Apr 22 20:53:55 2003 +0000 @@ -63,6 +63,7 @@ - HTML templating files now have a .html extension - Roundup templates are now distributed much more sanely, allowing for 3rd-party templates. +- extended date syntax to make range searches even more useful Fixed: - applied unicode patch. All data is stored in utf-8. Incoming messages
--- a/doc/user_guide.txt Mon Apr 21 22:38:48 2003 +0000 +++ b/doc/user_guide.txt Tue Apr 22 20:53:55 2003 +0000 @@ -2,7 +2,7 @@ User Guide ========== -:Version: $Revision: 1.20 $ +:Version: $Revision: 1.21 $ .. contents:: @@ -99,13 +99,13 @@ 1. English syntax:: - [[From] <value>][ To <value>] + [From <value>][To <value>] Keywords "From" and "To" are case insensitive. Keyword "From" is optional. 2. "Geek" syntax:: - [<value>][; <value>] + [<value>];[<value>] Either first or second ``<value>`` can be omitted in both syntaxes. @@ -117,24 +117,30 @@ Other possible examples (consider local time is Sat Mar 8 22:07:48 2003):: - >>> Range("from 2-12 to 4-2") - <Range from 2003-02-12.00:00:00 to 2003-04-02.00:00:00> - - >>> Range("18:00 TO +2m") - <Range from 2003-03-08.18:00:00 to 2003-05-08.20:07:48> - - >>> Range("12:00") - <Range from 2003-03-08.12:00:00 to None> - - >>> Range("tO +3d") - <Range from None to 2003-03-11.20:07:48> - - >>> Range("2002-11-10; 2002-12-12") - <Range from 2002-11-10.00:00:00 to 2002-12-12.00:00:00> + >>> Range("from 2-12 to 4-2") + <Range from 2003-02-12.00:00:00 to 2003-04-02.00:00:00> + + >>> Range("FROM 18:00 TO +2m") + <Range from 2003-03-08.18:00:00 to 2003-05-08.20:07:48> + + >>> Range("12:00;") + <Range from 2003-03-08.12:00:00 to None> + + >>> Range("tO +3d") + <Range from None to 2003-03-11.20:07:48> + + >>> Range("2002-11-10; 2002-12-12") + <Range from 2002-11-10.00:00:00 to 2002-12-12.00:00:00> - >>> Range("; 20:00 +1d") - <Range from None to 2003-03-09.20:00:00> + >>> Range("; 20:00 +1d") + <Range from None to 2003-03-09.20:00:00> + >>> Range("2003") + <Range from 2003-01-01.00:00:00 to 2003-12-31.23:59:59> + + >>> Range("2003-04") + <Range from 2003-04-01.00:00:00 to 2003-04-30.23:59:59> + Interval properties ~~~~~~~~~~~~~~~~~~~ @@ -486,10 +492,10 @@ -u -- the user[:password] to use for commands -d -- print full designators not just class id numbers -c -- when outputting lists of data, comma-separate them. - Same as '-S ","'. + Same as '-S ","'. -S <string> -- when outputting lists of data, string-separate them -s -- when outputting lists of data, space-separate them. - Same as '-S " "'. + Same as '-S " "'. Only one of -s, -c or -S can be specified. @@ -549,6 +555,8 @@ "11-07.09:32:43" yyyy-11-07.14:32:43 "14:25" yyyy-mm-dd.19:25:00 "8:47:11" yyyy-mm-dd.13:47:11 + "2003" 2003-01-01.00:00:00 + "2003-04" 2003-04-01.00:00:00 "." "right now" - Link values are printed as item designators. When given as an argument, @@ -625,7 +633,7 @@ or status:: shell% roundup-admin get name `/tools/roundup/bin/roundup-admin \ - -dc -i /var/roundup/sysadmin get status issue3,issue1` + -dc -i /var/roundup/sysadmin get status issue3,issue1` unread deferred @@ -644,7 +652,7 @@ Also the tautological:: shell% roundup-admin get name \ - `roundup-admin -dc get status \`roundup-admin -dc find issue \ + `roundup-admin -dc get status \`roundup-admin -dc find issue \ status=chatting\`` chatting chatting
--- a/roundup/backends/back_anydbm.py Mon Apr 21 22:38:48 2003 +0000 +++ b/roundup/backends/back_anydbm.py Tue Apr 22 20:53:55 2003 +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.119 2003-04-20 11:58:45 kedder Exp $ +#$Id: back_anydbm.py,v 1.120 2003-04-22 20:53:54 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 @@ -1767,10 +1767,10 @@ 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]): + if not (v.from_value <= node[k] and v.to_value >= node[k]): break else: - if not (v.from_value < node[k]): + if not (v.from_value <= node[k]): break elif t == OTHER: # straight value comparison for the other types
--- a/roundup/backends/rdbms_common.py Mon Apr 21 22:38:48 2003 +0000 +++ b/roundup/backends/rdbms_common.py Tue Apr 22 20:53:55 2003 +0000 @@ -1,4 +1,4 @@ -# $Id: rdbms_common.py,v 1.54 2003-04-20 11:58:45 kedder Exp $ +# $Id: rdbms_common.py,v 1.55 2003-04-22 20:53:54 kedder Exp $ ''' Relational database (SQL) backend common code. Basics: @@ -1852,10 +1852,10 @@ # Try to filter on range of dates date_rng = Range(v, date.Date, offset=timezone) if (date_rng.from_value): - where.append('_%s > %s'%(k, a)) + where.append('_%s >= %s'%(k, a)) args.append(date_rng.from_value.serialise()) if (date_rng.to_value): - where.append('_%s < %s'%(k, a)) + where.append('_%s <= %s'%(k, a)) args.append(date_rng.to_value.serialise()) except ValueError: # If range creation fails - ignore that search parameter @@ -1870,10 +1870,10 @@ # Try to filter on range of intervals date_rng = Range(v, date.Interval) if (date_rng.from_value): - where.append('_%s > %s'%(k, a)) + where.append('_%s >= %s'%(k, a)) args.append(date_rng.from_value.serialise()) if (date_rng.to_value): - where.append('_%s < %s'%(k, a)) + where.append('_%s <= %s'%(k, a)) args.append(date_rng.to_value.serialise()) except ValueError: # If range creation fails - ignore that search parameter
--- a/roundup/date.py Mon Apr 21 22:38:48 2003 +0000 +++ b/roundup/date.py Tue Apr 22 20:53:55 2003 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: date.py,v 1.52 2003-04-21 14:29:39 kedder Exp $ +# $Id: date.py,v 1.53 2003-04-22 20:53:54 kedder Exp $ __doc__ = """ Date, time and time interval handling. @@ -59,6 +59,8 @@ "11-07.09:32:43" means <Date yyyy-11-07.14:32:43> "14:25" means <Date yyyy-mm-dd.19:25:00> "8:47:11" means <Date yyyy-mm-dd.13:47:11> + "2003" means <Date 2003-01-01.00:00:00> + "2003-06" means <Date 2003-06-01.00:00:00> "." means "right now" The Date class should understand simple date expressions of the form @@ -89,6 +91,7 @@ minute, second) is the serialisation format returned by the serialise() method, and is accepted as an argument on instatiation. ''' + def __init__(self, spec='.', offset=0, add_granularity=0): """Construct a date given a specification and a time zone offset. @@ -104,8 +107,10 @@ self.year, self.month, self.day, self.hour, self.minute, \ self.second, x, x, x = time.gmtime(ts) + usagespec='[yyyy]-[mm]-[dd].[H]H:MM[:SS][offset]' def set(self, spec, offset=0, date_re=re.compile(r''' - (((?P<y>\d\d\d\d)[/-])?(?P<m>\d\d?)?[/-](?P<d>\d\d?))? # [yyyy-]mm-dd + ((?P<y>\d\d\d\d)([/-](?P<m>\d\d?)([/-](?P<d>\d\d?))?)? # yyyy[-mm[-dd]] + |(?P<a>\d\d?)[/-](?P<b>\d\d?))? # or mm-dd (?P<n>\.)? # . (((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)? # hh:mm:ss (?P<o>.+)? # offset @@ -125,24 +130,27 @@ # not serialised data, try usual format m = date_re.match(spec) if m is None: - raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' - '[[h]h:mm[:ss]][offset]') + raise ValueError, _('Not a date spec: %s' % self.usagespec) info = m.groupdict() if add_granularity: - _add_granularity(info, 'SMHdmy') + _add_granularity(info, 'SMHdmyab') # get the current date as our default y,m,d,H,M,S,x,x,x = time.gmtime(time.time()) - # override year, month, day parts - if info['m'] is not None and info['d'] is not None: - m = int(info['m']) - d = int(info['d']) + if info['y'] is not None or info['a'] is not None: if info['y'] is not None: y = int(info['y']) - # time defaults to 00:00:00 GMT - offset (local midnight) + m,d = (1,1) + if info['m'] is not None: + m = int(info['m']) + if info['d'] is not None: + d = int(info['d']) + if info['a'] is not None: + m = int(info['a']) + d = int(info['b']) H = -offset M = S = 0 @@ -165,8 +173,7 @@ try: self.applyInterval(Interval(info['o'], allowdate=0)) except ValueError: - raise ValueError, _('Not a date spec: [[yyyy-]mm-dd].' - '[[h]h:mm[:ss]][offset]') + raise ValueError, _('Not a date spec: %s' % self.usagespec) def addInterval(self, interval): ''' Add the interval to this date, returning the date tuple
--- a/test/test_dates.py Mon Apr 21 22:38:48 2003 +0000 +++ b/test/test_dates.py Tue Apr 22 20:53:55 2003 +0000 @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_dates.py,v 1.23 2003-04-21 14:29:40 kedder Exp $ +# $Id: test_dates.py,v 1.24 2003-04-22 20:53:54 kedder Exp $ import unittest, time @@ -56,6 +56,8 @@ ae(str(date), '%s-%02d-%02d.14:25:00'%(y, m, d)) date = Date("8:47:11") ae(str(date), '%s-%02d-%02d.08:47:11'%(y, m, d)) + ae(str(Date('2003')), '2003-01-01.00:00:00') + ae(str(Date('2004-06')), '2004-06-01.00:00:00') def testDateError(self): self.assertRaises(ValueError, Date, "12") @@ -249,6 +251,8 @@ ae = self.assertEqual ae(str(Date('2003-2-12', add_granularity=1)), '2003-02-12.23:59:59') ae(str(Date('2003-1-1.23:00', add_granularity=1)), '2003-01-01.23:00:59') + ae(str(Date('2003', add_granularity=1)), '2003-12-31.23:59:59') + ae(str(Date('2003-5', add_granularity=1)), '2003-05-31.23:59:59') ae(str(Interval('+1w', add_granularity=1)), '+ 14d') ae(str(Interval('-2m 3w', add_granularity=1)), '- 2m 14d')
--- a/test/test_db.py Mon Apr 21 22:38:48 2003 +0000 +++ b/test/test_db.py Tue Apr 22 20:53:55 2003 +0000 @@ -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.87 2003-04-21 22:38:48 richard Exp $ +# $Id: test_db.py,v 1.88 2003-04-22 20:53:55 kedder Exp $ import unittest, os, shutil, time @@ -703,6 +703,7 @@ ae(filt(None, {'deadline': 'from 2003-02-16'}), ['2', '3', '4']) ae(filt(None, {'deadline': '2003-02-16;'}), ['2', '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']) @@ -713,7 +714,7 @@ 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'}), []) + ae(filt(None, {'foo': 'to 0:05'}), []) def testFilteringIntervalSort(self): ae, filt = self.filteringSetup()
