[gen] Bugfixes and use of Ref.autoref fto avoid circular references within cross-class Ref fields.
This commit is contained in:
parent
e1b6b1b951
commit
ef21375410
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -324,7 +324,6 @@ class ToolMixin(BaseMixin):
|
|||
|
||||
If p_refObject and p_refField are given, the query is limited to the
|
||||
objects that are referenced from p_refObject through p_refField.'''
|
||||
|
||||
params = {'ClassName': className}
|
||||
appyClass = self.getAppyClass(className, wrapper=True)
|
||||
if not brainsOnly: params['batch'] = True
|
||||
|
|
|
@ -874,19 +874,22 @@ class AbstractWrapper(object):
|
|||
replaced with normal chars.'''
|
||||
return normalizeString(s, usage)
|
||||
|
||||
def search(self, klass, sortBy='', maxResults=None, noSecurity=False,
|
||||
**fields):
|
||||
def search(self, klass, sortBy='', sortOrder='asc', maxResults=None,
|
||||
noSecurity=False, **fields):
|
||||
'''Searches objects of p_klass. p_sortBy must be the name of an indexed
|
||||
field (declared with indexed=True); every param in p_fields must
|
||||
take the name of an indexed field and take a possible value of this
|
||||
field. You can optionally specify a maximum number of results in
|
||||
p_maxResults. If p_noSecurity is specified, you get all objects,
|
||||
even if the logged user does not have the permission to view it.'''
|
||||
field (declared with indexed=True); p_sortOrder can be "asc"
|
||||
(ascending, the defaut) or "desc" (descending); every param in
|
||||
p_fields must take the name of an indexed field and take a possible
|
||||
value of this field. You can optionally specify a maximum number of
|
||||
results in p_maxResults. If p_noSecurity is specified, you get all
|
||||
objects, even if the logged user does not have the permission to
|
||||
view it.'''
|
||||
# Find the content type corresponding to p_klass
|
||||
tool = self.tool.o
|
||||
contentType = tool.getPortalType(klass)
|
||||
# Create the Search object
|
||||
search = Search('customSearch', sortBy=sortBy, **fields)
|
||||
search = Search('customSearch', sortBy=sortBy, sortOrder=sortOrder,
|
||||
**fields)
|
||||
if not maxResults:
|
||||
maxResults = 'NO_LIMIT'
|
||||
# If I let maxResults=None, only a subset of the results will be
|
||||
|
|
Loading…
Reference in a new issue