diff --git a/constraint.py b/constraint.py new file mode 100644 index 0000000..42c332c --- /dev/null +++ b/constraint.py @@ -0,0 +1,69 @@ +# +# Copyright (c) 2004 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 +# + +""" +Definition of the ResourceConstraint class. + +$Id$ +""" + +from zope.interface import implements + +from interfaces import IResourceConstraint + + +class ResourceConstraint(object): + + implements(IResourceConstraint) + + explanation = u'' + constraintType = 'select' + referenceType = 'explicit' + referenceKey = None + + + def __init__(self, task): + self.referenceValues = [] + self._task = task + + + def isResourceAllowed(self, resource): + if self.referenceType == 'parent': + for r in self.referenceValues: + m = getattr(r, self.referenceKey) + if resource in m(): + return True + return False + elif self.referenceType == 'explicit': + return resource in self.referenceValues + else: + return False + + + def getAllowedResources(self, candidates=None): + if self.referenceType == 'parent': + result = [] + for r in self.referenceValues: + m = getattr(r, self.referenceKey) + result.extend(m()) + return tuple(result) + elif self.referenceType == 'explicit': + return tuple(self.referenceValues) + else: + return () + diff --git a/interfaces.py b/interfaces.py index 1b9aa18..f78d894 100644 --- a/interfaces.py +++ b/interfaces.py @@ -25,7 +25,7 @@ $Id$ from zope.interface import Interface from zope.app.container.interfaces import IOrderedContainer -from zope.schema import TextLine, List, Object +from zope.schema import Text, TextLine, List, Object class ITask(IOrderedContainer): @@ -127,21 +127,22 @@ class IResourceConstraint(Interface): allocated to a Task object. """ - task = Object(ITask, - title=u'Task', - description=u'Task object this ResourceConstraint belongs to', + explanation = Text( + title=u'Explanation', + description=u'Explanation of this constraint - ' + 'why or why not certain resources may be allowed', required=True) constraintType = TextLine( title=u'Constraint Type', - description=u'Type of the constraint: select, require, or disallow', + description=u'Type of the constraint: select, require, disallow', default=u'select', required=True) referenceType = TextLine( title=u'Reference Type', description=u'Type of reference to the resource attribute to check: ' - 'explicit, type, container, attribute, property, or parent', + 'explicit, parent, type, attribute, property, method' default=u'explicit', required=True) @@ -149,7 +150,7 @@ class IResourceConstraint(Interface): title=u'Reference Key', description=u'Key for referencing the resource attribute') - referenceValue = List( + referenceValues = List( title=u'Reference Values', description=u'Attribute values to check for; may be any kind of object', value_type=Object(Interface, title=u'Value')) @@ -164,6 +165,5 @@ class IResourceConstraint(Interface): If given, use candidates as a list of possible resources (candidates must implement the IResource interface). - """ diff --git a/tests/test_constraint.py b/tests/test_constraint.py new file mode 100755 index 0000000..bcb4483 --- /dev/null +++ b/tests/test_constraint.py @@ -0,0 +1,65 @@ +# $Id$ + +import unittest +#from zope.testing.doctestunit import DocTestSuite +from zope.interface.verify import verifyClass +from zope.app.container.interfaces import IContained +from zope.app.folder import Folder + +from loops.task import Task +from loops.resource import Resource +from loops.constraint import ResourceConstraint +from loops.interfaces import IResourceConstraint + +class Test(unittest.TestCase): + "Test methods of the ResourceConstraint class." + + def setUp(self): + #placelessSetUp() + self.f1 = Folder() + self.f1.__name__ = u'f1' + self.r1 = Resource() + self.f1['rsc1'] = self.r1 + self.t1 = Task() + self.f1['tsk1'] = self.t1 + self.rc1 = ResourceConstraint(self.t1) + + def tearDown(self): + pass + + # the tests... + + def testInterface(self): + self.failUnless(IResourceConstraint.providedBy(self.rc1), + 'Interface IResourceConstraint is not implemented by class ResourceConstraint.') + verifyClass(IResourceConstraint, ResourceConstraint) + + def testSelectExplicit(self): + rc1 = self.rc1 + r1 = self.r1 + self.assertEqual(False, rc1.isResourceAllowed(r1)) + self.assertEqual((), rc1.getAllowedResources()) + rc1.referenceValues = ([r1]) + self.assertEqual(True, rc1.isResourceAllowed(r1)) + self.assertEqual((r1,), rc1.getAllowedResources()) + + def testSelectParent(self): + rc1 = self.rc1 + r1 = self.r1 + t2 = Task() + t2.allocateResource(r1) + rc1.referenceType = 'parent' + rc1.referenceKey = 'getAllocatedResources' + rc1.referenceValues = ([t2]) + self.assertEqual(True, rc1.isResourceAllowed(r1)) + self.assertEqual((r1,), rc1.getAllowedResources()) + + +def test_suite(): + return unittest.TestSuite(( +# DocTestSuite('loops.tests.doctests'), + unittest.makeSuite(Test), + )) + +if __name__ == '__main__': + unittest.main(defaultTest='test_suite')