Code

. lots of date/interval related changes:
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Wed, 16 Jan 2002 07:02:57 +0000 (07:02 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Wed, 16 Jan 2002 07:02:57 +0000 (07:02 +0000)
   - 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
roundup/cgi_client.py
roundup/date.py
roundup/hyperdb.py
test/test_dates.py
test/test_db.py

index 3276532c28f5b4b517248ae2786d14dce44304a6..825972cede0e4d4261afed778c442267ec9574cc 100644 (file)
@@ -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
index 5489426c1e20dbda376e669c2dd31b09dc311cc0..aea9d1d13ee74a57e5b5290944dae517a3190e54 100644 (file)
@@ -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
index a74fcc217b75e7625c37775a25b5c9cf04b890bf..bc96c830f9693f69b4f71c46848fbb1e410cb115 100644 (file)
@@ -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<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<n>\.)?                                       # .
               (((?P<H>\d?\d):(?P<M>\d\d))?(:(?P<S>\d\d))?)?    # hh:mm:ss
               (?P<o>.+)?                                       # 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
 #
index c221d0adf3346e722f1bcc01af63f971551fa56c..6551535e8cd734278511b306555819a7c8d072d5 100644 (file)
@@ -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
index 42cf18b2501720b82b40c14c2cb92afc4705af0f..624b3124786123501829a35e48301c8b17183b23 100644 (file)
@@ -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
 #
index ec7ba763e419e9946adbfdd1b9138410c50240f3..8e51e01d23cfc0c4c4f81d4a691eddccb8a13afe 100644 (file)
 # 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,