I've been experimenting with creating virtual fields and have come across 
what may be a possible bug when
they are created via old style (class definitions). 

I created a small table with 3 fields (ID, Name and dob). I've added some 
virtual fields to compute the age in days using all the options defined in 
the docs.  
http://web2py.com/books/default/chapter/29/6?search=virtual+fields#Virtual-fields

I see the following (unexpected results) (See the test code below)

1) For old style (class defined vf's) - Results returned from virtual 
fields computations are incorrect. The same value for all records is shown 
- 
(the last value in the table is displayed in each case)

2) For New style vfs: - Correct results are returned:

Is there bug in my code, or has anyone seen this behaviour before?

Below is sample o/p from my tests and the test program

Vclass : name: fred; dayage: 34427
Vclass : name: joe; dayage: 18730
Vclass : name: harry; dayage: 15382

Name: fred; DOB: 1917-11-10 12:00:00;
 **** Using VF Class:   Age (class): 15382; Age(Lazy); 15382; Age(Lazy 
Lambda): 15382
 **** Using New Style VFs: Age (new style): 34427; Age(new style (Lazy)); 
34427 

Name: joe; DOB: 1960-11-01 12:00:00;
 **** Using VF Class:   Age (class): 15382; Age(Lazy); 15382; Age(Lazy 
Lambda): 15382
 **** Using New Style VFs: Age (new style): 18730; Age(new style (Lazy)); 
18730 

Name: harry; DOB: 1970-01-01 12:00:00;
 **** Using VF Class:   Age (class): 15382; Age(Lazy); 15382; Age(Lazy 
Lambda): 15382
 **** Using New Style VFs: Age (new style): 15382; Age(new style (Lazy)); 
15382 


****** Test Code ******

import os, sys
sdir = '/home/web2py'
sys.path.append(sdir)

try:    
    from gluon import DAL, Field
except ImportError as err:
    print('gluon path not found')
    
# target db - sqlite    
db = DAL("sqlite://mydb.sqlite")    

# define view/table
##################
#
# db view testing
# define some virtual fields here (psa stale, fustale)
#
##################
db.define_table('person',
    Field('name', type='string'),
    Field('dob', type='datetime'),
    migrate=False)

import datetime
now = datetime.datetime.now()

# define new style virtual fields - age in days (aid)
db.person.virtual_aid =Field.Virtual(lambda row : (now - 
row.person.dob).days )
db.person.lazy_aid =Field.Lazy(lambda row : (now - row.person.dob).days )
 
# lambda version
class   MyVf(object):

    # define a new virtual field value
    def vfclass_aid(self):
        self.daycount = (now - self.person.dob).days
        print 'Vclass : dayage: %s' %self.daycount
        return lambda : self.daycount
    
    # define a lazy vf
    def vfclass_lazy_aid(self):
        def lazy(self=self):
            return (now - self.person.dob).days
        return lazy
    
    # define a lazy lambda vf
    def vfclass_lazy_lambda_aid(self):
            return lambda self= self: (now - self.person.dob).days
                        
if __name__ == "__main__":
    
    import datetime
    dtstart = datetime.datetime.now()
    print '\n>>>>Starting at: %s <<<<\n' %dtstart.ctime()
            
    # create virtual field (using a class)
    db.person.virtualfields.append(MyVf())    
    
    for item in db(db.person).select():
        print '\nName: %s; DOB: %s;'%(item.name, item.dob)
        print '\t **** Using VF Class:  \t\tAge (class): %s;\t\tAge(Lazy); 
%s;\t Age(Lazy Lambda): %s' \
                %(item.vfclass_aid(), item.vfclass_lazy_aid(), 
item.vfclass_lazy_lambda_aid() )
        
        print '\t **** Using New Style VFs: \tAge (new style): %s; 
\tAge(new style (Lazy)); %s ' \
                %(item.virtual_aid, item.lazy_aid())
                
        
    dtend = datetime.datetime.now()
    print '\n>>>>Ending at: %s <<<<\n' %dtend.ctime()
        



Reply via email to