[Zope-CVS] SVN: eventworkflow/ Initial import of the event
subscriber based
Thomas Förster
t.foerster at biologie.hu-berlin.de
Wed Oct 20 15:43:47 EDT 2004
Log message for revision 28222:
Initial import of the event subscriber based
workflow prototype from IsarSprint
Changed:
A eventworkflow/
A eventworkflow/branches/
A eventworkflow/tags/
A eventworkflow/trunk/
A eventworkflow/trunk/README.txt
A eventworkflow/trunk/__init__.py
A eventworkflow/trunk/doc/
A eventworkflow/trunk/doc/mappings.txt
A eventworkflow/trunk/doc/problems.txt
A eventworkflow/trunk/event.py
A eventworkflow/trunk/interfaces.py
A eventworkflow/trunk/publication/
A eventworkflow/trunk/publication/README.txt
A eventworkflow/trunk/publication/__init__.py
A eventworkflow/trunk/publication/configure.zcml
A eventworkflow/trunk/publication/definition.py
A eventworkflow/trunk/publication/interfaces.py
A eventworkflow/trunk/publication/simplesub.txt
A eventworkflow/trunk/publication/tests.py
A eventworkflow/trunk/review/
A eventworkflow/trunk/review/README.txt
A eventworkflow/trunk/review/__init__.py
A eventworkflow/trunk/review/configure.zcml
A eventworkflow/trunk/review/definition.py
A eventworkflow/trunk/review/interfaces.py
A eventworkflow/trunk/review/tests/
A eventworkflow/trunk/review/tests/__init__.py
A eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
A eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
A eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
A eventworkflow/trunk/review/tests/reviewprocess.txt
A eventworkflow/trunk/review/tests/setup.py
A eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
A eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
A eventworkflow/trunk/tests/
A eventworkflow/trunk/tests/__init__.py
A eventworkflow/trunk/tests/test_worklistUtility.py
A eventworkflow/trunk/worklist.py
-=-
Added: eventworkflow/trunk/README.txt
===================================================================
--- eventworkflow/trunk/README.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/README.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,9 @@
+Prototype for a subscriber based activity workflow (WfMC style)
+===============================================================
+
+This package contains a prototype for workflow definitions,
+that solely uses Zope's event subscriptions as the workflow "engine".
+It is meant as a proof of concept.
+
+The subpackages 'review' and 'publication' each contain a complete
+concrete workflow.
Property changes on: eventworkflow/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/__init__.py
===================================================================
--- eventworkflow/trunk/__init__.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/__init__.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,16 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+#
+# This file is necessary to make this directory a package.
+
Property changes on: eventworkflow/trunk/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/doc/mappings.txt
===================================================================
--- eventworkflow/trunk/doc/mappings.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/doc/mappings.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,49 @@
+Mappings of WfMC terms -> Zope3 Event Model
+=======================================
+
+ProcessDefinition and Activity(=ActivityDefinition) map to
+class definitions. That way its easy to instantiate them,
+meaning that ProcessInstance and ActivityInstance map to
+objects. Each Activity defines its own interface (mostly
+just a marker to subscribe to).
+
+A SubProcess is a ProcessInstance that behaves like an
+ActivityInstance in the parent process (see e.g. the reuse of the
+review workflow within the publication workflow) Storing of the
+results of the sub process can be done by a subscriber to
+ProcessFinishedEvent of the sub process.
+
+Transitions are subscribers to workflow related events (process
+started, activity finished, process finished, ...).
+
+Splits & Joins
+--------------
+
+Since you can control the starting of activities using the full
+expressive power of Python, implementing AND, OR, XOR-Splits is
+straight forward. Just start as many activity instances as
+needed.
+
+Joins are a bit more complicated:
+
+OR-Joins (1 of many parallel activities finished suffices to
+start next) can be modelled using a single subscriber which is
+subscribed to ActivityFinished events of multiple activities.
+State has to be tracked somewhere though, if the following
+activity should be fired once only.
+
+AND-Joins depend on the nature of the join condition
+
+a) If you just want to keep track that the all previous activities are
+finished you can put an annotation to the follow up activity which
+is generated in an inactive state. On meeting the precondition
+this instance is activated (i.e. generates the work items). The
+annotation stores the state of the join. A single multiple interface
+subscriber cares about tracking state and condition.
+
+b) The condition is about workflow data, so there is no need for the
+annotation. State is stored implicitly in the workflow data.
+A single subscriber is sufficient checking the precondition every
+time one of the previous activities finishes. There is no need for
+having a stateful follow up activity, since it is created after the
+precondition is met.
Property changes on: eventworkflow/trunk/doc/mappings.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/doc/problems.txt
===================================================================
--- eventworkflow/trunk/doc/problems.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/doc/problems.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,32 @@
+Areas in subscriber based workflow I (TF) feel uneasy about
+== i.e. need more brain storming
+
+Subprocesses
+------------
+
+A nested subprocess is mapped to a process that also implements
+IActivity. This naturally fits to the adapter model.
+
+I wasn't able yet to come up with an adapter solution though.
+
+Passing data from subprocess to parent process
+----------------------------------------------
+
+At the moment the data is just copied over the parents
+process data. No unique ids. No removal of attributes. E.g.
+there is the reviewComment data hanging around in the workflow data
+but it is obsolete when the object under review is accepted.
+
+AND Join
+--------
+
+The AND join is implemented using annotations. That requires
+stateful activities (inactive -> active). Maybe we could get
+around this storing the JOIN state somewhere else. Workflow data?
+Annotations to process instance?
+
+Workflow data handling
+----------------------
+
+This is a simple dict of the process instance as of now. Depending
+on the complexity of the data that might not be sufficient.
Property changes on: eventworkflow/trunk/doc/problems.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/event.py
===================================================================
--- eventworkflow/trunk/event.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/event.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import zope.interface
+import eventworkflow.interfaces
+
+from zope.app.event.objectevent import ObjectEvent
+
+class ProcessStartedEvent(ObjectEvent):
+ zope.interface.implements(eventworkflow.interfaces.IProcessStartedEvent)
+
+class ProcessFinishedEvent(ObjectEvent):
+ zope.interface.implements(eventworkflow.interfaces.IProcessFinishedEvent)
+
+class ActivityFinishedEvent(ObjectEvent):
+ zope.interface.implements(eventworkflow.interfaces.IActivityFinishedEvent)
+
+class WorkitemFinishedEvent(ObjectEvent):
+ zope.interface.implements(eventworkflow.interfaces.IWorkitemFinishedEvent)
Property changes on: eventworkflow/trunk/event.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/interfaces.py
===================================================================
--- eventworkflow/trunk/interfaces.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/interfaces.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,107 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import zope.interface
+from zope.app.annotation.interfaces import IAttributeAnnotatable
+
+import zope.app.event.interfaces
+
+### Event Interfaces
+class IActivityFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+ """Signal a finished activity"""
+
+class IProcessStartedEvent(zope.app.event.interfaces.IObjectEvent):
+ """Signal starting a process"""
+
+class IProcessFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+ """Signal finished process"""
+
+class IWorkitemFinishedEvent(zope.app.event.interfaces.IObjectEvent):
+ """Signal a finished workitem"""
+
+### WfMC type entities in a workflow
+# we're not heading for compliance yet
+class IProcess(zope.interface.Interface):
+ """An instance of a process (definition)
+
+ An IProcessStartedEvent is generated in the constructor.
+ """
+
+ activities = zope.interface.Attribute(
+ "list of current activities")
+
+ workflowData = zope.interface.Attribute(
+ "data associated with the process")
+
+class IActivity(zope.interface.Interface):
+ """An instance of a specific activity"""
+
+ processDefinition = zope.interface.Attribute(
+ "a reference to the process the activity belongs to")
+
+ def __init__(pi):
+ """constructs new instance
+
+ pi - process instance the activity belongs to
+ """
+
+class IJoiningActivity(IActivity, IAttributeAnnotatable):
+ """Activity that is activated after a join in the workflow
+
+ This is used for stateful activities, that are needed after
+ AND-joins without workflow data related preconditions, i.e.
+ all predecessors must be finished
+ """
+
+ state = zope.interface.Attribute(
+ "the state of the activity instance, one of waiting/active")
+
+ def activate():
+ """activate activity
+
+ activity instances start in a waiting state. This methods
+ propagates them to the active state and creates the
+ work items.
+ """
+
+
+class IWorklistUtility(zope.interface.Interface):
+ """Manage workitems in workflows"""
+
+ def addWorkitem(item):
+ """Add new IWorkitem"""
+
+ def itemsFor(principalId):
+ """Return list of all workitems for a principal
+
+ Returns empty list if no principal can be
+ retrieved for the given id. If the principal
+ belongs to groups, also the workitems assigned
+ to these groups are returned.
+ """
+
+class IWorkitem(zope.interface.Interface):
+ """A single workitem"""
+
+ activity = zope.interface.Attribute(
+ "activity this work item belongs to")
+
+ description = zope.schema.TextLine(
+ title = u'Description',
+ )
+
+ principals = zope.schema.List(
+ title = u"Principals",
+ value_type = zope.schema.TextLine(),
+ )
+
Property changes on: eventworkflow/trunk/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/README.txt
===================================================================
--- eventworkflow/trunk/publication/README.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/README.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,2 @@
+This package constains a weird publication process for
+example reasons.
Property changes on: eventworkflow/trunk/publication/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/__init__.py
===================================================================
--- eventworkflow/trunk/publication/__init__.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/__init__.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
Property changes on: eventworkflow/trunk/publication/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/configure.zcml
===================================================================
--- eventworkflow/trunk/publication/configure.zcml 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/configure.zcml 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,56 @@
+<configure
+ xmlns='http://namespaces.zope.org/zope'
+ xmlns:browser='http://namespaces.zope.org/browser'
+ i18n_domain="pubwf"
+ xmlns:i18n="http://namespaces.zope.org/i18n"
+ >
+
+<!-- remove finished activities from the process -->
+<subscriber
+ factory=".definition.cleanupFinishedActivities"
+ for="workflow.interfaces.IActivityFinishedEvent"
+ />
+
+
+<!-- TRANSITIONS -->
+
+<!-- initialize process -->
+<subscriber
+ factory=".definition.startCreateArticle"
+ for=".interfaces.IPublicationProcessInstance
+ workflow.interfaces.IProcessStartedEvent"
+ />
+
+<!-- normal transitions (between activities) -->
+<!-- one per activity ? -->
+<subscriber
+ factory=".definition.handleFinishedCreateArticle"
+ for=".interfaces.ICreateArticleActivity
+ workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<subscriber
+ factory=".definition.handleFinishedReviewArticle"
+ for=".interfaces.IReviewArticleActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<!-- going for a press release, these two subscriptions comprise a single join -->
+<subscriber
+ factory=".workflow.handlePublications"
+ for=".interfaces.IPublishOnlineActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<subscriber
+ factory=".workflow.handlePublications"
+ for=".interfaces.IPublishDeadTreeActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+
+
+
+
+
+</configure>
Property changes on: eventworkflow/trunk/publication/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/definition.py
===================================================================
--- eventworkflow/trunk/publication/definition.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/definition.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,168 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+
+# This process definition (re)uses a review subprocess defined
+# in eventworkflow.review
+
+import zope.interface
+import zope.event
+import zope.app.zapi
+import eventworkflow.event
+import interfaces
+
+from eventworkflow.review.definition import ReviewProcess
+from eventworkflow.interfaces import IActivity
+
+from zope.app.annotation.interfaces import IAnnotations, IAttributeAnnotatable
+
+class PublicationWorkflow:
+ zope.interface.implements(interfaces.IPublicationProcess)
+
+ def __init__(self):
+ self.activities = []
+ self.workflowData = {}
+ zope.event.notify(eventworkflow.event.ProcessStartedEvent(self))
+
+# the activities
+class BaseActivity:
+ def __init__(self, pi):
+ self.processInstance = pi
+
+class CreateArticleActivity(BaseActivity):
+ zope.interface.implements(interfaces.ICreateArticleActivity)
+
+class PublishOnlineActivity(BaseActivity):
+ zope.interface.implements(interfaces.IPublishOnlineActivity)
+
+class PublishDeadTreeActivity(BaseActivity):
+ zope.interface.implements(interfaces.IPublishDeadTreeActivity)
+
+class DoPressReleaseActivity:
+ zope.interface.implements(interfaces.IDoPressReleaseActivity)
+
+ def __init__(self, pi):
+ self.processInstance = pi
+ self.state = 'waiting'
+
+ def activate(self):
+ self.state = 'active'
+ #XXXcreate work items
+
+
+# the review sub process
+
+#XXX I wonder if this could also be implemented using an adapter
+# from IReviewProcess to IActivity
+
+class ReviewSubProcess(ReviewProcess):
+ zope.interface.implements(IActivity,
+ ReviewProcess.__provides__)
+
+ def __init__(self, pi):
+ self.processInstance = pi
+ ReviewProcess.__init__(self)
+
+
+# 2 more generic handlers
+
+def cleanupFinishedActivities(event):
+ """Remove finished activities from process"""
+ process = event.object.processInstance
+ process.activities.remove(event.object)
+
+def handleFinishedSubprocess(event):
+ """What happens with subprocess data
+
+ This handler writes the subflow data to the parents
+ workflow data (dict update for now)
+ """
+ pi = event.object
+ parent = pi.processInstance
+
+ if parent is None: # not a sub process
+ return
+
+ data = pi.workflowData
+ parent.workflowData.update(data)
+
+ zope.event.notify(eventworkflow.event.ActivityFinishedEvent(pi))
+
+def startCreateArticle(pi, event):
+ """start the initial activities of the process"""
+ pi.activities.append(CreateArticleActivity(pi))
+
+def handleFinishedCreateArticle(activity, event):
+ """Transitions from CreateArticleActivity"""
+
+ pi = activity.processInstance
+
+ # start the review sub process
+ pi.activities.append(ReviewSubProcess(pi))
+
+def handleFinishedReviewArticle(activity, event):
+ """Transitions from Review Article
+ """
+
+ pi = activity.processInstance
+
+ data = pi.workflowData
+
+ # OR-split
+ if data.get('reviewDecision', None) == 'accept':
+ # AND-split
+ pi.activities.append(PublishOnlineActivity(pi))
+ pi.activities.append(PublishDeadTreeActivity(pi))
+
+ else:
+ pi.activities.append(CreateArticleActivity(pi))
+
+
+AnnotationKey="pubwf.activitycount"
+
+def handlePublications(activity, event):
+ """Transitions from article publications to press release
+
+ This functions handles the transition to the
+ DoPressReleaseActivity. It ensures that both
+ publication activities are finished before
+ activating the press release activity. (AND-Join)
+ """
+ process = activity.processInstance
+
+ # get an IDoPressRelease from process activities, should be just 1
+ activities = [x for x in process.activities
+ if interfaces.IDoPressReleaseActivity.providedBy(x)]
+
+ try:
+ next_activity = activities.pop()
+ except IndexError:
+ next_activity = None
+
+ if not next_activity:
+ next_activity = DoPressReleaseActivity(activity.processInstance)
+ process.activities.append(next_activity)
+
+ # put an annotation onto activity
+ annotation = IAnnotations(next_activity)
+ annotation[AnnotationKey] = 1
+ else:
+ annotation = IAnnotations(next_activity)
+ count = annotation.get(AnnotationKey, 0)
+ count += 1
+
+ annotation[AnnotationKey] = count
+
+ if count == 2:
+ next_activity.activate()
+ #XXX maybe remove annotation
Property changes on: eventworkflow/trunk/publication/definition.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/interfaces.py
===================================================================
--- eventworkflow/trunk/publication/interfaces.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/interfaces.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import eventworkflow.interfaces
+
+class IPublicationProcess(eventworkflow.interfaces.IProcess):
+ """An instance of the example publication process.
+ """
+
+class ICreateArticleActivity(eventworkflow.interfaces.IActivity):
+ """Marker interface for 'Create Article' activity"""
+
+class IReviewArticleActivity(eventworkflow.interfaces.IActivity):
+ """Marker interface for 'Review Article' activity"""
+
+class IPublishOnlineActivity(eventworkflow.interfaces.IActivity):
+ """Marker interface for 'Publish online' activity"""
+
+class IPublishDeadTreeActivity(eventworkflow.interfaces.IActivity):
+ """Marker interface for 'Publish on paper' activity"""
+
+class IDoPressReleaseActivity(eventworkflow.interfaces.IJoiningActivity):
+ """Marker interface for 'Leak press release' activity"""
Property changes on: eventworkflow/trunk/publication/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/simplesub.txt
===================================================================
--- eventworkflow/trunk/publication/simplesub.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/simplesub.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,138 @@
+Using the publication workflow
+==============================
+
+Ok, here we go
+
+ >>> import eventworkflow.publication.definition
+ >>> pi = eventworkflow.publication.definition.PublicationWorkflow()
+
+Check the workflow for the right initialization
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.publication.interfaces.ICreateArticleActivity.providedBy(a)
+ True
+
+And now for the fun part, we're finished with that activity
+
+ >>> import zope.event
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+Lets check the workflow again. The current activity really is
+a (sub-)process
+
+ >>> len(pi.activities)
+ 1
+ >>> subpi = pi.activities[0]
+ >>> eventworkflow.review.interfaces.IReviewProcess.providedBy(subpi)
+ True
+
+Lets drive straight through the review. We just reject this first
+try. Nothing's done right the first time. Except it is but then its
+not worth publishing either :-)
+
+ >>> a = subpi.activities[0] # take assignment
+ >>> subpi.workflowData['reviewer'] = 'thomas'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+ >>> a = subpi.activities[0] # decide work object
+ >>> subpi.workflowData['reviewDecision'] = 'reject'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+ >>> class FakeComment:
+ ... def __init__(self, foo):
+ ... self.foo = foo
+
+ >>> a = subpi.activities[0] # write comment
+ >>> subpi.workflowData['reviewComment'] = FakeComment('You suck')
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That should bring us back to the create article activity, with
+all the comment and things available in the workflow data
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.publication.interfaces.ICreateArticleActivity.providedBy(a)
+ True
+
+Check out the workflow data
+
+ >>> data = pi.workflowData
+ >>> k = data.keys()
+ >>> k.sort()
+ >>> k
+ ['reviewComment', 'reviewDecision', 'reviewer']
+ >>> data['reviewer']
+ 'thomas'
+ >>> data['reviewDecision']
+ 'reject'
+ >>> data['reviewComment'].foo
+ 'You suck'
+
+OK, got this far. But you paid for another round. Here we go...
+
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+ >>> subpi = pi.activities[0]
+ >>> a = subpi.activities[0] # take assignment
+ >>> subpi.workflowData['reviewer'] = 'jim'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+ >>> a = subpi.activities[0] # decide work object
+ >>> subpi.workflowData['reviewDecision'] = 'accept'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That was the OR-split again, but now heavy publishing is going on
+
+ >>> len(pi.activities)
+ 2
+ >>> a,b = pi.activities
+ >>> eventworkflow.publication.interfaces.IPublishOnlineActivity.providedBy(a)
+ True
+ >>> eventworkflow.publication.interfaces.IPublishDeadTreeActivity.providedBy(b)
+ True
+
+But to be sure let's check the workflow data
+
+ >>> data = pi.workflowData
+ >>> k = data.keys()
+ >>> k.sort()
+ >>> k
+ ['reviewComment', 'reviewDecision', 'reviewer']
+ >>> data['reviewer']
+ 'jim'
+ >>> data['reviewDecision']
+ 'accept'
+ >>> data['reviewComment'].foo
+ 'You suck'
+
+Transitioning to the final state is more complicated, because this
+involves an AND-join of the last two activities.
+
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+After finishing one, there should be the IDoPressReleaseActivity created
+but it is in the waiting state
+
+ >>> len(pi.activities)
+ 2
+ >>> a,b = pi.activities
+ >>> eventworkflow.publication.interfaces.IPublishDeadTreeActivity.providedBy(a)
+ True
+ >>> eventworkflow.publication.interfaces.IDoPressReleaseActivity.providedBy(b)
+ True
+ >>> b.state
+ 'waiting'
+
+#XXX check the annotation here
+
+Finishing the second parallel activity should start the press release
+
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.publication.interfaces.IDoPressReleaseActivity.providedBy(a)
+ True
Property changes on: eventworkflow/trunk/publication/simplesub.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/publication/tests.py
===================================================================
--- eventworkflow/trunk/publication/tests.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/publication/tests.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,64 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+import eventworkflow.review.tests.setup
+
+from zope.app.tests import placelesssetup, ztapi
+from zope.app.tests.setup import setUpAnnotations
+
+import eventworkflow.interfaces
+import eventworkflow.publication.interfaces
+import eventworkflow.publication.definition
+import eventworkflow.review.interfaces
+
+def setUp(test):
+ eventworkflow.review.tests.setup.setUp(test)
+
+ ztapi.subscribe([eventworkflow.interfaces.IProcessFinishedEvent],
+ None,
+ eventworkflow.publication.definition.handleFinishedSubprocess)
+
+ ztapi.subscribe([eventworkflow.publication.interfaces.IPublicationProcess,
+ eventworkflow.interfaces.IProcessStartedEvent],
+ None,
+ eventworkflow.publication.definition.startCreateArticle)
+ ztapi.subscribe([eventworkflow.publication.interfaces.ICreateArticleActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.publication.definition.handleFinishedCreateArticle)
+ ztapi.subscribe([eventworkflow.review.interfaces.IReviewProcess,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.publication.definition.handleFinishedReviewArticle)
+ ztapi.subscribe([eventworkflow.publication.interfaces.IPublishOnlineActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.publication.definition.handlePublications)
+ ztapi.subscribe([eventworkflow.publication.interfaces.IPublishDeadTreeActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.publication.definition.handlePublications)
+
+ setUpAnnotations()
+
+def test_suite():
+ suite = unittest.TestSuite((
+ DocFileSuite('simplesub.txt',
+ setUp=setUp,
+ tearDown=placelesssetup.tearDown),
+
+ ))
+
+ return suite
Property changes on: eventworkflow/trunk/publication/tests.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/README.txt
===================================================================
--- eventworkflow/trunk/review/README.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/README.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1 @@
+This package constains a process for reviewing an object.
Property changes on: eventworkflow/trunk/review/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/__init__.py
===================================================================
--- eventworkflow/trunk/review/__init__.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/__init__.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
Property changes on: eventworkflow/trunk/review/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/configure.zcml
===================================================================
--- eventworkflow/trunk/review/configure.zcml 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/configure.zcml 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,54 @@
+<configure
+ xmlns='http://namespaces.zope.org/zope'
+ xmlns:browser='http://namespaces.zope.org/browser'
+ i18n_domain="pubwf"
+ xmlns:i18n="http://namespaces.zope.org/i18n"
+ >
+
+<!-- remove finished activities from the process -->
+<subscriber
+ factory=".definition.cleanupFinishedActivities"
+ for="workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<!-- TRANSITIONS -->
+<!-- initialize process -->
+<subscriber
+ factory=".definition.startCreateArticle"
+ for=".interfaces.IPublicationProcessInstance
+ workflow.interfaces.IProcessStartedEvent"
+ />
+
+<!-- normal transitions (between activities) -->
+<!-- one per activity ? -->
+<subscriber
+ factory=".definition.handleFinishedCreateArticle"
+ for=".interfaces.ICreateArticleActivity
+ workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<subscriber
+ factory=".definition.handleFinishedReviewArticle"
+ for=".interfaces.IReviewArticleActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<!-- going for a press release, these two subscriptions comprise a single join -->
+<subscriber
+ factory=".workflow.handlePublications"
+ for=".interfaces.IPublishOnlineActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+<subscriber
+ factory=".workflow.handlePublications"
+ for=".interfaces.IPublishDeadTreeActivity
+ .workflow.interfaces.IActivityFinishedEvent"
+ />
+
+
+
+
+
+
+</configure>
Property changes on: eventworkflow/trunk/review/configure.zcml
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/definition.py
===================================================================
--- eventworkflow/trunk/review/definition.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/definition.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,194 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import zope.interface
+import zope.event
+import zope.app.zapi
+import eventworkflow.event
+import eventworkflow.interfaces
+import interfaces
+
+class ReviewProcess:
+ zope.interface.implements(interfaces.IReviewProcess)
+
+ def __init__(self):
+ self.activities = []
+ self.workflowData = {}
+ zope.event.notify(eventworkflow.event.ProcessStartedEvent(self))
+
+class AcceptResponsibilityActivity:
+ zope.interface.implements(interfaces.IAcceptResponsibilityActivity)
+
+ def __init__(self, pi):
+ self.processInstance = pi
+
+ # initialize/reset workflow data
+ try:
+ del pi.workflowData['reviewer']
+ except KeyError:
+ pass
+
+ worklist = zope.app.zapi.getUtility(
+ eventworkflow.interfaces.IWorklistUtility)
+
+ item = AcceptReviewWI(self,
+ "Take responsibility",
+ ['thomas', 'jim', 'stephan'])
+
+ worklist.addWorkitem(item)
+
+ def checkPostCondition(self):
+ data = self.processInstance.workflowData
+ if data.has_key('reviewer'):
+ zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+
+class DecideDraftActivity:
+ zope.interface.implements(interfaces.IDecideDraftActivity)
+
+ def __init__(self, pi):
+ self.processInstance = pi
+
+ # initialize/reset workflow data
+ try:
+ del pi.workflowData['reviewDecision']
+ except KeyError:
+ pass
+
+ worklist = zope.app.zapi.getUtility(
+ eventworkflow.interfaces.IWorklistUtility)
+
+ item = DecideReviewWI(self,
+ "Decide about publication of the reviewed object",
+ [pi.workflowData['reviewer']])
+
+ worklist.addWorkitem(item)
+
+ def checkPostCondition(self):
+ data = self.processInstance.workflowData
+ if data.has_key('reviewDecision'):
+ zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+
+class WriteCommentActivity:
+ zope.interface.implements(interfaces.IWriteCommentActivity)
+
+ def __init__(self, pi):
+ self.processInstance = pi
+
+ # initialize/reset workflow data
+ try:
+ del pi.workflowData['reviewComment']
+ except KeyError:
+ pass
+
+ worklist = zope.app.zapi.getUtility(
+ eventworkflow.interfaces.IWorklistUtility)
+
+ item = WriteCommentWI(self,
+ "Write review comment",
+ [pi.workflowData['reviewer']])
+
+ worklist.addWorkitem(item)
+
+ def checkPostCondition(self):
+ data = self.processInstance.workflowData
+ if data.has_key('reviewComment'):
+ zope.event.notify(eventworkflow.event.ActivityFinishedEvent(self))
+
+
+class Workitem:
+ """Just a generic work item prototype
+
+ for testing
+ """
+ zope.interface.implements(eventworkflow.interfaces.IWorkitem)
+
+ def __init__(self, activity, description, principals):
+ self.activity = activity
+ self.description = description
+ self.principals = principals
+
+ def finish(self):
+ zope.event.notify(eventworkflow.event.WorkitemFinishedEvent(self))
+
+class AcceptReviewWI(Workitem):
+ def finish(self, reviewerid):
+ process = self.activity.processInstance
+ data = process.workflowData
+ data['reviewer'] = reviewerid
+
+ Workitem.finish(self)
+
+class DecideReviewWI(Workitem):
+ def finish(self, decision):
+ process = self.activity.processInstance
+ data = process.workflowData
+ data['reviewDecision'] = decision
+
+ Workitem.finish(self)
+
+class WriteCommentWI(Workitem):
+ def finish(self, comment):
+ process = self.activity.processInstance
+ data = process.workflowData
+ data['reviewComment'] = comment
+
+ Workitem.finish(self)
+
+
+
+#XXX These 2 handlers might be general workflow handlers
+
+def cleanupFinishedActivities(event):
+ """Remove finished activities from process"""
+ process = event.object.processInstance
+ process.activities.remove(event.object)
+
+def workitemFinished(event):
+ wi = event.object
+ activity = wi.activity
+
+ # remove from worklist
+ worklist = zope.app.zapi.getUtility(eventworkflow.interfaces.IWorklistUtility)
+ worklist.items.remove(wi)
+
+ # then notify the activity
+ activity.checkPostCondition()
+
+
+
+### transition handlers (specific to this process)
+
+def processStarted(process, event):
+ """Activate initial activities"""
+ a = AcceptResponsibilityActivity(process)
+ process.activities.append(a)
+
+def reviewerAssigned(activity, event):
+ pi = activity.processInstance
+
+ a = DecideDraftActivity(pi)
+ pi.activities.append(a)
+
+def decisionMade(activity, event):
+ pi = activity.processInstance
+
+ if pi.workflowData.get('reviewDecision', 'reject') == 'accept':
+ zope.event.notify(eventworkflow.event.ProcessFinishedEvent(pi))
+
+ else:
+ a = WriteCommentActivity(pi)
+ pi.activities.append(a)
+
+def commentWritten(activity, event):
+ pi = activity.processInstance
+ zope.event.notify(eventworkflow.event.ProcessFinishedEvent(pi))
Property changes on: eventworkflow/trunk/review/definition.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/interfaces.py
===================================================================
--- eventworkflow/trunk/review/interfaces.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/interfaces.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,26 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import eventworkflow.interfaces
+
+class IReviewProcess(eventworkflow.interfaces.IProcess):
+ """A review process"""
+
+class IAcceptResponsibilityActivity(eventworkflow.interfaces.IActivity):
+ """ Marker interface for activity"""
+
+class IDecideDraftActivity(eventworkflow.interfaces.IActivity):
+ """ Marker interface for activity"""
+
+class IWriteCommentActivity(eventworkflow.interfaces.IActivity):
+ """ Marker interface for activity"""
Property changes on: eventworkflow/trunk/review/interfaces.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/__init__.py
===================================================================
--- eventworkflow/trunk/review/tests/__init__.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/__init__.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
Property changes on: eventworkflow/trunk/review/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitems.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitems.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,94 @@
+Review process with workitems (straight accept)
+===============================================
+
+Ok, here we go
+
+ >>> import zope.event
+ >>> import eventworkflow.review.definition
+ >>> pi = eventworkflow.review.definition.ReviewProcess()
+
+Check the workflow for the right initialization
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.review.interfaces.IAcceptResponsibilityActivity.providedBy(a)
+ True
+
+Lets get a workitem for us
+
+ >>> from zope.app import zapi
+ >>> from eventworkflow.interfaces import IWorklistUtility
+ >>> worklist = zapi.getUtility(IWorklistUtility)
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+ >>> len(worklist.itemsFor('jim'))
+ 1
+ >>> len(worklist.itemsFor('peter'))
+ 0
+
+Damn, that is a really busy site. There are lots of processes
+running in parallel
+
+ >>> pi2 = eventworkflow.review.definition.ReviewProcess()
+ >>> pi3 = eventworkflow.review.definition.ReviewProcess()
+
+That should put a bit of load to the reviewers
+
+ >>> len(worklist.itemsFor('thomas'))
+ 3
+
+Ok, Ok. Got me. I'm to move my ass eventually
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> process = wi.activity.processInstance
+ >>> process.workflowData.has_key('reviewer')
+ False
+ >>> wi.finish('thomas')
+
+Lets test the progress in the workflow
+
+ >>> process.workflowData['reviewer']
+ 'thomas'
+ >>> len(process.activities)
+ 1
+ >>> a = process.activities[0]
+ >>> eventworkflow.review.interfaces.IDecideDraftActivity.providedBy(a)
+ True
+
+Great but theres more to it, look...
+
+ >>> len(worklist.itemsFor('stephan'))
+ 2
+ >>> len(worklist.itemsFor('jim'))
+ 2
+
+Any volunteers? Especially since you can't complain, see
+
+ >>> len(worklist.itemsFor('thomas'))
+ 3
+
+2 of them should be the same like before for the additional processes, the
+third being the workitem to decide about the object to be reviewed
+
+ >>> wi = worklist.itemsFor('thomas')[2]
+ >>> assert wi.__class__ == eventworkflow.review.definition.DecideReviewWI
+
+I'm pretty quick (or kind of sloppy with QA ;-)), so I accept
+
+ >>> wi.finish('accept')
+
+I'm done now, equal positions for everyone
+
+ >>> len(worklist.itemsFor('stephan'))
+ 2
+ >>> len(worklist.itemsFor('jim'))
+ 2
+ >>> len(worklist.itemsFor('thomas'))
+ 2
+ >>> len(worklist.itemsFor('peter'))
+ 0
+
+ >> process = wi.activity.processInstance
+ >> process.workflowData
+ {'reviewDecision':'accept', 'reviewer':'thomas'}
Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitems.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,72 @@
+Review process with workitems (2 Reviewer, straight accept)
+===========================================================
+
+Ok, here we go, starting 2 review processes
+
+ >>> import zope.event
+ >>> import eventworkflow.review.definition
+ >>> pi = eventworkflow.review.definition.ReviewProcess()
+ >>> pi2 = eventworkflow.review.definition.ReviewProcess()
+
+Lets check the workitems
+
+ >>> from zope.app import zapi
+ >>> from eventworkflow.interfaces import IWorklistUtility
+ >>> worklist = zapi.getUtility(IWorklistUtility)
+
+ >>> len(worklist.itemsFor('thomas'))
+ 2
+ >>> len(worklist.itemsFor('jim'))
+ 2
+ >>> len(worklist.itemsFor('peter'))
+ 0
+
+Damn, that is a really busy site. There are lots of processes
+running in parallel. After finishing the first activity all
+subsequent activities assign their workitems to a single principal
+Therefore 2 items for thomas (1 awaiting reviewer assignment +
+1 awaiting review decision) and 1 for jim (reviewer assignment)
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> wi.finish('thomas')
+
+ >>> len(worklist.itemsFor('thomas'))
+ 2
+ >>> len(worklist.itemsFor('jim'))
+ 1
+
+Now its Jim's turn (both processes now awaiting review decision)
+
+ >>> wi = worklist.itemsFor('jim')[0]
+ >>> wi.finish('jim')
+
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+ >>> len(worklist.itemsFor('jim'))
+ 1
+
+
+For sake of simplicity both accept (jim first)
+
+ >>> wi = worklist.itemsFor('jim')[0]
+ >>> wi.finish('accept')
+
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+ >>> len(worklist.itemsFor('jim'))
+ 0
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> wi.finish('accept')
+
+ >>> len(worklist.itemsFor('thomas'))
+ 0
+ >>> len(worklist.itemsFor('jim'))
+ 0
+
+Workflow data should reflect this session
+
+ >> pi.workflowData
+ {'reviewDecision':'accept', 'reviewer':'thomas'}
+ >> pi2.workflowData
+ {'reviewDecision':'accept', 'reviewer':'jim'}
Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitemsParallelReviewers.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,64 @@
+Review process with workitems (rejection)
+=========================================
+
+Ok, here we go (same as in reviewWithWorkitems to the point were
+'thomas' is to decide about the reviewed doc)
+
+ >>> import zope.event
+ >>> import eventworkflow.review.definition
+ >>> pi = eventworkflow.review.definition.ReviewProcess()
+
+ >>> from zope.app import zapi
+ >>> from eventworkflow.interfaces import IWorklistUtility
+ >>> worklist = zapi.getUtility(IWorklistUtility)
+
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+ >>> len(worklist.itemsFor('jim'))
+ 1
+ >>> len(worklist.itemsFor('peter'))
+ 0
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> wi.finish('thomas')
+
+ >>> len(worklist.itemsFor('jim'))
+ 0
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> assert wi.__class__ == eventworkflow.review.definition.DecideReviewWI
+
+This time I'm really picky
+
+ >>> wi.finish('reject')
+
+ >>> len(worklist.itemsFor('jim'))
+ 0
+ >>> len(worklist.itemsFor('thomas'))
+ 1
+
+ >>> wi = worklist.itemsFor('thomas')[0]
+ >>> assert wi.__class__ == eventworkflow.review.definition.WriteCommentWI
+
+But then I'm to write a comment now
+
+ >>> class FakeComment:
+ ... def __init__(self, text):
+ ... self.text = text
+
+ >>> wi.finish(FakeComment('Your article sucks'))
+
+ >>> len(worklist.itemsFor('jim'))
+ 0
+ >>> len(worklist.itemsFor('thomas'))
+ 0
+
+ >> process = wi.activity.processInstance
+ >> process.workflowData['reviewDecision']
+ 'reject'
+ >> process.workflowData['reviewer']
+ 'thomas'
+ >> process.workflowData['reviewComment'].text
+ 'Your article sucks'
Property changes on: eventworkflow/trunk/review/tests/reviewWithWorkitemsReject.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/reviewprocess.txt
===================================================================
--- eventworkflow/trunk/review/tests/reviewprocess.txt 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/reviewprocess.txt 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,53 @@
+The review process (workflow)
+=============================
+
+Ok, here we go
+
+ >>> import zope.event
+ >>> import eventworkflow.review.definition
+ >>> pi = eventworkflow.review.definition.ReviewProcess()
+
+Check the workflow for the right initialization
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.review.interfaces.IAcceptResponsibilityActivity.providedBy(a)
+ True
+
+ >>> data = pi.workflowData
+ >>> data['reviewer'] = 'thomas'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+Lets check the workflow again
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.review.interfaces.IDecideDraftActivity.providedBy(a)
+ True
+
+ >>> data = a.processInstance.workflowData
+ >>> data['reviewDecision'] = 'reject'
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+
+That article was real crap, but now I've to provide a comment
+
+ >>> len(pi.activities)
+ 1
+ >>> a = pi.activities[0]
+ >>> eventworkflow.review.interfaces.IWriteCommentActivity.providedBy(a)
+ True
+
+ >>> class FakeComment: pass
+ >>> data = a.processInstance.workflowData
+ >>> data['reviewComment'] = FakeComment()
+
+The process is done, no activities left
+
+ >>> zope.event.notify(eventworkflow.event.ActivityFinishedEvent(a))
+ >>> len(pi.activities)
+ 0
+
+
+
Property changes on: eventworkflow/trunk/review/tests/reviewprocess.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/setup.py
===================================================================
--- eventworkflow/trunk/review/tests/setup.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/setup.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+from zope.app.tests import placelesssetup, ztapi
+from zope.app.tests.setup import setUpAnnotations
+
+import eventworkflow.review.interfaces
+import eventworkflow.review.definition
+
+import eventworkflow.interfaces
+
+
+def setUpUtilities(test):
+ from eventworkflow.interfaces import IWorklistUtility
+ from eventworkflow.worklist import BasicWorklistUtility
+
+ ztapi.provideUtility(IWorklistUtility, BasicWorklistUtility())
+
+
+def setUpSubscriptions(test):
+ ztapi.subscribe([eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.review.definition.cleanupFinishedActivities)
+
+ ztapi.subscribe([eventworkflow.interfaces.IWorkitemFinishedEvent],
+ None,
+ eventworkflow.review.definition.workitemFinished)
+
+ ztapi.subscribe([eventworkflow.review.interfaces.IReviewProcess,
+ eventworkflow.interfaces.IProcessStartedEvent],
+ None,
+ eventworkflow.review.definition.processStarted)
+
+ ztapi.subscribe([eventworkflow.review.interfaces.IAcceptResponsibilityActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.review.definition.reviewerAssigned)
+
+ ztapi.subscribe([eventworkflow.review.interfaces.IDecideDraftActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.review.definition.decisionMade)
+
+ ztapi.subscribe([eventworkflow.review.interfaces.IWriteCommentActivity,
+ eventworkflow.interfaces.IActivityFinishedEvent],
+ None,
+ eventworkflow.review.definition.commentWritten)
+
+def setUp(test):
+ placelesssetup.setUp(test)
+ setUpUtilities(test)
+ setUpSubscriptions(test)
+ setUpAnnotations()
Property changes on: eventworkflow/trunk/review/tests/setup.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
===================================================================
--- eventworkflow/trunk/review/tests/test_ReviewHighlevel.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/test_ReviewHighlevel.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,22 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+from zope.app.tests import placelesssetup
+from setup import setUp
+
+def test_suite():
+ return DocFileSuite('reviewprocess.txt',
+ setUp=setUp,
+ tearDown=placelesssetup.tearDown)
Property changes on: eventworkflow/trunk/review/tests/test_ReviewHighlevel.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
===================================================================
--- eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import unittest
+from zope.testing.doctest import DocFileSuite, DocTestSuite
+from zope.app.tests import placelesssetup
+
+from setup import setUp
+
+def test_suite():
+ return unittest.TestSuite((
+ DocFileSuite('reviewWithWorkitems.txt',
+ setUp=setUp,
+ tearDown=placelesssetup.tearDown),
+ DocFileSuite('reviewWithWorkitemsReject.txt',
+ setUp=setUp,
+ tearDown=placelesssetup.tearDown),
+ DocFileSuite('reviewWithWorkitemsParallelReviewers.txt',
+ setUp=setUp,
+ tearDown=placelesssetup.tearDown),
+ ))
+
+
Property changes on: eventworkflow/trunk/review/tests/test_ReviewWithWorkitems.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/tests/__init__.py
===================================================================
--- eventworkflow/trunk/tests/__init__.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/tests/__init__.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,13 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
Property changes on: eventworkflow/trunk/tests/__init__.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/tests/test_worklistUtility.py
===================================================================
--- eventworkflow/trunk/tests/test_worklistUtility.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/tests/test_worklistUtility.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,44 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import eventworkflow.worklist
+from zope.testing.doctest import DocTestSuite
+
+def testService(test):
+ """
+ >>> wl = eventworkflow.worklist.BasicWorklistUtility()
+ >>> wl.itemsFor('foo')
+ []
+
+ Define a some work items
+
+ >>> class FakeWorkItem:
+ ... def __init__(self, principals=[], name=''):
+ ... self.principals = principals
+ ... self.name = name
+
+ >>> foo = FakeWorkItem(['thomas', 'peter'], 'Learn Zope 3')
+ >>> bar = FakeWorkItem(['thomas'], 'Find Zope 3 Zen')
+ >>> wl.addWorkitem(foo)
+ >>> wl.addWorkitem(bar)
+
+ >>> wl.itemsFor('foo')
+ []
+ >>> [x.name for x in wl.itemsFor('peter')]
+ ['Learn Zope 3']
+ >>> [x.name for x in wl.itemsFor('thomas')]
+ ['Learn Zope 3', 'Find Zope 3 Zen']
+ """
+
+def test_suite():
+ return DocTestSuite()
Property changes on: eventworkflow/trunk/tests/test_worklistUtility.py
___________________________________________________________________
Name: svn:eol-style
+ native
Added: eventworkflow/trunk/worklist.py
===================================================================
--- eventworkflow/trunk/worklist.py 2004-10-19 22:52:08 UTC (rev 28221)
+++ eventworkflow/trunk/worklist.py 2004-10-20 19:43:47 UTC (rev 28222)
@@ -0,0 +1,31 @@
+##############################################################################
+#
+# Copyright (c) 2004 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import zope.interface
+from interfaces import IWorklistUtility
+
+class BasicWorklistUtility:
+ """A simple worklist utility"""
+ zope.interface.implements(IWorklistUtility)
+
+ def __init__(self):
+ self.items = []
+
+ def addWorkitem(self, item):
+ self.items.append(item)
+
+ def itemsFor(self, pid):
+ """Return all wokitems for principal"""
+
+ #XXX groups support
+ return [x for x in self.items if pid in x.principals]
Property changes on: eventworkflow/trunk/worklist.py
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Zope-CVS
mailing list