<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lonely Code</title>
	<atom:link href="http://www.lonelycode.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.lonelycode.com</link>
	<description>Code, for one...</description>
	<lastBuildDate>Sat, 05 May 2012 16:56:20 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Using OpenCV, Python and Face.com for simple face recognition</title>
		<link>http://www.lonelycode.com/2012/05/05/using-opencv-python-and-face-com-to-build-a-simple-face-recognition-system/</link>
		<comments>http://www.lonelycode.com/2012/05/05/using-opencv-python-and-face-com-to-build-a-simple-face-recognition-system/#comments</comments>
		<pubDate>Sat, 05 May 2012 16:54:31 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=503</guid>
		<description><![CDATA[<strong><a href="/2012/05/05/using-opencv-python-and-face-com-to-build-a-simple-face-recognition-system/"><img class="aligncenter size-full wp-image-510" title="face_title_png" src="http://www.lonelycode.com/wp-content/uploads/2012/05/face_title_png.png" alt="" /></a></strong>

<p>I've been interested in computer vision for quite some time, and the opportunity to tinker with face detection (in an ongoing project to weaponise our beer fridge) was just the the thing to get to grips with the rather awesome bit of technology that is OpenCV. </p>

<p>An intro into the PyOfSauron image detection project in Python, using both OpenCV and the Face.com API to perform face detection and recognition.</p>]]></description>
			<content:encoded><![CDATA[<p><strong><a href="http://www.lonelycode.com/wp-content/uploads/2012/05/face_title_png.png"><img class="aligncenter size-full wp-image-510" title="face_title_png" src="http://www.lonelycode.com/wp-content/uploads/2012/05/face_title_png.png" alt="" /></a></strong></p>
<p>I&#8217;ve been interested in computer vision for quite some time, and the opportunity to tinker with face detection (in an ongoing project to weaponise our beer fridge) was just the the thing to get to grips with the rather awesome bit of technology that is OpenCV.</p>
<p><strong>What is OpenCV?</strong></p>
<p>OpenCV is an open source computer vision project (it&#8217;s in the name!) that&#8217;s been around for quite some time and is one of the most powerful (and easy to get started with) libraries to start working with computer vision without paying for it.</p>
<p>What makes OpenCV even more powerful is that it has Python bindings, that means you can use almost all of its functionality seamlessly in Python &#8211; the syntax and API is one-to-one, so getting to grips with the documentation is pretty straight forward, and there are plenty of examples around to get started with simple object detection.</p>
<p><strong>What is Face.com?</strong></p>
<p>As part of the PyOfSauron project, we make use of the face.com API &#8211; Face.com is a free-to-use face recognition API that (quite handily) has an excellent Python wrapper to get started with using it.</p>
<p><strong>The Project: PyOfSauron</strong></p>
<p>As mentioned earlier, the project PyOfSauron was initially meant to help us count how many beer cans were left in the beer fridge &#8211; and although that project is still on going &#8211; a much more fun side-project emerged to protect the beer fridge with an impromptu security system.</p>
<p>So what does the system do? The main module runs off of watch_me.py, it initiates a loop that starts grabbing images from the first webcam on the system and runs it through one of OpenCV&#8217;s detection algorithms, these are pre-set and can be changed in the command line.</p>
<p>The easiest way to detect a face (or any other body part) in OpenCV is to use a haar detector. These are handily encapsulated in easy-to-transport XML files that will do all the work for you. It&#8217;s even possible to develop your own Haar profiles with enough sample imagery and patience.</p>
<p>As it passes the images through this filter, the script will trigger a callback event with the details of the detected objects as parameters.</p>
<p>The callbacks are modular, so you can develop your own callback modules to do with the image and data what you like. In this case, we&#8217;ve developed the FaceClipper module the most.</p>
<p>The FaceClipper module will take the detected coordinates, create an identity for each (so it can be tracked over time) and draw a crop square around the detected object to feed back to the screen.</p>
<p>In the background, if a face comes close enough to the screen, a capture will be taken and uploaded to Amazon S3 for processing by the Face.com API &#8211; if a successful detection has happened, the script will then assign the identity of that face to the tracked object in memory.</p>
<p><strong>Highlights and cool bits</strong></p>
<p><strong>1. Giving a detected object a lifespan &#8211; inventing visual memory</strong></p>
<p><a href="http://www.lonelycode.com/wp-content/uploads/2012/05/face-memory.jpg"><img class="aligncenter size-full wp-image-509" title="face-memory" src="http://www.lonelycode.com/wp-content/uploads/2012/05/face-memory.jpg" alt="" width="500" height="400" /></a></p>
<p>One of the key problems with object detection is that the computer is completely ignorant as to what is detected &#8211; so when the callback module gets passed a list of the detected objects and their coordinates, it has no way of knowing if item in position 1 is the same as it was in the previous frame &#8211; the detected objects have no identity.</p>
<p>To solve this, @errkk and I (mainly @errkk) came up with a simple solution to identify (or assume) whether a detected object is the same as a previous one.</p>
<p>To do this, the system determines a &#8216;maximum area&#8217; that the face can move in before it is determined to be new &#8211; using some simple geometry (an actual use for Pythagoras!) we detect the distance the face has moved from the centre and compare it to any previous objects from the last frame &#8211; if there&#8217;s a match (within a certain maximum distance) then the face is assigned an ID and will (hopefully) be identified next time.</p>
<p>Each of the identified objects (remembered objects) has a memory decay time so that it is erased from the &#8216;memory&#8217; list if it hasn&#8217;t been renewed (re-identified) within a second (this can be changed, but this seems to work, mainly for those occasions when a face moves out of frame for a second or looks sideways &#8211; stopping detection for a frame or two).</p>
<p><strong>2. Recognising a face</strong></p>
<p>Identifying that there is an object in the frame is one thing, but if you are looking for Faces, and then want to have those faces identified, you&#8217;re looking at a wwhole new hyper-complicated ballgame, it can be done using something called eigenfaces, but I&#8217;d rather use someone else&#8217;s tweaked API then try to bend my head around that.</p>
<p>This is where Face.com comes in &#8211; Face.com has an excellent face recognition system that is very easy to implement (and fast as well).</p>
<p>The FaceClipper module will take a cropped snapshot of a detected face once it reaches a certain size, this file is then sent to Amazon S3 for online storage and then Face.com is used to try to identify the face.</p>
<p>To ensure a smooth frame rate, this whole process happens in a thread that writes it&#8217;s results back to a queue that is checked on every frame, intitially, face recognition took ~5 seconds per face &#8211; which is good, but not ideal given how much people move about in frame.</p>
<p>By keeping the http connection open to S3 when the app starts, we managed to shave the recognition time down to ~1.5 seconds &#8211; which is much better. Naturally when the connection times out you&#8217;ll be back to a ~5 second recognition for one frame.</p>
<p><strong>Getting your hands on the code</strong></p>
<p><a href="https://bitbucket.org/Tinkerbell/pyofsauron" target="_blank">The whole project is hosted on BitBucket here</a> &#8211; have a go, make sure all the pre-requisites are installed, and if you happen to make a module that works with PyOfSauron, drop me a line on twitter for some show and tell.</p>
<p>happy hacking,<br />
Martin</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2012/05/05/using-opencv-python-and-face-com-to-build-a-simple-face-recognition-system/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>One year (and a lot of swearing) later, Loadzen finally launches</title>
		<link>http://www.lonelycode.com/2012/01/10/one-year-and-a-lot-of-swearing-later-loadzen-finally-launches/</link>
		<comments>http://www.lonelycode.com/2012/01/10/one-year-and-a-lot-of-swearing-later-loadzen-finally-launches/#comments</comments>
		<pubDate>Tue, 10 Jan 2012 10:21:59 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[Amazon]]></category>
		<category><![CDATA[load testing]]></category>
		<category><![CDATA[Loadzen]]></category>
		<category><![CDATA[performance testing]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=467</guid>
		<description><![CDATA[<a href="/2012/01/10/one-year-and-a-lot-of-swearing-later-loadzen-finally-launches"><img src="http://www.lonelycode.com/wp-content/uploads/2012/01/loadzen-load-testing-title-graphic.png" alt="" title="loadzen-load-testing-title-graphic" /></a>

<p>The birth, architecture and tech behind Loadzen - our shiny new load testing start up that wa as much a technical challenge as it was an intellectual one, as well as an opportunity to play with some really cool toys...</p>

<p>It all started off with such a simple idea - we had a client, their site was <em>not</em> performing well, so we started load testing. Now we didn't have LoadRunner or any other expensive load testing solution to hand, so we opted for a web-based system instead.</p>

<p>The system ran really well, in fact it did exactly what we wanted (albeit for a little chunky interface), and an intellectual challenge was born - surely it must be easy as pie to write a script that will zombie a bunch of servers in the cloud and point them at a target...</p>]]></description>
			<content:encoded><![CDATA[<p><a href="/2012/01/10/one-year-and-a-lot-of-swearing-later-loadzen-finally-launches"><img src="http://www.lonelycode.com/wp-content/uploads/2012/01/loadzen-load-testing-title-graphic.png" alt="" title="loadzen-load-testing-title-graphic" width="600" height="140" class="aligncenter size-full wp-image-488" /></a></p>
<p>It all started off with such a simple idea &#8211; we had a client, their site was <em>not</em> performing well, so we started load testing. Now we didn&#8217;t have LoadRunner or any other expensive load testing solution to hand, so we opted for a web-based system instead.</p>
<p>The system ran really well, in fact it did exactly what we wanted (albeit for a little chunky interface), and an intellectual challenge was born &#8211; surely it must be easy as pie to write a script that will zombie a bunch of servers in the cloud and point them at a target&#8230; an ethical DDoS <img src='http://www.lonelycode.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>So <a href="http://loadzen.com">Loadzen was born</a> &#8211; as a python shell script and some cobbled together RPC code.</p>
<p>It was only after it actually worked and was surprisingly effective that we thought about taking it to market, so the long road started to making it market worthy.</p>
<p>As this is a technical blog for technical people, let&#8217;s talk about what it does under the hood&#8230;</p>
<p><span style="text-decoration: underline;"><strong>The Architecture</strong></span></p>
<p>The whole system runs of a three-tier architecture:</p>
<p style="text-align: center;"><a style="align: center;" href="http://www.lonelycode.com/wp-content/uploads/2012/01/LZ_Overview.jpg"><img class="size-full wp-image-469 aligncenter" title="LZ_Overview" src="http://www.lonelycode.com/wp-content/uploads/2012/01/LZ_Overview.jpg" alt="" width="371" height="563" /></a></p>
<p>This separation is essentially so that the website acts as a client to the job server, ensuring the machinery that manages and generates tests is fully separated and isolated from the business end. We can bring down the site and the job server will continue running (and retain your results).</p>
<p>The job server will spawn generators as needed to meet the specific load requirement as required by the test being run at that moment.</p>
<p>But that&#8217;s not all, the system actually uses a single thread for each &#8220;virtual user&#8221;, given we know how many threads any specific generator can support we simply meter out accordingly, this way we can load-share multiple tests on the same load generators, with some processes running one set of test scenarios while the others are running a completely different test. This ensures maximum utilisation of the systems running at that moment (they&#8217;re expensive!) and also ensures we&#8217;re not just spawning a ton of new servers for each test.</p>
<p>This is the basic architecture of the system at the highest level, but there are a few cool little tricks in the overall architecture that we&#8217;ll get into later as we discuss the feature set.</p>
<p><span style="text-decoration: underline;"><strong>The workflow</strong></span></p>
<p>The standard workflow for a load test is:</p>
<ol>
<li>Identify your use cases</li>
<li>Create scenarios for those use cases</li>
<li>Determine the &#8216;mix&#8217; of the use cases (e.g. 20% of visitors will buy something, 50% will bounce and 30% will just browse or search)</li>
<li>Set up the test and the load maximum</li>
<li>Run the test</li>
</ol>
<p><a href="http://loadzen.com">Loadzen</a> does all of the above, the load generators will automatically scale out the &#8216;mix&#8217; of tests based on the growth rate of the test curve, they will act in complete lock-step to ensure that each &#8216;wave&#8217; of users starts at the same time and they will strive to introduce some realistic behaviour by running the virtual users at various stages of &#8216;drunkeness&#8217;, varying their step-rate through a scenario randomly so that we simulate more realistic user loads.</p>
<p><span style="text-decoration: underline;"><strong>The kit</strong></span></p>
<p>The Load generators will then record and average out each wave and report the data back to the job server, which stores it and makes it available to a client.</p>
<p>The load generators and the job server both work with Python running Pyro RPC, the reason for this choice? Complete object transparency and interropability between client and server, so that load generators have access to jobserver functions and jobservers can pass test objects to load generators with a single function call with no translation layer. This is a little fiddly, but in the end offers us the ability to just code without worrying about data types and formatting errors.</p>
<p>Both the job server and the load generators run as instances in Amazon EC2, and are controlled using the rather awesome Boto library for AWS.</p>
<p><span style="text-decoration: underline;"><strong>The Website</strong></span></p>
<p>The website is written in Django with MySQL and a shiny fat server provided by the good folks at Media Temple.</p>
<p>Probably the most interesting part of the website is the real-time results and control feed that is induced every time a test is started. This is actually a real-time push feed form the job server that uses a bastardisation of Socket.IO and an EventJS clone for Python called Tornado (from those good folks at live journal) all backed by an infrastructure queue powered using RabbitMQ and Pika.</p>
<p>The actual infrastructure for the site looks like this when we introduce these systems back in (and to think, all of this effort just so you get some shiny animations and a graph on a screen!):</p>
<p><a href="http://www.lonelycode.com/wp-content/uploads/2012/01/LZ_Infrastructure.jpg"><img class="size-full wp-image-468 aligncenter" title="LZ_Infrastructure" src="http://www.lonelycode.com/wp-content/uploads/2012/01/LZ_Infrastructure.jpg" alt="Loadzen infrastructure" width="572" height="471" /></a></p>
<p>Can I just say this now: I love RabbitMQ, I have fallen in love with real-time systems thanks to setting this up &#8211; it&#8217;s amazing how your viewpoint changes when you start thinking in terms of queues and channels and processors. When this feed was set up we briefly considered completely re-tooling the system to have a full-blown RabbitMQ back-end to power ALL of the things.</p>
<p>Pragmatism (thankfully) won out.</p>
<p>We chose Tornado / TornadIO because the Socket.IO JavaScript client is so versatile and offers a bunch of compatibility, taking care of back-ends, transports and browser compliance for you without having to mess around with concepts such as long-polling, STOMP or Comet.</p>
<p>By running a seperate Tornado server to handle the push feed we again managed to decouple everything, this way the thing that manages the transport is decoupled form the web client is decoupled form the work generator, ensuring we can work on each independently and not have a monolithic code base.</p>
<p><span style="text-decoration: underline;"><strong>Making it easy to use</strong></span></p>
<p>The day before launch (I really shouldn&#8217;t be admitting this), I wrote the Chrome extension client that made Scenario creation MUCH easier than was originally built into the website (although the manual wizard still had to be built to pave the way for other clients).</p>
<p>Chrome extensions really are quite simple &#8211; using a messaging infrastructure to make all the bits work together nicely, and all in JavaScript and HTML, so it&#8217;s not much different from building a website.</p>
<p><span style="text-decoration: underline;"><strong>Conclusion</strong></span></p>
<p>It&#8217;s a massive bit of kit, that works but could always be made better, one of the key things learnt from this exercise is making a decision of when to make something work and when to make something beautiful, we all want to code stunning software and have great code that is well architected, but if you want to get something out the door, you need to make pragmatic choices of when to say &#8220;earmark it for the next build, iterate and improve as you go.</p>
<p>At the same time, we learnt to ry to identify those bugs that seem niggling that you know will turn into cancerous, nasty, evil blobs that you have to work around because you were too lazy to tackle that nasty problem head on.</p>
<p>Anyway, I hope you guys <a href="http://www.loadzen.com">enjoy load testing with Loadzen</a>!</p>
<p>Happy coding (and testing),</p>
<p>Martin</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2012/01/10/one-year-and-a-lot-of-swearing-later-loadzen-finally-launches/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Use Tornadio to create a websockets RabbitMQ bridge</title>
		<link>http://www.lonelycode.com/2011/11/27/use-tornadio-to-create-a-websockets-rabbitmq-bridge/</link>
		<comments>http://www.lonelycode.com/2011/11/27/use-tornadio-to-create-a-websockets-rabbitmq-bridge/#comments</comments>
		<pubDate>Sun, 27 Nov 2011 23:30:55 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[RabbitMQ]]></category>
		<category><![CDATA[TornadIO]]></category>
		<category><![CDATA[Tornado]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=456</guid>
		<description><![CDATA[<a href="http://www.lonelycode.com/2011/11/27/use-tornadio-to-create-a-websockets-rabbitmq-bridge"><img title="phonegap-sencha-touch-tutorial-android" src="http://www.lonelycode.com/wp-content/uploads/2011/11/tornadio.jpg" alt="Building mobile apps with Sencha Touch and Phonegap" /></a>

<p>If you want to enable real-time push notifications to your users, SocketIO is your friend, if you don't like NodeJS running on your server, or like me you are a python fan, then this guide to Tornado and TornadIO will make it simple to set up an implementation on your system. </p>

<p>
In this post we go further and show you how to plug your Tornado implementation into a RabbitMQ message queue, and show you how to publish into Tornado (and your web client) to enable real-time communications for your web users without being tied to a single platform.</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/2011/11/27/use-tornadio-to-create-a-websockets-rabbitmq-bridge"><img title="phonegap-sencha-touch-tutorial-android" src="http://www.lonelycode.com/wp-content/uploads/2011/11/tornadio.jpg" alt="Building mobile apps with Sencha Touch and Phonegap" width="500px" /></a></p>
<p>It&#8217;s very likely that you&#8217;ve heard of node.js, the event-based JavaScript powered server &#8211; and to go hand in hand with it, SocketIO: the cross-browser websockets implementation that plugs right into it.</p>
<p>If not, I&#8217;d recommend you go look that up, then come back here so we can talk&#8230;</p>
<p>Ready? Good.</p>
<p>What makes SocketIO so appealing is it&#8217;s client-side implementation &#8211; it is completely cross-browser compatible and basically makes it very simple for you to read and write directly to web clients from your server implementation and making that real-time app you&#8217;ve always wanted to make without implementing something wierd like COMET, Twisted, Orbited or STOMP.</p>
<p>The only drawback is that in order to use SocketIO you need to use Node.js, which means you have to use a JS stack server-side&#8230; and that just doesn&#8217;t feel right.</p>
<p>Lucky for us, there&#8217;s a python event-based server very similar to node.js that can be implemented instead, and even better, it has a SocketIO plugin that speaks the same language as the SocketIO client-side library. So now you can implement SocketIO with a python stack.</p>
<p>With this server implementation you can develop a SocketIO based site that runs entirely in python, which is great.</p>
<p>Unfortunately, if you&#8217;re trying to add real-time to your existing site the last thing you want to have to do is re-write everything in another stack (that would just be silly) or be forced to use the Tornado server to build your app, ideally you will want to just be able to bolt it on.</p>
<p>That&#8217;s where RabbitMQ comes in &#8211; RabbitMQ is an AMPQ queue implementation &#8211; you can set it up to pipe information throughout your application and transport messages, commands or data to different clients and functions in your app. What RabbitMQ will do for you is serve as a backbone for you to be able to pipe events out of your traditional website implementation, hold onto those messages and pipe them into your Tornado server.</p>
<p>Pythons AMPQ client is called Pika, so, if like me you are using Django you can bridge the two using Django&#8217;s eventing system.</p>
<p>In order to get SocketIO on your front-end to talk to TornadIO and in turn receive messages from your webapp you need to pipe those messages via RabbitMQ into a TornadIO listener that is implementing Pika to recieve them.</p>
<p>The traditional implementation for one of these apps would be a chat server, but as this could easily be done with tornado alone and would have few tie-ins with your webapp, so for this how-to we&#8217;ll use the example of sending notifications to your users when they receive a notification that is specific to their UserID (like an email, or one-on-one chat invitation).</p>
<p><strong>Setting up your front end:</strong></p>
<p>To get things going, let&#8217;s set up your front end. Here all we need to do is link to the SocketIO library on the SocketIO CDN and implement a few functions when the page loads that will initiate your connection to your TornadIO server.</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;">&lt;!-- Include the SockeIO script --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;http://cdn.socket.io/stable/socket.io.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
<span style="color: #808080; font-style: italic;">&lt;!-- This library is a little better at handling malformed JSON --&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;{{ STATIC_URL }}js/json2.js&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
// For backward compatability you need a flash transport layer <br />
WEB_SOCKET_SWF_LOCATION = 'http://cdn.socket.io/stable/WebSocketMain.swf';<br />
<br />
// This will st up our listener<br />
function setupConnection(key) {<br />
&nbsp; &nbsp; var liveServer = 'localhost';<br />
&nbsp; &nbsp; var s = new io.Socket(liveServer,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;port: 8081,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;rememberTransport: false,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;resource: 'messaging/'+key <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 'messaging' is a channel resource and 'key' can be anything<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; });<br />
&nbsp; &nbsp; s.connect();<br />
<br />
&nbsp; &nbsp; // Do this stuff when the connection is readdy, we just append to a UL<br />
&nbsp; &nbsp; s.addEvent('connect', function(data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; $('#statuses').append(('--&gt; Connected!<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a><span style="color: #66cc66;">/</span>&gt;</span>'));<br />
&nbsp; &nbsp; });<br />
<br />
&nbsp; &nbsp; // Do stuff when you receive something from the server<br />
&nbsp; &nbsp; // We assume it's JSON data here, this isn't necessarily pretty!<br />
&nbsp; &nbsp; s.addEvent('message', function(data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; try {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var obj = JSON.parse(data);<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $('#statuses').prepend('<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span>' + obj.text + '<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span>')<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; &nbsp; &nbsp; catch(err) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $('#statuses').prepend('<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span>FAIL!<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/li.html"><span style="color: #000000; font-weight: bold;">li</span></a>&gt;</span>')<br />
&nbsp; &nbsp; &nbsp; &nbsp; }<br />
&nbsp; &nbsp; });<br />
}<br />
// ---- END CONNECTOR CODE ----<br />
<br />
$(document).ready(function() {<br />
<br />
&nbsp; &nbsp; $('#start-connection').click(function() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; $('#statuses').append(('--&gt; Starting connection<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/br.html"><span style="color: #000000; font-weight: bold;">br</span></a><span style="color: #66cc66;">/</span>&gt;</span>'));<br />
&nbsp; &nbsp; &nbsp; &nbsp; setupConnection('channelname')<br />
&nbsp; &nbsp; });<br />
});<br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span></div></td></tr></tbody></table></div>
<p>The code above is slightly adapted boilerplate from the SocketIO documentation. First, we set up a connection to the SocketIO server, connect to the server and finally set up some event handlers to fire when things happen. In our case those handlers simply populate an un-ordered list so we can capture the messages on screen. </p>
<p><strong>Tornado and TornadIO</strong></p>
<p>First of all you will need to get your hands on Tornado, TornadIO and Pika &#8211; all of which can be installed via easy_install, so I won&#8217;t go into it here.</p>
<p>To get the server side part working, we need to set up Tornado with a Tornadio implementation, and have TornadIO listen to RabbitMQ to bridge the queue down to the browser-level elements.</p>
<p>The code we will be working with is this:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #808080; font-style: italic;"># Instantiate the Tornadio router</span><br />
MyRouter <span style="color: #66cc66;">=</span> tornadio.<span style="color: black;">get_router</span><span style="color: black;">&#40;</span>MyConnection<span style="color: #66cc66;">,</span> <span style="color: #dc143c;">resource</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'messaging'</span><span style="color: #66cc66;">,</span> extra_re<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\w</span>+'</span><span style="color: #66cc66;">,</span> extra_sep<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'/'</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># When the script starts, start the event loop!</span><br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Port defintions for SocketIO, make sure these match your front end</span><br />
&nbsp; &nbsp; sio_port <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">8081</span><br />
&nbsp; &nbsp; fpp <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">844</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># configure the webapp</span><br />
&nbsp; &nbsp; application <span style="color: #66cc66;">=</span> tornado.<span style="color: black;">web</span>.<span style="color: black;">Application</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Declare your routes here, you can also display HTML files in this list</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: black;">&#91;</span>MyRouter.<span style="color: black;">route</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># We support everything in this case</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; enabled_protocols <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'websocket'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #483d8b;">'flashsocket'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #483d8b;">'xhr-multipart'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #483d8b;">'htmlfile'</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span style="color: #483d8b;">'xhr-polling'</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flash_policy_port <span style="color: #66cc66;">=</span> fpp<span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Set up a ROOT variable that points to where the Flashpolicy XML is</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># You can find this in the TornadIO git</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; flash_policy_file <span style="color: #66cc66;">=</span> op.<span style="color: black;">join</span><span style="color: black;">&#40;</span>ROOT<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'flashpolicy.xml'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; socket_io_port <span style="color: #66cc66;">=</span> sio_port<br />
&nbsp; &nbsp; <span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># We're using logbook for logging all errors here, you don;t have to</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">with</span> handler.<span style="color: black;">threadbound</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; log.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Starting SocketIO Server...&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tornadio.<span style="color: black;">server</span>.<span style="color: #dc143c;">SocketServer</span><span style="color: black;">&#40;</span>application<span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>The code above, when put into a file called socket_server.py will start your SocketIO server. Some interesting aprts to note are that MyConnection hasn&#8217;t been declared yet, this is a class that will manage the various events that happen to the tornadIO implementation, so running this will fail at the moment.</p>
<p>The TornadIO setup is pretty straightforward and is actually very well documented at the TornadIO git repository, all the real action happens in MyRouter, which is documented below:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> MyConnection<span style="color: black;">&#40;</span>tornadio.<span style="color: black;">SocketConnection</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;TornadIO Socket Connection&quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> protocol<span style="color: #66cc66;">,</span> io_loop<span style="color: #66cc66;">,</span> heartbeat_interval<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#We override init so we can apply data to the connection</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">this_id</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">running_thread</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; tornadio.<span style="color: black;">SocketConnection</span>.<span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> protocol<span style="color: #66cc66;">,</span> io_loop<span style="color: #66cc66;">,</span> heartbeat_interval<span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_open<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> *args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># When the connection opens, get the data passed through the connection</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># via the router - this way each connection can be unique.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">this_id</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>kwargs<span style="color: black;">&#91;</span><span style="color: #483d8b;">'extra'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#Our implementation of RabbitMQ is threaded, this is because</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#In order to pipe data from the server down, we need an open line to the</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#RabbitMQ server.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; a <span style="color: #66cc66;">=</span> thisRabbit<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">running_thread</span> <span style="color: #66cc66;">=</span> a<br />
&nbsp; &nbsp; &nbsp; &nbsp; a.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_message<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> message<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Unused as this is a server-&gt;client bridge, you could</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># make the connection two-way and talk back via the client into another queue</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">pass</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_close<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#This is important, when the connection closes, kill the RabbitMQ listener.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">running_thread</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">running_thread</span>.<span style="color: black;">kill_me</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This class is instantiated whenever a SocketIO connection is made, in the traditional implementation of a chat server the connection is stored in a list in the class, which we can&#8217;t implement as we are running a server to client bridge and not inter-client communication and need to keep a connection open.</p>
<p>It is because of this bridging aspect that we instantiate our RabbitMQ listener as a thread &#8211; store it in a variable (this should be in a list really) so that we can kill it when the connection drops and save some memory on your server.</p>
<p><strong>Setting up your RabbitMQ listener</strong></p>
<p>This part of the code will define the thisRabbit() class, this class will listen to your RabbitMQ queue and keep the connection open, piping data back down to the client vie TornadIO when needed:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> thisRabbit<span style="color: black;">&#40;</span><span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> t_client<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">t_client</span> <span style="color: #66cc66;">=</span> t_client<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">key</span> <span style="color: #66cc66;">=</span> t_client.<span style="color: black;">this_id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">started</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>._stop <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">threading</span>.<span style="color: black;">Event</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> stop<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>._stop.<span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> stopped<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>._stop.<span style="color: black;">isSet</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_connected<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> connection<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Connected...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: black;">channel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">on_channel_open</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span> <span style="color: #66cc66;">=</span> connection<br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_channel_open<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> new_channel<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Channel open&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span> <span style="color: #66cc66;">=</span> new_channel<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#try:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># &nbsp; &nbsp;self.channel.queue_delete(queue=self.key)</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#except:</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># &nbsp; &nbsp;print &quot;Couldn't delete queue&quot;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Declaring queue&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span>.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span>queue<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">key</span><span style="color: #66cc66;">,</span> durable<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> exclusive<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> auto_delete<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> callback<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">on_queue_declared</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Queue declare done&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_queue_declared<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> frame<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Trying to listen...&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span>.<span style="color: black;">basic_consume</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">handle_delivery</span><span style="color: #66cc66;">,</span> queue<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">key</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Listening to: &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">key</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">' [*] Waiting for messages. To exit press CTRL+C'</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> kill_me<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> clear <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Killing&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Active threads: &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">threading</span>.<span style="color: black;">active_count</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> clear:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span>.<span style="color: black;">queue_delete</span><span style="color: black;">&#40;</span>queue<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">key</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> handle_delivery<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> channel<span style="color: #66cc66;">,</span> header<span style="color: #66cc66;">,</span> method<span style="color: #66cc66;">,</span> body<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; [x] Received %r&quot;</span> % <span style="color: black;">&#40;</span>body<span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> body <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;die&quot;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">kill_me</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">t_client</span>.<span style="color: black;">send</span><span style="color: black;">&#40;</span>body<span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> startCall<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">last_active</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection <span style="color: #66cc66;">=</span> pika.<span style="color: black;">SelectConnection</span><span style="color: black;">&#40;</span>pika.<span style="color: black;">ConnectionParameters</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; host<span style="color: #66cc66;">=</span>RABBIT_SERVER<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">on_connected</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Starting connection&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: black;">ioloop</span>.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Running new thread:&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">name</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">startCall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>This is a lot of boring code, but in order to understand it, think of each of the various methods as a waterfall of functions that are callbacks instantiated as the events happen. So open connection -&gt; define what to do when connection is made -&gt; connection made -&gt; call callback for connection made -&gt; declare queue -&gt; define function to declare queue etc. etc.</p>
<p>The one to look at here is the handle_delivery() which will do something with the message received from the queue, in our case we parse the message to check if it is a commadn to kill  the connection, or, alternatively &#8211; to use the t_client property &#8211; the TornadIO connection class &#8211; to send a response down the wire to the client.</p>
<p>As the thread is tied to the connection, this is a server -> individual client call, strictly speaking this could be mediated here with an arbitrary protocol definition in the queue messages as one queue could individually manage individual messages for clients, although it would be more efficient to have a queue for each if that were really what you wanted to set up.</p>
<p><strong>Sending a Signal</strong></p>
<p>Sending a message to RabbitMQ is quite simple, the class below sshould make it easy to send a message:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> RabbitProducer:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> key<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">key</span> <span style="color: #66cc66;">=</span> key<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">message</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">None</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Called when our connection to RabbitMQ is closed</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_closed<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> frame<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># connection.ioloop is blocking, this will stop and exit the app</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span>.<span style="color: black;">ioloop</span>.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Called when we have connected to RabbitMQ</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_connected<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> connection<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Create a channel on our connection passing the on_channel_open callback</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span> <span style="color: #66cc66;">=</span> connection<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span>.<span style="color: black;">channel</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">on_channel_open</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Called when our channel is open</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_channel_open<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> channel_<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Our usable channel has been passed to us, assign it for future use</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span> <span style="color: #66cc66;">=</span> channel_<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Declare a queue</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span>.<span style="color: black;">queue_declare</span><span style="color: black;">&#40;</span>queue<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">key</span><span style="color: #66cc66;">,</span> durable<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; exclusive<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> auto_delete<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; callback<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">on_queue_declared</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Called our queue is declared.</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> on_queue_declared<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> frame<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Add a callback so we can stop the ioloop</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span>.<span style="color: black;">add_on_close_callback</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">on_closed</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">send_message</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> startCall<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Create our connection parameters and connect to RabbitMQ</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; parameters <span style="color: #66cc66;">=</span> pika.<span style="color: black;">ConnectionParameters</span><span style="color: black;">&#40;</span>RABBIT_SERVER<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection <span style="color: #66cc66;">=</span> pika.<span style="color: black;">SelectConnection</span><span style="color: black;">&#40;</span>parameters<span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span>.<span style="color: black;">on_connected</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Start our IO/Event loop</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; connection.<span style="color: black;">ioloop</span>.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> send_message<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Send a message</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">channel</span>.<span style="color: black;">basic_publish</span><span style="color: black;">&#40;</span>exchange<span style="color: #66cc66;">=</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; routing_key<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">key</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; body<span style="color: #66cc66;">=</span><span style="color: #008000;">self</span>.<span style="color: black;">message</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; properties<span style="color: #66cc66;">=</span>pika.<span style="color: black;">BasicProperties</span><span style="color: black;">&#40;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; content_type<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;text/plain&quot;</span><span style="color: #66cc66;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; delivery_mode<span style="color: #66cc66;">=</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Close our connection</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">connection</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
new_rabbit <span style="color: #66cc66;">=</span> RabbitProducer<span style="color: black;">&#40;</span><span style="color: #483d8b;">'channelname'</span><span style="color: black;">&#41;</span><br />
new_rabbit.<span style="color: black;">message</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;Hi there!&quot;</span><br />
new_rabbit.<span style="color: black;">startCall</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p><strong>Testing the implementation</strong></p>
<p>When yo use the Rabbit Producer, you will be opeining a connection, passing a message to the queue and quitting, there are better ways of doing this and this is a little quick and dirty, however for one off pulses this should suffice.</p>
<p><strong>Some thoughts</strong></p>
<p>What makes this so interesting is that RabbitMQ will enable you to build streams of messages that can be scaled and attached to whatever data consumer you need, be that another Tornado service or streaming messages directly to your users, this implementation offers a scalable and robust way to manage data streams without having to use NodeJS and SocketIO.</p>
<p>This implementation will also enable you to decouple your real-time data from the rest of your site, by using RabbitMQ as a mediator, you can connect as many services together as needed, make them event based or publishers into the queue without having to change or be tied to a platform (RabbitMQ has a wide set of client libraries).</p>
<p>Good luck!</p>
<p>M.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2011/11/27/use-tornadio-to-create-a-websockets-rabbitmq-bridge/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>EU Cookie Directive &#8211; How to fix your site with a minimum of fuss</title>
		<link>http://www.lonelycode.com/2011/05/11/eu-cookie-directive-how-to-fix-your-site-with-a-minimum-of-fuss/</link>
		<comments>http://www.lonelycode.com/2011/05/11/eu-cookie-directive-how-to-fix-your-site-with-a-minimum-of-fuss/#comments</comments>
		<pubDate>Wed, 11 May 2011 20:30:59 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[EU Cookies]]></category>
		<category><![CDATA[JavaScript]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=429</guid>
		<description><![CDATA[<a href="/2011/05/11/eu-cookie-directive-how-to-fix-your-site-with-a-minimum-of-fuss/"><img title="EU Cookie Law - How to sort your site out" src="http://www.lonelycode.com/wp-content/uploads/2011/05/cookie.png" alt="" /></a>

<p>As you may or may not know, the EU is introducing some new legislation that comes into effect on the 25th of May 2011 that will force website owners to expressly ask permission of their users to store a cookie on your site.</p>

<p>Now this is a little troubling, since anyone that is using Google Analytics will be storing a cookie on your machine just to know how well their site is performing! Unfortunately, a simple act as tracking your user behavior via a free, awesome service like GA will probably fall afoul of the 'absolutely necessary' clause that comes as part of the directive.</p>

<p>This post has one solution in nice, hacked together JavaScript :-)</p>]]></description>
			<content:encoded><![CDATA[<p><a href="/2011/05/11/eu-cookie-directive-how-to-fix-your-site-with-a-minimum-of-fuss/"><img title="EU Cookie Law - How to sort your site out" src="http://www.lonelycode.com/wp-content/uploads/2011/05/cookie.png" alt="" Width="500px"/></a></p>
<p>As you may or may not know, the EU is introducing some new legislation that comes into effect on the 25th of May 2011 that will force website owners to expressly ask permission of their users to store a cookie on your site.</p>
<p>Now this is a little troubling, since anyone that is using Google Analytics will be storing a cookie on your machine just to know how well their site is performing! Unfortunately, a simple act as tracking your user behavior via a free, awesome service like GA will probably fall afoul of the &#8216;absolutely necessary&#8217; clause that comes as part of the directive.</p>
<p>So how do you, as a site owner or manager of a site go about making the site compatible with these new regulations? Well, put simply it&#8217;s a mess, as a site owner you will need to:</p>
<ol>
<li>Get permission form the user prior to storing any cookies</li>
<li>Clearly explain to the user about how you use cookies</li>
</ol>
<p>Now that will be quite difficult for most site owners as if you use a framework, third party plugin, tracking tool etc. You might not even be aware of how many different cookies are being stored on your users machine, or what they do for that matter.</p>
<p>But that&#8217;s a different matter that can most likely be covered by some boilerplate legalese on a page somewhere (and I am sure there are lawyers out there already drafting the documentation). What&#8217;s more important is how you can stop your carefully crafted site from using cookies without expending too much time and effort.</p>
<p>One solution would be to simply ask the user before any JavaScript is executed on your page that could put a cookie on the machine. To that end, I put together a little script that will:</p>
<ol>
<li>Stop the browser from loading the page</li>
<li>Ask for permission</li>
<li>Offer to redirect the user to a page where you explain how the site uses cookies</li>
<li>Will redirect the user to a custom page if they say &#8216;no&#8217; where you can tell them very politely to grow a pair</li>
<li>Only asks once, so once they say yes it&#8217;s all good they will never be asked again</li>
</ol>
<p><a href="http://www.lonelycode.com/wp-content/uploads/2011/05/idiaftCookie.zip" target="_blank">The source code for the script is available here</a> &#8211; do with it what you will, there&#8217;s no warranty from me. I&#8217;ve also put the script on a site called <a title="I Did It All For The Cookie" href="http://IDidItAllForTheCookie.com" target="_blank">IDidItAllForTheCookie.com</a> &#8211; so you can just add a short code snippet to your site and the script will take care of the rest.</p>
<p>Enjoy!</p>
<p>Martin</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2011/05/11/eu-cookie-directive-how-to-fix-your-site-with-a-minimum-of-fuss/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Building mobile apps with Sencha Touch and Phonegap</title>
		<link>http://www.lonelycode.com/2011/05/02/building-mobile-apps-with-sencha-touch-and-phonegap/</link>
		<comments>http://www.lonelycode.com/2011/05/02/building-mobile-apps-with-sencha-touch-and-phonegap/#comments</comments>
		<pubDate>Mon, 02 May 2011 11:29:11 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[phonegap]]></category>
		<category><![CDATA[sencha touch]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=409</guid>
		<description><![CDATA[<a href="http://www.lonelycode.com/2011/05/02/building-mobile-apps-with-sencha-touch-and-phonegap/"><img title="phonegap-sencha-touch-tutorial-android" src="http://www.lonelycode.com/wp-content/uploads/2011/05/phonegap-sencha-touch-tutorial-android.png" alt="Building mobile apps with Sencha Touch and Phonegap" /></a>

<p>I recently came into posesion of an Advent Vega android tablet - it's a 2.2 tablet with a nice big screen and a very sweet price spot (£200). Having already installed a custom ROM and tweaked the settings to  no end to get the tablet to behave how I like, I've been more and more interested in actually building mobile apps (actually, the fact that to flash a new ROM onto a virgin device requires you to set up the android SDK gets well on your way!).</p>

<p>This piost will describe how to go about building a fledgling andriod app without having to learn Java, but instead build the entire thing in HTML, CSS and JavaScript. What we won't go though is all the intial stuff such as getting the JDK, installing the SDK and installing Eclipse - that is all nicely covered in <a title="Phonegap quick start - android" href="http://www.phonegap.com/start#android" target="_blank">Phonegap's quick-start documentation</a>.</p>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/2011/05/02/building-mobil…h-and-phonegap/"><img title="phonegap-sencha-touch-tutorial-android" src="http://www.lonelycode.com/wp-content/uploads/2011/05/phonegap-sencha-touch-tutorial-android.png" alt="Building mobile apps with Sencha Touch and Phonegap" /></a></p>
<p>I recently came into posesion of an Advent Vega android tablet &#8211; it&#8217;s a 2.2 tablet with a nice big screen and a very sweet price spot (£200). Having already installed a custom ROM and tweaked the settings to  no end to get the tablet to behave how I like, I&#8217;ve been more and more interested in actually building mobile apps (actually, the fact that to flash a new ROM onto a virgin device requires you to set up the android SDK gets well on your way!).</p>
<p>This piost will describe how to go about building a fledgling andriod app without having to learn Java, but instead build the entire thing in HTML, CSS and JavaScript. What we won&#8217;t go though is all the intial stuff such as getting the JDK, installing the SDK and installing Eclipse &#8211; that is all nicely covered in <a title="Phonegap quick start - android" href="http://www.phonegap.com/start#android" target="_blank">Phonegap&#8217;s quick-start documentation</a>.</p>
<p>What we will cover is how to get started with Phonegap and Sencha Touch &#8211; the two frameworks that I feel are the best options out there for someone who isn&#8217;t versed in Java or Objective-C and wants to rapidly prototype applications that can get up and go.</p>
<p>In this post we&#8217;ll walk through building a simple Reddit client for Tablet PC&#8217;s &#8211; at the moment only for android as I don&#8217;t have the spare cash to get a Mac as a build machine.</p>
<p>Our app will be simple &#8211; it will pull the posts from the /r/pics subreddit, and display the images in a right hand panel of the app, the application will also enable forward and backward movement through the posts list.</p>
<p><span style="text-decoration: underline;"><strong>What is Phonegap?</strong></span></p>
<p>Phonegap is a set of libraries that have been created to build a bridge between a mobile platforms&#8217; native API and a JavaScript &#8216;Hook&#8217; &#8211; what all mobile platform API&#8217;s have in common is that they all have a web view &#8211; some way of rendering a web page in a discrete window. What PhoneGap does is help you set up a basic natural-API environment that will host your app, and then let you focus on actually building the app in languages more familliar to you such as HTML/CSS for layout and Javascript for functionality.</p>
<p><span style="text-decoration: underline;"><strong>What is Sencha Touch?</strong></span></p>
<p>Strictly speaking you don&#8217;t need this library, you can start building your apps straight off with Phonegap &#8211; however, as all smartphone users can attest to, there&#8217;s something about the interface of a mobile app, the momentum-asssisted scrolling, pinch to zoom and swipe gestures to navgate between screens. Sencha Touch (along with XUI and JQuery Mobile) are pre-built frameworks that make building simple User Interfaces easy and pre-styled.</p>
<p>I selected Sencha touch for this post becuase it is by far the most advanced of the lot &#8211; jQuery mobile is still in Alpha and XUI doesn&#8217;t quite cover what I want out of my layout language.</p>
<p>Above and beyond this is also the fact that Sencha Touch is based on ExtJS, which is a framework for web-app creation and follows a (loosely) MVC approach. It&#8217;s a bit of a paradigm shift if you are used to jQuery, as Sencha Touch can generate most of your HTML for you without you ever writing a line yourself, while easily adding hooks to actions that hapen to your on-screen items. At some ppoint in the future I may repeat this process with jQuery mobile, however as it is still in alpha I feel this isn&#8217;t for practical use in production scenarios.</p>
<p><span style="text-decoration: underline;"><strong>Getting Started</strong></span></p>
<p>First off &#8211; the best thing to do to debug and test your app is to set up Xamp or WampServer on your dev machine and allow it to be accessed from anyone in your network.</p>
<p>The reason being that you will be able to use your tablet / phone device to access the web version of the app with the native mobile browser &#8211; which would pretty much be exactly the same as the phonegap application &#8211; so you can test without deploying via eclipse.</p>
<p>Once you&#8217;re happy with everything &#8211; go ahead and download Sencha Touch and unzip it to a folder in your www directory so you can access it like this: http://localhost/sencha. This will give you access to the demos, source code and most importantly the API documentation.</p>
<p><span style="text-decoration: underline;"><strong>Setting up your first project:</strong></span></p>
<p>First, create a folder in your www directory for your project, in this case we&#8217;ll call it andreddit &#8211; the exact structure is laid out below:</p>
<ul>
<li>www</li>
<li>&#8211; andreddit</li>
<li>&#8212;- lib</li>
<li>&#8212;&#8212; touch</li>
<li>&#8212;&#8212; andreddit</li>
<li>&#8212;&#8212; phonegap</li>
<li>&#8212;- imgs</li>
<li>&#8212;- index.html</li>
</ul>
<p>Pretty straight-forward so far. Your app will be running in index.html, and it will reference your application logic in the libs/andreddit folder, while the sencha files will live under the /touch folder.</p>
<p>Your first job is to copy (or symlink) the sencha folder into the /touch folder, this will make those files available to your application.</p>
<p><span style="text-decoration: underline;"><strong>Writing some code</strong></span></p>
<p>Open up your favourit editor (I use Notepad++) and edit index.html, copy and paste the code below into the file:</p>
<div class="codecolorer-container html4strict dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br /></div></td><td><div class="html4strict codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #00bbdd;">&lt;!DOCTYPE html&gt;</span><br />
<span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/meta.html"><span style="color: #000000; font-weight: bold;">meta</span></a> <span style="color: #000066;">http-equiv</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;Content-Type&quot;</span> <span style="color: #000066;">content</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/html; charset=utf-8&quot;</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span>Andreddit<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/title.html"><span style="color: #000000; font-weight: bold;">title</span></a>&gt;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;lib/touch/sencha-touch-debug.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/link.html"><span style="color: #000000; font-weight: bold;">link</span></a> <span style="color: #000066;">href</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;lib/touch/resources/css/sencha-touch.css&quot;</span> <span style="color: #000066;">rel</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;stylesheet&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/css&quot;</span> <span style="color: #66cc66;">/</span>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;lib/phonegap.0.9.5.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;lib/andreddit/application.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a> <span style="color: #000066;">src</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;lib/andreddit/models.js&quot;</span> <span style="color: #000066;">type</span><span style="color: #66cc66;">=</span><span style="color: #ff0000;">&quot;text/javascript&quot;</span>&gt;&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/script.html"><span style="color: #000000; font-weight: bold;">script</span></a>&gt;</span><br />
<br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/head.html"><span style="color: #000000; font-weight: bold;">head</span></a>&gt;</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/body.html"><span style="color: #000000; font-weight: bold;">body</span></a>&gt;</span><br />
<span style="color: #009900;">&lt;<span style="color: #66cc66;">/</span><a href="http://december.com/html/4/element/html.html"><span style="color: #000000; font-weight: bold;">html</span></a>&gt;</span></div></td></tr></tbody></table></div>
<p>The most important bits here are the script and link tags:</p>
<ul>
<li>sencha-touch-debug.js &#8211; this is the sencha touch library in a friendly debug version that will give meaningful error messages</li>
<li>sencha-touch.css &#8211; all they styling info for your app, not to be used for any custom styles!</li>
<li>phonegap.0.9.5.js &#8211; Phonegap, you won&#8217;t actually be using this</li>
<li>application.js &#8211; your sencha-touch application</li>
<li>models.js &#8211; your sencha touch models, more on this later</li>
</ul>
<p>The models file is a little odd, and it may be worthwhile explaining here how Sencha touch is organised in terms of handling data sources&#8230;</p>
<p><span style="text-decoration: underline;"><strong>Models and Data Stores</strong></span></p>
<p>Sencha uses Models to represent the structure of a data source &#8211; that can be XML or JSON data that s comming in via a web service and the beauty of the model is that it follows a very simple layout &#8211; essentially you define the &#8216;model&#8217; of the data to create a programmatic representation of it&#8217;s structure &#8211; this is a fairly detailed topic, I&#8217;d recommend reading up on it in the main API documentation to find out more &#8211; for now, suffice  it to say that you&#8217;ll be using models to represent the structure of the data you will be accessing from the Reddit feed.</p>
<p>Having a model is all well and good, however it is irelevant if you don&#8217;t have a place to store your data, this is where Sencha has the concept of the &#8216;Data Stores&#8217;, these are essentially the machinery that do all the calling, processing and filtering of your data according to the rules you set out in your models.</p>
<p>To recap &#8211; you plug your models into the data store, you plug the data store into a web service / XML feed and then you access the data store from your application logic. This way, if the data changes, you can just modify the store to make that data available throughout your application.</p>
<p><span style="text-decoration: underline;"><strong>Setting up your model</strong></span></p>
<p>The reddit API works by sticking a &#8216;.json&#8217; parameter at the end of a URL, so to get the structure, you could pull the front page and run the returned text through JSONLint &#8211; it will give you a much better picture of what the structure of your JSON looks like (instead of the gunk you get back normally!):</p>
<p><a href="http://www.lonelycode.com/wp-content/uploads/2011/05/jsonlint_small.png"><img class="aligncenter size-full wp-image-411" title="jsonlint_small" src="http://www.lonelycode.com/wp-content/uploads/2011/05/jsonlint_small.png" alt="" width="620" height="270" /></a></p>
<p>Loking at the JSON data &#8211; you can see that the root of the data we really want is under data -&gt; children, so we will set up our model respectively, paste the folling into your models.js file:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Ext.<span style="color: #660066;">regModel</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'RedditModel'</span><span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; fields<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'kind'</span><span style="color: #339933;">,</span> type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'string'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><span style="color: #000066;">name</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'data'</span><span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>So what is going on here? First, we create a new Model instance &#8211; this is called the Ext.regModel, we then give the model a name (&#8216;RedditModel&#8217;), and then go on to define the fields that will be found in the data set. You can explicitly define field types using the common identifiers such as boolean, string, long, int, float etc. However in the case of the &#8216;data&#8217; field, since it is actually further nested JSON, we don&#8217;t assign anything and let Javascript figure out that it&#8217;s a JSON object on its own.</p>
<p>Models are complicated, and can be nested for related data sets (for example if you have a list of customers and their related orders) &#8211; the documentation in Sencha is very good for this, so I&#8217;d recommend taking a peek at that if you are applying this to another data set.</p>
<p>Now that we&#8217;ve created the model, we can create the data store &#8211; this will handle the calls to the service as well as manage the &#8216;active&#8217; data as you change the parameters of the store programmatically later. Paste the folling underneath your model code:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">data</span>.<span style="color: #660066;">Store</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; model<span style="color: #339933;">:</span> <span style="color: #3366CC;">'RedditModel'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; proxy<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'scripttag'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; url<span style="color: #339933;">:</span> <span style="color: #3366CC;">'http://www.reddit.com/r/pics.json'</span><span style="color: #339933;">,</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; method<span style="color: #339933;">:</span> <span style="color: #3366CC;">'GET'</span> <span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; callbackParam<span style="color: #339933;">:</span> <span style="color: #3366CC;">'jsonp'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; reader<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'json'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; root<span style="color: #339933;">:</span> <span style="color: #3366CC;">'data.children'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; autoLoad<span style="color: #339933;">:</span><span style="color: #003366; font-weight: bold;">true</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>The Data Store does four things:</p>
<ol>
<li>Assign the model to the store</li>
<li>Set up a proxy &#8211; this is the thing that will access the service, since this is a mobile app, you are 95% guaranteed that you will be accessing data from third-party domains, which means you will need to make JSONP calls instead of standard Ajax JSON requessts. The proxy will take care of this for you by using a &#8216;scripttag&#8217; type instead of a &#8216;httpproxy&#8217;, the &#8216;scripttag&#8217; type will manage all the crap around making JSONP calls (HttpProxy will juist perform a standard &#8216;GET&#8221;) so you wonl;t need to worry about the ins and outs, however if you want to know more, please see this page which explains it quite nicely.</li>
<li>Set up a reader &#8211; the reader is the thing that interprets the data t put into the store &#8211; you can see here that we are using the &#8216;json&#8217; type (there is also an XML type) and have set a &#8216;root&#8217; parameter &#8211; remember how we stated earlier that all the interesting bits live under data -&gt; children? Well, by setting up the root parameter we can skip all the boring parsing and tell the store to focus only on this one node of the JSON data.</li>
<li>Autoload &#8211; this will re-load the store when it is created, you can also call the load() method against the model to manually load the store programatically later (we actually dot his later on, so hold your horses).</li>
</ol>
<p>So far so boring &#8211; we still havenlt made any pretty things! Strictly speaking we&#8217;re building this app the wrong way round &#8211; starting with the data and then moving to the UI, most processes will focus on UI first. However, in terms of &#8216;building up&#8217; the application layers, this approach makes the most sense in terms of a step-by-step approach as the display layers consume the data stores in order to work correctly, so having them set up first will save you a lot of time and debugging.</p>
<p><strong><u>Setting up your Viewport and User Interface</u></strong></p>
<p>On to the more exciting stuff &#8211; Sencha makes it very easy to start prototyping a UI programatically without having to directly manuipulate the HTML yourself &#8211; this is done mainly through objects called Panels.</p>
<p>But we&#8217;re getting ahead of ourselves here &#8211; first you need to set up your application &#8211; this is pretty straightforward:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">Ext.<span style="color: #660066;">ns</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;AndReddit&quot;</span><span style="color: #339933;">,</span> <span style="color: #3366CC;">&quot;AndReddit.stores&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>&nbsp; &nbsp; <br />
post_index <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><br />
<br />
Ext.<span style="color: #660066;">setup</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; onReady<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">Panel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fullscreen<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">true</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layout<span style="color: #339933;">:</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type<span style="color: #339933;">:</span> <span style="color: #3366CC;">'vbox'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; align<span style="color: #339933;">:</span> <span style="color: #3366CC;">'left'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dockedItems<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></div></td></tr></tbody></table></div>
<p>Here we do two things &#8211; first we create a namespace for the application (you&#8217;ll notice we used this namespace in the models.js to define our data store), we then run the setup function to create our main Panel. The most interesting bit here is the dockedItems property &#8211; this is where you can plug in a bunch of new Panels and UI elements.</p>
<p>So lets do just that &#8211; paste the following into the docketItems list:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; dockedItems<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dock<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;top&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">'toolbar'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ui<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;light&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; title<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;AndReddit - a Reddit client&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">Panel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dock<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;left&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;panel&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;30%&quot;</span><span style="color: #339933;">,</span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dockedItems<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">// Add the ViewDock</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; viewDock<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #009900;">&#93;</span></div></td></tr></tbody></table></div>
<p>&nbsp;</p>
<p>Also, add this above the Ext.Setup() function:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">viewDock <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> Ext.<span style="color: #660066;">Panel</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dock<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;left&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;panel&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span style="color: #339933;">:</span><span style="color: #3366CC;">'viewDock'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;70%&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066;">scroll</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">'both'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;100%&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;background-color: #fff&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; html<span style="color: #339933;">:</span> <span style="color: #3366CC;">'&lt;center&gt;&lt;img src=&quot;imgs/reddit-logo-webtreatsetc.png&quot; border=&quot;0&quot; style=&quot;margin-top:30px&quot;&gt;&lt;/center&gt;'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span></div></td></tr></tbody></table></div>
<p>What have we done here? We&#8217;ve built our User Interface! I realise it looks like a horrible mess of nested curly brackets &#8211; but essentially what we have done is added two items to the main panel:</p>
<ol>
<li>A toolbar</li>
<li>A left hand panel</li>
<li>A right hand panel (this is just called ViewDock, this is because we want to be able to manipulate it later directly you can use the Cmp() function to call it by name, however being old-school I just assigned it a full blown variable name)</li>
</ol>
<p>Lets look at the more interesting bits:</p>
<p>First of all, xtype and ui &#8211; these are properties that tell Sencha Touch what the item you are creating is &#8211; we are using &#8216;toolbar&#8217; and &#8216;panel&#8217; in this example.</p>
<p>Next, you&#8217;ll notice how we are fitting objects &#8211; there are properties we are using a percentage to handle widths as this way we can be sure the UI will display on variable-width screens.</p>
<p>Most importantly, you will notice in the left hand panel that there is another dockedItems[] array, we will be using this to set up our post list and forward and back buttons as follows:</p>
<div class="codecolorer-container javascript dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br />40<br />41<br />42<br />43<br />44<br />45<br />46<br />47<br />48<br />49<br />50<br />51<br />52<br />53<br />54<br />55<br />56<br />57<br />58<br />59<br />60<br />61<br />62<br />63<br />64<br />65<br />66<br />67<br />68<br />69<br />70<br />71<br />72<br /></div></td><td><div class="javascript codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">&nbsp; &nbsp; &nbsp; &nbsp; dockedItems<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span>&nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dock<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;top&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;toolbar&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ui<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;light&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;border-right: thick solid #000&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; items<span style="color: #339933;">:</span> <span style="color: #009900;">&#91;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Back&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ui<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;back&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; align<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;left&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>button<span style="color: #339933;">,</span> event<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">if</span> <span style="color: #009900;">&#40;</span>post_index <span style="color: #339933;">&lt;=</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; post_index <span style="color: #339933;">=</span> <span style="color: #CC0000;">0</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #000066; font-weight: bold;">else</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; post_index <span style="color: #339933;">-=</span> <span style="color: #CC0000;">25</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last_id <span style="color: #339933;">=</span> AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">getAt</span><span style="color: #009900;">&#40;</span><span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">proxy</span>.<span style="color: #660066;">extraParams</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'count'</span><span style="color: #339933;">:</span> post_index<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'before'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;t3_&quot;</span> <span style="color: #339933;">+</span> last_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ext.<span style="color: #660066;">getCmp</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'post-list'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">scroller</span>.<span style="color: #660066;">scrollTo</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'top'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype<span style="color: #339933;">:</span> <span style="color: #3366CC;">'spacer'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; text<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Next&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ui<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;forward&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; align<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;right&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; handler<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>button<span style="color: #339933;">,</span> event<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; post_index <span style="color: #339933;">+=</span> <span style="color: #CC0000;">25</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; numposts <span style="color: #339933;">=</span> AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">data</span>.<span style="color: #660066;">length</span> <span style="color: #339933;">-</span><span style="color: #CC0000;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; last_id <span style="color: #339933;">=</span> AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">getAt</span><span style="color: #009900;">&#40;</span>numposts<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">id</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">proxy</span>.<span style="color: #660066;">extraParams</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'count'</span><span style="color: #339933;">:</span> post_index<span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #3366CC;">'after'</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;t3_&quot;</span> <span style="color: #339933;">+</span> last_id<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">load</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Ext.<span style="color: #660066;">getCmp</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'post-list'</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">scroller</span>.<span style="color: #660066;">scrollTo</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'top'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">0</span><span style="color: #009900;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span><br />
<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; dock<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;left&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; id<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;post-list&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; xtype <span style="color: #339933;">:</span> <span style="color: #3366CC;">'list'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; style<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;border-right: thick solid #000&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; store <span style="color: #339933;">:</span> AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; itemTpl <span style="color: #339933;">:</span> <span style="color: #3366CC;">'&lt;div id=&quot;{data.url}&quot;&gt;{data.title}&lt;/div&gt;'</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;100%&quot;</span><span style="color: #339933;">,</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onItemTap<span style="color: #339933;">:</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #000066; font-weight: bold;">item</span><span style="color: #339933;">,</span> index<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; waitTpl <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;center&gt;&lt;img src=&quot;imgs/loading.gif&quot; border=&quot;0&quot; style=&quot;margin-top:30px&quot;&gt;&lt;/center&gt;'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; viewDock.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span>waitTpl<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pxHeight <span style="color: #339933;">=</span> <span style="color: #3366CC;">'200px'</span> <span style="color: #006600; font-style: italic;">//viewDock.getHeight()</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pxWidth <span style="color: #339933;">=</span> <span style="color: #3366CC;">'300px'</span> <span style="color: #006600; font-style: italic;">//viewDock.getWidth()</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> thisPost <span style="color: #339933;">=</span> AndReddit.<span style="color: #660066;">stores</span>.<span style="color: #660066;">Posts</span>.<span style="color: #660066;">getAt</span><span style="color: #009900;">&#40;</span>index<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">get</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;data&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">url</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #006600; font-style: italic;">//var newTpl = &quot;&lt;iframe frameborder='0' src='&quot; + thisPost + &quot;' width='&quot;+ pxWidth +&quot;px' height='&quot;+ pxHeight +&quot;px' id='iframe-external' scrolling='auto'&gt;&lt;/iframe&gt;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #003366; font-weight: bold;">var</span> newTpl <span style="color: #339933;">=</span> <span style="color: #3366CC;">'&lt;img style=&quot;padding:20px; max-width:600px&quot; src=&quot;'</span><span style="color: #339933;">+</span> thisPost <span style="color: #339933;">+</span><span style="color: #3366CC;">'&quot; /&gt;'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; viewDock.<span style="color: #660066;">update</span><span style="color: #009900;">&#40;</span>newTpl<span style="color: #009900;">&#41;</span> <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#93;</span></div></td></tr></tbody></table></div>
<p>In this code snippet we are:</p>
<ol>
<li>Adding a toolbar to the left hand panel</li>
<li>Adding a list to the left hand panel</li>
<li>Adding a forward and back button tot he left hand toolbar</li>
</ol>
<p>Furthermore, we are attaching functionality to the &#8216;handler&#8217; property of the buttons to move forward and back and onItemTap event of the post list object.</p>
<p>As you can see the post list is plugged into our Data Store using the store property, using the temTpl proeprty we can define how the list item will look and what elements from the data store we want to plug in. We then add the onItemTap event handler, which essentially pulls the record from the data store and modifies the html property of the viewDock, followed by an update() call to make the change visible.</p>
<p>The buttons on the other hand do something more interesting, we use the handlers to modify the extraParams property of the store to modify the web service endpoint to pull the next 25 records from the web service. Now this is specifically for reddit but you can see how just modifying these params and calling load() on the store will also update the list itself &#8211; so you won&#8217;t need to update display objects that are bound to data stores as updating one will trigger an update in the other.</p>
<p>You&#8217;ll have noticed we haven&#8217;t written any HTML yet &#8211; if you browse to you rindex.html file now though, you should see something that looks like this:</p>
<p><a href="http://www.lonelycode.com/wp-content/uploads/2011/05/screenshot1.png"><img class="aligncenter size-full wp-image-417" title="screenshot1" src="http://www.lonelycode.com/wp-content/uploads/2011/05/screenshot1.png" alt="" width="600" height="353" /></a></p>
<p>&nbsp;</p>
<p>What Sencha does is create the HTML for you based on your docking options and how you nest your panels, to create the above we had an overall framework of top bar, left bar and right panel, then sub-divided the left panel into the back/forward toolbar and the post list &#8211; Sencha was clever enough to interpret this properly and build up the interface appropriately.</p>
<p>Using the models/stores approach, the list was populated form a web service with relatively little fuss and the loading of new or old posts only required a minor change to the store paramters to make possible.</p>
<p><span style="text-decoration: underline;"><strong>Testing this on your tablet / Phonegap</strong></span></p>
<p>Now you may say this is all well and good &#8211; but if you&#8217;ve set up your HelloWorld app as advised in the Phonegap quick start then you should be able to re-map that to a new AndReddit application. If you have your basic project set up &#8211; simply put your lib folder and the index.html file into the assets/www directory of your phonegap project (copy them, do not link them).</p>
<p>Once this is done, plugging in your tablet via USB (make sure debug mode is on and you&#8217;ve installed the coreect drivers for your tablet) and right clicking the project and selecting Run As -&gt; Android Application, your tablet should display on the list of available devices, clicking &#8216;Run&#8217; will then install and run the app on your device.</p>
<p><strong><u>Round-Up</u></strong></p>
<p>You&#8217;ll have noticed we didn&#8217;t actually use any of Phonegap&#8217;s functionality to do anything with the device &#8211; more on that later, this tutorial was to get you started building a UI that seems familliar using one of the more popular frameworks and how to interface that with the Phonegap method of building Android apps.</p>
<p>However, had you set up your UI the same way and used a list of locations you could activate the mapping API of phonegap and display it in one of your panels, enabling the nice UI interfaces as well as interfacing directly with the device.</p>
<p>I&#8217;llbe making the full project avaialble soon, ion the meantime if you want a copy leave a comment <img src='http://www.lonelycode.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>Happy hacking,</p>
<p>Martin</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2011/05/02/building-mobile-apps-with-sencha-touch-and-phonegap/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Python Threading and Queues &#8211; and why it&#8217;s awesome</title>
		<link>http://www.lonelycode.com/2011/02/04/python-threading-and-queues-and-why-its-awesome/</link>
		<comments>http://www.lonelycode.com/2011/02/04/python-threading-and-queues-and-why-its-awesome/#comments</comments>
		<pubDate>Fri, 04 Feb 2011 16:48:27 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[The Rest]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=393</guid>
		<description><![CDATA[I&#8217;ve done quite a bit of work doing web development with Django, and one thing that doesn&#8217;t really come up when doing standard CRUD work is that mostly all web sites are linear &#8211; take a request, process it and spit out a response. Sure you&#8217;re underlying architecture uses threading, but that&#8217;s invisible to the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/2011/04/11/python-threadi…hy-its-awesome/"><img src="http://www.lonelycode.com/wp-content/uploads/2011/04/threads.jpg" alt="" title="threads" /></a></p>
<p>I&#8217;ve done quite a bit of work doing web development with Django, and one thing that doesn&#8217;t really come up when doing standard CRUD work is that mostly all web sites are linear &#8211; take a request, process it and spit out a response. Sure you&#8217;re underlying architecture uses threading, but that&#8217;s invisible to the humble web developer, and most of the time is completely unused.</p>
<p>Recently I&#8217;ve been working on an application, a genuine client/server system that didn&#8217;t HTTP, that didn&#8217;t use SQL databases and relied solely on good ol&#8217; memory to function &#8211; continuously &#8211; and respond to multiple requests quickly and speedily without locking up a client.</p>
<p>This is where I learned that threading is awesome, and learned to love the Queue.</p>
<p><span id="more-393"></span></p>
<p><strong>What is threading?</strong></p>
<p>Threading is when you take a function or a process that takes a long time and is quite independent form the rest of your application and let it run in it&#8217;s own memory space, or &#8216;thread&#8217; &#8211; the function will split off from your main execution loop and finish its business all of its own accord. The benefits? It frees up your application to stay responsive, and not ignore other user inputs while it&#8217;s executing.</p>
<p>Take for example a web server &#8211; if it were a linear application it would not acept requests while it was processing a page request from a user until it was done. In the case of a web server &#8211; it will take the request, launch a thread and immediately return to a listening state to handle the next one, without having to actually manage the request.</p>
<p><strong>A threading example in Python</strong></p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> count_stuff<span style="color: black;">&#40;</span><span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; A thread class that will count a number, sleep and output that number<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> start_num<span style="color: #66cc66;">,</span> end<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">num</span> <span style="color: #66cc66;">=</span> start_num<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">num</span> <span style="color: #66cc66;">!=</span> end:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">num</span> +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Outputting: &quot;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">num</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">time</span>.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">break</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
myThread <span style="color: #66cc66;">=</span> count_stuff<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><br />
myThread.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Let&#8217;s walk through the code:</p>
<ol>
<li>First we import threading and time &#8211; threading is the base class that allows you to run your function/object as a thread</li>
<li>Since we want to pass values to intitialise the thread, we override the __init__() function &#8211; remember to call the base class init function afterward otherwise you will get an error</li>
<li>The run() function is the real meat of your class &#8211; this is where you put the code that will kick off the thread &#8211; in this case we take a number, increment it &#8211; if it equals our end value we break otherwise, keep going and sleep 5 seconds</li>
</ol>
<p>Pretty simple right?</p>
<p>The kicker is that you might want to do something with the output of your calculation separately in another part of your application &#8211; this is where a Queue comes in.</p>
<p><strong>What is a Queue?</strong></p>
<p>A Queue is a memory structure that is thread-safe, it will not cause collisions in your application or memory space (for example, if you started 5 threads of the above and wrote to a text file it could cause an error as two or more threads try to write to the file at the same time). Queues work on three principles: LIFO, FIFO and Sorted.</p>
<p>So, how do we write and pull data from a queue?</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">threading</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">Queue</span><br />
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span><br />
<br />
myQueue <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">Queue</span>.<span style="color: #dc143c;">Queue</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> count_stuff<span style="color: black;">&#40;</span><span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot; <br />
&nbsp; &nbsp; &nbsp; &nbsp; A thread class that will count a number, sleep and output that number<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> start_num<span style="color: #66cc66;">,</span> end<span style="color: #66cc66;">,</span> q<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">num</span> <span style="color: #66cc66;">=</span> start_num<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">q</span> <span style="color: #66cc66;">=</span> q<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">threading</span>.<span style="color: black;">Thread</span>.<span style="color: #0000cd;">__init__</span> <span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> run<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">num</span> <span style="color: #66cc66;">!=</span> end:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">num</span> +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">q</span>.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">num</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #dc143c;">time</span>.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">break</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
myThread <span style="color: #66cc66;">=</span> count_stuff<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> myQueue<span style="color: black;">&#41;</span><br />
myThread.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> myQueue.<span style="color: black;">empty</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; val <span style="color: #66cc66;">=</span> myQueue.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Outputting: &quot;</span><span style="color: #66cc66;">,</span> val<br />
&nbsp; &nbsp; <span style="color: #dc143c;">time</span>.<span style="color: black;">wait</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Let&#8217;s walk through the differences here:</p>
<ol>
<li>First we import Queue</li>
<li>We create a Queue object</li>
<li>We modify the __init__() function to take a new parameter &#8211; here we pass it the queue object for modification</li>
<li>When the thread runs, it will put its output into the queue using the put() method</li>
<li>In our main execution section we have added a loop that will poll the queue and pull out data &#8211; Queue&#8217;s are sensitive things and can behave in complex ways, so I&#8217;d recommend reading the docs to get more detail (after all this is just an intro)</li>
</ol>
<p>The most interesting part of this code is the last section where we poll the queue &#8211; we are using a loop to continually poll the queue &#8211; naturally a queue could be polled by other threads in your application to allow for message passing between running processes.</p>
<p>Queue&#8217;s are everywhere &#8211; most notably (and a great example) is in Hadoop and AWS Simple Messaging Service &#8211; both have simple messaging systems that replicate the functionality of a Queue on a cluster level, which is awesome.</p>
<p>Some really handy links:</p>
<ul>
<li><a href="http://www.devshed.com/c/a/Python/Basic-Threading-in-Python/" target="_blank">Dev Shed article on threading in python</a></li>
<li><a href="http://www.ibm.com/developerworks/aix/library/au-threadingpython/">Practical threaded programming in Python</a></li>
</ul>
<p>Enjoy,<br />
Martin</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2011/02/04/python-threading-and-queues-and-why-its-awesome/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing a basic plugin framework in Python</title>
		<link>http://www.lonelycode.com/2010/11/30/writing-a-basic-plugin-framework-in-python/</link>
		<comments>http://www.lonelycode.com/2010/11/30/writing-a-basic-plugin-framework-in-python/#comments</comments>
		<pubDate>Tue, 30 Nov 2010 16:30:23 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=387</guid>
		<description><![CDATA[While working on the initial version of DjangoSVN, I realised that one of the coolest things I could do with the DjangoSVN command interpreter was to make it pluggable. The idea was simple: You can set up a DjangoSVN server anywhere, then write your own custom plug-ins that you can just drop into the plug-in [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/wp-content/uploads/2011/04/plugs.jpg"><img src="http://www.lonelycode.com/wp-content/uploads/2011/04/plugs.jpg" alt="" title="plugs"  /></a></p>
<p>While working on the initial version of DjangoSVN, I realised that one of the coolest things I could do with the DjangoSVN command interpreter was to make it pluggable.</p>
<p>The idea was simple: You can set up a DjangoSVN server anywhere, then write your own custom plug-ins that you can just drop into the plug-in folder AND make use of the Django ORM should you want to give it database backing and an admin screen.</p>
<p><span id="more-387"></span></p>
<p>So I had to figure out how to make that work, and it was surprisingly easy, so this will be a short post. Credit where it is due, I found a lot of help over at StackOverflow &#8211; so never underestimate the true power of Google <img src='http://www.lonelycode.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>So, how do you write a plug-in framework?</p>
<p>The first step is planning &#8211; in order to use a plug-in, it should have a set, fixed format that can be written in. In the case of DjangoSVN, I wrote a &#8216;master&#8217; plug-in class that could be inherited from any new plug-in to add functionality &#8211; this would ensure that the interface between your app and any new plug-in will always work the same way. It also gives you a chance to think about how you&#8217;ll pass values to it and return them in a standardised way.</p>
<p>Here&#8217;s the interface for DjangoSVN plug-ins:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> dsvn_hook:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Base SVN Hook class, svncommand will load a hook class from the<br />
&nbsp; &nbsp; &nbsp; &nbsp; target command and pass it the args and dsvncommand() object.<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
<br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> args<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> dsvnobj<span style="color: #66cc66;">=</span><span style="color: #008000;">None</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">args</span> <span style="color: #66cc66;">=</span> args <span style="color: #808080; font-style: italic;"># The command arguments that are after the command</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">dsvnobj</span> <span style="color: #66cc66;">=</span> dsvnobj <span style="color: #808080; font-style: italic;"># the dsvncommand() object that is called by the parser</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Can be ignored, but if set in init() will have an effect on how repository</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># paths are managed.</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">django</span> <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> execute_hook<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; This is what gets called by the command parser - override this function to<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; execute complex scripts<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">None</span></div></td></tr></tbody></table></div>
<p>It&#8217;s pretty straightforward &#8211; essentially you have a class, with an init() function you can override. You can put whatever you like in here that&#8217;s specific to your app.</p>
<p>It get&#8217;s interesting when you look at how a plug-in gets called in the app itself &#8211; here&#8217;s the command loader from DjangoSVN that loads up a plug-in:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">def</span> CommandHook<span style="color: black;">&#40;</span>command<span style="color: #66cc66;">,</span> args<span style="color: #66cc66;">,</span> dsvnobj<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; This will take the command and args variables, check a module list <br />
&nbsp; &nbsp; in the COMMAND_PATH directory for a new hook<br />
&nbsp; &nbsp; if it finds one it will kick off the execute_command() function after <br />
&nbsp; &nbsp; importing the module<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; Module loading is dynamic, so more commands can be added as needed!<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; commands_dir <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span>COMMAND_PATH<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; found <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> command.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> commands_dir: &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; hook_module <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;from command_list.&quot;</span> + command.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;.hook import hook&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Importing hook class<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">exec</span> hook_module<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Import complete<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; found <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; found <span style="color: #66cc66;">=</span> <span style="color: #008000;">False</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Import failed:'</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> found:<br />
&nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;FOUND HOOK: &quot;</span> + <span style="color: #008000;">str</span><span style="color: black;">&#40;</span>command<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Executing hook...<span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thishook <span style="color: #66cc66;">=</span> hook<span style="color: black;">&#40;</span>args<span style="color: #66cc66;">=</span>args<span style="color: #66cc66;">,</span> dsvnobj<span style="color: #66cc66;">=</span>dsvnobj<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; thishook.<span style="color: black;">execute_hook</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span><span style="color: #66cc66;">,</span> e:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #483d8b;">'Execute failed... <span style="color: #000099; font-weight: bold;">\n</span>'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; logme<span style="color: black;">&#40;</span><span style="color: #008000;">str</span><span style="color: black;">&#40;</span>e<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>What is happening here is this:</p>
<ol>
<li>Get a list of the plug-ins that you have created in a directory &#8211; the plug-in name is the name of the directory (they are basically python modules)</li>
<li>If the plug-in we&#8217;re looking for is in the commands[] dictionary, set up a load statement as a string. It&#8217;s important to get the parent module here &#8211; it might be worth it dynamically generating this if you don;t have your app in you PYTHONPATH</li>
<li>Run exec hook_module &#8211; this will actually run the string as if it were typed in the interpreter</li>
<li>Try / Catch that thing to ensure that you can shoot out an error if it doesn&#8217;t work</li>
<li>Run the hooks main function &#8211; in the case of our interface, we use execute_hook()</li>
</ol>
<p>That&#8217;s it &#8211; essentially this is all that is required to make your app plugable.</p>
<p>To make it more Django-specific, we include the following lines in the actual hook to load up the ORM machinery:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">os</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> dsvn.<span style="color: black;">svnwrapper</span>.<span style="color: black;">dsvn_hook</span> <span style="color: #ff7700;font-weight:bold;">import</span> dsvn_hook<br />
<br />
<span style="color: #ff7700;font-weight:bold;">class</span> hook<span style="color: black;">&#40;</span>dsvn_hook<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> execute_hook<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#Put what you like in here...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#Initialise Django settings</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">core</span>.<span style="color: black;">management</span> <span style="color: #ff7700;font-weight:bold;">import</span> setup_environ&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> dsvn <span style="color: #ff7700;font-weight:bold;">import</span> settings<br />
&nbsp; &nbsp; &nbsp; &nbsp; setup_environ<span style="color: black;">&#40;</span>settings<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #008000;">self</span>.<span style="color: black;">do_something</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Here we load up the django machinery in the init function and can essentially bolt-on a django app as a manager to your plug-in using your normal settings.py file!</p>
<p>How would you improve this model? Do you have ideas on making a plug-in framework that can be re-used in python easily?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2010/11/30/writing-a-basic-plugin-framework-in-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Quick Guide on Python Remote Objects (PYRO)</title>
		<link>http://www.lonelycode.com/2010/11/27/a-quick-guide-on-python-remote-objects-pyro/</link>
		<comments>http://www.lonelycode.com/2010/11/27/a-quick-guide-on-python-remote-objects-pyro/#comments</comments>
		<pubDate>Sat, 27 Nov 2010 16:30:56 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=380</guid>
		<description><![CDATA[Recently I have been contemplating client-server applications, how these can eventually be tied into a web app and how best to write all of this in Python. This post will outline the usage of one of the more awesome XMLRPC libraries and also discuss why it&#8217;s better than what else is out there&#8230; So, the [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/2010/11/27/a-quick-guide-…e-objects-pyro/"><img src="http://www.lonelycode.com/wp-content/uploads/2010/11/pyro.jpg" alt="" title="pyro"  align="center" height="103" /></a></p>
<p>Recently I have been contemplating client-server applications, how these can eventually be tied into a web app and how best to write all of this in Python. This post will outline the usage of one of the more awesome XMLRPC libraries and also discuss why it&#8217;s better than what else is out there&#8230;</p>
<p><span id="more-380"></span></p>
<p>So, the first place that good ol&#8217; Google too me was the XMLRPC library for Python, however &#8211; may I recommend to steer clear of this library as it suffers from the following most immediate problems:</p>
<ol>
<li>Complex python objects cannot be passed easily, not without writing your own picking</li>
<li>It presents errors when handling types it can;t marshal &#8211; things such as lists and dictionaries, which, out of pure interest are possibly some of the more useful elements in python</li>
<li>No traceback for errors &#8211; this is a biggie, debugging an RPC client/server app is a pain in a** when you can;t clearly identify which part of the server code is failing since all your errors are coming from the XMLRPC library.</li>
</ol>
<p>So, enough about that. If you are interested in torturing yourself with XMLRPC, you can find some really nice tutorials from IBM here on building a simple client / server.</p>
<p>Having given up on XMLRPC, I swiftly moved to the rather wonderful PYRO library. This library has great documentation, a clear syntax and some very handy features. Particularly, I would really enjoy:</p>
<ol>
<li>When you pass objects from client to server, they are full-blown python objects that retain all properties, not some poxy proxy</li>
<li>It can handle all those un-marshalable types, so passing a really complex custom class down the wire isn&#8217;t a problem</li>
<li>Full blown exception handling &#8211; you can trap the traceback of the error to your server app with a really nice error handler</li>
</ol>
<p>So, without further ado &#8211; here&#8217;s the simplest way to use the PYRO library (this is pretty much a copy of the main example &#8211; I&#8217;ve just expanded with some additional notes underneath to save everyone some frustration):</p>
<p><strong>The server:</strong></p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br />24<br />25<br />26<br />27<br />28<br />29<br />30<br />31<br />32<br />33<br />34<br />35<br />36<br />37<br />38<br />39<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">class</span> aService<span style="color: black;">&#40;</span>Pyro.<span style="color: black;">core</span>.<span style="color: black;">ObjBase</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; This is our server application<br />
&nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;">#You can do what you like in here to inittialise your server</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># However, it's worth remembering to rais PYRO's own</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># init() method!</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; Pyro.<span style="color: black;">core</span>.<span style="color: black;">ObjBase</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>&nbsp; &nbsp; <br />
<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> whatsMyName<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> name<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># This is a service we are going to make public</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;Your name is &nbsp;%s, hi %s!&quot;</span> % <span style="color: black;">&#40;</span>name<span style="color: #66cc66;">,</span> name<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">def</span> startServer<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #483d8b;">&quot;&quot;&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; We'll start the server with this function<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;&quot;&quot;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Get the server ready</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; Pyro.<span style="color: black;">core</span>.<span style="color: black;">initServer</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Create a daemon object - you can set host and port here too</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; daemon<span style="color: #66cc66;">=</span>Pyro.<span style="color: black;">core</span>.<span style="color: black;">Daemon</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># This is the URI of the service once it launches</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; uri<span style="color: #66cc66;">=</span>daemon.<span style="color: black;">connect</span><span style="color: black;">&#40;</span>aService<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #483d8b;">&quot;aservice&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Server URI is:&quot;</span><span style="color: #66cc66;">,</span> uri<br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Start the server...</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; daemon.<span style="color: black;">requestLoop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <br />
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />
&nbsp; &nbsp; startServer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">&quot;__main__&quot;</span>:<br />
&nbsp; &nbsp; main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>As you can see from the code above, it&#8217;s very similar to the XMLRPC implementation of a service &#8211; essentially, all you need to do is create a class that represents your server, add some methods that do fancy things and return some kind of object. Unlike XMLRPC, PYRO will not crash if your method returns None.</p>
<p>Once you have created the server, the startServer() function is only used to kick off the daemon serving loop, an interesting thing to note here is the URI that the daemon spits out, because it will look horrendous and changes each time the server boots up. Now this might seem like quite silly behaviour, but it only occurs because there are different ways of accessing PYRO objects from a client, and the difference in the access URI&#8217;s left me with quite a bit of confusion for a while. But all will become clear.</p>
<p><strong>Part 2 &#8211; The client:</strong></p>
<p>Create a new client.py file and stick this code into it:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">import</span> Pyro.<span style="color: black;">core</span><br />
<br />
proxy <span style="color: #66cc66;">=</span> Pyro.<span style="color: black;">core</span>.<span style="color: black;">getProxyForURI</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;PYROLOC://localhost:7766/jobserver&quot;</span><span style="color: black;">&#41;</span><br />
<br />
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Calling remote function whatsMyName()...&quot;</span><br />
return_value <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;&quot;</span><br />
<br />
<span style="color: #808080; font-style: italic;"># This is really handy for debugging your server code:</span><br />
<span style="color: #ff7700;font-weight:bold;">try</span>:<br />
&nbsp; &nbsp; return_value <span style="color: #66cc66;">=</span> proxy.<span style="color: black;">whatsMyName</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Jively'</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> return_value<br />
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span><span style="color: #66cc66;">,</span>x:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>Pyro.<span style="color: black;">util</span>.<span style="color: black;">getPyroTraceback</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Simples! So, what&#8217;s happening in this piece of code?</p>
<p>After importing the library, we create a proxy object &#8211; you will never call an object directly on the server &#8211; all calls are handled through a proxy. In pythonic terms, this is essentially the same as creating a local object based on the aService() class with all calls being called remotely (thanks to inheriting the server class from the Pyro ObjBase class).</p>
<p>You then treat the methods of the server class as if they were local &#8211; in this case we call whatsMyName() and it will return the string &#8220;Your name is Jively, Hi Jively!&#8221; and print this out.</p>
<p>What is important to note and to include is the structure of the try/except exception handling &#8211; this wonderful bit of code will make it super simple to debug your server app.</p>
<p>If you&#8217;ve worked with Pyro or think there&#8217;s any really useful resources out there &#8211; let me know in the comments!</p>
<p><strong>Resources:</strong></p>
<ol>
<li><a href="http://www.xs4all.nl/~irmen/pyro3/">Pyro3</a></li>
<li><a href="http://www.ibm.com/developerworks/webservices/library/ws-pyth10.html">IBM Developerworks XMLRPC with Python</a></li>
<li><a href="http://www.oreillynet.com/onlamp/blog/2005/10/why_i_ditched_xmlrpc_in_favor.html">Why I ditched XMLRPC in favor of Pyro</a></li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2010/11/27/a-quick-guide-on-python-remote-objects-pyro/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing PyTranscode</title>
		<link>http://www.lonelycode.com/2009/11/21/announcing-pytranscode/</link>
		<comments>http://www.lonelycode.com/2009/11/21/announcing-pytranscode/#comments</comments>
		<pubDate>Sat, 21 Nov 2009 21:23:29 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[FFMPEG]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=350</guid>
		<description><![CDATA[<a rel="attachment wp-att-352" href="http://www.lonelycode.com/2009/11/21/announcing-pytranscode/"><img class="aligncenter size-full wp-image-352" title="PyTranscode" src="http://www.lonelycode.com/wp-content/uploads/2009/11/pt1.jpg" alt="PyTranscode - FFMPEG management for python"  /></a>

<p>
PyTranscode is a set of classes that control and report from FFMPEG. They also make using FFMPEG from python very very simple.</p>

<strong>Things you can do with PyTranscode:</strong>
<ul>
	<li>Transcode videos from format a to b using presets stored in another file</li>
	<li>Extract splash images from a video file (actually extracts a series of splash images at user-defined intervals)</li>
	<li>Objectify video files - create a VideoObject form a file and it will provide you with all the details of the file from framerate to duration to formats used in both audio and video</li>
	<li>Runner - run FFMPEG command and trap the output, reporting back percentage complete of any action</li>
</ul>]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-352" href="http://www.lonelycode.com/2009/11/21/announcing-pytranscode/pt1/"><img class="aligncenter size-full wp-image-352" title="PyTranscode" src="http://www.lonelycode.com/wp-content/uploads/2009/11/pt1.jpg" alt="PyTranscode - FFMPEG management for python"  /></a></p>
<p>PyTranscode is a set of classes that control and report from FFMPEG. They also make using FFMPEG from python very very simple.</p>
<p><strong>Things you can do with PyTranscode:</strong></p>
<ul>
<li>Transcode videos from format a to b using presets stored in another file</li>
<li>Extract splash images from a video file (actually extracts a series of splash images at user-defined intervals)</li>
<li>Objectify video files &#8211; create a VideoObject form a file and it will provide you with all the details of the file from framerate to duration to formats used in both audio and video</li>
<li>Runner &#8211; run FFMPEG command and trap the output, reporting back percentage complete of any action</li>
</ul>
<p>This software is being released under the GPL v3 because I think it should be out there and I think it&#8217;s important to get a handle on video in python as there just isn&#8217;t any up-to-date code out there that truly wraps FFMPEG&#8217;s functionality up (not in any modern way anyway).</p>
<p>There is an overarching strategy to this, PyTranscode will hopefully form a cornerstone of my next Django project &#8211; unnamed at the time of writing, that will essentially offer:</p>
<ul>
<li>A storage engine for local or cloud-based storage</li>
<li>A queue manager for scaling, this again would have vairous back-ends for local queue management or something like Amazon Queue Service</li>
<li>A transcode server that can be run on multpile machines and be managed via an API <em>OR </em>be run in a mode to interact with the queue service</li>
<li>An API wrapper to control the transcode-server for common tasks</li>
</ul>
<p>Anyone interested in contributing please contact me on Twitter @lonelycode or leave a message on the blog &#8211; I&#8217;ll be glad to get back to you.</p>
<p>The project is hosted on google code and can be found <a href="http://code.google.com/p/pytranscode/" target="_blank">here</a></p>
<p><strong>Sample usage:</strong></p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:400px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />10<br />11<br />12<br />13<br />14<br />15<br />16<br />17<br />18<br />19<br />20<br />21<br />22<br />23<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #ff7700;font-weight:bold;">from</span> ffmpeg <span style="color: #ff7700;font-weight:bold;">import</span> *<br />
<span style="color: #ff7700;font-weight:bold;">from</span> presets <span style="color: #ff7700;font-weight:bold;">import</span> *<br />
<span style="color: #ff7700;font-weight:bold;">from</span> runner <span style="color: #ff7700;font-weight:bold;">import</span> *<br />
<br />
<span style="color: #ff7700;font-weight:bold;">def</span> testrun<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; infile <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'video.avi'</span><br />
&nbsp; &nbsp; outfile <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'result.flv'</span><br />
&nbsp; &nbsp; logfile <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'logthis.txt'</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Create the command line</span><br />
&nbsp; &nbsp; cl <span style="color: #66cc66;">=</span> ffmpeg<span style="color: black;">&#40;</span>infile<span style="color: #66cc66;">,</span> outfile<span style="color: #66cc66;">,</span> logfile<span style="color: #66cc66;">,</span> HQ_FLV_VIDEO<span style="color: #66cc66;">,</span> HQ_FLV_AUDIO<span style="color: black;">&#41;</span>.<span style="color: black;">build_command_line</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># setup the command thread</span><br />
&nbsp; &nbsp; run <span style="color: #66cc66;">=</span> FuncThread<span style="color: black;">&#40;</span>runTranscode<span style="color: #66cc66;">,</span> cl<span style="color: #66cc66;">,</span> logfile<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Set up the tracking thread</span><br />
&nbsp; &nbsp; track <span style="color: #66cc66;">=</span> FuncThread<span style="color: black;">&#40;</span>runTracker<span style="color: #66cc66;">,</span> logfile<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; <span style="color: #808080; font-style: italic;"># Start run and tracker</span><br />
&nbsp; &nbsp; run.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; track.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; <br />
testrun<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div></td></tr></tbody></table></div>
<p>Enjoy!,</p>
<p>M</p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2009/11/21/announcing-pytranscode/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon RDS and Django</title>
		<link>http://www.lonelycode.com/2009/10/27/amazon-rds-and-django/</link>
		<comments>http://www.lonelycode.com/2009/10/27/amazon-rds-and-django/#comments</comments>
		<pubDate>Tue, 27 Oct 2009 12:03:59 +0000</pubDate>
		<dc:creator>Martin</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[Amazn RDS]]></category>
		<category><![CDATA[Amazon EC2]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SimpleDB]]></category>

		<guid isPermaLink="false">http://www.lonelycode.com/?p=320</guid>
		<description><![CDATA[Amazon has recently released a long-awaited feature addition to it&#8217;s Web Services infrastructure: Relational Databases. Having for a long time only had SimpleDB on offer (non-relational and weird to implement), it&#8217;s always been something of a struggle to get MySQL running on EC2. Traditionally one would have to set up a block storage device, mount [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lonelycode.com/2009/10/27/amazon-rds-and-django/awsdjango/" rel="attachment wp-att-337"><img src="http://www.lonelycode.com/wp-content/uploads/2009/10/awsdjango.jpg" alt="Amazon Relational Database Service and Django" title="awsdjango" class="aligncenter size-full wp-image-337" /></a></p>
<p>Amazon has recently released a long-awaited feature addition to it&#8217;s Web Services infrastructure: <a href="http://aws.amazon.com/rds/" target="_blank">Relational Databases</a>. Having for a long time only had SimpleDB on offer (non-relational and weird to implement), it&#8217;s always been something of a struggle to get MySQL running on EC2.</p>
<p>Traditionally one would have to set up a block storage device, mount it, hack the mySQL  configuration to use the mounted EBS volume for storage (not to mention messing around with XFS locking and snapshotting the DB when the instance goes down). All in all a pain to implement and maintain.</p>
<p>Now with Amazon&#8217;s Relational Database Service, you get a MySQL database, hosted in the cloud &#8211; auto backed-up, patched and running on a scalable infrastructure (you can re-size it to your hearts content) and at the same time independent of your instances &#8211; meaning no more messing around with block storage for your database.</p>
<p>Now RDS is actually completely compatible with all mySQL tools, so interfacing it with django is stupid simple &#8211; but, for those that want a quick walkthrough, I&#8217;ve prepared one below, from getting the service running to getting django to use it:</p>
<p><strong>1. Sign up for the RDS account</strong></p>
<p>I&#8217;m going to assume you&#8217;re already using amazon AWS, or at least have an account &#8211; if not, <a href="http://aws.amazon.com/" target="_blank">sign up now</a>. Once done, go tot he rds page and <a href="http://aws.amazon.com/rds/" target="_blank">sign up for the RDS service</a>.</p>
<p><strong>2. Get the tools</strong></p>
<p>You&#8217;ll need the command line tools, if you&#8217;re familiar with EC2 this should be easy, but if not, you will need to download <a href="http://java.com/en/download/manual.jsp" target="_blank">Java and install it</a>.</p>
<p>Next, <a href="http://developer.amazonwebservices.com/connect/entry.jspa?externalID=2928" target="_blank">download the command line tools</a> and unzip them to a friendly directory.</p>
<p><strong>3. Set up your paths</strong></p>
<p>I&#8217;ve put together a simple batch script (for windows) that will set all the paths up for you, it is helpfully included below:</p>
<p><em>setuprds.bat</em></p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap"><span style="color: #66cc66;">@</span>echo off<br />
<span style="color: #008000;">set</span> AWS_RDS_HOME<span style="color: #66cc66;">=</span>C:\RDSCli-1.0.001<br />
<span style="color: #008000;">set</span> PATH<span style="color: #66cc66;">=</span>%PATH%<span style="color: #66cc66;">;</span>%AWS_RDS_HOME%\bin<br />
<span style="color: #008000;">set</span> AWS_CREDENTIAL_FILE<span style="color: #66cc66;">=</span>%AWS_RDS_HOME%\aws_credentials<br />
<span style="color: #008000;">set</span> JAVA_HOME<span style="color: #66cc66;">=</span>C:\Program Files\Java\jre6</div></td></tr></tbody></table></div>
<p>make sure to set the JAVA_HOME path to your java installation</p>
<p>4<strong>. Set up your credentials template</strong></p>
<p>If you look at the above path, I&#8217;ve put it into the command line tools  home, name it aws_credentials and it should look something like this:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">AWSAccessKeyId<span style="color: #66cc66;">=</span>YOUR_ACCESS_ID<br />
AWSSecretKey<span style="color: #66cc66;">=</span>YOUR_SECRET_KEY</div></td></tr></tbody></table></div>
<p>For those that don&#8217;t know where to get these ID&#8217;s, you can get them from your AWS account page under <em>&#8216;Your Account&#8217; -&gt; Security Credentials</em></p>
<p><strong>5.  Set up your paths</strong></p>
<p>Run the batch file you&#8217;ve set up &#8211; that should get all your paths sorted out &#8211; if you want to make the changes permanent, you will need to set the paths up in your control panel to make them permanent.</p>
<p>To test if everything is running type in:</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">c:\&amp;gt; rds --help</div></td></tr></tbody></table></div>
<p><strong>6. Let&#8217;s get started &#8211; setting up your first instance</strong></p>
<p>I&#8217;ve based these instructions on the <a href="http://docs.amazonwebservices.com/AmazonRDS/latest/GettingStartedGuide/" target="_blank">Amazon quick start guide</a>, so if you want to see the originals just head over there, here&#8217;s how you would start up your first instance:</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">c:\&amp;gt; rds-create-db-instance --db-instance-identifier TestInstanceName --allocated-storage 20 --db-instance-class db.m1.xlarge --engine MySQL5.1  --master-username mymasteruser --master-user-password mymasterpass  --db-name TESTDB --headers</div></td></tr></tbody></table></div>
<p>Change the names of the instance, username, password, DB Size and DB name in the command line before running it, you should get output showing that the instance is starting.</p>
<p><strong>7. checking your instances</strong></p>
<p>Make sure that your instance is started &#8211; and get the address of your new DB, simply type in:</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">c:\&amp;gt; rds-describe-db-instances --headers</div></td></tr></tbody></table></div>
<p>If your instance has started, you&#8217;ll see something along the lines of:</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">available  xxxx.xxxx.us-east-1.rds.amazonaws.com  3306  us-east-1a  1</div></td></tr></tbody></table></div>
<p>In the output, that&#8217;s your db host name &#8211; write it down.</p>
<p><strong>8. Set up the security settings.</strong></p>
<p>For simplicity (and testing) you can grant access to the instance using an IP range, it&#8217;s easy &#8211; just enter the range with the following command</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">c:\ &amp;gt; rds-authorize-db-security-group-ingress default --cidr-ip xx.xx.xx.xx/10 --headers</div></td></tr></tbody></table></div>
<p>If you want to grant access to an EC2 security group, you will need your account ID (this is different from your access ID) &#8211; you will find it under &#8216;Your Account&#8217; on the top right, it will say something along the lines of:</p>
<blockquote><p><em><span class="txtxxsm">Account Number XXXX-XXXX-XXXX</span></em></p></blockquote>
<p>remove the dashes and place the account number into the following command:</p>
<div class="codecolorer-container text dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br /></div></td><td><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">c:\&amp;gt; rds-authorize-db-security-group-ingress default --ec2-security-group-name SECURITY_GROUP_NAME --ec2-security-group-owner-id XXXXXXXXXXXX</div></td></tr></tbody></table></div>
<p><strong>9. Try it out with django</strong></p>
<p>I set up a standard app and ran it from localhost, the most important thing is to set up your settings.py file:</p>
<div class="codecolorer-container python dawn" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><table cellspacing="0" cellpadding="0"><tbody><tr><td style="padding:5px;text-align:center;color:#888888;background-color:#EEEEEE;border-right: 1px solid #9F9F9F;font: normal 12px/1.4em Monaco, Lucida Console, monospace;"><div>1<br />2<br />3<br />4<br />5<br />6<br /></div></td><td><div class="python codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">DATABASE_ENGINE <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'mysql'</span><br />
DATABASE_NAME <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'DB_NAME'</span><br />
DATABASE_USER <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'mymasteruser'</span><br />
DATABASE_PASSWORD <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'mymasterpass'</span><br />
DATABASE_HOST <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'xxxxx.xxxxx.us-east-1.rds.amazonaws.com'</span><br />
DATABASE_PORT <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">''</span></div></td></tr></tbody></table></div>
<p>In your app models.py create your model the same way you would normally, go to the command prompt and run syncdb. Your model will be created and you can go on ahead and use it to your hearts content the same way you would any other MySQL back-end.</p>
<p>I&#8217;d recommend reading up on the RDS command line tools &#8211; the documentation <a href="http://aws.amazon.com/documentation/" target="_blank">can be found here</a></p>
<p>Hopefully Amazon will add RDS to the AWS management console like they did EBS, which would circumvent this whole set up malarkey.</p>
<p><em>What are your thoughts on this new service? Is it too pricey?</em></p>
]]></content:encoded>
			<wfw:commentRss>http://www.lonelycode.com/2009/10/27/amazon-rds-and-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

