Your script doesn't behave like expected, though the
syntax is correct and code looks sane. Here are some tricky things which
can explain its observed behaviour.
"is" usage
Python "is" keyword gives unexpected results when comparing objects.
>>> context.foo is context.foo
False
This is because foo object is wrapped by zope at access in an acquisition wrapper, and that acquisition wrapper is generated at every access. A possible solution if you want to stick to "is" keyword would be
>>> from Acquisition import aq_base
>>> aq_base(context.foo) is aq_base(context.foo)
True
But
be reminded that this relies on zope's object cache behaviour: if one
day it decides to cache multiple versions of the same object from the
point of view of a given thread, this test will fail. Another
possibility, if you can access it, is to check for object's oid, but it
requires at least a (sub) transaction to have been commited since object
was created, and oid is not directly available from restricted
environment.
General acquisition warning
When accessing any object, be prepared to get trapped by acquisition. Accessing successfully foo from bar does not mean the foo was the object you were searching for in the first place. This
is espacially tricky in categories when the same structure is repeated
among multiples "brothers" trees, with some exceptions. For example, the
following structure (taken from ERP5Banking unit tests) can easily mislead the programer into thinking his code works:
Here,
accessing testsite/siege/caveau will end up with testsite/caveau object
inside an "unusual" acquisition context which will make getParentValue
use tricky.
Another example:
getattr(context.portal_categories.testsite.paris, "another_id", None)
will return None, unless another_id can be acquired from context. In this case, it's recommanded to start from the portal object, using:
getattr(context.getPortalObject().portal_categories.testsite.paris, "another_id", None)