initial set up for new composer.rule package
git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@2118 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
parent
2ab7fc800b
commit
c701a05d9e
11 changed files with 422 additions and 5 deletions
|
@ -37,11 +37,15 @@ class MessageManager(object):
|
||||||
messagesFactory = Jeep
|
messagesFactory = Jeep
|
||||||
|
|
||||||
messages = None
|
messages = None
|
||||||
|
manager = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
if self.messagesFactory is not None:
|
if self.messagesFactory is not None:
|
||||||
self.messages = self.messagesFactory()
|
self.messages = self.messagesFactory()
|
||||||
|
|
||||||
|
def getManager(self):
|
||||||
|
return self.manager
|
||||||
|
|
||||||
|
|
||||||
class Message(Template):
|
class Message(Template):
|
||||||
|
|
||||||
|
@ -55,5 +59,3 @@ class Message(Template):
|
||||||
for k, v in kw.items():
|
for k, v in kw.items():
|
||||||
setattr(self, k, v)
|
setattr(self, k, v)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
28
composer/rule/README.txt
Normal file
28
composer/rule/README.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
===============================
|
||||||
|
Rule-based Execution of Actions
|
||||||
|
===============================
|
||||||
|
|
||||||
|
($Id$)
|
||||||
|
|
||||||
|
>>> from zope import component
|
||||||
|
>>> from cybertools.composer.rule.base import RuleManager, Rule, Action
|
||||||
|
>>> from cybertools.composer.rule.base import EventType, Event
|
||||||
|
|
||||||
|
>>> manager = RuleManager()
|
||||||
|
|
||||||
|
>>> loginEvent = EventType('login')
|
||||||
|
>>> checkoutEvent = EventType('service.checkout')
|
||||||
|
|
||||||
|
>>> checkoutRule = Rule('regcheckoutmail', manager=manager)
|
||||||
|
>>> checkoutRule.events.append(checkoutEvent)
|
||||||
|
>>> checkoutRule.actions.append(Action('message',
|
||||||
|
... parameters = dict(messageName='confirmation_mail')))
|
||||||
|
>>> checkoutRule.actions.append(Action('sendmail'))
|
||||||
|
>>> manager.rules.append(checkoutRule)
|
||||||
|
|
||||||
|
>>> manager.handleEvent(Event(loginEvent))
|
||||||
|
|
||||||
|
>>> client = object()
|
||||||
|
|
||||||
|
>>> manager.handleEvent(Event(checkoutEvent, client))
|
||||||
|
|
4
composer/rule/__init__.py
Normal file
4
composer/rule/__init__.py
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
"""
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
149
composer/rule/base.py
Normal file
149
composer/rule/base.py
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 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 classes for rules and actions.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from cybertools.composer.base import Component, Element, Compound
|
||||||
|
from cybertools.composer.base import Template
|
||||||
|
from cybertools.composer.interfaces import IInstance
|
||||||
|
from cybertools.composer.rule.interfaces import IRuleManager, IRule
|
||||||
|
from cybertools.composer.rule.interfaces import IEvent, ICondition
|
||||||
|
from cybertools.composer.rule.interfaces import IAction, IActionHandler
|
||||||
|
from cybertools.util.jeep import Jeep
|
||||||
|
|
||||||
|
|
||||||
|
# rules
|
||||||
|
|
||||||
|
class RuleManager(object):
|
||||||
|
|
||||||
|
implements(IRuleManager)
|
||||||
|
|
||||||
|
rulesFactory = Jeep
|
||||||
|
rules = None
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
if self.rulesFactory is not None:
|
||||||
|
self.rules = self.rulesFactory()
|
||||||
|
|
||||||
|
def handleEvent(self, event):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class Rule(Template):
|
||||||
|
|
||||||
|
implements(IRule)
|
||||||
|
|
||||||
|
name = title = description = u''
|
||||||
|
manager = None
|
||||||
|
actions = None
|
||||||
|
events = None
|
||||||
|
conditions = None
|
||||||
|
|
||||||
|
def __init__(self, name, **kw):
|
||||||
|
self.name = name
|
||||||
|
for k, v in kw.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
self.events = []
|
||||||
|
self.conditions = []
|
||||||
|
self.actions = []
|
||||||
|
|
||||||
|
|
||||||
|
class RuleInstance(object):
|
||||||
|
|
||||||
|
implements(IInstance)
|
||||||
|
|
||||||
|
template = None
|
||||||
|
|
||||||
|
def applyTemplate(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# events
|
||||||
|
|
||||||
|
class EventType(object):
|
||||||
|
|
||||||
|
def __init__(self, name, title=None):
|
||||||
|
self.name = name
|
||||||
|
self.title = title or name
|
||||||
|
|
||||||
|
|
||||||
|
class Event(object):
|
||||||
|
|
||||||
|
implements(IEvent)
|
||||||
|
|
||||||
|
def __init__(self, eventType, context=None):
|
||||||
|
self.eventType = eventType
|
||||||
|
self.name = eventType.name
|
||||||
|
self.title = eventType.title
|
||||||
|
self.context = context
|
||||||
|
|
||||||
|
|
||||||
|
# conditions
|
||||||
|
|
||||||
|
class ConditionType(object):
|
||||||
|
|
||||||
|
def __init__(self, name, title):
|
||||||
|
self.name = name
|
||||||
|
self.title = title
|
||||||
|
|
||||||
|
|
||||||
|
class Condition(object):
|
||||||
|
|
||||||
|
implements(ICondition)
|
||||||
|
|
||||||
|
def __init__(self, conditionType):
|
||||||
|
self.conditionType = conditionType
|
||||||
|
self.name = conditionType.name
|
||||||
|
self.title = conditionType.title
|
||||||
|
|
||||||
|
def __call__(self, context, params):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
# actions
|
||||||
|
|
||||||
|
class Action(object):
|
||||||
|
|
||||||
|
implements(IAction)
|
||||||
|
|
||||||
|
name = u''
|
||||||
|
handlerName = u''
|
||||||
|
parameters = None
|
||||||
|
rule = None
|
||||||
|
|
||||||
|
def __init__(self, name, **kw):
|
||||||
|
for k, v in kw.items():
|
||||||
|
setattr(self, k, v)
|
||||||
|
if self.parameters is None:
|
||||||
|
self.parameters = {}
|
||||||
|
if not self.handlerName:
|
||||||
|
self.handlerName = self.name
|
||||||
|
|
||||||
|
|
||||||
|
class ActionHandler(object):
|
||||||
|
|
||||||
|
implements(IActionHandler)
|
||||||
|
|
||||||
|
def __call__(self, data, params):
|
||||||
|
pass
|
8
composer/rule/configure.zcml
Normal file
8
composer/rule/configure.zcml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<!-- $Id$ -->
|
||||||
|
|
||||||
|
<configure
|
||||||
|
xmlns="http://namespaces.zope.org/zope"
|
||||||
|
xmlns:browser="http://namespaces.zope.org/browser"
|
||||||
|
i18n_domain="zope">
|
||||||
|
|
||||||
|
</configure>
|
43
composer/rule/instance.py
Normal file
43
composer/rule/instance.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Rule instance and related classes.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from string import Template
|
||||||
|
from zope import component
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from cybertools.composer.instance import Instance
|
||||||
|
from cybertools.composer.interfaces import IInstance
|
||||||
|
|
||||||
|
|
||||||
|
class RuleInstance(Instance):
|
||||||
|
|
||||||
|
template = client = None
|
||||||
|
|
||||||
|
def __init__(self, client, template):
|
||||||
|
self.client = client
|
||||||
|
self.template = template
|
||||||
|
|
||||||
|
def applyTemplate(self, **kw):
|
||||||
|
pass
|
||||||
|
|
112
composer/rule/interfaces.py
Normal file
112
composer/rule/interfaces.py
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Message management.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.interface import Interface, Attribute
|
||||||
|
from zope.i18nmessageid import MessageFactory
|
||||||
|
from zope import schema
|
||||||
|
|
||||||
|
from cybertools.composer.interfaces import ITemplate, IComponent
|
||||||
|
|
||||||
|
_ = MessageFactory('zope')
|
||||||
|
|
||||||
|
|
||||||
|
class IRuleManager(Interface):
|
||||||
|
""" A manager (or container) for rules.
|
||||||
|
"""
|
||||||
|
|
||||||
|
title = schema.TextLine(
|
||||||
|
title=_(u'Title'),
|
||||||
|
description=_(u'The title of the object.'),
|
||||||
|
required=True,)
|
||||||
|
|
||||||
|
rules = Attribute('An ordered collection of rules managed by this object.')
|
||||||
|
|
||||||
|
def handleEvent(event):
|
||||||
|
""" Handle the event given and apply the corresponding rules
|
||||||
|
to the client object.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class IRule(ITemplate):
|
||||||
|
""" A rule that will be applied .
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = schema.ASCII(
|
||||||
|
title=_(u'Name'),
|
||||||
|
description=_(u'The internal name of the rule.'),
|
||||||
|
required=True,)
|
||||||
|
title = schema.TextLine(
|
||||||
|
title=_(u'Title'),
|
||||||
|
description=_(u'The title or label of the rule.'),
|
||||||
|
required=True,)
|
||||||
|
description = schema.Text(
|
||||||
|
title=_(u'Description'),
|
||||||
|
description=_(u'A brief description of the rule.'),
|
||||||
|
required=False,)
|
||||||
|
|
||||||
|
manager = Attribute('The associated rule manager.')
|
||||||
|
events = Attribute('The events to be handled by this rule.')
|
||||||
|
conditions = Attribute('Conditions to be checked.'
|
||||||
|
'This is typically a list of names of ICondition adapters.')
|
||||||
|
actions = Attribute('Sequence of actions to be carried out by this rule.')
|
||||||
|
|
||||||
|
|
||||||
|
class IEvent(Interface):
|
||||||
|
|
||||||
|
name = Attribute('The name by which the event will be identified.')
|
||||||
|
title = Attribute('A human readable title or label.')
|
||||||
|
context = Attribute('An object that is associated with the event.')
|
||||||
|
|
||||||
|
|
||||||
|
class ICondition(Interface):
|
||||||
|
|
||||||
|
def __call__(context, params):
|
||||||
|
""" Should return True if the condition should be fulfilled;
|
||||||
|
will allow the rule to call its actions.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class IAction(IComponent):
|
||||||
|
""" Controls what will be done.
|
||||||
|
"""
|
||||||
|
|
||||||
|
name = schema.ASCII(
|
||||||
|
title=_(u'Name'),
|
||||||
|
description=_(u'The name of the action.'),
|
||||||
|
required=True,)
|
||||||
|
|
||||||
|
handlerName = Attribute('Name of the adapter that will carry out the action.')
|
||||||
|
parameters = Attribute('Mapping with additional preset informations that '
|
||||||
|
'will be supplied to the action handlers.')
|
||||||
|
rule = Attribute('The rule the action belongs to.')
|
||||||
|
|
||||||
|
|
||||||
|
class IActionHandler(Interface):
|
||||||
|
""" Does the real work.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __call__(data, params):
|
||||||
|
""" Execute the action, using the data and parameters given (mappings).
|
||||||
|
"""
|
||||||
|
|
33
composer/rule/mail.py
Normal file
33
composer/rule/mail.py
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#
|
||||||
|
# Copyright (c) 2007 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
|
||||||
|
#
|
||||||
|
|
||||||
|
"""
|
||||||
|
Event definitions.
|
||||||
|
|
||||||
|
$Id$
|
||||||
|
"""
|
||||||
|
|
||||||
|
from zope.interface import implements
|
||||||
|
|
||||||
|
from cybertools.composer.rule.base import ActionHandler
|
||||||
|
|
||||||
|
|
||||||
|
class MailActionHandler(ActionHandler):
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
22
composer/rule/tests.py
Executable file
22
composer/rule/tests.py
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
# $Id$
|
||||||
|
|
||||||
|
import unittest, doctest
|
||||||
|
from zope.testing.doctestunit import DocFileSuite
|
||||||
|
|
||||||
|
|
||||||
|
class Test(unittest.TestCase):
|
||||||
|
"Basic tests."
|
||||||
|
|
||||||
|
def testBasics(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')
|
|
@ -17,7 +17,8 @@
|
||||||
#
|
#
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Basic classes for a complex template structures.
|
Basic classes for schemas, i.e. sets of fields that may be used for creating
|
||||||
|
editing forms or display views for objects.
|
||||||
|
|
||||||
$Id$
|
$Id$
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -31,6 +31,7 @@ from zope import component
|
||||||
from zope.interface import implements, Interface
|
from zope.interface import implements, Interface
|
||||||
|
|
||||||
from cybertools.composer.interfaces import IInstance
|
from cybertools.composer.interfaces import IInstance
|
||||||
|
from cybertools.composer.rule.base import RuleManager, EventType
|
||||||
from cybertools.composer.schema.interfaces import IClientManager, IClient
|
from cybertools.composer.schema.interfaces import IClientManager, IClient
|
||||||
from cybertools.stateful.definition import registerStatesDefinition
|
from cybertools.stateful.definition import registerStatesDefinition
|
||||||
from cybertools.stateful.definition import StatesDefinition
|
from cybertools.stateful.definition import StatesDefinition
|
||||||
|
@ -43,16 +44,18 @@ from cybertools.organize.interfaces import IRegistration, IRegistrationTemplate
|
||||||
from cybertools.organize.interfaces import IClientRegistrations
|
from cybertools.organize.interfaces import IClientRegistrations
|
||||||
|
|
||||||
|
|
||||||
class ServiceManager(object):
|
class ServiceManager(RuleManager):
|
||||||
|
|
||||||
implements(IServiceManager, IClientManager)
|
implements(IServiceManager, IClientManager)
|
||||||
|
|
||||||
servicesFactory = Jeep
|
servicesFactory = Jeep
|
||||||
clientSchemasFactory = Jeep
|
clientSchemasFactory = Jeep
|
||||||
clientsFactory = OOBTree
|
clientsFactory = OOBTree
|
||||||
|
rulesFactory = Jeep
|
||||||
|
|
||||||
services = None
|
services = None
|
||||||
clients = None
|
clients = None
|
||||||
|
rules = None
|
||||||
|
|
||||||
allowRegWithNumber = False
|
allowRegWithNumber = False
|
||||||
allowDirectRegistration = True
|
allowDirectRegistration = True
|
||||||
|
@ -62,6 +65,8 @@ class ServiceManager(object):
|
||||||
self.services = self.servicesFactory()
|
self.services = self.servicesFactory()
|
||||||
if self.clientSchemasFactory is not None:
|
if self.clientSchemasFactory is not None:
|
||||||
self.clientSchemas = self.clientSchemasFactory()
|
self.clientSchemas = self.clientSchemasFactory()
|
||||||
|
if self.rulesFactory is not None:
|
||||||
|
self.rules = self.rulesFactory()
|
||||||
|
|
||||||
def getServices(self, categories=[]):
|
def getServices(self, categories=[]):
|
||||||
return self.services
|
return self.services
|
||||||
|
@ -88,6 +93,9 @@ class ServiceManager(object):
|
||||||
def checkClientName(self, name):
|
def checkClientName(self, name):
|
||||||
return name not in self.getClients()
|
return name not in self.getClients()
|
||||||
|
|
||||||
|
def getRules(self):
|
||||||
|
return self.rules
|
||||||
|
|
||||||
|
|
||||||
class Service(object):
|
class Service(object):
|
||||||
|
|
||||||
|
@ -274,7 +282,14 @@ registerStatesDefinition(
|
||||||
))
|
))
|
||||||
|
|
||||||
|
|
||||||
# event handlers
|
# event types
|
||||||
|
|
||||||
|
eventTypes = Jeep((
|
||||||
|
EventType('service.checkout'),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
|
# Zope event handlers
|
||||||
|
|
||||||
def clientRemoved(obj, event):
|
def clientRemoved(obj, event):
|
||||||
""" Handle removal of a client object.
|
""" Handle removal of a client object.
|
||||||
|
|
Loading…
Add table
Reference in a new issue