diff --git a/configure.zcml b/configure.zcml index 6477d65..e45b55e 100644 --- a/configure.zcml +++ b/configure.zcml @@ -30,11 +30,11 @@ - + - + @@ -46,7 +46,7 @@ - + - + - + - + - + - + @@ -265,16 +265,16 @@ - + - + - + - + - + @@ -318,6 +318,7 @@ + diff --git a/process/README.txt b/process/README.txt new file mode 100644 index 0000000..47edceb --- /dev/null +++ b/process/README.txt @@ -0,0 +1,75 @@ +=============================================================== +loops - Linked Objects for Organization and Processing Services +=============================================================== + + ($Id$) + +Note: This package depends on cybertools.knowledge and cybertools.organize. + +Let's do some basic set up + + >>> from zope.app.testing.setup import placefulSetUp, placefulTearDown + >>> site = placefulSetUp(True) + + >>> from zope import component, interface + >>> from zope.app import zapi + +and setup a simple loops site with a concept manager and some concepts +(with all the type machinery, what in real life is done via standard +ZCML setup): + + >>> from cybertools.relation.interfaces import IRelationRegistry + >>> from cybertools.relation.registry import DummyRelationRegistry + >>> relations = DummyRelationRegistry() + >>> component.provideUtility(relations, IRelationRegistry) + + >>> from cybertools.typology.interfaces import IType + >>> from loops.interfaces import IConcept, ITypeConcept + >>> from loops.type import ConceptType, TypeConcept + >>> component.provideAdapter(ConceptType, (IConcept,), IType) + >>> component.provideAdapter(TypeConcept, (IConcept,), ITypeConcept) + + >>> from loops.interfaces import ILoops + >>> from loops.setup import ISetupManager + >>> from loops.process.setup import SetupManager + >>> component.provideAdapter(SetupManager, (ILoops,), ISetupManager, + ... name='process') + + >>> from loops import Loops + >>> loopsRoot = site['loops'] = Loops() + + >>> from loops.setup import SetupManager + >>> setup = SetupManager(loopsRoot) + >>> concepts, resources, views = setup.setup() + +We need some type concepts for controlling the meaning of the concepts objects, +these have already been created during setup: + + >>> process = concepts['process'] + + +Manage processes +================ + +The classes used in this package are just adapters to IConcept. + + >>> from loops.process.definition import ProcessDefinition + >>> from cybertools.process.interfaces import IProcessDefinition + >>> component.provideAdapter(ProcessDefinition, (IConcept,), IProcessDefinition) + +We start with creating a process definition. +Note that in order to discern the concepts created +from their typeInterface adapters we here append a 'C' to the name of +the variables: + + >>> from loops.concept import Concept + >>> myProcessC = concepts['myProcess'] = Concept(u'A Simple Process') + >>> myProcessC.conceptType = process + >>> myProcess = IProcessDefinition(myProcessC) + + +Fin de partie +============= + + >>> placefulTearDown() + diff --git a/process/__init__.py b/process/__init__.py new file mode 100644 index 0000000..4bc90fb --- /dev/null +++ b/process/__init__.py @@ -0,0 +1,4 @@ +""" +$Id$ +""" + diff --git a/process/configure.zcml b/process/configure.zcml new file mode 100644 index 0000000..0827d61 --- /dev/null +++ b/process/configure.zcml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/process/definition.py b/process/definition.py new file mode 100644 index 0000000..86afe3f --- /dev/null +++ b/process/definition.py @@ -0,0 +1,60 @@ +# +# Copyright (c) 2006 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Adapters for IConcept providing interfaces from the +cybertools.knowledge package. + +$Id$ +""" + +from zope import interface, component +from zope.app import zapi +from zope.component import adapts +from zope.interface import implements +from zope.cachedescriptors.property import Lazy + +from cybertools.typology.interfaces import IType +from cybertools.process.interfaces import IProcessDefinition +from cybertools.process.definition import ProcessDefinition as BaseProcessDefinition +from loops.interfaces import IConcept +from loops.type import TypeInterfaceSourceList, AdapterBase + + +# register type interfaces - (TODO: use a function for this) + +TypeInterfaceSourceList.typeInterfaces += (IProcessDefinition,) + + +class ProcessAdapterMixin(object): + + @Lazy + def conceptManager(self): + return self.context.getLoopsRoot().getConceptManager() + + @Lazy + def successorPred(self): + return self.conceptManager['successor'] + + +class ProcessDefinition(AdapterBase, BaseProcessDefinition, ProcessAdapterMixin): + """ A typeInterface adapter for concepts of type 'process'. + """ + + implements(IProcessDefinition) + diff --git a/process/interfaces.py b/process/interfaces.py new file mode 100644 index 0000000..5284f2e --- /dev/null +++ b/process/interfaces.py @@ -0,0 +1,33 @@ +# +# Copyright (c) 2006 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Interfaces for process/workflow management with loops. + +$Id$ +""" + +from zope.interface import Interface, Attribute +from zope import interface, component, schema +from zope.i18nmessageid import MessageFactory +from zope.security.proxy import removeSecurityProxy + +from cybertools.process.interfaces import IProcessDefinition + +_ = MessageFactory('zope') + diff --git a/process/setup.py b/process/setup.py new file mode 100644 index 0000000..cd722a6 --- /dev/null +++ b/process/setup.py @@ -0,0 +1,50 @@ +# +# Copyright (c) 2006 Helmut Merz helmutm@cy55.de +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +# + +""" +Automatic setup of a loops site for the process package. + +$Id$ +""" + +from zope.component import adapts +from zope.interface import implements, Interface + +from cybertools.process.interfaces import IProcessDefinition +from loops.concept import Concept +from loops.interfaces import ITypeConcept +from loops.setup import SetupManager as BaseSetupManager + + +class SetupManager(BaseSetupManager): + + def setup(self): + concepts = self.context.getConceptManager() + type = concepts.getTypeConcept() + predicate = concepts['predicate'] + # type concepts: + process = self.addObject(concepts, Concept, 'process', title=u'Process', + conceptType=type) + processTypeAdapter = ITypeConcept(process) + if not processTypeAdapter.typeInterface: + processTypeAdapter.typeInterface = IProcessDefinition + # predicates: + successor = self.addObject(concepts, Concept, 'successor', title=u'successor', + conceptType=predicate) + + diff --git a/process/tests.py b/process/tests.py new file mode 100755 index 0000000..a2e2e58 --- /dev/null +++ b/process/tests.py @@ -0,0 +1,24 @@ +# $Id$ + +import unittest, doctest +from zope.testing.doctestunit import DocFileSuite +from zope.app.testing import ztapi +from zope.interface.verify import verifyClass +from loops.organize.party import Person + +class Test(unittest.TestCase): + "Basic tests for the process sub-package." + + def testSomething(self): + pass + + +def test_suite(): + flags = doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS + return unittest.TestSuite(( + unittest.makeSuite(Test), + DocFileSuite('README.txt', optionflags=flags), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite') diff --git a/type.py b/type.py index d6ca785..ba7c5bf 100644 --- a/type.py +++ b/type.py @@ -39,9 +39,9 @@ from loops.resource import Resource, Document, MediaAsset class LoopsType(BaseType): - + adapts(ILoopsObject) - + factoryMapping = dict(concept=Concept, resource=Resource) containerMapping = dict(concept='concepts', resource='resources') @@ -60,7 +60,7 @@ class LoopsType(BaseType): tp = self.typeProvider typeName = tp is None and 'unknown' or str(zapi.getName(tp)) return ':'.join(('loops', self.qualifiers[0], typeName,)) - + @Lazy def typeInterface(self): adapter = zapi.queryAdapter(self.typeProvider, ITypeConcept) @@ -79,11 +79,11 @@ class LoopsType(BaseType): if ti is None or not issubclass(ti, IResourceAdapter): return ('concept',) return ('resource',) - + @Lazy def factory(self): return self.factoryMapping.get(self.qualifiers[0], Concept) - + @Lazy def defaultContainer(self): return self.root[self.containerMapping.get(self.qualifiers[0], 'concept')] @@ -107,7 +107,7 @@ class LoopsTypeInfo(LoopsType): class ConceptType(LoopsType): - """ The IType adapter for concept objects. + """ The IType adapter for concept objects. Probably obsolete because all real stuff has gone to LoopsType. """ @@ -186,7 +186,7 @@ class LoopsTypeManager(TypeManager): return ConceptTypeInfo(self.context.loopsTraverse(token)) return ResourceTypeInfo(self.context, resolve(token)) - @property + @property def types(self): return self.conceptTypes() + self.resourceTypes() @@ -277,10 +277,10 @@ class AdapterBase(object): """ adapts(IConcept) - + _attributes = ('context', '__parent__', ) _schemas = list(IConcept) - + def __init__(self, context): self.context = context # to get the permission stuff right self.__parent__ = context @@ -300,3 +300,7 @@ class AdapterBase(object): if attr not in self._schemas: raise AttributeError(attr) + def __eq__(self, other): + return self.context == other.context + +