changeset 4877:2ba982dcdf2c

New Link / Multilink option "try_id_parsing"
author Ralf Schlatterbeck <rsc@runtux.com>
date Fri, 28 Mar 2014 16:47:36 +0100
parents 74b24b14071a
children f6e76a03b502
files CHANGES.txt roundup/hyperdb.py test/test_hyperdbvals.py
diffstat 3 files changed, 30 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/CHANGES.txt	Fri Mar 28 15:14:29 2014 +0100
+++ b/CHANGES.txt	Fri Mar 28 16:47:36 2014 +0100
@@ -26,6 +26,11 @@
   much better to use timezone names. (Thomas Arendsen Hein)
 - issue2550793: Wrap messages with very long lines in the web interface.
   (Thomas Arendsen Hein)
+- New Link / Multilink option "try_id_parsing": Sometimes the key of a
+  class can be numeric -- in that case roundup will try to parse the
+  value as an ID when evaluating form values -- not as a key. Specifying
+  try_id_parsing='no' for these Link/Multilink will skip the ID step,
+  default is 'yes'.
 
 Fixed:
 
--- a/roundup/hyperdb.py	Fri Mar 28 15:14:29 2014 +0100
+++ b/roundup/hyperdb.py	Fri Mar 28 16:47:36 2014 +0100
@@ -127,13 +127,19 @@
 class _Pointer(_Type):
     """An object designating a Pointer property that links or multilinks
     to a node in a specified class."""
-    def __init__(self, classname, do_journal='yes', required=False,
-                 default_value = None):
-        """ Default is to journal link and unlink events
+    def __init__(self, classname, do_journal='yes', try_id_parsing='yes',
+                 required=False, default_value=None):
+        """ Default is to journal link and unlink events.
+            When try_id_parsing is false, we don't allow IDs in input
+            fields (the key of the Link or Multilink property must be
+            given instead). This is useful when the name of a property
+            can be numeric. It will only work if the linked item has a
+            key property and is a questionable feature for multilinks.
         """
         super(_Pointer, self).__init__(required, default_value)
         self.classname = classname
         self.do_journal = do_journal == 'yes'
+        self.try_id_parsing = try_id_parsing == 'yes'
     def __repr__(self):
         """more useful for dumps. But beware: This is also used in schema
         storage in SQL backends!
@@ -145,10 +151,13 @@
     """An object designating a Link property that links to a
        node in a specified class."""
     def from_raw(self, value, db, propname, **kw):
-        if value == '-1' or not value:
+        if (self.try_id_parsing and value == '-1') or not value:
             value = None
         else:
-            value = convertLinkValue(db, propname, self, value)
+            if self.try_id_parsing:
+                value = convertLinkValue(db, propname, self, value)
+            else:
+                value = convertLinkValue(db, propname, self, value, None)
         return value
     def sort_repr (self, cls, val, name):
         if not val:
@@ -213,7 +222,10 @@
                 do_set = 0
 
             # look up the value
-            itemid = convertLinkValue(db, propname, self, item)
+            if self.try_id_parsing:
+                itemid = convertLinkValue(db, propname, self, item)
+            else:
+                itemid = convertLinkValue(db, propname, self, item, None)
 
             # perform the add/remove
             if remove:
@@ -1356,7 +1368,7 @@
 def convertLinkValue(db, propname, prop, value, idre=re.compile('^\d+$')):
     """ Convert the link value (may be id or key value) to an id value. """
     linkcl = db.classes[prop.classname]
-    if not idre.match(value):
+    if not idre or not idre.match(value):
         if linkcl.getkey():
             try:
                 value = linkcl.lookup(value)
--- a/test/test_hyperdbvals.py	Fri Mar 28 15:14:29 2014 +0100
+++ b/test/test_hyperdbvals.py	Fri Mar 28 16:47:36 2014 +0100
@@ -23,6 +23,7 @@
             'date': hyperdb.Date(),
             'interval': hyperdb.Interval(),
             'link': hyperdb.Link('test'),
+            'linkkeyonly': hyperdb.Link('test', try_id_parsing='no'),
             'link2': hyperdb.Link('test2'),
             'multilink': hyperdb.Multilink('test'),
             'multilink2': hyperdb.Multilink('test2'),
@@ -104,11 +105,15 @@
         self.assertRaises(hyperdb.HyperdbValueError, self._test, 'interval',
             'fubar')
     def testLink(self):
-        self.assertEqual(self._test('password', ''), None)
         self.assertEqual(self._test('link', '1'), '1')
         self.assertEqual(self._test('link', 'valid'), '1')
+        self.assertEqual(self._test('linkkeyonly', 'valid'), '1')
         self.assertRaises(hyperdb.HyperdbValueError, self._test, 'link',
             'invalid')
+        self.assertRaises(hyperdb.HyperdbValueError, self._test, 'linkkeyonly',
+            '1')
+        self.assertRaises(hyperdb.HyperdbValueError, self._test, 'linkkeyonly',
+            'invalid')
     def testMultilink(self):
         self.assertEqual(self._test('multilink', '', '1'), [])
         self.assertEqual(self._test('multilink', '1', '1'), ['1'])

Roundup Issue Tracker: http://roundup-tracker.org/