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

Reply via email to