diff --git a/composer/message/README.txt b/composer/message/README.txt new file mode 100644 index 0000000..c91b933 --- /dev/null +++ b/composer/message/README.txt @@ -0,0 +1,54 @@ +================== +Message Management +================== + + ($Id$) + + >>> from zope import component + >>> from cybertools.composer.message.base import MessageManager, Message + + >>> manager = MessageManager() + + >>> manager.messages.append(Message('feedback_html', manager=manager)) + >>> manager.messages.append(Message('feedback_text', manager=manager)) + >>> manager.messages.append(Message('footer', manager=manager)) + + >>> messageText = '''Dear $person.firstname $person.lastname, + ... You have been registered for the following $services. + ... $@@list_registrations + ... $footer + ... ''' + + >>> manager.messages['feedback_text'].text = messageText + >>> manager.messages['footer'].text = 'Best regards, $sender' + + >>> manager.messages.append(Message('sender', manager=manager, text='Jack')) + >>> manager.messages.append(Message('services', manager=manager, text='events')) + +Message interpolation +--------------------- + + >>> from cybertools.composer.message.instance import MessageTemplate + >>> t = MessageTemplate(messageText) + >>> print t.safe_substitute({ + ... 'person.firstname': 'John', 'person.lastname': 'Smith', + ... '@@list_registrations': '0815: Python Introduction', + ... 'services': 'events', + ... 'footer': 'Regards, $sender'}) + Dear John Smith, + You have been registered for the following events. + 0815: Python Introduction + Regards, $sender + + +Working with message instances +------------------------------ + + >>> from cybertools.composer.message.instance import MessageInstance + >>> mi = MessageInstance(None, manager.messages['feedback_text']) + >>> print mi.applyTemplate() + Dear $person.firstname $person.lastname, + You have been registered for the following events. + $@@list_registrations + Best regards, Jack + diff --git a/composer/message/__init__.py b/composer/message/__init__.py new file mode 100644 index 0000000..4bc90fb --- /dev/null +++ b/composer/message/__init__.py @@ -0,0 +1,4 @@ +""" +$Id$ +""" + diff --git a/composer/message/base.py b/composer/message/base.py new file mode 100644 index 0000000..ce1e848 --- /dev/null +++ b/composer/message/base.py @@ -0,0 +1,59 @@ +# +# 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 message management. + +$Id$ +""" + +from zope.interface import implements + +from cybertools.composer.base import Component, Element, Compound +from cybertools.composer.base import Template +from cybertools.composer.message.interfaces import IMessageManager, IMessage +from cybertools.util.jeep import Jeep + + +class MessageManager(object): + + implements(IMessageManager) + + messagesFactory = Jeep + + messages = None + + def __init__(self): + if self.messagesFactory is not None: + self.messages = self.messagesFactory() + + +class Message(Template): + + implements(IMessage) + + name = u'' + manager = None + + def __init__(self, name, **kw): + self.name = name + for k, v in kw.items(): + setattr(self, k, v) + + + diff --git a/composer/message/configure.zcml b/composer/message/configure.zcml new file mode 100644 index 0000000..02b5d8b --- /dev/null +++ b/composer/message/configure.zcml @@ -0,0 +1,8 @@ + + + + + diff --git a/composer/message/instance.py b/composer/message/instance.py new file mode 100644 index 0000000..1944909 --- /dev/null +++ b/composer/message/instance.py @@ -0,0 +1,81 @@ +# +# 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 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 MessageInstance(Instance): + + template = client = None + + def __init__(self, client, template): + self.client = client + self.template = template + + def applyTemplate(self, **kw): + data = DataProvider(self) + return MessageTemplate(self.template.text).safe_substitute(data) + + +class DataProvider(object): + + def __init__(self, context): + self.context = context + + def __getitem__(self, key): + client = self.context.client + messageManager = self.context.template.manager + if key.startswith('@@'): + viewName = key[2:] + if client is None: + return '$' + key + view = component.getMultiAdapter( + (client.manager, TestRequest(form=form)), name=viewName) + return view() + elif key in messageManager.messages: + #mi = component.getMultiAdapter( + # (client, messageManager.messages[key]), IInstance) + mi = MessageInstance(client, messageManager.messages[key]) + return mi.applyTemplate() + elif '.' in key: + if client is None: + return '$' + key + schemaName, fieldName = key.split('.', 1) + schema = client.manager.clientSchemas[schemaName] + instance = IInstance(client) + instance.template = schema + data = instance.applyTemplate() + return data[fieldName] + else: + raise KeyError(key) + + +class MessageTemplate(Template): + + idpattern = r'@{0,2}[_a-z][_.a-z0-9]*[_a-z0-9]+' diff --git a/composer/message/interfaces.py b/composer/message/interfaces.py new file mode 100644 index 0000000..3341a9e --- /dev/null +++ b/composer/message/interfaces.py @@ -0,0 +1,48 @@ +# +# 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 IMessageManager(Interface): + """ A manager (or container) for complex messages. + """ + + messages = Attribute('A collection of message objects managed.') + + +class IMessage(ITemplate): + """ A complex message that may be expanded using instance data. + """ + + manager = Attribute('The manager of this message object') + + text = schema.Text() + diff --git a/composer/message/tests.py b/composer/message/tests.py new file mode 100755 index 0000000..9886053 --- /dev/null +++ b/composer/message/tests.py @@ -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')