[Zope-dev] ZPatterns; possible bug?

Steve Alexander steve@cat-box.net
Thu, 04 Jan 2001 18:03:11 +0000


I have a specialist "Instructors".

It holds a rack, containing DataSkin-derived ZClasses of meta-type 
"Instructor".

The Instructor class has a DataSkin Attribute propertysheet called 
"Basic", and this has properties for forename, surname, address, areas.

I have some skinscript in the Instructors specialist:


WITH SELF COMPUTE
   name='%s %s' % (forename, surname),
   areas_comma_sep=_.string.join(areas, ','),
   address_lines=_.string.join(address, '\n'),
   address_comma_sep=_.string.join(address, (', '))

WITH SELF COMPUTE
   __roles__=_.None
   # XXX publicly visible!! Nutter!!
   # change __roles__ to ('Operator',) later.

This works fine. The __roles__ bit is a hack to make Zope 2.3 ZCatalog 
play nicely with the Specialist and __bobo_traverse__.

I have some other skinscript that keeps an instructors index in a 
ZCatalog inside Instructors.

WHEN OBJECT ADDED CALL
   Catalog.catalog_object(self, _.string.join(self.getPhysicalPath(),'/'))
WHEN OBJECT DELETED CALL
   Catalog.uncatalog_object(_.string.join(self.getPhysicalPath(),'/'))
WHEN OBJECT CHANGED CALL
   Catalog.uncatalog_object(_.string.join(self.getPhysicalPath(),'/')),
   Catalog.catalog_object(self, _.string.join(self.getPhysicalPath(),'/'))

This worked fine.

When I changed the first skinscript to make one WITH SELF statement, I 
got some strange inconsistencies:

WITH SELF COMPUTE
   name='%s %s' % (forename, surname),
   areas_comma_sep=_.string.join(areas, ','),
   address_lines=_.string.join(address, '\n'),
   address_comma_sep=_.string.join(address, (', ')),
   __roles__=_.None

On changing an instructor's properties using manage_changeProperties on 
its propertysheet, I'd see the change in the instructor. However, the 
ZCatalog metadata would always have the most recent value for "surname", 
but the last value for "name".

Changing the skinscript back to using two statements makes cataloging 
function normally again.

I could tell when the catalog was doing by instrumenting the recordify 
method of Catalog.py:

     def recordify(self, object):
         """ turns an object into a record tuple """
         print "recordify %s" % (object)
         record = []
         # the unique id is allways the first element
         for x in self.names:
             try:
                 attr = getattr(object, x)
                 if(callable(attr)):
                     attr = attr()

             except:
                 attr = MV
             print "  appending %s:%s" % (x, attr)
             record.append(attr)

         return tuple(record)

A typical (wrong) debug output would be:

recordify <Instructor instance at 86c16b0>
   appending id:instructor-977678608
   appending meta_type:Instructor
   appending bobobase_modification_time:2001/01/04 17:26:01.35408 GMT
   appending name:Bob Collins8
   appending surname:Collins9
   appending areas_comma_sep:M12

This is after changing the surname of the instructor from "Collins8" to 
"Collins9".

The cause of the problem? I don't know. Maybe I'm doing something silly.

I think what is happening in the broken example is that when the zope 
security machinery asks for __roles__, name is also computed. The 
machinery must request __roles__ before changing anything.

After that, surname gets changed. However, changing "surname" only 
invalidates "surname" in the cache; not anything that is computed using 
surname.

At the end of the transaction, when the triggers are called, name is 
already in the dataskin's attribute cache, so it does not get recomputed.

In the working example, when __roles__ is requested, it is in a 
different skinscript statement, so it does not cause "name" to be 
computed. Thus, "name" can be computed freshly after "surname" is set.

Is this behaviour intended, is it a bug, or is it an unimplemented feature?

Thanks.


Oh, almost forgot: ZPatterns-0-4-3b2

--
Steve Alexander
Software Engineer
Cat-Box limited
http://www.cat-box.net

I