From e2b84cddf058518c493ede3c58a162a0b2cc6521 Mon Sep 17 00:00:00 2001 From: richard Date: Wed, 16 Jan 2002 07:02:57 +0000 Subject: [PATCH] . lots of date/interval related changes: - more relaxed date format for input git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@555 57a73879-2fb5-44c3-a270-3262357dd7e2 --- CHANGES.txt | 3 +++ roundup/cgi_client.py | 20 ++++++++++++++++---- roundup/date.py | 11 +++++++++-- roundup/hyperdb.py | 23 ++++++++++++++++------- test/test_dates.py | 9 ++++++++- test/test_db.py | 26 +++++++++++++++++++++++--- 6 files changed, 75 insertions(+), 17 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 3276532..825972c 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -28,6 +28,9 @@ Fixed: . #503340 ] creating issue with [asignedto=p.ohly] . #502949 ] index view for non-issues and redisplay . #503793 ] changing assignedto resets nosy list + . lots of date/interval related changes: + - more relaxed date format for input + - handle None for date/interval properties 2002-01-08 - 0.4.0b1 diff --git a/roundup/cgi_client.py b/roundup/cgi_client.py index 5489426..aea9d1d 100644 --- a/roundup/cgi_client.py +++ b/roundup/cgi_client.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: cgi_client.py,v 1.99 2002-01-16 03:02:42 richard Exp $ +# $Id: cgi_client.py,v 1.100 2002-01-16 07:02:57 richard Exp $ __doc__ = """ WWW request handler (also used in the stand-alone server). @@ -309,7 +309,8 @@ class Client: ', '.join(props.keys())} elif self.form.has_key('__note') and self.form['__note'].value: message = _('note added') - elif self.form.has_key('__file'): + elif (self.form.has_key('__file') and + self.form['__file'].filename): message = _('file added') else: message = _('nothing changed') @@ -1115,9 +1116,17 @@ def parsePropsFromForm(db, cl, form, nodeid=0): elif isinstance(proptype, hyperdb.Password): value = password.Password(form[key].value.strip()) elif isinstance(proptype, hyperdb.Date): - value = date.Date(form[key].value.strip()) + value = form[key].value.strip() + if value: + value = date.Date(form[key].value.strip()) + else: + value = None elif isinstance(proptype, hyperdb.Interval): - value = date.Interval(form[key].value.strip()) + value = form[key].value.strip() + if value: + value = date.Interval(form[key].value.strip()) + else: + value = None elif isinstance(proptype, hyperdb.Link): value = form[key].value.strip() # see if it's the "no selection" choice @@ -1173,6 +1182,9 @@ def parsePropsFromForm(db, cl, form, nodeid=0): # # $Log: not supported by cvs2svn $ +# Revision 1.99 2002/01/16 03:02:42 richard +# #503793 ] changing assignedto resets nosy list +# # Revision 1.98 2002/01/14 02:20:14 richard # . changed all config accesses so they access either the instance or the # config attriubute on the db. This means that all config is obtained from diff --git a/roundup/date.py b/roundup/date.py index a74fcc2..bc96c83 100644 --- a/roundup/date.py +++ b/roundup/date.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: date.py,v 1.16 2002-01-08 11:56:24 richard Exp $ +# $Id: date.py,v 1.17 2002-01-16 07:02:57 richard Exp $ __doc__ = """ Date, time and time interval handling. @@ -153,6 +153,8 @@ class Date: def __cmp__(self, other): """Compare this date to another date.""" + if other is None: + return 1 for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'): r = cmp(getattr(self, attr), getattr(other, attr)) if r: return r @@ -170,7 +172,7 @@ class Date: self.day, self.hour, self.minute, self.second, 0, 0, 0)) def set(self, spec, offset=0, date_re=re.compile(r''' - (((?P\d\d\d\d)-)?((?P\d\d)-(?P\d\d))?)? # yyyy-mm-dd + (((?P\d\d\d\d)-)?((?P\d\d?)-(?P\d\d?))?)? # yyyy-mm-dd (?P\.)? # . (((?P\d?\d):(?P\d\d))?(:(?P\d\d))?)? # hh:mm:ss (?P.+)? # offset @@ -254,6 +256,8 @@ class Interval: def __cmp__(self, other): """Compare this interval to another interval.""" + if other is None: + return 1 for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'): r = cmp(getattr(self, attr), getattr(other, attr)) if r: return r @@ -379,6 +383,9 @@ if __name__ == '__main__': # # $Log: not supported by cvs2svn $ +# Revision 1.16 2002/01/08 11:56:24 richard +# missed an import _ +# # Revision 1.15 2002/01/05 02:27:00 richard # I18N'ification # diff --git a/roundup/hyperdb.py b/roundup/hyperdb.py index c221d0a..6551535 100644 --- a/roundup/hyperdb.py +++ b/roundup/hyperdb.py @@ -15,7 +15,7 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: hyperdb.py,v 1.48 2002-01-14 06:32:34 richard Exp $ +# $Id: hyperdb.py,v 1.49 2002-01-16 07:02:57 richard Exp $ __doc__ = """ Hyperdatabase implementation, especially field types. @@ -348,11 +348,11 @@ class Class: raise TypeError, 'new property "%s" not a Password'%key elif isinstance(prop, Date): - if not isinstance(value, date.Date): + if value is not None and not isinstance(value, date.Date): raise TypeError, 'new property "%s" not a Date'%key elif isinstance(prop, Interval): - if not isinstance(value, date.Interval): + if value is not None and not isinstance(value, date.Interval): raise TypeError, 'new property "%s" not an Interval'%key # make sure there's data where there needs to be @@ -370,9 +370,11 @@ class Class: # convert all data to strings for key, prop in self.properties.items(): if isinstance(prop, Date): - propvalues[key] = propvalues[key].get_tuple() + if propvalues[key] is not None: + propvalues[key] = propvalues[key].get_tuple() elif isinstance(prop, Interval): - propvalues[key] = propvalues[key].get_tuple() + if propvalues[key] is not None: + propvalues[key] = propvalues[key].get_tuple() elif isinstance(prop, Password): propvalues[key] = str(propvalues[key]) @@ -414,8 +416,12 @@ class Class: # possibly convert the marshalled data to instances if isinstance(prop, Date): + if d[propname] is None: + return None return date.Date(d[propname]) elif isinstance(prop, Interval): + if d[propname] is None: + return None return date.Interval(d[propname]) elif isinstance(prop, Password): p = password.Password() @@ -561,12 +567,12 @@ class Class: raise TypeError, 'new property "%s" not a Password'% key propvalues[key] = value = str(value) - elif isinstance(prop, Date): + elif value is not None and isinstance(prop, Date): if not isinstance(value, date.Date): raise TypeError, 'new property "%s" not a Date'% key propvalues[key] = value = value.get_tuple() - elif isinstance(prop, Interval): + elif value is not None and isinstance(prop, Interval): if not isinstance(value, date.Interval): raise TypeError, 'new property "%s" not an Interval'% key propvalues[key] = value = value.get_tuple() @@ -1041,6 +1047,9 @@ def Choice(name, *options): # # $Log: not supported by cvs2svn $ +# Revision 1.48 2002/01/14 06:32:34 richard +# . #502951 ] adding new properties to old database +# # Revision 1.47 2002/01/14 02:20:15 richard # . changed all config accesses so they access either the instance or the # config attriubute on the db. This means that all config is obtained from diff --git a/test/test_dates.py b/test/test_dates.py index 42cf18b..624b312 100644 --- a/test/test_dates.py +++ b/test/test_dates.py @@ -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.7 2001-08-13 23:01:53 richard Exp $ +# $Id: test_dates.py,v 1.8 2002-01-16 07:02:57 richard Exp $ import unittest, time @@ -35,6 +35,10 @@ class DateTestCase(unittest.TestCase): ae = self.assertEqual date = Date("2000-04-17") ae(str(date), '2000-04-17.00:00:00') + date = Date("2000-4-7") + ae(str(date), '2000-04-07.00:00:00') + date = Date("2000-4-17") + ae(str(date), '2000-04-17.00:00:00') date = Date("01-25") y, m, d, x, x, x, x, x, x = time.gmtime(time.time()) ae(str(date), '%s-01-25.00:00:00'%y) @@ -83,6 +87,9 @@ def suite(): # # $Log: not supported by cvs2svn $ +# Revision 1.7 2001/08/13 23:01:53 richard +# fixed a 2.1-ism +# # Revision 1.6 2001/08/07 00:24:43 richard # stupid typo # diff --git a/test/test_db.py b/test/test_db.py index ec7ba76..8e51e01 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -15,13 +15,14 @@ # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE, # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. # -# $Id: test_db.py,v 1.13 2002-01-14 02:20:15 richard Exp $ +# $Id: test_db.py,v 1.14 2002-01-16 07:02:57 richard Exp $ import unittest, os, shutil from roundup.hyperdb import String, Password, Link, Multilink, Date, \ Interval, Class, DatabaseError from roundup.roundupdb import FileClass +from roundup import date def setupSchema(db, create): status = Class(db, "status", name=String()) @@ -33,7 +34,7 @@ def setupSchema(db, create): status.create(name="resolved") Class(db, "user", username=String(), password=Password()) Class(db, "issue", title=String(), status=Link("status"), - nosy=Multilink("user")) + nosy=Multilink("user"), deadline=Date(), foo=Interval()) FileClass(db, "file", name=String(), type=String()) db.commit() @@ -76,9 +77,19 @@ class anydbmDBTestCase(MyTestCase): props = self.db.issue.getprops() keys = props.keys() keys.sort() - self.assertEqual(keys, ['fixer', 'id', 'nosy', 'status', 'title']) + self.assertEqual(keys, ['deadline', 'fixer', 'foo', 'id', 'nosy', + 'status', 'title']) self.db.issue.set('5', status='2') self.db.issue.get('5', "status") + + a = self.db.issue.get('5', "deadline") + self.db.issue.set('5', deadline=date.Date()) + self.assertNotEqual(a, self.db.issue.get('5', "deadline")) + + a = self.db.issue.get('5', "foo") + self.db.issue.set('5', foo=date.Interval('-1d')) + self.assertNotEqual(a, self.db.issue.get('5', "foo")) + self.db.status.get('2', "name") self.db.issue.get('5', "title") self.db.issue.find(status = self.db.status.lookup("in-progress")) @@ -274,6 +285,15 @@ def suite(): # # $Log: not supported by cvs2svn $ +# Revision 1.13 2002/01/14 02:20:15 richard +# . changed all config accesses so they access either the instance or the +# config attriubute on the db. This means that all config is obtained from +# instance_config instead of the mish-mash of classes. This will make +# switching to a ConfigParser setup easier too, I hope. +# +# At a minimum, this makes migration a _little_ easier (a lot easier in the +# 0.5.0 switch, I hope!) +# # Revision 1.12 2001/12/17 03:52:48 richard # Implemented file store rollback. As a bonus, the hyperdb is now capable of # storing more than one file per node - if a property name is supplied, -- 2.30.2