工作流管理联盟工作流引擎

shoobx.wfmc的Python项目详细描述


详细文档

工作流管理联盟工作流引擎

此包提供工作流管理的实现 联盟(WFMC)工作流引擎。发动机作为 工作流流程组件的集合。工作流过程可以是 用python或通过xml过程定义语言xpdl定义。

在本文档中,我们将查看python定义的流程定义:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')

进程的参数是进程ID。

一个过程有许多部分。让我们看一个样本回顾 流程:

                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------

这里我们有一个开始活动和两个结束活动。我们可以 已经用单端活动对此进行了建模,但这不是 必修的。需要一个启动活动 。过程定义 有一组活动,它们之间有转换。让我们来定义 流程定义的活动:

< Buff行情>
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )

我们提供活动作为关键字参数。参数名提供 定义转换时将使用的活动标识:

< Buff行情>
>>> pd.defineTransitions(
...     process.TransitionDefinition('author', 'review'),
...     process.TransitionDefinition('review', 'publish'),
...     process.TransitionDefinition('review', 'reject'),
...     )

每个转换都由一个用于开始的标识符构造 活动,以及结束活动的标识符。

在使用工作流定义之前,我们必须将其注册为 实用工具。这是必要的,以便流程实例可以找到 定义。此外,实用程序名称必须与进程ID匹配:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)

现在,有了这个定义,我们就可以执行我们的工作流了。我们还没有 已经定义了任何工作,但是我们可以看到工作流的执行。我们会看到的 通过注册记录工作流的订阅服务器来执行的工作流 事件:

< Buff行情>
>>> def log_workflow(event):
...     print (event)
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)

要使用工作流定义,我们需要创建一个实例:

< Buff行情>
>>> proc = pd()

现在,如果我们启动工作流:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))

我们看到我们立即过渡到作者活动,然后 发表评论。通常,我们需要在每个 活动和转换只有在工作完成后才能继续 但是,在本例中,我们没有定义任何工作,所以 活动立即完成。

注意,我们没有转换到被拒绝的活动。通过 默认情况下,当活动完成时,第一个转换 其条件评估为 true 被使用。默认情况下,转换 具有计算结果为 true 的布尔条件,因此转换 使用to publish 是因为它是在转换到 拒绝 。我们想要的是转换到 发布 批准要发布的内容,但如果审阅者 拒绝要发布的内容。我们可以使用以下条件:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
0
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
1

我们重新定义了工作流过程,为 转换到 发布 。布尔条件只是可调用的对象 获取一个数据对象并返回一个布尔值。数据对象是 称为"工作流相关数据"。流程实例具有数据对象 包含此数据。在上面的例子中,条件只是 返回 publish 属性的值。这个属性如何 准备好了吗?它需要由评审活动设置。为此,我们 需要安排活动来设置数据。这让我们想到 应用程序。

流程定义用于不同的 应用。因此,流程定义不包括 应用程序逻辑。它们所包含的是 要调用的应用程序和与工作流相关的数据流 从申请表上。现在,我们可以定义我们的应用程序:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
2

我们对应用程序使用的名称与 活动。这不是必需的,但却是一种常见的做法。注意 应用程序包含输出的规范 参数。既然我们已经定义了应用程序,我们需要修改 我们使用它们的活动:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
3

一个活动可以使用许多应用程序,因此我们调用 addapplication 。 在"审查"申请的申请定义中,我们 提供与工作流相关的数据变量的名称 为应用程序定义的输出参数。当使用 活动中的应用程序,与工作流相关的数据变量名 必须为 申请的签名。在活动中使用应用程序时, 为每个输入参数和 由每个输出参数设置。在本例中,输出 参数,将用于向工作流添加 publish 属性 相关数据。

参与者

我们已经宣布了一些申请,我们已经把它们连接到 活动,但我们仍然没有指定任何应用程序代码。以前 我们可以指定应用程序代码,我们需要考虑 正在执行应用程序。工作流应用程序通常 由人或其他外部行为体执行。与应用程序一样, 流程定义允许声明工作流中的参与者 与活动有关。我们宣布参与者与我们 声明应用程序,除非没有参数:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
4

在本例中,我们碰巧重用了一个活动名,但是 不是两个参与者。在定义了这些参与者之后,我们 可以将它们与活动关联:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
5

应用程序集成

要使用流程定义来控制应用程序逻辑,我们需要 将其与"集成"对象相关联。

当流程需要获取参与者时,它调用createparticipant 在其integration属性上,传递进程id和 执行者ID。如果活动没有 执行者,则上面的过程与空的执行者ID一起使用。

类似地,当流程需要工作项时,它调用createworkitem 在其integration属性上,传递进程id和 应用程序ID.

工作项提供用于启动工作的 start 方法 并传递输入参数。这是工作项目的责任, 稍后,调用 活动,通知活动工作项 完整的。输出参数被传递到工作项finished 方法:

创建集成对象的一个简单方法是 shoobx.wfmc.attributeintegration.attributeintegration

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
6

我们将首先定义一个简单的参与者类:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
7
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
8

我们为每个参与者设置集成属性:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
9

我们还为参与者定义了一个属性,用于 有表演者:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
0

现在我们将定义我们的工作项。首先,我们将定义一些类:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
1
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
2
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
3
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
4
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
5

然后我们将它们连接到集成对象:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
6

使用工作流过程

要使用流程定义,请将其实例化并调用其start方法 开始执行:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
7

我们进入作者活动,等待工作完成。 为了继续前进,我们需要找到创作工作项,这样我们就可以 完成它。我们的工作项添加到工作列表中,这样我们就可以 从列表中获取项目。

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
8

现在,我们可以通过调用其finish方法来完成工作项:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
9

我们看到我们过渡到了审查活动。请注意 finish 方法不是工作流api的一部分。它的定义是 我们的示例类。其他应用程序可以使用不同的机制。

现在,我们将通过调用评审工作项的 完成 。我们将通过 false ,表明内容不应 出版日期:

< Buff行情>
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
0

排序输出转换

通常,传出转换按转换顺序排列 使用定义和给定活动的所有转换。

如果转换是以不方便的顺序定义的,则工作流 可能无法按预期工作。例如,让我们修改上面的 通过改变一些 转变。我们将重用以前的集成对象 将其传递给定义构造函数的示例:

< Buff行情>
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
1
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
2
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
2
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
3
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
4
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
5

运行我们的流程:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
7
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
8

这次,我们会说我们应该发布:

< Buff行情>
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
9

但我们还是去了拒绝活动。为什么?因为转换 按顺序测试。因为到拒绝活动的转换是 先测试,没有条件,我们没有检查 转换到发布活动的条件。我们可以解决这个问题 通过直接在审阅者活动上指定传出转换。 为此,我们还需要在转换中指定id。让我们 重新定义流程:

< Buff行情>
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
1
>>> pd.defineTransitions(
...     process.TransitionDefinition('author', 'review'),
...     process.TransitionDefinition('review', 'publish'),
...     process.TransitionDefinition('review', 'reject'),
...     )
1
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
2
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
3
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
4
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
5
>>> pd.defineTransitions(
...     process.TransitionDefinition('author', 'review'),
...     process.TransitionDefinition('review', 'publish'),
...     process.TransitionDefinition('review', 'reject'),
...     )
6

现在,当我们运行这个过程时,我们将以 需要:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
7
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
8
>>> pd.defineTransitions(
...     process.TransitionDefinition('author', 'review'),
...     process.TransitionDefinition('review', 'publish'),
...     process.TransitionDefinition('review', 'reject'),
...     )
9

让我们看看另一种方法,我们应该转换到拒绝:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
7
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
8
>>> pd.defineActivities(
...     author  = process.ActivityDefinition(),
...     review  = process.ActivityDefinition(),
...     publish = process.ActivityDefinition(),
...     reject  = process.ActivityDefinition(),
...     )
0

复杂流

让我们看一个更复杂的例子。在本例中,我们将扩展 与多个审阅者一起工作的过程。我们还将 工作列表处理更复杂一些。我们还将介绍 一些新概念:

  • 拆分和联接
  • 处理参数

考虑出版 流程如下所示:

>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
3

在这里,我们将流程图排列成列,其中 每个参与者的活动。我们有四个参与者, 作者、两名技术评审员和一名编辑评审员。这个 作者准备了一份草稿。作者将草稿发送到 both 技术评审员进行评审。当技术评审 完成后,编辑评论将进行初步编辑 复习。根据技术评论,编辑可以选择:

  • 拒绝文档
  • 按原样发布文档
  • 请求技术更改(基于技术评审员 注释),或
  • 请求编辑更改。

如果需要进行技术更改,则工作将返回到 "准备"活动。如果有必要进行编辑性修改,那么 流向"准备最终"活动。当作者制作了 编辑修改,工作流程到"审查最终"。编辑可以 请求其他更改,在这种情况下,工作流程返回到"准备 "最终",否则,工作将流向"发布"。

这个例子说明了不同类型的"连接"和"拆分"。这个 术语"join"是指传入活动的转换方式 处理。连接有两种:"and"和"xor"。加上"和" join,活动将等待每个传入的转换。在 本例中,"编辑评论"活动的输入构成 "和"加入。编辑评论要等到每个技术 评审完成。本例中的其余连接是 "异或"连接。活动在转换为活动时开始。

"拆分"一词是指从一个活动向外转换的方式 都处理好了。通常,一个活动的一个转换是 使用。这称为"异或"分裂。加上"和"分开,全部 使用计算结果为 true 的布尔条件转换。 在本例中,"prepare"活动有一个"and"分隔符。工作 同时流向两个技术审查活动。其余的 本例中的拆分是"异或"拆分。

让我们创建新的工作流过程。我们会重新利用现有的 集成对象:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
4
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
5

在这里,我们将字符串传递给活动定义 名字。名称必须是Unicode或ASCII字符串。

我们定义转换:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
6

我们指定"和"拆分并加入:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
7

我们定义参与者和应用程序:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
8
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)
9
>>> def log_workflow(event):
...     print (event)
0
>>> def log_workflow(event):
...     print (event)
1
>>> def log_workflow(event):
...     print (event)
2
>>> def log_workflow(event):
...     print (event)
3
>>> def log_workflow(event):
...     print (event)
4
>>> def log_workflow(event):
...     print (event)
5
>>> def log_workflow(event):
...     print (event)
6

我们希望在启动进程时能够指定作者。 我们还想知道最后的处理过程。到 完成此操作后,我们将为流程定义参数:

< Buff行情>
>>> def log_workflow(event):
...     print (event)
7

既然我们已经定义了流程,我们需要提供参与者和 应用程序组件。让我们从参与者开始。宁愿 与共享单个工作列表相比,我们将为每个用户提供他们自己的 工作清单。我们还将创建先前存在的参与者并返回 他们。最后,我们将创建多个作者并使用选定的作者:

< Buff行情>
>>> def log_workflow(event):
...     print (event)
8
>>> def log_workflow(event):
...     print (event)
9
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
0
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
1

在本例中,我们需要为每个参与者定义一个单独的属性:

< Buff行情>
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
2

创建进程时,将传入作者名并 分配给工作流相关数据。我们的author类使用这个 选择指定用户的信息。

< Buff行情>
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
3
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
4
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
5

我们将利用我们的原始参与课程进行 表演者:

< Buff行情>
                            -----------
                         -->| Publish |
----------   ---------- /   -----------
| Author |-->| Review |-    ----------
----------   ---------- \-->| Reject |
                            ----------
0

现在我们将创建我们的应用程序。让我们从作者开始:

< Buff行情>
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
7
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
8
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
9

因为我们使用了"准备修订申请"和"初始修订申请" 准备,我们提供了一个总结方法来说明我们必须做什么。

这里我们得到作者创建的文档,它作为 finish方法的参数。在更现实的实施中, author任务将在任务开始时创建文档,并且 提供用户界面供用户编辑。我们存储 文档作为应用程序相关数据,因为我们希望审阅者 能够访问它,但我们不需要它直接用于工作流 控制,

< Buff行情>
>>> proc = pd()
0
>>> proc = pd()
1

在这里,我们提供了一种访问原始文档的方法。

< Buff行情>
>>> proc = pd()
2
>>> proc = pd()
3

在这个实现中,如果 技术编辑建议拒绝并将工作发回 如果有任何技术变更,请做好准备。我们还将 techreview 获取 getdoc 方法。

我们将重用前一个应用程序中的 publish reject 应用程序 例子:

< Buff行情>
>>> proc = pd()
4
>>> proc = pd()
5

在这个应用程序中,我们只是更新文档以反映 变化:

< Buff行情>
>>> proc = pd()
6
>>> proc = pd()
7

我们的进程现在返回数据。当我们创建一个流程时,我们需要 提供一个可以调用的对象:

< Buff行情>
>>> proc = pd()
8

现在,让我们试试我们的流程:

< Buff行情>
>>> proc = pd()
9

我们应该在鲍勃的工作清单上加上一项。我们去拿吧 完成它,提交文档:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
0

注意,我们转换到了 两个 活动, tech1 技术2 。这是因为准备活动有一个"和"分隔。 现在我们做一个技术回顾。让我们看看Tech1有哪些功能:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
1

让我们告诉作者将"美国人"改为"地球人":

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
2

在这里我们转到了编辑评论活动,但是我们没有 开始吧。这是因为编辑评论活动有一个"and" 连接,这意味着在两个转换都 发生。

现在我们将进行另一项技术回顾:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
3

现在,当我们转到编辑评论活动时,我们开始 因为每个输入转换都发生了。我们的社论 审核申请自动将工作发回准备, 因为有技术评论。当然,作者仍然是鲍勃。 让我们发表评论:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
4
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
5

和以前一样,在完成最初的编辑之后,我们开始 再次回顾活动。我们再复习一遍。这次,我们没有 注释,因为作者应用了我们请求的更改:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
6
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
7

这次,我们留在技术评审活动中,因为 没有任何技术上的改变。我们准备好做社论评论了。 我们将请求编辑更改:

< Buff行情>
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
8
>>> proc.start()
ProcessStarted(Process('sample'))
Transition(None, Activity('sample.author'))
ActivityStarted(Activity('sample.author'))
ActivityFinished(Activity('sample.author'))
Transition(Activity('sample.author'), Activity('sample.review'))
ActivityStarted(Activity('sample.review'))
ActivityFinished(Activity('sample.review'))
Transition(Activity('sample.review'), Activity('sample.publish'))
ActivityStarted(Activity('sample.publish'))
ActivityFinished(Activity('sample.publish'))
ProcessFinished(Process('sample'))
9

因为我们要求修改社论,所以我们转到了决赛 编辑活动,以便作者(仍然是bob)可以进行更改:

< Buff行情> α
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
00
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
01

我们转向行动用于审阅最终编辑的ITY。我们 审阅文档并批准发布:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
02
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
03

在这一点上,剩下的过程会自动完成。在 此外,决策记录在流程上下文对象中:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
04

即将推出

  • 超时/异常

另请参见

http://www.wfmc.org http://www.wfmc.org/standards/standards.htm

xpdl导入

我们可以从xml进程中的文件导入进程定义 定义语言(xpdl)格式。xpdl文件包含多个 在包中排列的进程定义。当我们加载文件时 获取包含一些进程定义的包。

让我们看一个例子。文件 publication.xpdl 包含在 "readme.txt"文件。我们可以使用xpdl模块阅读:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
05

此软件包包含单个定义:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
06
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
07

现在,在阅读了流程定义之后,我们可以像以前那样使用它 之前(在"readme.txt"中)。和以前一样,我们将创建一个事件订阅服务器 这样我们就可以看到发生了什么:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
08
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)

我们将把进程定义注册为实用程序:

< Buff行情>
>>> import zope.component
>>> from shoobx.wfmc.process import StaticProcessDefinitionFactory
>>> pdfactory = StaticProcessDefinitionFactory()
>>> zope.component.provideUtility(pdfactory)
>>> pdfactory.register(pd)

我们将定义并注册参与者和应用程序适配器:

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
7
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
8
>>> def log_workflow(event):
...     print (event)
8
>>> def log_workflow(event):
...     print (event)
9
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
0
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
16
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
2
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
3
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
4
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
5
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
21
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
7
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
23
>>> import zope.event
>>> zope.event.subscribers.append(log_workflow)
9
>>> proc = pd()
0
>>> proc = pd()
1
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
27
>>> proc = pd()
3
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
29
>>> proc = pd()
5
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
31
>>> proc = pd()
7
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
33
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
34
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
35
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
36

以及进程上下文,以便我们可以传递参数:

< Buff行情>
>>> proc = pd()
8

现在,让我们试试我们的流程。我们会按照之前的步骤 "readme.txt",得到相同的结果:

< Buff行情> αααα138
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
39
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
40
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
41
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
42 αααα143
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
44
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
45
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
46 αααα147 αααα148 αααα149
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
50
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
51
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
52
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
04

说明

大多数流程元素都可以有名称和说明。

< Buff行情>
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
54
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
55
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
56
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
57
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
58
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
59
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
60
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
61
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
62
>>> from shoobx.wfmc import process
>>> pd = process.ProcessDefinition('sample')
63

更改

4.2.0(2018-11-12)

  • 添加Python3.7支持。
  • 删除python 3.5支持。
  • 删除所有折旧和资源警告。

4.1.1(2018-02-08)

  • 更多的python 3兼容性。

4.1.0(2018-02-06)

  • 支持Python 3。

4.0.4(2017-11-01)

  • 立即使 功能可插入。

4.0.3(2017-06-20)

  • 什么都没变。

4.0.2(2017-05-25)

  • 更新和改进trove分类器。

4.0.1(2017-05-25)

  • 修复小的rest问题,以便pypi描述能够呈现出来。

4.0.0(2017-05-25)

  • zope.wfmc 重命名为 shoobx.wfmc

  • 增加了对社区CI和覆盖工具的支持。

  • 在单个 扩展属性 容器

  • 使用IProcessDefinitionFactory检索流程定义,而不是 命名实用程序。这个额外的间接层允许生成 定义动态调用Y.P/P>

  • 支持同步和异步执行WFMC子流。 子流作为主进程的一部分执行,但是它们有各自的 状态(工作流变量)。

  • 简单的python evaluate(expr,locals) 函数已被替换 通过pythonexpressionevaluator组件,它是来自 i处理 ipythonexpressionevaluator 。求值局部变量命名空间 自动填充与工作流和应用程序相关的数据 属性、进程的上下文和传入的局部变量。

    evaluate() 的所有调用都已更新为使用适配器。

    这种变化使得评估引擎的更换变得容易 一个安全的python引擎(即restrictedpython)并提供更多的名称空间 条目.

  • 转换条件现在可以在 处理,而不仅仅是与工作流相关的数据。因此他们的召唤 签名从 条件(数据) 更改为 条件(过程、数据)

  • textcondition 已更改为使用pythonexpressionevaluator 组件。另外,编译优化也被删除了,因为 expression evalautor可以更有效地执行此操作。

  • 支持中止流程和活动。

    • 工作项可以通过实现 iabortworkitem 来中止。

    • 如果工作项实现了icleanupWorkitem,则可以对其进行清理。

    • 活动跟踪已完成的工作项。

    • 活动可以通过清理工作项来自我清理。

    • 流程跟踪已完成的活动。

    • 当进程中止时,将执行以下操作:

      • 所有活动都将中止。

      • 所有已完成的活动都已清除。

        < Buff行情>
        • 在进程上设置了isaborted标志。
  • 添加了对读取xpdl-2.1的支持

  • 从xpdl添加了读取池和通道

3.5.0(2009年7月24日)

  • 将测试更新到最新的软件包版本。

3.4.0(2007-11-02)

  • 独立于主zope树的初始版本。

欢迎加入QQ群-->: 979659372 Python中文网_新手群

推荐PyPI第三方库


热门话题
java如何将jasper集成到jhipster项目中   java无法忽略lombok注释   关于tomcat日志的java问题   java@Autowired未设置字段>NullPointerException   GUI提交按钮不工作   java气泡和选择排序   java如何编写规则来匹配两个数组?   java如何找出某个字符在字符串中的第一次、第二次或第三次出现?   java通过字符串引用id   javascript在网络视图中加载在线图表   java保留web应用程序中用户更改的日志   在安卓中尝试使用Mandrill SMTP发送电子邮件时出现java错误   用java语言将a2b4c5等字符串转换为AABBCCCCC的程序是什么?   java无需TODO即可删除所有注释   java JMX MBean在应用程序部署时自动注册   java如何使用JSON解析从任何url解析数据   java@transactional注释类使用代理包装,但未创建事务   JavaFx转换和打印