Palladion Software
user icon Guest

Sample Pipelines Usage

Created by tseaver. Last modified 2005-06-27 14:33:37.

Pipelined Event Subscription
============================

The traditional Zope3 event subscription model provides no guarantees
of ordering in the delivery of event to subscribers.

This package provides an extension to allow the site manager to arrange
a set of subscribers for a particular event in order.

Use Cases
+++++++++

Site Integrator Imposes Site Identity
-------------------------------------

An integrator can take the output rendered by the CMS and
impose corporate standards / logos, etc., without modifying
the skins of the CMS. She does this by registering a pipeline
for the IEndRequestEvent emitted by the publication object, and
transform the response body. Each transformation would be
a filter in an event pipeline.

Let's create the pipeline filters. The first one just converts the
response body to a DOM:

>>> def domify(event, state):
... # Add a 'dom' attribute to the response, using minidom.
... from xml.dom.minidom import parseString
... response = event.request.response
... state.dom = parseString(response.body)

The second filter adds a copyright statement at the very end of the
body of the response:

>>> def addCopyright(event, state):
... # Add a copyright paragraph at the end of the response's body.
... # N.B.: expects DOM already parsed.
... from xml.dom.minidom import Element, Text
... dom = state.dom
... graph = Element(tagName='p')
... text = Text()
... text.data = 'Copyright 2005 Example Company'
... graph.appendChild(text)
... body = dom.getElementsByTagName('body')[0]
... body.appendChild(graph)

The last filter re-stringifies the DOM and replaces the response body.

>>> def replaceBodyFromDOM(event, state):
... response = event.request.response
... dom = state.dom
... response.setBody(dom.toxml())

Now, construct a pipeline from the three filters:

>>> filters = (domify, addCopyright, replaceBodyFromDOM)
>>> from pipelines.pipeline import Pipeline
>>> pipeline = Pipeline(filters)

Next, synthesize a request / response for testing the event delivery:

>>> class FauxRequest:
... pass
>>> class FauxResponse:
... body = ''
... def setBody(self, value):
... self.body = value
>>> request = FauxRequest()
>>> response = request.response = FauxResponse()

Check that the pipeline works when handed directly to the pipeline:

>>> from zope.app.publication.interfaces import EndRequestEvent
>>> event = EndRequestEvent(None, request)
>>> response.setBody("<html><body></body></html>")
>>> pipeline.processFilters(event) and None # don't care about result
>>> print response.body

<html><body><p>Copyright 2005 Example Company</p></body></html>


Then, check that the pipeline works cleanly as a subscriber to the
EndRequestEvent.

>>> from zope.app.zapi import getGlobalSiteManager
>>> from zope.app.publication.interfaces import IEndRequestEvent
>>> gsm = getGlobalSiteManager()
>>> gsm.subscribe([IEndRequestEvent], None, pipeline)

Then, publish the "done publishing" event:

>>> from zope.event import notify
>>> response.setBody("<html><body></body></html>")
>>> notify(event)

Finally, verify that our pipeline ran in response to the event:

>>> print response.body

<html><body><p>Copyright 2005 Example Company</p></body></html>


User Requests Transform of a Document to PDF
--------------------------------------------

While viewing a document, a user requests a PDF version of the
document. The 'asPDF' view fetches the "raw" content of the document,
and then publishes an IContentRendering event. The transforms which
convert the raw content to PDF are defined as a pipeline, which
incrementally converts the content, e.g. from restructured text to HTML
to PDF.

In this mode, rather than registering the pipeline as an event subscriber,
we register it as a named utility implementing IPipeline. Application code
then looks it up as a utility in order to call it.