[Zope] need lesson in zope's OO architecture
Dieter Maurer
dieter at handshake.de
Tue Jul 27 15:33:42 EDT 2004
friedrich steindl wrote at 2004-7-26 22:24 +0200:
> ...
>for better control of these special objects i built a special folder, which
>holds those objects
>
>my problem -
>
>when my special folder is subfolder of a normal folder, and this normal folder
>is renamed, the rename method of the above normal folder is triggered
>
>but a rename does deletion of the children object and creates a new one
A "rename" does not delete the object (nor the children thereof).
>that means _my_ delObject() from special folder and special objects is
>executed and kills my external data )-:
Your "_delObject" is not called -- unless you do it in
"manage_beforeDelete"...
> ...
>def manage_renameObject(self, id, new_id, REQUEST=None):
> ...
> ...
> ob=self._getOb(id)
> ...
> ...
> self._delObject(id) ## this destroys my external data
This does not delete the object but just removes it from "self" --
and it calls the object's "manage_beforeDelete".
>From your description, the "_delObject" above is not your
"_delObject" but the (normal) "_delObject" of a (normal) folder
> ...
>the problem seems for me that methods from parent container take actions on
>their children
They do not do this.
However, they call the childrens "manage_beforeDelete" method
such that they can take appropriate actions (such as uncataloguing, for
example).
Unfortunately, the "manage_afterAdd/manage_beforeDelete" protocol
is too weakly implemented. These hook are not informed
whether the delete comes from a true deletion or instead
a rename or move (and analoguously for add).
Therefore, I was forced to implement an extension, described as
follows:
'''Enhanced Copy Support.
Zopes standard copy support is quite weak.
Its calling of 'manage_afterAdd', 'manage_beforeDelete' and 'manage_afterClone'
is not distinguished enough for copying versus moving on one hand
and moving versus deleting on the other hand.
Standard Zope calls (maybe indirectly):
creation - 'manage_afterAdd' (via '_setObject')
copying - '_getCopy',
'manage_afterAdd' (via '_setObject'),
'manage_afterClone'
moving(renaming) - 'manage_beforeDelete' (via '_delObject'),
'manage_afterAdd' (via '_setObject'),
deleting - 'manage_beforeDelete' (via '_delObject')
The enhanced copy support adds the attribute
'_v_EnhancedCopySupport__Operation' to the
copied/moved object. Its value is 'COPY' for a copy operation
and 'MOVE' for a move operation. For creation and deletion
the attribute is not defined.
This allows 'manage_afterAdd' and 'manage_beforeDelete' to
check in which context they are used.
We still do not distinguish between creation and import.
The enhancements are instantiated via 'monkey patching'.
**ATT**: it may come too late, to be effective everywhere.
'''
The implementation looks like this:
def manage_pasteObjects(...):
...
ob._p_sticky = 1 # prevent "_v_" loss
ob._v_EnhancedCopySupport__Operation= COPY
try:
self._setObject(id, ob)
finally: del ob._v_EnhancedCopySupport__Operation
...
def manage_renameObject(...):
...
ob._p_sticky = 1 # prevent "_v_" loss
ob._v_EnhancedCopySupport__Operation= MOVE
try:
self._delObject(id)
ob = aq_base(ob)
ob._setId(new_id)
# Note - because a rename always keeps the same context, we
# can just leave the ownership info unchanged.
self._setObject(new_id, ob, set_owner=0)
finally: del ob._v_EnhancedCopySupport__Operation
...
...
Note that in order to make this extension safe against
subtransactions (which may discard "_v_" attributes),
you need my ZODB "_p_sticky" extension.
I posted it as a patch to "zodb-dev at zope.org" (--> mailing list
archive). While the "CopySupport" enhancement can be
installed as a "monkey patch", the "_p_sticky" extension
is partly C level and requires your own ZODB version...
--
Dieter
More information about the Zope
mailing list