Wouldn’t it be nice if you coud use Yahoo Pipes as a visual editor for generating your own feed powered applications running on your own server? Now you can…
One of the concerns occasionally raised around Yahoo Pipes (other than the stability and responsiveness issues) relates to the dependence that results on the Yahoo pipes platform from creating a pipe. Where a pipe is used to construct an information feed that may get published on an “official” web page, users need to feel that content will always be being fed through the pipe, not just when when Pipes feels like it. (Actually, I think the Pipes backend is reasonably stable, it’s just the front end editor/GUI that has its moments…)
Earlier this year, I started to have a ponder around the idea of a Yahoo Pipes Documentation Project (the code appears to have rotted unfortunately; I think I need to put a proper JSON parser in place:-(, which would at least display a textual description of a pipe based on the JSON representation of it that you can access via the Pipes environment. Around the same time, I floated an idea for a code generator, that would take the JSON description of a pipe and generate Python or PHP code capable of achieving a similar function to the Pipe from the JSON description of it.
Greg Gaughan picked up the challenge and came up with a Python code generator for doing just that, written in Python. (I didn’t blog it at the time because I wanted to help Greg extend the code to cover more modules, but I never delivered on my part of the bargain:-(
Anyway – the code is at http://github.com/ggaughan/pipe2py and it works as follows. Install the universal feed parser (sudo easy_install feedparser) and simplejson (sudo easy_install simplejson), then download Greg’s code and declare the path to it, maybe something like:
export PYTHONPATH=$PYTHONPATH:/path/to/pipe2py.
Given the ID for a pipe on Yahoo pipes, generate a Python compiled version of it:
python compile.py -p PIPEID
This generates a file pipe_PIPEID.py containing a function pipe_PIPEID() which returns a JSON object equivalent of the output of the corresponding Yahoo pipe, the major difference being that it’s the locally compiled pipe code that’s running, not the Yahoo pipe…
So for example, for the following simple pipe, which just grabs the OUseful.info blog feed and passes it straight through:
we generate a Python version of the pipe as follows:
python compile.py -p 404411a8d22104920f3fc1f428f33642
This generates the following code:
from pipe2py import Context from pipe2py.modules import * def pipe_404411a8d22104920f3fc1f428f33642(context, _INPUT, conf=None, **kwargs): "Pipeline" if conf is None: conf = {} forever = pipeforever.pipe_forever(context, None, conf=None) sw_502 = pipefetch.pipe_fetch(context, forever, conf={u'URL': {u'type': u'url', u'value': u'https://blog.ouseful.info/feed'}}) _OUTPUT = pipeoutput.pipe_output(context, sw_502, conf={}) return _OUTPUT
We can then run this code as part of our own program. For example, grab the feed items and print out the feed titles:
context = Context() p = pipe_404411a8d22104920f3fc1f428f33642(context, None) for i in p: print i['title']
Not all the Yahoo Pipes blocks are implemented (if you want to volunteer code, I’m sure Greg would be happy to accept it!;-), but for simple pipes, it works a dream…
So for example, here’s a couple of feed mergers and then a sort on the title…
And a corresponding compilation, along with a small amount of code to display the titles of each post, and the author:
from pipe2py import Context from pipe2py.modules import * def pipe_2e4ef263902607f3eec61ed440002a3f(context, _INPUT, conf=None, **kwargs): "Pipeline" if conf is None: conf = {} forever = pipeforever.pipe_forever(context, None, conf=None) sw_550 = pipefetch.pipe_fetch(context, forever, conf={u'URL': [{u'type': u'url', u'value': u'https://blog.ouseful.info/feed'}, {u'type': u'url', u'value': u'http://feeds.feedburner.com/TheEdTechie'}]}) sw_572 = pipefetch.pipe_fetch(context, forever, conf={u'URL': {u'type': u'url', u'value': u'http://www.greenhughes.com/rssfeed'}}) sw_580 = pipeunion.pipe_union(context, sw_550, conf={}, _OTHER = sw_572) sw_565 = pipesort.pipe_sort(context, sw_580, conf={u'KEY': [{u'field': {u'type': u'text', u'value': u'title'}, u'dir': {u'type': u'text', u'value': u'ASC'}}]}) _OUTPUT = pipeoutput.pipe_output(context, sw_565, conf={}) return _OUTPUT context = Context() p = pipe_2e4ef263902607f3eec61ed440002a3f(context, None) for i in p: print i['title'], ' by ', i['author']
And the result?
MCMT013:pipes ajh59$ python basicTest.py
Build an app to search Delicious using your voice with the Android App Inventor by Liam Green-Hughes
Digging Deeper into the Structure of My Twitter Friends Network: Librarian Spotting by Tony Hirst
Everyday I write the book by mweller
...
So there we have it.. Thanks to Greg, the first pass at a Yahoo Pipes to Python compiler…
PS Note to self… I noticed that the ‘truncate’ module isn’t supported, so as it’s a relatively trivial function, maybe I should see if I can write a compiler block to implement it…
PPS Greg has also started exploring how to export a pipe so that it can be run on Google App Engine: Running Yahoo! Pipes on Google App Engine