Skip to main content

A library for abstracting interactions with different WASPs

Project description

This package is an abstraction of interactions with WASPs allowing application developers to send and recieve messages without having to worry about the mechanics of sending and recieving messages with a particular wasp.

It also allows the WASP being used to be changed by configuration only, without any changes to application code.

Installation

To install the package, unpack the source distribution and then do:

python setup.py install

You can also install with easy_install:

easy_install wasp

Alternatively, if you’re using zc.buildout, you can just specify the package as an egg requirement:

[buildout]
parts = myeggs ...
...

[myeggs]
recipe = zc.recipe.egg
eggs = wasp
...

Finally, if you’re using with Zope 2, just unpack the source distribution into $INSTANCE_HOME/lib/python. Be careful if you use easy_install or a buildout recipe with a Zope 2 base distribution, such as that used by Plone, as versions of the packages requires by wasp may be installed that are incompatible with Zope 2.

Configuration

The configuration of sending and receiving messages centres around the configuration of utilities providing ISendMessage, INotifyMessage and IRecieveMessage. Reading the documentation for these in interfaces.py will cover a lot of the explanation required to use the wasp package.

To use the package, the first thing you’ll need to do is choose a WASP implementation and load any ZCML directives it provides. For the examples here, we’ll use the demo implementations which basically echo all their actions to the console rather than actually doing anything:

>>> load_zcml('''
... <include package="wasp.demo" file="meta.zcml" />
... ''')

In order to send messages, you need to wire in the ISendMessage utility of your chosen WASP. WASP implementations usually provide a custom ZCML directive for doing this which allows you to specify the parameters.

The demo implementation is no exception:

>>> load_zcml('''
... <configure
...     xmlns="http://namespaces.zope.org/zope"
...     xmlns:wasp="http://namespaces.simplistix.co.uk/wasp">
...     <wasp:sender />
... </configure>
... ''')

Next, if you’re planning on receiving messages or notifications about messages you’ve sent, you need to wire in the Receiver view. For demonstration purposes, we wire it to all objects, but you probably only want to wire it in such that it appears at one particular url.

>>> load_zcml('''
... <configure
...     xmlns="http://namespaces.zope.org/zope"
...     xmlns:browser="http://namespaces.zope.org/browser">
...   <browser:page
...       name="wasp"
...       for="*"
...       class="wasp.Receiver"
...       permission="zope.Public"
...
...     />
... </configure>
... ''')

Again, if you’re planning on receiving messages or notifications about messages you’ve sent, you need to wire in an IProcessReponse utility. This is WASP-specific but can be changed independently of where the Receiver view is or how it’s wired in. This means that application developers only have to worry about wiring in the Receiver view where they want it and system administrators can choose and change the WASP implementation used whenever they want.

For the examples, we’ll use a wasp.demo.ProcessResponse implementation:

>>> load_zcml('''
... <configure
...     xmlns="http://namespaces.zope.org/zope">
...     <utility factory="wasp.demo.ProcessResponse"/>
... </configure>
... ''')

Sending Messages

Once configured, sending messages is as simple as:

>>> from wasp import send
>>> send('271234','some message')
Send to: '271234'
Message: 'some message'
     Id: None
True

As this shows, the send method takes an msisdn, a message and optionally a message_id.

If send returns True, it indicates that the message has been successfully delivered. If something goes wrong, an exception will be raised.

However, the most common case is when send returns False:

>>> load_zcml('''
... <configure
...     xmlns="http://namespaces.zope.org/zope"
...     xmlns:wasp="http://namespaces.simplistix.co.uk/wasp">
...     <wasp:sender response="False"/>
... </configure>
... ''')
>>> send('271234','some message','id4321')
Send to: '271234'
Message: 'some message'
     Id: 'id4321'
False

A return value of False means that the message has successfully been passed to the WASP, but the WASP didn’t have a definite response at this stage. To find out what happened, the application progammer must pass a message_id. This will be passed to the WASP and when the WASP calls back, this message_id will be returned. This is the subject of the next section.

Receiving Notifications About Sent Messages

To receive notifications about sent messages, the application programmer must provide an INotifyMessage utility.

Here’s a really simple example of this:

>>> class HandleNotification:
...     def __call__(self,message_id,status,details):
...         print "message_id:",repr(message_id)
...         print "    status:",repr(status)
...         print "   details:",repr(details)

Normally, we’d register this utility with ZCML, but here we do so directly with the component architecture:

>>> from wasp.interfaces import INotifyMessage
>>> from zope.component import provideUtility
>>> provideUtility(HandleNotification(),provides=INotifyMessage)

We can show this in action by using the demo WASP implementations method of calling back:

>>> browser.open('http://localhost/@@wasp?type=notification&message_id=123&status=delivered&details=ok')
message_id: u'123'
    status: <wasp.status.Delivered instance at ...>
   details: u'ok'

Now, in some cases, particularly if data is stored in the zodb, it’s convenient to have access to the context of the Receiver view. The wasp package supports this by letting you register an adapter instead of a utility.

Here’s a simple example of a suitable adapter:

>>> class HandleNotification:
...     def __init__(self,context):
...         self.context = context
...     def __call__(self,message_id,status,details):
...         print "   context:",self.context
...         print "message_id:",repr(message_id)
...         print "    status:",repr(status)
...         print "   details:",repr(details)

This should generally be registered for all objects as the Receiver view will make sure that only its context is adapted:

>>> from wasp.interfaces import INotifyMessage
>>> from zope.component import provideAdapter
>>> provideAdapter(HandleNotification,adapts=(None,),provides=INotifyMessage)

Now when a notification is received, the code called has access to the context:

>>> browser.open('http://localhost/@@wasp?type=notification&message_id=123&status=delivered&details=ok')
   context: <security proxied zope.app.folder.folder.Folder instance at ...>
message_id: u'123'
    status: <wasp.status.Delivered instance at ...>
   details: u'ok'

Receiving Messages

To receive messages, the application programmer must provide an IReceiveMessage utility.

Here’s a really simple example of this:

>>> class HandleMessage:
...     def __call__(self,msisdn,message_text):
...         print "      msisdn:",repr(msisdn)
...         print "message_text:",repr(message_text)

Normally, we’d register this utility with ZCML, but here we do so directly with the component architecture:

>>> from wasp.interfaces import IReceiveMessage
>>> from zope.component import provideUtility
>>> provideUtility(HandleMessage(),provides=IReceiveMessage)

We can show this in action by using the demo WASP implementations method of calling back:

>>> browser.open('http://localhost/@@wasp?type=message&msisdn=123&message_text=my+message')
      msisdn: u'123'
message_text: u'my message'

Now, in some cases, particularly if data is stored in the zodb, it’s convenient to have access to the context of the Receiver view. The wasp package supports this by letting you register an adapter instead of a utility.

Here’s a simple example of a suitable adapter:

>>> class HandleMessage:
...     def __init__(self,context):
...         self.context = context
...     def __call__(self,msisdn,message_text):
...         print "     context:",self.context
...         print "      msisdn:",repr(msisdn)
...         print "message_text:",repr(message_text)

This should generally be registered for all objects as the Receiver view will make sure that only its context is adapted:

>>> from wasp.interfaces import IReceiveMessage
>>> from zope.component import provideAdapter
>>> provideAdapter(HandleMessage,adapts=(None,),provides=IReceiveMessage)

Now when a message is received, the code called has access to the context:

>>> browser.open('http://localhost/@@wasp?type=message&msisdn=123&message_text=my+message')
     context: <security proxied zope.app.folder.folder.Folder instance at ...>
      msisdn: u'123'
message_text: u'my message'

Currently Available WASPs

Documentation for the configuration of the currently avalable WASPs is found in the ‘readme.txt’ of each of the wasp subpackages. Each subpackage represents a different WASP implementation.

The currently available WASP implementations are listed below:

demo

a WASP for testing that just echos requests and responses.

bulksms

an implementation for the service provided by http://bulksms.2way.co.za/

Licensing

Copyright (c) 2008 Simplistix Ltd

This Software is released under the MIT License: http://www.opensource.org/licenses/mit-license.html See license.txt for more details.

Credits

Roche Compaan and Rijk Stofberg at Upfront

Ideas and funding

Chris Withers

Development

Changes

1.0.1

  • first open source release

1.0.0

  • implementation for BulkSMS WASP.

  • clarified the meaning of msisdn in IReceiveMessage

  • added a generic SendException for use by WASP implementations.

  • change IProcessResponse to cater for returning notifications, messages and a response for the browser

0.9.0

  • initial release featuring only the demo implementation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wasp-1.0.1.tar.gz (19.1 kB view hashes)

Uploaded Source

Built Distribution

wasp-1.0.1-py2.4.egg (48.7 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page