Prevent Acquisition From Acquiring Restricted Properties In Python
The design of ERP5 is based on implicit acquisition just as most of Zope 2.
However, ERP5 has its own way of considering acquisition. In ERP5, acquisition of
methods is considered as a good thing while acquisition of document properties is
considered as risky . This is why all properties defined in property sheets are set
to 'None' at the level of the class or at the level of the PropertyHolder instance
created by _aq_dynamic in Base class.
This way, acquisition is blocked on all properties defined by property sheets on
portal types. If one wants to acquire a given property from a parent object or
through a relation, this should be explicitly defined in property sheets. For
an example, see Amount.py.
A good example would be acquiring methods through context or through containment,
which is perfectly acceptable.
It is used for example to access the current WebSection with the method getWebSectionValue in
WebSection.py. It may be used also to display on a child object some
properties which are defined on its parent. This is considered as normal in ERP5.
The required use of accessors in ERP5 for getting and setting properties removes
most risks related to implicit acquisition in Zope.
The use of acquisition for properties should therefore be considered only for
implementation purpose and with great care. This following bad example (broken link) bug fix gives a very
good example of what can happen if one does not care enough about property
acquisition. Before this bug fix, 'getToolByName' was called on 'business_template'
and therefore included 'business_template' in its acquisition chain.
The new business template which was created shortly after by 'newContent' would then
also acquire 'business_template' properties. As a result, calling 'install' and
'uninstall' would install not only those items which were defined on the new
business template but also all items for which nothing was defined on the new
business template. This is because the way business template documents look up
for business template items consists in accessing private properties such as
'_message_translation_item' through 'getattr' rather than with an accessor.
This is perfectly acceptable in the context of ERP5 since such properties are
considered as private or implementation related and we do not want to force
implementors to use accessors at this level. However, it has risks. The risk
in this case was to massively destroy installed scripts and forms in an ERP5
site in case of revert operation (and retrieve them later thanks to the portal_trash).
The bug fix consisted in removing the acquisition context of 'business_template'
by invoking 'getPortalObject()'.
To prevent further risk, we have set all private properties to None on the
BusinessTemplate.py class with the following. This is a
kind of application of the another principle, to write code
that works even if all else fails.