[Zope3-checkins] CVS: Zope3/src/zope/app/workflow - __init__.py:1.4 configure.zcml:1.1 definition.py:1.1 globalimportexport.py:1.1 instance.py:1.1 meta.zcml:1.1 metaconfigure.py:1.1 service.py:1.1
Ulrich Eck
ueck@net-labs.de
Thu, 8 May 2003 13:27:49 -0400
Update of /cvs-repository/Zope3/src/zope/app/workflow
In directory cvs.zope.org:/tmp/cvs-serv7538/src/zope/app/workflow
Added Files:
__init__.py configure.zcml definition.py globalimportexport.py
instance.py meta.zcml metaconfigure.py service.py
Log Message:
Finally got it into Zope3:
Workflow has arrived!
this is a merge of the workflow package that was seperatly developed
at /Packages3/workflow.
please to a
cvs update -dPA
to ensure that old files/directories are deleted, otherwise you'll
probably encounter errors when trying to run zope3
if you have problems .. send me an email ueck <at> net-labs.de
Ulrich
=== Zope3/src/zope/app/workflow/__init__.py 1.3 => 1.4 ===
=== Added File Zope3/src/zope/app/workflow/configure.zcml ===
<zopeConfigure
xmlns='http://namespaces.zope.org/zope'
xmlns:service='http://namespaces.zope.org/service'>
<!-- Workflow Permissions -->
<permission
id="zope.workflow.ManageProcessDefinitions"
title="Manage Workflow ProcessDefinitions" />
<permission
id="zope.workflow.CreateProcessInstances"
title="Create Workflow ProcessInstances" />
<permission
id="zope.workflow.UseProcessInstances"
title="Use Workflow ProcessInstances" />
<!-- Workflow Service -->
<content class="zope.app.workflow.service.WorkflowService">
<factory
id="WorkflowService"
permission="zope.ManageServices"
/>
<require
permission="zope.View"
interface="zope.app.interfaces.workflow.IWorkflowService"
attributes="queryConfigurations queryConfigurationsFor
listConfigurationNames" />
/>
<implements
interface="zope.app.interfaces.annotation.IAttributeAnnotatable"
/>
</content>
<serviceType
id='Workflows'
interface='zope.app.interfaces.workflow.IWorkflowService'
/>
<!-- Workflow Process Definition
This is only a generic placeholder for
future Process Definition implementations
-->
<content class="zope.app.workflow.definition.ProcessDefinition">
<factory
id="ProcessDefinition"
permission="zope.ManageServices"
/>
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.workflow.IProcessDefinition"
/>
<implements
interface="zope.app.interfaces.annotation.IAttributeAnnotatable"
/>
</content>
<!-- Process Definition Configuration -->
<content class="zope.app.workflow.service.ProcessDefinitionConfiguration">
<factory
id="ProcessDefinitionConfiguration"
permission="zope.ManageServices"
/>
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.workflow.IProcessDefinitionConfiguration"
set_schema="zope.app.interfaces.workflow.IProcessDefinitionConfiguration"
/>
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.container.IAddNotifiable"
/>
<require
permission="zope.ManageServices"
interface="zope.app.interfaces.container.IDeleteNotifiable"
/>
</content>
<!-- Process Instance Container -->
<content class="zope.app.workflow.definition.ProcessDefinitionElementContainer">
<implements interface="zope.app.interfaces.container.IContentContainer" />
<implements
interface="zope.app.interfaces.annotation.IAttributeAnnotatable"
/>
<require
permission="zope.View"
interface="zope.app.interfaces.container.IReadContainer"
/>
<require
permission="zope.workflow.ManageProcessDefinitions"
interface="zope.app.interfaces.container.IWriteContainer"
/>
</content>
<adapter factory="zope.app.workflow.instance.ProcessInstanceContainerAdapter"
provides="zope.app.interfaces.workflow.IProcessInstanceContainer"
for="zope.app.interfaces.annotation.IAnnotatable" />
<!-- Workflow Import/Export Utility -->
<utility
component=".globalimportexport.globalImportExport"
provides="zope.app.interfaces.workflow.IProcessDefinitionImportExport"
permission="zope.workflow.ManageProcessDefinitions"
/>
<include package=".stateful" />
</zopeConfigure>
=== Added File Zope3/src/zope/app/workflow/definition.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Implementation of workflow process definition.
$Id: definition.py,v 1.1 2003/05/08 17:27:18 jack-e Exp $
"""
__metaclass__ = type
from types import StringTypes
from persistence import Persistent
from persistence.dict import PersistentDict
from zope.proxy.context import ContextAware, getWrapperContainer
from zope.app.interfaces.workflow \
import IProcessDefinition, IProcessDefinitionElementContainer
class ProcessDefinition(Persistent):
__doc__ = IProcessDefinition.__doc__
__implements__ = IProcessDefinition
name = None
############################################################
# Implementation methods for interface
# zope.app.interfaces.workflow.IProcessDefinition
def createProcessInstance(self, definition_name):
return None
#
############################################################
class ProcessDefinitionElementContainer(ContextAware, Persistent):
""" See IProcessDefinitionElementContainer.
"""
__implements__ = IProcessDefinitionElementContainer
def __init__(self):
super(ProcessDefinitionElementContainer, self).__init__()
self.__data = PersistentDict()
def keys(self):
'''See interface IProcessDefinitionElementContainer'''
return self.__data.keys()
def __iter__(self):
return iter(self.__data.keys())
def __getitem__(self, key):
'''See interface IProcessDefinitionElementContainer'''
return self.__data[key]
def get(self, key, default=None):
'''See interface IProcessDefinitionElementContainer'''
return self.__data.get(key, default)
def values(self):
'''See interface IProcessDefinitionElementContainer'''
return self.__data.values()
def __len__(self):
'''See interface IProcessDefinitionElementContainer'''
return len(self.__data)
def items(self):
'''See interface IProcessDefinitionElementContainer'''
return self.__data.items()
def __contains__(self, key):
'''See interface IProcessDefinitionElementContainer'''
return self.__data.has_key(key)
has_key = __contains__
def setObject(self, key, object):
'''See interface IProcessDefinitionElementContainer'''
bad = False
if isinstance(key, StringTypes):
try:
unicode(key)
except UnicodeError:
bad = True
else:
bad = True
if bad:
raise TypeError("'%s' is invalid, the key must be an "
"ascii or unicode string" % key)
if len(key) == 0:
raise ValueError("The key cannot be an empty string")
self.__data[key] = object
return key
def __delitem__(self, key):
'''See interface IProcessDefinitionElementContainer'''
del self.__data[key]
def getProcessDefinition(self):
return getWrapperContainer(self)
=== Added File Zope3/src/zope/app/workflow/globalimportexport.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""ProcessDefinition Import Export Utility
$Id: globalimportexport.py,v 1.1 2003/05/08 17:27:18 jack-e Exp $
"""
__metaclass__ = type
from zope.interface.implementor import ImplementorRegistry
from zope.interface._flatten import _flatten
from zope.proxy.introspection import removeAllProxies
from zope.app.interfaces.workflow import IProcessDefinition
from zope.app.interfaces.workflow import IGlobalProcessDefinitionImportExport
from StringIO import StringIO
class ImportExportUtility:
__implements__ = IGlobalProcessDefinitionImportExport
def __init__(self):
self._importers = ImplementorRegistry()
self._exporters = ImplementorRegistry()
_clear = __init__
# IProcessDefinitionImportExport
def importProcessDefinition(self, context, data):
"""Import a Process Definition
"""
if not hasattr(data, "read"):
data = StringIO(data)
for iface, factory in self._importers.getRegisteredMatching():
if iface.extends(IProcessDefinition):
imp = factory()
data.seek(0)
if imp.canImport(context, data):
data.seek(0)
return imp.doImport(context, data)
raise ValueError, 'No Importer can handle that information'
def exportProcessDefinition(self, context, process_definition):
"""Export a Process Definition
"""
clean_pd = removeAllProxies(process_definition)
interfaces = filter(lambda x: x.extends(IProcessDefinition),
_flatten(clean_pd.__implements__))
for interface in interfaces:
factory = self._exporters.get(interface)
if factory is not None:
return factory().doExport(context, clean_pd)
raise TypeError, "object doesn't implement IProcessDefinition"
# IGlobalProcessDefinitionImportExport
def addImportHandler(self, interface, factory):
"""add Import Handler for ProcessDefinition
"""
self._importers.register(interface, factory)
def addExportHandler(self, interface, factory):
"""add Export Handler for ProcessDefinition
"""
self._exporters.register(interface, factory)
globalImportExport = ImportExportUtility()
_clear = globalImportExport._clear
# Register our cleanup with Testing.CleanUp to make writing unit tests simpler.
from zope.testing.cleanup import addCleanUp
addCleanUp(_clear)
del addCleanUp
=== Added File Zope3/src/zope/app/workflow/instance.py ===
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Implementation of workflow process instance.
$Id: instance.py,v 1.1 2003/05/08 17:27:18 jack-e Exp $
"""
__metaclass__ = type
from types import StringTypes
from persistence import Persistent
from persistence.dict import PersistentDict
from zope.proxy.context import ContextWrapper
from zope.proxy.introspection import removeAllProxies
from zope.app.interfaces.annotation import IAnnotatable, IAnnotations
from zope.app.interfaces.workflow \
import IProcessInstance, IProcessInstanceContainer
from zope.component import getAdapter
# XXX should an Instance be persistent by default ???
class ProcessInstance:
__doc__ = IProcessInstance.__doc__
__implements__ = IProcessInstance
def __init__(self, pd_name):
self._pd_name = pd_name
self._status = None
############################################################
# Implementation methods for interface
# zope.app.interfaces.workflow.IProcessInstance
processDefinitionName = property(lambda self: self._pd_name)
status = property(lambda self: self._status)
#
############################################################
## should probably have a method "getProcessDefinition"
_marker = object()
WFKey = "zope.app.worfklow.ProcessInstanceContainer"
class ProcessInstanceContainerAdapter:
__implements__ = IProcessInstanceContainer
__used_for__ = IAnnotatable
def __init__(self, context):
self.context = context
annotations = getAdapter(context, IAnnotations)
wfdata = annotations.get(WFKey)
if not wfdata:
wfdata = PersistentDict()
annotations[WFKey] = wfdata
self.wfdata = wfdata
def __getitem__(self, key):
"See IProcessInstanceContainer"
value = self.wfdata[key]
return ContextWrapper(value, self.context, name=key)
def get(self, key, default=None):
"See IProcessInstanceContainer"
value = self.wfdata.get(key, _marker)
if value is not _marker:
return ContextWrapper(value, self.context, name=key)
else:
return default
def __contains__(self, key):
"See IProcessInstanceContainer"
return key in self.wfdata
def values(self):
"See IProcessInstanceContainer"
container = self.wfdata
result = []
for key, value in container.items():
result.append(ContextWrapper(value, self.context, name=key))
return result
def keys(self):
"See IProcessInstanceContainer"
return self.wfdata.keys()
def __len__(self):
"See IProcessInstanceContainer"
return len(self.wfdata)
def items(self):
"See IProcessInstanceContainer"
container = self.wfdata
result = []
for key, value in container.items():
result.append((key, ContextWrapper(value, self.context, name=key)))
return result
def setObject(self, key, object):
"See IProcessInstanceContainer"
if not isinstance(key, StringTypes):
raise TypeError("Item name is not a string.")
container = self.wfdata
object = removeAllProxies(object)
container[key] = object
# publish event ??
return key
def __delitem__(self, key):
"See IZopeWriteContainer"
container = self.wfdata
# publish event ?
del container[key]
return key
def __iter__(self):
'''See interface IReadContainer'''
return iter(self.context)
=== Added File Zope3/src/zope/app/workflow/meta.zcml ===
<zopeConfigure xmlns='http://namespaces.zope.org/zope'>
<directives namespace="http://namespaces.zope.org/workflow">
<directive name="importHandler"
handler=".metaconfigure.importHandlerDirective">
<description>
Register an Import Handler, that is able to load a XML
Representation of a ProcessDefinition and create
a persistent Instance for it.
</description>
<attribute name="for" required="yes">
<description>
The interface of the process defintion,
this handler can load.
</description>
</attribute>
<attribute name="factory">
<description>
The factory for the instance that implements the handler.
</description>
</attribute>
</directive>
<directive name="exportHandler"
handler=".metaconfigure.exportHandlerDirective">
<description>
Register an Export Handler, that is able to save a XML
Representation of a ProcessDefinition from a given object.
</description>
<attribute name="for" required="yes">
<description>
The interface of the process defintion,
this handler can save.
</description>
</attribute>
<attribute name="factory">
<description>
The factory for the instance that implements the handler.
</description>
</attribute>
</directive>
</directives>
</zopeConfigure>
=== Added File Zope3/src/zope/app/workflow/metaconfigure.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""ProcessDefinition Import Export Utility
$Id: metaconfigure.py,v 1.1 2003/05/08 17:27:18 jack-e Exp $
"""
__metaclass__ = type
from zope.configuration.action import Action
from globalimportexport import globalImportExport
#
def importHandlerDirective(_context, interface, factory):
interface = _context.resolve(interface)
factory = _context.resolve(factory)
return [
Action(
discriminator = ('workflow','importHandler', interface),
callable = addImportHandler,
args = (interface, factory)
)
]
def exportHandlerDirective(_context, interface, factory):
interface = _context.resolve(interface)
factory = _context.resolve(factory)
return [
Action(
discriminator = ('workflow','exportHandler', interface),
callable = addExportHandler,
args = (interface, factory)
)
]
def addImportHandler(interface, factory):
globalImportExport.addImportHandler(interface, factory)
def addExportHandler(interface, factory):
globalImportExport.addExportHandler(interface, factory)
=== Added File Zope3/src/zope/app/workflow/service.py ===
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (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.
#
##############################################################################
"""Workflow service implementation.
Revision information:
$Id: service.py,v 1.1 2003/05/08 17:27:18 jack-e Exp $
"""
__metaclass__ = type
from persistence import Persistent
from zope.proxy.context import ContextMethod, ContextWrapper
from zope.component import getAdapter
from zope.app.component.nextservice import queryNextService
from zope.app.interfaces.services.configuration \
import INameComponentConfigurable
from zope.app.services.configuration import NameComponentConfigurable
from zope.app.services.configuration import NamedComponentConfiguration
from zope.app.services.configuration import ConfigurationStatusProperty
from zope.app.interfaces.services.configuration import IUseConfiguration
from zope.app.traversing import traverse, getPath
from zope.app.interfaces.services.service import ISimpleService
from zope.app.interfaces.workflow import IProcessDefinitionConfiguration
from zope.app.interfaces.workflow import IProcessDefinition
from zope.app.interfaces.workflow import IWorkflowService
class ILocalWorkflowService(IWorkflowService, INameComponentConfigurable):
"""A Local WorkflowService.
"""
class WorkflowService(Persistent, NameComponentConfigurable):
__doc__ = IWorkflowService.__doc__
__implements__ = ILocalWorkflowService, ISimpleService
############################################################
# Implementation methods for interface
# zope.app.interfaces.workflow.IWorkflowService
def getProcessDefinitionNames(self):
'See IWorkflowService'
definition_names = {}
for name in self.listConfigurationNames():
registry = self.queryConfigurations(name)
if registry.active() is not None:
definition_names[name] = 0
service = queryNextService(self, "Workflows")
if service is not None:
for name in service.getProcessDefinitionNames():
definition_names[name] = 0
return definition_names.keys()
getProcessDefinitionNames = ContextMethod(getProcessDefinitionNames)
def getProcessDefinition(self, name):
'See IWorkflowService'
pd = self.queryActiveComponent(name)
if pd is not None:
return ContextWrapper(pd, self, name=name)
service = queryNextService(self, "Workflows")
if service is not None:
return service.getProcessDefinition(name)
raise KeyError, name
getProcessDefinition = ContextMethod(getProcessDefinition)
def queryProcessDefinition(self, name, default=None):
'See IWorkflowService'
try:
return self.getProcessDefinition(name)
except KeyError:
return default
queryProcessDefinition = ContextMethod(queryProcessDefinition)
def createProcessInstance(self, definition_name):
pd = self.getProcessDefinition(definition_name)
return pd.createProcessInstance(definition_name)
createProcessInstance = ContextMethod(createProcessInstance)
#
############################################################
class ProcessDefinitionConfiguration(NamedComponentConfiguration):
__doc__ = IProcessDefinitionConfiguration.__doc__
__implements__ = (IProcessDefinitionConfiguration,
NamedComponentConfiguration.__implements__)
status = ConfigurationStatusProperty('Workflows')
def getInterface(self):
return IProcessDefinition
# The following hooks are called only if we implement
# IAddNotifiable and IDeleteNotifiable.
def afterAddHook(self, configuration, container):
"""Hook method will call after an object is added to container.
Defined in IAddNotifiable.
"""
super(ProcessDefinitionConfiguration, self).afterAddHook(configuration,
container)
pd = configuration.getComponent()
adapter = getAdapter(pd, IUseConfiguration)
adapter.addUsage(getPath(configuration))
def beforeDeleteHook(self, configuration, container):
"""Hook method will call before object is removed from container.
Defined in IDeleteNotifiable.
"""
pd = configuration.getComponent()
adapter = getAdapter(pd, IUseConfiguration)
adapter.removeUsage(getPath(configuration))
super(ProcessDefinitionConfiguration, self).beforeDeleteHook(configuration,
container)