added stateful package for assigning simple workflows to loops objects

git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@2467 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2008-03-21 17:51:30 +00:00
parent 64acbd439d
commit b7097a09c5
8 changed files with 168 additions and 6 deletions

View file

@ -118,10 +118,10 @@ So we are now ready to query the favorites.
>>> favs = favorites.query(userName=johnCId) >>> favs = favorites.query(userName=johnCId)
>>> favs >>> favs
[<Favorite ['27', 1, '33', '...']: {}>] [<Favorite ['29', 1, '35', '...']: {}>]
>>> list(favAdapted.list(johnC)) >>> list(favAdapted.list(johnC))
['27'] ['29']
>>> util.getObjectForUid(favs[0].taskId) is resources['d001.txt'] >>> util.getObjectForUid(favs[0].taskId) is resources['d001.txt']
True True

View file

@ -27,7 +27,7 @@ from zope.interface import implements, Interface
from loops.concept import Concept from loops.concept import Concept
from loops.interfaces import ITypeConcept from loops.interfaces import ITypeConcept
from loops.organize.interfaces import IPerson from loops.organize.interfaces import IPerson, ITask
from loops.setup import SetupManager as BaseSetupManager from loops.setup import SetupManager as BaseSetupManager
@ -39,10 +39,13 @@ class SetupManager(BaseSetupManager):
predicate = concepts['predicate'] predicate = concepts['predicate']
person = self.addObject(concepts, Concept, 'person', title=u'Person', person = self.addObject(concepts, Concept, 'person', title=u'Person',
conceptType=type) conceptType=type)
aPerson = ITypeConcept(person) aPerson = ITypeConcept(person)
if not aPerson.typeInterface: # allow overriding by other packages if not aPerson.typeInterface: # allow overriding by other packages
aPerson.typeInterface = IPerson aPerson.typeInterface = IPerson
owner = self.addObject(concepts, Concept, 'ownedby', title=u'owned by', owner = self.addObject(concepts, Concept, 'ownedby', title=u'owned by',
conceptType=predicate) conceptType=predicate)
task = self.addAndConfigureObject(concepts, Concept, 'task', title=u'Task',
conceptType=type, typeInterface=ITask)

59
stateful/README.txt Normal file
View file

@ -0,0 +1,59 @@
===============================================================
loops - Linked Objects for Organization and Processing Services
===============================================================
($Id$)
>>> from zope import component
>>> from zope.traversing.api import getName
First we set up a loops site with basic and example concepts and resources.
>>> from zope.app.testing.setup import placefulSetUp, placefulTearDown
>>> site = placefulSetUp(True)
>>> from loops.organize.setup import SetupManager
>>> component.provideAdapter(SetupManager, name='organize')
>>> from loops.tests.setup import TestSite
>>> t = TestSite(site)
>>> concepts, resources, views = t.setup()
>>> loopsRoot = site['loops']
Stateful Objects
================
Let's start with registering the states definitions and adapters needed.
The states definition (aka 'workflow') is registered as a utility; for
making an object statful we'll use an adapter.
>>> from cybertools.stateful.interfaces import IStatesDefinition, IStateful
>>> from cybertools.stateful.publishing import simplePublishing
>>> component.provideUtility(simplePublishing, IStatesDefinition,
... name='loops.simple_publishing')
>>> from loops.stateful.base import SimplePublishable
>>> component.provideAdapter(SimplePublishable, name='loops.simple_publishing')
We may now take a document and adapt it to IStateful so that we may
check the document's state and perform transitions to other states.
>>> doc01 = resources['d001.txt']
>>> statefulDoc01 = component.getAdapter(doc01, IStateful,
... name='loops.simple_publishing')
>>> statefulDoc01.state
'draft'
>>> statefulDoc01.doTransition('publish')
>>> statefulDoc01.state
'published'
Let's check if the state is really stored in the underlying object and
not just kept in the adapter.
>>> statefulDoc01_x = component.getAdapter(doc01, IStateful,
... name='loops.simple_publishing')
>>> statefulDoc01.state
'published'

3
stateful/__init__.py Normal file
View file

@ -0,0 +1,3 @@
"""
$Id$
"""

47
stateful/base.py Normal file
View file

@ -0,0 +1,47 @@
#
# Copyright (c) 2008 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
#
"""
Basic implementations for stateful objects and adapters.
$Id$
"""
from zope import component
from zope.component import adapts
from cybertools.stateful.base import Stateful as BaseStateful
from cybertools.stateful.base import StatefulAdapter
from cybertools.stateful.interfaces import IStatesDefinition
from loops.interfaces import ILoopsObject
class Stateful(BaseStateful):
def getStatesDefinition(self):
return component.getUtility(IStatesDefinition, self.statesDefinition)
class StatefulLoopsObject(Stateful, StatefulAdapter):
adapts(ILoopsObject)
class SimplePublishable(StatefulLoopsObject):
statesDefinition = 'loops.simple_publishing'

22
stateful/configure.zcml Normal file
View file

@ -0,0 +1,22 @@
<!-- $Id$ -->
<configure
xmlns:zope="http://namespaces.zope.org/zope"
xmlns:browser="http://namespaces.zope.org/browser"
i18n_domain="loops">
<zope:utility
factory="cybertools.stateful.publishing.simplePublishing"
name="loops.simple_publishing" />
<zope:adapter
factory="loops.stateful.base.SimplePublishable"
name="loops.simple_publishing" trusted="True" />
<zope:class class="loops.stateful.base.SimplePublishable">
<require permission="zope.View"
interface="cybertools.stateful.interfaces.IStateful" />
<require permission="zope.ManageContent"
set_schema="cybertools.stateful.interfaces.IStateful" />
</zope:class>
</configure>

28
stateful/tests.py Executable file
View file

@ -0,0 +1,28 @@
#! /usr/bin/python
"""
Tests for the 'loops.stateful' package.
$Id$
"""
import unittest, doctest
from zope.testing.doctestunit import DocFileSuite
class Test(unittest.TestCase):
"Basic tests for the storage package."
def testBasicStuff(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')

View file

@ -166,14 +166,14 @@ Updating the concept map
>>> topicId = xrf.getObjectByName('topic')['id'] >>> topicId = xrf.getObjectByName('topic')['id']
>>> xrf.createConcept(topicId, u'zope2', u'Zope 2') >>> xrf.createConcept(topicId, u'zope2', u'Zope 2')
{'description': u'', 'title': u'Zope 2', 'type': '22', 'id': '56', {'description': u'', 'title': u'Zope 2', 'type': '24', 'id': '56',
'name': u'zope2'} 'name': u'zope2'}
The name of the concept is checked by a name chooser; if the corresponding The name of the concept is checked by a name chooser; if the corresponding
parameter is empty, the name will be generated from the title. parameter is empty, the name will be generated from the title.
>>> xrf.createConcept(topicId, u'', u'Python') >>> xrf.createConcept(topicId, u'', u'Python')
{'description': u'', 'title': u'Python', 'type': '22', 'id': '58', {'description': u'', 'title': u'Python', 'type': '24', 'id': '58',
'name': u'python'} 'name': u'python'}
Changing the attributes of a concept Changing the attributes of a concept