ZPatterns -- trigger add events not working
I have a GenericTrigger in a Folder with Customizer support. When I set it to trigger upon Add, my method doesn't get triggered when I add a new DataSkin-derived-ZClass instance. However, when I set it to trigger on Change, my method gets called on adding a new DataSkin. I can't see anything obviously amiss in the ZPatterns code. I've inserted print statements into the _objectChanging() and _objectAdding() methods of DataManagers.DataManager. It seems that when I add a DataSkin-derived-ZClass, it gets added and also changed set in a single transaction, and only one of them gets reported to the trigger. Strangely, the call to _objectChanging() comes before the call to _objectAdding(). Is this a bug, or is it the expected behaviour? Thanks. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
At 09:29 PM 7/11/00 +0100, Steve Alexander wrote:
I've inserted print statements into the _objectChanging() and _objectAdding() methods of DataManagers.DataManager. It seems that when I add a DataSkin-derived-ZClass, it gets added and also changed set in a single transaction, and only one of them gets reported to the trigger.
Hm. That's a bug, since if an object is changed and added, it should only get the *add* event, not the change event.
Strangely, the call to _objectChanging() comes before the call to _objectAdding().
This would explain why you only get a change event, since if add happens after change, it is ignored. I'm curious how the change event is getting called first, since... Oh. I'll bet I know what it is. It's probably that manage_afterAdd is being called later in the ObjectManager code than it used to be, and/or Zope is trying to set an _owner attribute on the newly added object. Crap. This is going to take some rethinking to find another way to trap the Zope "add" event. :(
"Phillip J. Eby" wrote:
This would explain why you only get a change event, since if add happens after change, it is ignored. I'm curious how the change event is getting called first, since... Oh. I'll bet I know what it is. It's probably that manage_afterAdd is being called later in the ObjectManager code than it used to be, and/or Zope is trying to set an _owner attribute on the newly added object. Crap. This is going to take some rethinking to find another way to trap the Zope "add" event. :(
If it saves you any time, here's part of a traceback from an exception raised in _objectChanging(): File /lib/python/ZClasses/ZClass.py, line 466, in createInObjectManager File /lib/python/OFS/ObjectManager.py, line 258, in _setObject File /lib/python/AccessControl/Role.py, line 393, in manage_setLocalRoles Looks like you're right -- manage_setLocalRoles. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Steve Alexander wrote:
"Phillip J. Eby" wrote:
This would explain why you only get a change event, since if add happens after change, it is ignored. I'm curious how the change event is getting called first, since... Oh. I'll bet I know what it is. It's probably that manage_afterAdd is being called later in the ObjectManager code than it used to be, and/or Zope is trying to set an _owner attribute on the newly added object. Crap. This is going to take some rethinking to find another way to trap the Zope "add" event. :(
If it saves you any time, here's part of a traceback from an exception raised in _objectChanging():
File /lib/python/ZClasses/ZClass.py, line 466, in createInObjectManager File /lib/python/OFS/ObjectManager.py, line 258, in _setObject File /lib/python/AccessControl/Role.py, line 393, in manage_setLocalRoles
Looks like you're right -- manage_setLocalRoles.
I have patched the _objectAdding method of class Agent in Agents.py: def _objectAdding(self,client, _id=_id): print "_objectAdding" i = _id(client) l = self._v_tranlog c = l.get(i) if c is None: l[i] = AddedStatus, client, None return s,c,m = c # XXX Hack to make "add" triggers work if s is ChangedStatus: l[i] = AddedStatus, client, m # XXX if s is DeletedStatus: l[i] = ChangedStatus, client, m return I'm not sure whether this will have any nasty side-effects though. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
It could cause a problem if the object is added after any other sort of change from the point of view of the Agent. The Agent would view it as having been added, when in fact it is actually merely changed. I have not, however, been able to think of any scenario where this condition could occur unless the DataManager containing the Agent was itself being reconfigured during the same transaction as the other events, which is an "all bets are off, hold onto your butts" type proposition anyhow. My guess is that your patch will probably work fine. I've checked it in locally and will incorporate it into a release soon. At 04:09 PM 7/12/00 +0100, Steve Alexander wrote:
Steve Alexander wrote:
"Phillip J. Eby" wrote:
This would explain why you only get a change event, since if add happens after change, it is ignored. I'm curious how the change event is getting called first, since... Oh. I'll bet I know what it is. It's probably that manage_afterAdd is being called later in the ObjectManager code than it used to be, and/or Zope is trying to set an _owner attribute on the newly added object. Crap. This is going to take some rethinking to find another way to trap the Zope "add" event. :(
Looks like you're right -- manage_setLocalRoles.
I have patched the _objectAdding method of class Agent in Agents.py:
...
I'm not sure whether this will have any nasty side-effects though.
"Phillip J. Eby" wrote:
It could cause a problem if the object is added after any other sort of change from the point of view of the Agent. The Agent would view it as having been added, when in fact it is actually merely changed. I have not, however, been able to think of any scenario where this condition could occur unless the DataManager containing the Agent was itself being reconfigured during the same transaction as the other events, which is an "all bets are off, hold onto your butts" type proposition anyhow.
My guess is that your patch will probably work fine. I've checked it in locally and will incorporate it into a release soon.
The other approach would be to hold a list of the events that have happened during a transaction, and have a simple set of rules (regular grammar, implemented as a state machine, or regular expression) for condensing a list of events into the overall description of the event. I just made this regular grammar up without thinking particularly hard about them. The letters D, C, A stand for Delete, Change and Add respectively. "C*" means zero or more repeated "C". C* : C CA : A DA : C AC : A C*D : D AD : D Then again, if you can't think of any but the most unlikely exceptions to the current simple algorithm, I'll go with that :-) -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
"Phillip J. Eby" wrote:
This would explain why you only get a change event, since if add happens after change, it is ignored. I'm curious how the change event is getting called first, since... Oh. I'll bet I know what it is. It's probably that manage_afterAdd is being called later in the ObjectManager code than it used to be, and/or Zope is trying to set an _owner attribute on the newly added object. Crap. This is going to take some rethinking to find another way to trap the Zope "add" event. :(
Is this a way around the problem, or am I only seeing half the picture :-) ? You could have a flag in DataSkin instances called _has_been_added. It is initially cleared. It gets set when manage_afterAdd is called on it. The DataSkin sends an _objectChanging event only if the _has_been_added flag is set. -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
Steve Alexander wrote:
You could have a flag in DataSkin instances called _has_been_added. It is initially cleared. It gets set when manage_afterAdd is called on it.
The DataSkin sends an _objectChanging event only if the _has_been_added flag is set.
Of course, the name of the attribute should be more like _v_has_been_added :-) -- Steve Alexander Software Engineer Cat-Box limited http://www.cat-box.net
participants (2)
-
Phillip J. Eby -
Steve Alexander