Welcome, guest | Sign In | My Account | Store | Cart

Notice! PyPM is being replaced with the ActiveState Platform, which enhances PyPM’s build and deploy capabilities. Create your free Platform account to download ActivePython or customize Python with the packages you require and get automatic updates.

Download
ActivePython
INSTALL>
pypm install durian

How to install durian

  1. Download and install ActivePython
  2. Open Command Prompt
  3. Type pypm install durian
 Python 2.7Python 3.2Python 3.3
Windows (32-bit)
0.1.0 Available View build log
Windows (64-bit)
0.1.0 Available View build log
Mac OS X (10.5+)
0.1.0 Available View build log
Linux (32-bit)
0.1.0 Available View build log
Linux (64-bit)
0.1.0 Available View build log
 
Author
Lastest release
version 0.1.0 on Jan 5th, 2011
http://cloud.github.com/downloads/ask/durian/webhooks-logo.png

Introduction

We want the web sites we create to communicate with other sites. To enable this we give the clients an URL they can connect to. This is fine for most requests, but let's take a look at RSS.

RSS publishes your articles for others to subscribe to. Whenever you have a new article to publish you add it to the RSS document available at an URL like:

System Message: WARNING/2 (<string>, line 20)

Literal block expected; none found.

http://example.com/articles.rss

The client connects to this URL, say, every 20 minutes to check if there's something new. And if there is something new, it has to re-download the entire content, even if it already has some of the articles from before. We call this communication method pulling.

This is where web hooks (or HTTP callbacks) comes in, instead of giving the clients an URL they can connect to, the clients give you an URL you connect to every time there is something to update.

By pushing instead of pulling the updates, both you and your clients saves bandwidth, sometimes by a lot.

http://cloud.github.com/downloads/ask/durian/webhook-callback2.png

You can read more about web hooks at the Web Hooks Blog. These slides by Jeff Lindsay is a good introduction to the subject: Using Web Hooks.

System Message: WARNING/2 (<string>, line 42)

Explicit markup ends without a blank line; unexpected unindent.

http://www.slideshare.net/progrium/using-web-hooks .. pushing: http://en.wikipedia.org/wiki/Push_technology .. pulling: http://en.wikipedia.org/wiki/Pull_technology

NOTE This software is just in the planning stage and is going to change drastically. You can follow what is happening here, and is welcome to help out making it happen, but you should probably not use it for anything until it has reached an alpha version.

Examples

Creating an event with a model and a signal

In this example we'll be creating a ModelHook.

A ModelHook is a hook which takes a Django model and signal. So whenever that signal is fired, the hook is also triggered.

You can specify which of the model fields you want to pass on to the listeners via the provides_args attribute.

First let's create a simple model of a person storing the persons name, address and a secret field we don't want to pass on to listeners:

>>> from django.db import models
>>> from django.utils.translation import ugettext_lazy as _
>>> class Person(models.Model):
...     name = models.CharField(_(u"name"), blank=False, max_length=200)
...     address = models.CharField(_(u"address"), max_length=200)
...     secret = models.CharField(_(u"secret"), max_length=200)

Now to the hook itself. We subclass the ModelHook class and register it in the global webhook registry. For now we'll set async to False, this means the tasks won't be sent to celeryd but executed locally instead. In production you would certainly want the dispatch to be asynchronous.

>>> from durian.event import ModelHook
>>> from durian.registry import hooks
>>> from django.db.models import signals
>>> class PersonHook(ModelHook):
...     name = "person"
...     model = Person
...     signal = signals.post_save
...     provides_args = ["name", "address"]
...     async = False
>>> hooks.register(PersonHook)

Now we can create ourselves some listeners. They can be created manually or by using the web-interface. A listener must have a URL, which is the destination callback the signal is sent to, and you can optionally filter events so you only get the events you care about.

>>> # send event when person with name Joe is changed/added.
>>> PersonHook().listener(
...     url="http://where.joe/is/listening").match(
...     name="Joe").save()
>>> # send event whenever a person with a name that starts with the
>>> # letter "J" is changed/added:
>>> from durian.match import Startswith
>>> PersonHook().listener(
...     url="http://where.joe/is/listening").match(
...     name=Startswith("J").save()
>>> # send event when any Person is changed/added.
>>> PersonHook().listener(url="http://where.joe/is/listening").save()

The filters can use special matching classes, as you see with the Startswith above. See Matching classes for a list of these.

In this screenshot you can see the view for selecting the person event:

System Message: ERROR/3 (<string>, line 122)

Error in "image" directive: 1 argument(s) required, 0 supplied.

.. image::

System Message: WARNING/2 (<string>, line 123)

Explicit markup ends without a blank line; unexpected unindent.

http://cloud.github.com/downloads/ask/durian/durian-shot-select_event.png

and then creating a listener for that event:

System Message: ERROR/3 (<string>, line 127)

Error in "image" directive: 1 argument(s) required, 0 supplied.

.. image::

System Message: WARNING/2 (<string>, line 128)

Explicit markup ends without a blank line; unexpected unindent.

http://cloud.github.com/downloads/ask/durian/durian-shot-create_listenerv2.png

Creating custom hooks

Sometimes you'd like to create hooks for something else than a model. If there's already a Django signal you want to bind to there is the SignalHook. Otherwise you can send your own signal by creating a custom Hook.

The only required attribute of a hook is the name, so it can be uniquely identified in the hook registry.

There are two ways of defining a hook, either by instantiation a Hook class, or by subclassing one. You can register a hook instance, or a hook class, it doesn't matter as long as the name is different:

>>> from durian.registry import hooks
>>> # Defining a hook by instantiating a hook class:
>>> myhook = Hook(name="myhook")
>>> hooks.register(myhook)
>>> # Defining a hook by subclassing a hook class:
>>> class MyHook(Hook):
...     name = "myhook"
>>> hooks.register(MyHook)

These also supports the provides_args attribute which can automatically generate event filter forms.

See the API reference for a complete list of Hook arguments and attributes.

Triggering a hook is simple by using the send method:

>>> class MyHook(Hook):

System Message: ERROR/3 (<string>, line 167)

Inconsistent literal block quoting.

... name = "myhook" ... provides_args = ["name", "address"] ... async = False >>> hooks.register(MyHook)

>>> MyHook().send(sender=None,
...               name="George Constanza", address="New York City")
View for listening URL
>>> from django.http import HttpResponse
>>> from anyjson import deserialize
>>> def listens(request):
...     payload = deserialize(request.raw_post_data)
...     print(payload["name"])
...     return HttpResponse("thanks!")
Matching classes
  • Any()

System Message: WARNING/2 (<string>, line 193)

Bullet list ends without a blank line; unexpected unindent.

Matches anything. Even if the field is not sent at all.

  • Is(pattern)

System Message: WARNING/2 (<string>, line 196)

Bullet list ends without a blank line; unexpected unindent.

Strict equality. The values must match precisely.

  • Startswith(pattern)

System Message: WARNING/2 (<string>, line 199)

Bullet list ends without a blank line; unexpected unindent.

Matches if the string starts with the given pattern.

  • Endswith(pattern)

System Message: WARNING/2 (<string>, line 202)

Bullet list ends without a blank line; unexpected unindent.

Matches if the string ends with the given pattern

  • Contains(pattern)

System Message: WARNING/2 (<string>, line 205)

Bullet list ends without a blank line; unexpected unindent.

Matches if the string contains the given pattern.

  • Like(regex)

System Message: WARNING/2 (<string>, line 208)

Bullet list ends without a blank line; unexpected unindent.

Match by a regular expression.

Installation

You can install durian either via the Python Package Index (PyPI) or from source.

To install using pip,:

$ pip install durian

To install using easy_install,:

$ easy_install durian

If you have downloaded a source tarball you can install it by doing the following,:

$ python setup.py build

System Message: ERROR/3 (<string>, line 232)

Inconsistent literal block quoting.

# python setup.py install # as root

Examples

License

BSD License

Contact

Ask Solem <askh@opera.com>

Subscribe to package updates

Last updated Jan 5th, 2011

Download Stats

Last month:1

What does the lock icon mean?

Builds marked with a lock icon are only available via PyPM to users with a current ActivePython Business Edition subscription.

Need custom builds or support?

ActivePython Enterprise Edition guarantees priority access to technical support, indemnification, expert consulting and quality-assured language builds.

Plan on re-distributing ActivePython?

Get re-distribution rights and eliminate legal risks with ActivePython OEM Edition.