Sorry, I just saw that you had to revert the change, most probably because it makes test_dal.py fail. Row and Reference are callable() as well! This patch passes the tests but unfortunately doesn't make represent() look any nicer.
diff -r 7c6da73479e7 gluon/dal.py --- a/gluon/dal.py Wed Jan 26 22:48:10 2011 -0600 +++ b/gluon/dal.py Thu Jan 27 15:54:20 2011 +0100 @@ -1070,7 +1070,7 @@ return self.log_execute(*a, **b) def represent(self, obj, fieldtype): - if isinstance(obj,(types.LambdaType,types.FunctionType)): + if callable(obj) and not isinstance(obj, (Row, Reference)): obj = obj() if isinstance(fieldtype, SQLCustomType): return fieldtype.encoder(obj) @@ -2307,7 +2307,7 @@ class NoSQLAdapter(BaseAdapter): def represent(self, obj, fieldtype): - if isinstance(obj,(types.LambdaType,types.FunctionType)): + if callable(obj) and not isinstance(obj, (Row, Reference)): obj = obj() if isinstance(fieldtype, SQLCustomType): return fieldtype.encoder(obj) I didn't look deep into this but maybe it would help a lot to subclass Field (StringField, IntegerField, BooleanField, ReferenceField,...). It could well remove the if cascades from represent(), parse() - seems like these are the "hot spots". Of course this is not an easy thing to do and as I understand dal has just been redesigned. Cheers, Bernd On 26 Jan., 01:36, Bernd Rothert <roth...@googlemail.com> wrote: > A table definition from the DAL chapter of the Web2py book: > > db.define_table('person', > Field('uuid', length=64, default=uuid.uuid4()), > Field('modified_on', 'datetime', default=now), > Field('name'), > format='%(name)s') > > "now" usually contains the current datetime from request.now and > that's fine but the default for "uuid" would be identical for all > inserts. Although the example doesn't use the default so it is not a > problem there. > > If you omit the parenthesis behind "default=uuid.uuid4()" and simple > pass the uuid4 function as the default it works as expected - the > default is evaluated at insert time and yields a fresh uuid for each > new record. I assume this is the intended behaviour although I > couldn't find it documented(!?). > > Strangely replacing "default=now" in the same way with e.g. > "default=datetime.datetime.now" does not work: > > now=datetime.datetime.now > db.define_table('person', > Field('uuid', length=64, default=uuid.uuid4), > Field('modified_on', 'datetime', default=now), > Field('name'), > format='%(name)s') > > db.person.insert(name='Ernie') > db.person.insert(name='Bert') > > db(db.person).select() > > >>> ValueError: invalid literal for int() with base 10: '<built' > > Umm,... > > db.executesql(db(db.person)._select())>>> [(1, > > u'b35cc052-3800-42a9-b7eb-bb9bc8ada271', > u'<built-in method now of type object at 0x37c520>', > u'Ernie'), > (2, > u'003ab438-f3aa-4474-8c24-b07d85406930', > u'<built-in method now of type object at 0x37c520>', > u'Bert')] > > (only works with Sqlite - MySQL would throw an error earlier) > > I think this check in BaseAdapter.represent (dal.py) is the culprit: > > def represent(self, obj, fieldtype): > if type(obj) in (types.LambdaType, types.FunctionType): > obj = obj() > > print type(datetime.datetime.now) in (types.LambdaType, > types.FunctionType) > > >>> False > > This version lets you use any callable for generating "dynamic" > default values (plus it's 3-4 times faster): > > def represent(self, obj, fieldtype): > if callable(obj): > obj = obj() > > I hope this doesn't cause any side effects - at least I could not find > any (at this late/early hour)... > > Thanks