[gen] Bugfixes and use of Ref.autoref fto avoid circular references within cross-class Ref fields.

This commit is contained in:
Gaetan Delannay 2014-04-22 19:37:36 +02:00
parent e1b6b1b951
commit ef21375410
4 changed files with 60 additions and 30 deletions

View file

@ -1129,6 +1129,36 @@ def autoref(klass, field):
class A:
attr1 = Ref(None)
autoref(A, A.attr1)
This function can also be used to avoid circular imports between 2
classes from 2 different packages. Imagine class P1 in package p1 has a
Ref to class P2 in package p2; and class P2 has another Ref to p1.P1
(which is not the back Ref of the previous one: it is another,
independent Ref).
In p1, you have
from p2 import P2
class P1:
ref1 = Ref(P2)
Then, if you write the following in p2, python will complain because of a
circular import:
from p1 import P1
class P2:
ref2 = Ref(P1)
The solution is to write this. In p1:
from p2 import P2
class P1:
ref1 = Ref(P2)
autoref(P1, P2.ref2)
And, in p2:
class P2:
ref2 = Ref(None)
'''
field.klass = klass
setattr(klass, field.back.attribute, field.back)

View file

@ -332,23 +332,21 @@ class Transition:
if msgPart: msg += msgPart
return msg
def trigger(self, transitionName, obj, wf, comment, doAction=True,
doNotify=True, doHistory=True, doSay=True, reindex=True,
noSecurity=False):
'''This method triggers this transition on p_obj. The transition is
supposed to be triggerable (call to self.isTriggerable must have been
performed before calling this method). If p_doAction is False, the
action that must normally be executed after the transition has been
triggered will not be executed. If p_doNotify is False, the
email notifications that must normally be launched after the
transition has been triggered will not be launched. If p_doHistory is
False, there will be no trace from this transition triggering in the
workflow history. If p_doSay is False, we consider the transition is
trigger programmatically, and no message is returned to the user.
If p_reindex is False, object reindexing will be performed by the
calling method.'''
# Security check
if not noSecurity and not self.isTriggerable(obj, wf):
def trigger(self, name, obj, wf, comment, doAction=True, doNotify=True,
doHistory=True, doSay=True, reindex=True, noSecurity=False):
'''This method triggers this transition (named p_name) on p_obj. If
p_doAction is False, the action that must normally be executed after
the transition has been triggered will not be executed. If p_doNotify
is False, the email notifications that must normally be launched
after the transition has been triggered will not be launched. If
p_doHistory is False, there will be no trace from this transition
triggering in the workflow history. If p_doSay is False, we consider
the transition is triggered programmatically, and no message is
returned to the user. If p_reindex is False, object reindexing will
be performed by the calling method.'''
# "Triggerability" and security checks.
if (name != '_init_') and \
not self.isTriggerable(obj, wf, noSecurity=noSecurity):
raise Exception('Transition "%s" can\'t be triggered.' % name)
# Create the workflow_history dict if it does not exist.
if not hasattr(obj.aq_base, 'workflow_history'):
@ -371,8 +369,8 @@ class Transition:
targetStateName = targetState.getName(wf)
break
# Create the event and add it in the object history
action = transitionName
if transitionName == '_init_': action = None
action = name
if name == '_init_': action = None
if not doHistory: comment = '_invisible_'
obj.addHistoryEvent(action, review_state=targetStateName,
comments=comment)
@ -384,9 +382,9 @@ class Transition:
if reindex and not obj.isTemporary(): obj.reindex()
# Send notifications if needed
if doNotify and self.notify and obj.getTool(True).mailEnabled:
sendNotification(obj.appy(), self, transitionName, wf)
sendNotification(obj.appy(), self, name, wf)
# Return a message to the user if needed
if not doSay or (transitionName == '_init_'): return
if not doSay or (name == '_init_'): return
if not msg: msg = obj.translate('object_saved')
obj.say(msg)