[Checkins] SVN: hurry.workflow/trunk/ turn WorkflowInfo.info() and WorkflowInfo.state() functions into classmethods as they are not of much use otherwise

Jan-Wijbrand Kolman janwijbrand at gmail.com
Mon May 2 09:25:50 EDT 2011


Log message for revision 121510:
  turn WorkflowInfo.info() and WorkflowInfo.state() functions into classmethods as they are not of much use otherwise

Changed:
  U   hurry.workflow/trunk/CHANGES.txt
  U   hurry.workflow/trunk/buildout.cfg
  U   hurry.workflow/trunk/src/hurry/workflow/workflow.py
  U   hurry.workflow/trunk/src/hurry/workflow/workflow.txt

-=-
Modified: hurry.workflow/trunk/CHANGES.txt
===================================================================
--- hurry.workflow/trunk/CHANGES.txt	2011-05-02 12:12:50 UTC (rev 121509)
+++ hurry.workflow/trunk/CHANGES.txt	2011-05-02 13:25:50 UTC (rev 121510)
@@ -1,12 +1,13 @@
+======================
 hurry.workflow changes
-**********************
+======================
 
 0.12 (unreleased)
 =================
 
-- Nothing changed yet.
+- Make the info() and state() functions on the WorkflowInfo class into
+  classmethods as they are not of much use otherwise.
 
-
 0.11 (2010-04-16)
 =================
 
@@ -44,7 +45,7 @@
 Bug fixes
 ---------
 
-* zope.security changes broke imports in hurry.workflow. 
+* zope.security changes broke imports in hurry.workflow.
 
 * localUtility directive is now deprecated, so don't use it anymore.
 

Modified: hurry.workflow/trunk/buildout.cfg
===================================================================
--- hurry.workflow/trunk/buildout.cfg	2011-05-02 12:12:50 UTC (rev 121509)
+++ hurry.workflow/trunk/buildout.cfg	2011-05-02 13:25:50 UTC (rev 121510)
@@ -1,9 +1,9 @@
 [buildout]
-develop = . 
+develop = .
 parts = test
 newest = false
 
 [test]
 recipe = zc.recipe.testrunner
 eggs = hurry.workflow [test]
-defaults = ['--tests-pattern', '^f?tests$', '-v']
+defaults = ['--tests-pattern', '^f?tests$', '-v', '--auto-color']

Modified: hurry.workflow/trunk/src/hurry/workflow/workflow.py
===================================================================
--- hurry.workflow/trunk/src/hurry/workflow/workflow.py	2011-05-02 12:12:50 UTC (rev 121509)
+++ hurry.workflow/trunk/src/hurry/workflow/workflow.py	2011-05-02 13:25:50 UTC (rev 121510)
@@ -48,7 +48,7 @@
         self.permission = permission
         self.order = order
         self.user_data = user_data
-        
+
     def __cmp__(self, other):
         return cmp(self.order, other.order)
 
@@ -59,7 +59,7 @@
 # mixes these in if you need persistent workflow
 class Workflow(object):
     implements(IWorkflow)
-    
+
     def __init__(self, transitions):
         self.refresh(transitions)
 
@@ -74,13 +74,13 @@
         for transition in transitions:
             self._register(transition)
         self._p_changed = True
-        
+
     def getTransitions(self, source):
         try:
             return self._sources[source].values()
         except KeyError:
             return []
-        
+
     def getTransition(self, source, transition_id):
         transition = self._id_transitions[transition_id]
         if transition.source != source:
@@ -106,34 +106,36 @@
         wf_versions = component.queryUtility(IWorkflowVersions)
         if wf_versions is not None:
             self.setId(wf_versions.createVersionId())
-        
+
     def setState(self, state):
         if state != self.getState():
             self._annotations[self.state_key] = state
-            
+
     def setId(self, id):
         # XXX catalog should be informed (or should it?)
         self._annotations[self.id_key] = id
-        
+
     def getState(self):
         return self._annotations.get(self.state_key, None)
 
     def getId(self):
         return self._annotations.get(self.id_key, None)
-            
+
 class WorkflowInfo(object):
     implements(IWorkflowInfo)
     name = u''
-    
+
     def __init__(self, context):
         self.context = context
         self.wf = component.getUtility(IWorkflow, name=self.name)
 
-    def info(self, obj):
-        return component.getAdapter(obj, IWorkflowInfo, name=self.name)
+    @classmethod
+    def info(cls, obj):
+        return component.getAdapter(obj, IWorkflowInfo, name=cls.name)
 
-    def state(self, obj):
-        return component.getAdapter(obj, IWorkflowState, name=self.name)
+    @classmethod
+    def state(cls, obj):
+        return component.getAdapter(obj, IWorkflowState, name=cls.name)
 
     def fireTransition(self, transition_id, comment=None, side_effect=None,
                        check_security=True):
@@ -153,7 +155,7 @@
         if not checkPermission(
             transition.permission, self.context):
             raise Unauthorized(self.context,
-                               'transition: %s' % transition_id, 
+                               'transition: %s' % transition_id,
                                transition.permission)
         # now make sure transition can still work in this context
         if not transition.condition(self, self.context):
@@ -202,7 +204,7 @@
             raise interfaces.AmbiguousTransitionError
         return self.fireTransition(transition_ids[0],
                                    comment, side_effect, check_security)
-        
+
     def fireTransitionForVersions(self, state, transition_id):
         id = self.state(self.context).getId()
         wf_versions = component.getUtility(IWorkflowVersions)
@@ -223,12 +225,12 @@
                 # if we actually managed to fire a transition,
                 # we're done with this one now.
                 return
-            
+
     def hasVersion(self, state):
         wf_versions = component.getUtility(IWorkflowVersions)
         id = self.state(self.context).getId()
         return wf_versions.hasVersion(state, id)
-    
+
     def getManualTransitionIds(self):
         try:
             checkPermission = getInteraction().checkPermission
@@ -247,7 +249,7 @@
 
     def getFireableTransitionIds(self):
         return self.getManualTransitionIds() + self.getSystemTransitionIds()
-    
+
     def getFireableTransitionIdsToward(self, state):
         result = []
         for transition_id in self.getFireableTransitionIds():
@@ -255,7 +257,7 @@
             if transition.destination == state:
                 result.append(transition_id)
         return result
-    
+
     def getAutomaticTransitionIds(self):
         return [transition.transition_id for transition in
                 self._getTransitions(AUTOMATIC)]
@@ -272,7 +274,7 @@
         # transitions in this context, and return their ids
         return [transition for transition in transitions if
                 transition.trigger == trigger]
-            
+
 class WorkflowVersions(object):
     implements(IWorkflowVersions)
 

Modified: hurry.workflow/trunk/src/hurry/workflow/workflow.txt
===================================================================
--- hurry.workflow/trunk/src/hurry/workflow/workflow.txt	2011-05-02 12:12:50 UTC (rev 121509)
+++ hurry.workflow/trunk/src/hurry/workflow/workflow.txt	2011-05-02 13:25:50 UTC (rev 121510)
@@ -10,12 +10,12 @@
 Let's first make a content object that can go into a workflow::
 
    >>> from zope.interface import implements, Attribute
- 
+
    >>> from zope.annotation.interfaces import IAttributeAnnotatable
    >>> class IDocument(IAttributeAnnotatable):
    ...    title = Attribute('Title')
    >>> class Document(object):
-   ...    implements(IDocument) 
+   ...    implements(IDocument)
    ...    def __init__(self, title):
    ...        self.title = title
 
@@ -38,9 +38,9 @@
 
 But let's set it back to None again, so we can start again in a
 pristine state for this document::
- 
+
     >>> state.setState(None)
- 
+
 It's not recommended use setState() do this ourselves, though: usually
 we'll let the workflow system take care of state transitions and the
 setting of the initial state.
@@ -59,14 +59,14 @@
 
 Now let's construct a transition::
 
-    >>> from hurry.workflow import workflow 
-    >>> transition = workflow.Transition( 
-    ...     transition_id='a_to_b', 
-    ...     title='A to B', 
-    ...     source='a', 
-    ...     destination='b', 
-    ...     condition=NullCondition, 
-    ...     action=NullAction, 
+    >>> from hurry.workflow import workflow
+    >>> transition = workflow.Transition(
+    ...     transition_id='a_to_b',
+    ...     title='A to B',
+    ...     source='a',
+    ...     destination='b',
+    ...     condition=NullCondition,
+    ...     action=NullAction,
     ...     trigger=interfaces.MANUAL)
 
 The transition trigger is either MANUAL, AUTOMATIC or SYSTEM. MANUAL
@@ -91,7 +91,7 @@
     ...     title='Delete',
     ...     source='b',
     ...     destination=None)
- 
+
 Now let's put the transitions in an workflow utility::
 
     >>> wf = workflow.Workflow([transition, init_transition, final_transition])
@@ -260,6 +260,21 @@
     >>> state.getState()
     'paid'
 
+To make it easier to get the state and info adapters for a particular context
+object, there are two convenience functions on the workflow info object. The
+info object "knows" what workflow utility to look for, as they are associated
+by name::
+
+    >>> info_ = InvoiceWorkflowInfo.info(invoice)
+    >>> interfaces.IWorkflowInfo.providedBy(info_)
+    True
+
+    >>> state_ = InvoiceWorkflowInfo.state(invoice)
+    >>> interfaces.IWorkflowState.providedBy(state_)
+    True
+    >>> state.getState() is state_.getState()
+    True
+
 Of course, this document always have the default unnamed workflow::
 
     >>> info = interfaces.IWorkflowInfo(invoice)
@@ -268,7 +283,6 @@
     >>> state.getState()
     'a'
 
-   
 Multi-version workflow
 ----------------------
 
@@ -358,9 +372,9 @@
 from the CLOSED version::
 
    >>> def CanCopyCondition(wf, context):
-   ...     return (not wf.hasVersion(UNPUBLISHED) and 
+   ...     return (not wf.hasVersion(UNPUBLISHED) and
    ...         not wf.hasVersion(PUBLISHED))
- 
+
    >>> copy_closed_transition = workflow.Transition(
    ...     transition_id='copy_closed',
    ...     title='Copy',
@@ -385,7 +399,7 @@
 
 Now let's build and provide the workflow utility::
 
-   >>> wf = workflow.Workflow([init_transition, 
+   >>> wf = workflow.Workflow([init_transition,
    ...                         publish_transition, close_transition,
    ...                         copy_transition, copy_closed_transition,
    ...                         archive_transition])
@@ -499,9 +513,9 @@
 
   >>> interfaces.IWorkflowState(document3).getState()
   'published'
- 
+
 And the previously published version is now closed::
-  
+
   >>> interfaces.IWorkflowState(document2).getState()
   'closed'
 
@@ -576,7 +590,7 @@
    >>> workflow_versions.fireAutomatic()
 
 Nothing should have happened as we are still at time moment 0::
-  
+
    >>> state = interfaces.IWorkflowState(document)
    >>> state.getState()
    'unpublished'
@@ -590,7 +604,7 @@
    >>> workflow_versions.fireAutomatic()
 
 The transition has fired, so the state will be 'published'::
- 
+
    >>> state.getState()
    'published'
 
@@ -696,8 +710,8 @@
 Now set up the workflow using these transitions, plus our
 init_transition::
 
-   >>> wf = workflow.Workflow([init_transition, 
-   ...     publish_1_transition, publish_2_transition, 
+   >>> wf = workflow.Workflow([init_transition,
+   ...     publish_1_transition, publish_2_transition,
    ...     publish_auto_transition])
    >>> component.provideUtility(wf, interfaces.IWorkflow)
 
@@ -746,12 +760,12 @@
 
 Let's set up the security context::
 
-   >>> from zope.security.interfaces import Unauthorized 
+   >>> from zope.security.interfaces import Unauthorized
    >>> from zope.security.management import newInteraction, endInteraction
    >>> class Principal:
    ...    def __init__(self, id):
    ...        self.id = id
-   ...        self.groups = [] 
+   ...        self.groups = []
    >>> class Participation:
    ...   interaction = None
    ...   def __init__(self, principal):
@@ -775,8 +789,8 @@
 
 The system user is however allowed to do it::
 
-   >>> from zope.security.management import system_user   
-   >>> endInteraction() 
+   >>> from zope.security.management import system_user
+   >>> endInteraction()
    >>> newInteraction(Participation(system_user))
    >>> info.fireTransition('publish')
 
@@ -804,7 +818,7 @@
 however, it would get information about the new copy *before* the
 editing took place. To allow an editing to take place between the
 creation of the new copy and the firing of the event, a side effect
-function can be passed along when a transition is fired. 
+function can be passed along when a transition is fired.
 
 The sequence of execution then is:
 
@@ -843,9 +857,9 @@
 Now fire the transition, with a side effect::
 
    >>> new_version = info.fireTransition('foo', side_effect=side_effect)
-   
+
 The title of the new version should now have a ! at the end::
-  
+
    >>> new_version.title[-1] == '!'
    True
 



More information about the checkins mailing list