Code

Unit tests and a few fixes.
authorrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 18 Jul 2002 23:07:08 +0000 (23:07 +0000)
committerrichard <richard@57a73879-2fb5-44c3-a270-3262357dd7e2>
Thu, 18 Jul 2002 23:07:08 +0000 (23:07 +0000)
git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@902 57a73879-2fb5-44c3-a270-3262357dd7e2

TODO.txt
roundup/backends/back_anydbm.py
roundup/date.py
roundup/htmltemplate.py
test/test_db.py
test/test_htmltemplate.py

index 91b5c5b41a691e0b3b3b9a9370128724bcebab9b..e41bb1e1128f0e0287c2b585881f30afd730bbf6 100644 (file)
--- a/TODO.txt
+++ b/TODO.txt
@@ -10,10 +10,6 @@ pending  hyperdb: range searching of values (dates in particular)
          - filter specifies {property: (comparison function, value)}
            comparison functions: lt, le, eq, ge, gt. eq and
            [value, value, ...] implies "in"
-active   hyperdb: add tests for Number and Boolean
-                  - htmltemplate
-                  - schema
-                  - db
 pending  hyperdb: make creator, creation and activity available pre-commit
 pending  instance: including much simpler upgrade path and the use of
                    non-Python configuration files (ConfigParser)
index fa550fdc84b5dd9a3c6f1b0db62a1378c775d8bd..dbdd21bc93fb1bc05863a8bfa727ebfca67142ff 100644 (file)
@@ -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.50 2002-07-18 11:50:58 richard Exp $
+#$Id: back_anydbm.py,v 1.51 2002-07-18 23:07:08 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
@@ -732,27 +732,15 @@ class Class(hyperdb.Class):
 
             elif value is not None and isinstance(prop, Number):
                 try:
-                    int(value)
+                    float(value)
                 except ValueError:
-                    try:
-                        float(value)
-                    except ValueError:
-                        raise TypeError, 'new property "%s" not numeric'%key
+                    raise TypeError, 'new property "%s" not numeric'%key
 
             elif value is not None and isinstance(prop, Boolean):
-                if isinstance(value, type('')):
-                    s = value.lower()
-                    if s in ('0', 'false', 'no'):
-                        value = 0
-                    elif s in ('1', 'true', 'yes'):
-                        value = 1
-                    else:
-                        raise TypeError, 'new property "%s" not boolean'%key
-                else:
-                    try:
-                        int(value)
-                    except TypeError:
-                        raise TypeError, 'new property "%s" not boolean'%key
+                try:
+                    int(value)
+                except ValueError:
+                    raise TypeError, 'new property "%s" not boolean'%key
 
         # make sure there's data where there needs to be
         for key, prop in self.properties.items():
@@ -1037,30 +1025,15 @@ class Class(hyperdb.Class):
 
             elif value is not None and isinstance(prop, Number):
                 try:
-                    int(value)
+                    float(value)
                 except ValueError:
-                    try:
-                        float(value)
-                    except ValueError:
-                        raise TypeError, 'new property "%s" not '\
-                            'numeric'%propname
+                    raise TypeError, 'new property "%s" not numeric'%propname
 
             elif value is not None and isinstance(prop, Boolean):
-                if isinstance(value, type('')):
-                    s = value.lower()
-                    if s in ('0', 'false', 'no'):
-                        value = 0
-                    elif s in ('1', 'true', 'yes'):
-                        value = 1
-                    else:
-                        raise TypeError, 'new property "%s" not '\
-                            'boolean'%propname
-                else:
-                    try:
-                        int(value)
-                    except ValueError:
-                        raise TypeError, 'new property "%s" not '\
-                            'boolean'%propname
+                try:
+                    int(value)
+                except ValueError:
+                    raise TypeError, 'new property "%s" not boolean'%propname
 
             node[propname] = value
 
@@ -1703,6 +1676,9 @@ class IssueClass(Class, roundupdb.IssueClass):
 
 #
 #$Log: not supported by cvs2svn $
+#Revision 1.50  2002/07/18 11:50:58  richard
+#added tests for number type too
+#
 #Revision 1.49  2002/07/18 11:41:10  richard
 #added tests for boolean type, and fixes to anydbm backend
 #
index 94db02e986bbc7a450ef5b64a535db7f5c9c613d..a7f212a553c0ca3c15a9a96db610c37afe49beb6 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.22 2002-07-14 06:05:50 richard Exp $
+# $Id: date.py,v 1.23 2002-07-18 23:07:08 richard Exp $
 
 __doc__ = """
 Date, time and time interval handling.
@@ -190,6 +190,8 @@ class Date:
         if other is None:
             return 1
         for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'):
+            if not hasattr(other, attr):
+                return 1
             r = cmp(getattr(self, attr), getattr(other, attr))
             if r: return r
         return 0
@@ -304,6 +306,8 @@ class Interval:
         if other is None:
             return 1
         for attr in ('year', 'month', 'day', 'hour', 'minute', 'second'):
+            if not hasattr(other, attr):
+                return 1
             r = cmp(getattr(self, attr), getattr(other, attr))
             if r: return r
         return 0
@@ -438,6 +442,9 @@ if __name__ == '__main__':
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.22  2002/07/14 06:05:50  richard
+#  . fixed the date module so that Date(". - 2d") works
+#
 # Revision 1.21  2002/05/15 06:32:46  richard
 #  . reverting to dates for intervals > 2 months sucks
 #
index 0b930c5f0187aedf5b4a6e8ba26efe0ff9d608d0..57b555af8ff4cda705f4320f90b72406b25ef3be 100644 (file)
@@ -15,7 +15,7 @@
 # BASIS, AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
 # SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 # 
-# $Id: htmltemplate.py,v 1.101 2002-07-18 11:17:30 gmcm Exp $
+# $Id: htmltemplate.py,v 1.102 2002-07-18 23:07:08 richard Exp $
 
 __doc__ = """
 Template engine.
@@ -386,11 +386,13 @@ class TemplateFunctions:
 
         # get the value
         value = self.determine_value(property)
-        if not value:
+        if value in ('', None, []):
             return _('[no %(propname)s]')%{'propname':property.capitalize()}
 
         propclass = self.properties[property]
-        if isinstance(propclass, hyperdb.Link):
+        if isinstance(propclass, hyperdb.Boolean):
+            value = value and "Yes" or "No"
+        elif isinstance(propclass, hyperdb.Link):
             linkname = propclass.classname
             linkcl = self.db.classes[linkname]
             k = linkcl.labelprop(1)
@@ -407,7 +409,7 @@ class TemplateFunctions:
                     linkvalue, title, label)
             else:
                 return '<a href="%s%s"%s>%s</a>'%(linkname, value, title, label)
-        if isinstance(propclass, hyperdb.Multilink):
+        elif isinstance(propclass, hyperdb.Multilink):
             linkname = propclass.classname
             linkcl = self.db.classes[linkname]
             k = linkcl.labelprop(1)
@@ -1362,6 +1364,11 @@ class NewItemTemplate(TemplateFunctions):
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.101  2002/07/18 11:17:30  gmcm
+# Add Number and Boolean types to hyperdb.
+# Add conversion cases to web, mail & admin interfaces.
+# Add storage/serialization cases to back_anydbm & back_metakit.
+#
 # Revision 1.100  2002/07/18 07:01:54  richard
 # minor bugfix
 #
index fd7453f20c800366b61c5e5416fdc8418b148030..fc97d18462a51f0b8901d1bd30dfc1fb63842e9d 100644 (file)
@@ -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.34 2002-07-18 11:52:00 richard Exp $ 
+# $Id: test_db.py,v 1.35 2002-07-18 23:07:08 richard Exp $ 
 
 import unittest, os, shutil, time
 
@@ -112,14 +112,11 @@ class anydbmDBTestCase(MyTestCase):
 
     def testBooleanChange(self):
         self.db.user.create(username='foo', assignable=1)
+        self.db.user.create(username='foo', assignable=0)
         a = self.db.user.get('1', 'assignable')
-        self.db.user.set('1', assignable='false')
+        self.db.user.set('1', assignable=0)
         self.assertNotEqual(self.db.user.get('1', 'assignable'), a)
-        self.db.user.set('1', assignable='FaLse')
-        self.db.user.set('1', assignable='nO')
         self.db.user.set('1', assignable=0)
-        self.db.user.set('1', assignable='tRuE')
-        self.db.user.set('1', assignable='yEs')
         self.db.user.set('1', assignable=1)
 
     def testNumberChange(self):
@@ -265,12 +262,12 @@ class anydbmDBTestCase(MyTestCase):
         # invalid number value
         ar(TypeError, self.db.user.create, username='foo', age='a')
         # invalid boolean value
-        ar(TypeError, self.db.user.create, username='foo', assignable='fubar')
+        ar(TypeError, self.db.user.create, username='foo', assignable='true')
         self.db.user.create(username='foo')
         # invalid number value
         ar(TypeError, self.db.user.set, '3', username='foo', age='a')
         # invalid boolean value
-        ar(TypeError, self.db.user.set, '3', username='foo', assignable='fubar')
+        ar(TypeError, self.db.user.set, '3', username='foo', assignable='true')
 
     def testJournals(self):
         self.db.issue.addprop(fixer=Link("user", do_journal='yes'))
@@ -562,6 +559,9 @@ def suite():
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.34  2002/07/18 11:52:00  richard
+# oops
+#
 # Revision 1.33  2002/07/18 11:50:58  richard
 # added tests for number type too
 #
index 3342ab19985c021192bca22800b04df1e80e4298..8461e7e67a01096581a3144185a98955e956047e 100644 (file)
@@ -8,14 +8,15 @@
 # but WITHOUT ANY WARRANTY; without even the implied warranty of
 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 #
-# $Id: test_htmltemplate.py,v 1.16 2002-07-09 05:20:09 richard Exp $ 
+# $Id: test_htmltemplate.py,v 1.17 2002-07-18 23:07:07 richard Exp $ 
 
 import unittest, cgi, time
 
 from roundup import date, password
 from roundup.htmltemplate import TemplateFunctions
 from roundup.i18n import _
-from roundup.hyperdb import String, Password, Date, Interval, Link, Multilink
+from roundup.hyperdb import String, Password, Date, Interval, Link, \
+    Multilink, Boolean, Number
 
 class Class:
     def get(self, nodeid, attribute, default=None):
@@ -25,6 +26,10 @@ class Class:
             return 'file.foo'
         elif attribute == 'date':
             return date.Date('2000-01-01')
+        elif attribute == 'boolean':
+            return 0
+        elif attribute == 'number':
+            return 1234
         elif attribute == 'reldate':
             return date.Date() + date.Interval('- 2y 1m')
         elif attribute == 'interval':
@@ -52,7 +57,8 @@ class Class:
             'link': Link('other'), 'multilink': Multilink('other'),
             'password': Password(), 'html': String(), 'key': String(),
             'novalue': String(), 'filename': String(), 'multiline': String(),
-            'reldate': Date(), 'email': String()}
+            'reldate': Date(), 'email': String(), 'boolean': Boolean(),
+            'number': Number()}
     def labelprop(self, default_to_id=0):
         return 'key'
 
@@ -103,6 +109,11 @@ class NodeCase(unittest.TestCase):
     def testPlain_multilink(self):
         self.assertEqual(self.tf.do_plain('multilink'), 'the key1, the key2')
 
+    def testPlain_boolean(self):
+        self.assertEqual(self.tf.do_plain('boolean'), 'No')
+
+    def testPlain_number(self):
+        self.assertEqual(self.tf.do_plain('number'), '1234')
 
 #    def do_field(self, property, size=None, showid=0):
     def testField_string(self):
@@ -149,6 +160,16 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_field('multilink', size=10),
             '<input name="multilink" size="10" value="the key1,the key2">')
 
+    def testField_boolean(self):
+        self.assertEqual(self.tf.do_field('boolean'),
+            '<input type="checkbox" name="boolean" >')
+
+    def testField_number(self):
+        self.assertEqual(self.tf.do_field('number'),
+            '<input name="number" value="1234" size="30">')
+        self.assertEqual(self.tf.do_field('number', size=10),
+            '<input name="number" value="1234" size="10">')
+
 #    def do_multiline(self, property, rows=5, cols=40)
     def testMultiline_string(self):
         self.assertEqual(self.tf.do_multiline('multiline'),
@@ -168,6 +189,8 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_multiline('password'), s)
         self.assertEqual(self.tf.do_multiline('link'), s)
         self.assertEqual(self.tf.do_multiline('multilink'), s)
+        self.assertEqual(self.tf.do_multiline('boolean'), s)
+        self.assertEqual(self.tf.do_multiline('number'), s)
 
 #    def do_menu(self, property, size=None, height=None, showid=0):
     def testMenu_nonlinks(self):
@@ -176,6 +199,8 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_menu('date'), s)
         self.assertEqual(self.tf.do_menu('interval'), s)
         self.assertEqual(self.tf.do_menu('password'), s)
+        self.assertEqual(self.tf.do_menu('boolean'), s)
+        self.assertEqual(self.tf.do_menu('number'), s)
 
     def testMenu_link(self):
         self.assertEqual(self.tf.do_menu('link'), '''<select name="link">
@@ -250,6 +275,14 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_link('multilink', showid=1),
             '<a href="other1" title="the key1">1</a>, <a href="other2" title="the key2">2</a>')
 
+    def testLink_boolean(self):
+        self.assertEqual(self.tf.do_link('boolean'),
+            '<a href="test_class1">No</a>')
+
+    def testLink_number(self):
+        self.assertEqual(self.tf.do_link('number'),
+            '<a href="test_class1">1234</a>')
+
 #    def do_count(self, property, **args):
     def testCount_nonlinks(self):
         s = _('[Count: not a Multilink]')
@@ -258,6 +291,8 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_count('interval'), s)
         self.assertEqual(self.tf.do_count('password'), s)
         self.assertEqual(self.tf.do_count('link'), s)
+        self.assertEqual(self.tf.do_count('boolean'), s)
+        self.assertEqual(self.tf.do_count('number'), s)
 
     def testCount_multilink(self):
         self.assertEqual(self.tf.do_count('multilink'), '2')
@@ -270,6 +305,8 @@ class NodeCase(unittest.TestCase):
         self.assertEqual(self.tf.do_reldate('password'), s)
         self.assertEqual(self.tf.do_reldate('link'), s)
         self.assertEqual(self.tf.do_reldate('multilink'), s)
+        self.assertEqual(self.tf.do_reldate('boolean'), s)
+        self.assertEqual(self.tf.do_reldate('number'), s)
 
     def testReldate_date(self):
         self.assertEqual(self.tf.do_reldate('reldate'), '- 2y 1m')
@@ -308,15 +345,25 @@ class NodeCase(unittest.TestCase):
             '<a href="other1/the key1">the key1</a>, '
             '<a href="other2/the key2">the key2</a>')
 
+    def testDownload_boolean(self):
+        self.assertEqual(self.tf.do_download('boolean'),
+            '<a href="test_class1/No">No</a>')
+
+    def testDownload_number(self):
+        self.assertEqual(self.tf.do_download('number'),
+            '<a href="test_class1/1234">1234</a>')
+
 #    def do_checklist(self, property, reverse=0):
-    def testChecklink_nonlinks(self):
+    def testChecklist_nonlinks(self):
         s = _('[Checklist: not a link]')
         self.assertEqual(self.tf.do_checklist('string'), s)
         self.assertEqual(self.tf.do_checklist('date'), s)
         self.assertEqual(self.tf.do_checklist('interval'), s)
         self.assertEqual(self.tf.do_checklist('password'), s)
+        self.assertEqual(self.tf.do_checklist('boolean'), s)
+        self.assertEqual(self.tf.do_checklist('number'), s)
 
-    def testChecklink_link(self):
+    def testChecklstk_link(self):
         self.assertEqual(self.tf.do_checklist('link'),
             '''the key1:<input type="checkbox" checked name="link" value="the key1">
 the key2:<input type="checkbox"  name="link" value="the key2">
@@ -340,6 +387,8 @@ the key2:<input type="checkbox" checked name="multilink" value="the key2">''')
         self.assertEqual(self.tf.do_list('interval'), s)
         self.assertEqual(self.tf.do_list('password'), s)
         self.assertEqual(self.tf.do_list('link'), s)
+        self.assertEqual(self.tf.do_list('boolean'), s)
+        self.assertEqual(self.tf.do_list('number'), s)
 
     def testList_multilink(self):
         # TODO: test this (needs to have lots and lots of support!
@@ -362,6 +411,8 @@ the key2:<input type="checkbox" checked name="multilink" value="the key2">''')
         self.assertEqual(self.tf.do_email('password'), s)
         self.assertEqual(self.tf.do_email('link'), s)
         self.assertEqual(self.tf.do_email('multilink'), s)
+        self.assertEqual(self.tf.do_email('boolean'), s)
+        self.assertEqual(self.tf.do_email('number'), s)
 
 def suite():
    return unittest.makeSuite(NodeCase, 'test')
@@ -369,6 +420,10 @@ def suite():
 
 #
 # $Log: not supported by cvs2svn $
+# Revision 1.16  2002/07/09 05:20:09  richard
+#  . added email display function - mangles email addrs so they're not so easily
+#    scraped from the web
+#
 # Revision 1.15  2002/07/08 06:39:00  richard
 # Fixed unit test support class so the tests ran again.
 #