Skip to content

Commit 9f5210e

Browse files
committed
New Link / Multilink option "try_id_parsing"
1 parent c1198b5 commit 9f5210e

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

CHANGES.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ Features:
2626
much better to use timezone names. (Thomas Arendsen Hein)
2727
- issue2550793: Wrap messages with very long lines in the web interface.
2828
(Thomas Arendsen Hein)
29+
- New Link / Multilink option "try_id_parsing": Sometimes the key of a
30+
class can be numeric -- in that case roundup will try to parse the
31+
value as an ID when evaluating form values -- not as a key. Specifying
32+
try_id_parsing='no' for these Link/Multilink will skip the ID step,
33+
default is 'yes'.
2934

3035
Fixed:
3136

roundup/hyperdb.py

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -127,13 +127,19 @@ def sort_repr (self, cls, val, name):
127127
class _Pointer(_Type):
128128
"""An object designating a Pointer property that links or multilinks
129129
to a node in a specified class."""
130-
def __init__(self, classname, do_journal='yes', required=False,
131-
default_value = None):
132-
""" Default is to journal link and unlink events
130+
def __init__(self, classname, do_journal='yes', try_id_parsing='yes',
131+
required=False, default_value=None):
132+
""" Default is to journal link and unlink events.
133+
When try_id_parsing is false, we don't allow IDs in input
134+
fields (the key of the Link or Multilink property must be
135+
given instead). This is useful when the name of a property
136+
can be numeric. It will only work if the linked item has a
137+
key property and is a questionable feature for multilinks.
133138
"""
134139
super(_Pointer, self).__init__(required, default_value)
135140
self.classname = classname
136141
self.do_journal = do_journal == 'yes'
142+
self.try_id_parsing = try_id_parsing == 'yes'
137143
def __repr__(self):
138144
"""more useful for dumps. But beware: This is also used in schema
139145
storage in SQL backends!
@@ -145,10 +151,13 @@ class Link(_Pointer):
145151
"""An object designating a Link property that links to a
146152
node in a specified class."""
147153
def from_raw(self, value, db, propname, **kw):
148-
if value == '-1' or not value:
154+
if (self.try_id_parsing and value == '-1') or not value:
149155
value = None
150156
else:
151-
value = convertLinkValue(db, propname, self, value)
157+
if self.try_id_parsing:
158+
value = convertLinkValue(db, propname, self, value)
159+
else:
160+
value = convertLinkValue(db, propname, self, value, None)
152161
return value
153162
def sort_repr (self, cls, val, name):
154163
if not val:
@@ -213,7 +222,10 @@ def from_raw(self, value, db, klass, propname, itemid, **kw):
213222
do_set = 0
214223

215224
# look up the value
216-
itemid = convertLinkValue(db, propname, self, item)
225+
if self.try_id_parsing:
226+
itemid = convertLinkValue(db, propname, self, item)
227+
else:
228+
itemid = convertLinkValue(db, propname, self, item, None)
217229

218230
# perform the add/remove
219231
if remove:
@@ -1356,7 +1368,7 @@ class HyperdbValueError(ValueError):
13561368
def convertLinkValue(db, propname, prop, value, idre=re.compile('^\d+$')):
13571369
""" Convert the link value (may be id or key value) to an id value. """
13581370
linkcl = db.classes[prop.classname]
1359-
if not idre.match(value):
1371+
if not idre or not idre.match(value):
13601372
if linkcl.getkey():
13611373
try:
13621374
value = linkcl.lookup(value)

test/test_hyperdbvals.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def getprops(self):
2323
'date': hyperdb.Date(),
2424
'interval': hyperdb.Interval(),
2525
'link': hyperdb.Link('test'),
26+
'linkkeyonly': hyperdb.Link('test', try_id_parsing='no'),
2627
'link2': hyperdb.Link('test2'),
2728
'multilink': hyperdb.Multilink('test'),
2829
'multilink2': hyperdb.Multilink('test2'),
@@ -104,11 +105,15 @@ def testInterval(self):
104105
self.assertRaises(hyperdb.HyperdbValueError, self._test, 'interval',
105106
'fubar')
106107
def testLink(self):
107-
self.assertEqual(self._test('password', ''), None)
108108
self.assertEqual(self._test('link', '1'), '1')
109109
self.assertEqual(self._test('link', 'valid'), '1')
110+
self.assertEqual(self._test('linkkeyonly', 'valid'), '1')
110111
self.assertRaises(hyperdb.HyperdbValueError, self._test, 'link',
111112
'invalid')
113+
self.assertRaises(hyperdb.HyperdbValueError, self._test, 'linkkeyonly',
114+
'1')
115+
self.assertRaises(hyperdb.HyperdbValueError, self._test, 'linkkeyonly',
116+
'invalid')
112117
def testMultilink(self):
113118
self.assertEqual(self._test('multilink', '', '1'), [])
114119
self.assertEqual(self._test('multilink', '1', '1'), ['1'])

0 commit comments

Comments
 (0)