<?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>Giv Parvaneh &#187; Python</title>
	<atom:link href="http://www.givp.org/blog/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.givp.org/blog</link>
	<description>::::..::..:::::::...:::::....::......:::::::::....::::......::::::::::::::::</description>
	<lastBuildDate>Mon, 23 Jan 2012 17:50:02 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<meta xmlns="http://www.w3.org/1999/xhtml" name="robots" content="noindex,follow" />
		<item>
		<title>MongoDB in Django</title>
		<link>http://www.givp.org/blog/2011/11/30/mongodb-in-django/</link>
		<comments>http://www.givp.org/blog/2011/11/30/mongodb-in-django/#comments</comments>
		<pubDate>Wed, 30 Nov 2011 12:59:28 +0000</pubDate>
		<dc:creator>Giv</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[MongoDB]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[mongoDB]]></category>

		<guid isPermaLink="false">http://www.givp.org/blog/?p=301</guid>
		<description><![CDATA[Traditional relational databases (mySQL PostgreSQL etc) and noSQL systems are not mutually exclusive. I have several Django applications that are happily using mySQL. If your site is not scaling due to your database, you are doing it wrong! noSQL will not help you until you start caching some of those expensive queries using something like [...]]]></description>
			<content:encoded><![CDATA[<p>Traditional relational databases (mySQL PostgreSQL etc) and noSQL systems are not mutually exclusive. I have several Django applications that are happily using mySQL. If your site is not scaling due to your database, you are doing it wrong! noSQL will not help you until you start caching some of those expensive queries using something like Memcached.</p>
<p>I use MongoDB alongside mySQL for all the dirty work like storing stats for later processing. There&#8217;s no point in polluting mySQL with this sort of data, especially when you&#8217;re dealing with millions of entries.</p>
<p>This post is intended for absolute beginners who use Django tranditionally and are curious about how they can integrate a secondary storage service into their apps. I&#8217;m assuming you have already <a href="http://www.mongodb.org/display/DOCS/Quickstart" onclick="pageTracker._trackPageview('/outgoing/www.mongodb.org/display/DOCS/Quickstart?referer=');">installed MongoDB</a> on your dev environment. You will also need to install the <a href="http://mongoengine.org" onclick="pageTracker._trackPageview('/outgoing/mongoengine.org?referer=');">MongoEngine </a>library for Python.</p>
<p>Let&#8217;s start.</p>
<p>You already know how to create data models in Django, but let&#8217;s say we want to store an activity feed for your users everytime they do something on your site. We begin by creating a data model similar to Django&#8217;s ORM using MongoEngine but the difference here is that you don&#8217;t need to run &#8220;syncdb&#8221; to create your tables. Mongo&#8217;s collections (similar to SQL tables) are schemaless so these models can be manipulated and you won&#8217;t need to worry about running migration scripts.</p>
<p>Let&#8217;s create a simple collection for storing user activities. Create a file where you normally keep your Django models and call it mongomodel.py</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> mongoengine <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># connect to a db (no need to create this - it will be created automagically)</span>
connect<span style="color: black;">&#40;</span><span style="color: #483d8b;">'useractivity'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Author<span style="color: black;">&#40;</span>Document<span style="color: black;">&#41;</span>:
    pk = IntField<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    name = StringField<span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">200</span>, required=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Activity<span style="color: black;">&#40;</span>Document<span style="color: black;">&#41;</span>:
    message = StringField<span style="color: black;">&#40;</span>max_length=<span style="color: #ff4500;">200</span><span style="color: black;">&#41;</span>
    author = ReferenceField<span style="color: black;">&#40;</span>Author, reverse_delete_rule=CASCADE<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>&#8220;What&#8217;s this??!! Django already has a User model, why do I need another in Mongo?&#8221; Well, you don&#8217;t, but say you want your activity to say something like: &#8220;Joe uploaded a photo&#8221; and you want Joe&#8217;s name to be linked to his profile page. We keep a reference to his mySQL id in case we need to look up other info or construct a URL.</p>
<p>You&#8217;ll also notice in the Activity model we are referencing the Author model. This is like a foreign key that will allow us to create relationships, similar to SQL. The CASCADE option will make sure if the user is deleted, all activities are also cleared out.</p>
<p>Ok, let&#8217;s start using this puppy! Using the example above we want to create an activity for Joe next time he uploads a photo. First, import mongomodel.py whenever you&#8217;re planning to interact with Mongo. In my photo upload view function I will create an activity like so:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># After photo upload is complete</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> main.<span style="color: black;">mongomodel</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># first create a user object - you can grab data from request object</span>
the_author = Author<span style="color: black;">&#40;</span>pk=request.<span style="color: #dc143c;">user</span>.<span style="color: #008000;">id</span>, name=request.<span style="color: #dc143c;">user</span>.<span style="color: black;">first_name</span><span style="color: black;">&#41;</span>
the_author.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># now create the activity</span>
activity = Activity<span style="color: black;">&#40;</span>message=<span style="color: #483d8b;">'uploaded a new photo'</span>, author=the_author<span style="color: black;">&#41;</span>
activity.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>That&#8217;s it. If you decide later you also want to add the name of the file uploaded you can simply add a new field to your Activity model and it will just work, plus it will be backwards compatible, i.e. older records without this field will not complain. Lovely.</p>
<p>Displaying the activity is just as simple. In your view function pull out the record and push down to your template:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> main.<span style="color: black;">mongomodel</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># get all activities</span>
activities = Activity.<span style="color: black;">objects</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># push down to template</span>
<span style="color: #ff7700;font-weight:bold;">return</span> render_to_response<span style="color: black;">&#40;</span><span style="color: #483d8b;">'activities.html'</span>, <span style="color: black;">&#123;</span><span style="color: #483d8b;">'activities'</span>:activites<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Now in your template loop and output like any other model:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&lt;</span>ul<span style="color: #66cc66;">&gt;</span>
<span style="color: black;">&#123;</span><span style="color: #66cc66;">%</span> <span style="color: #ff7700;font-weight:bold;">for</span> a <span style="color: #ff7700;font-weight:bold;">in</span> activites <span style="color: #66cc66;">%</span><span style="color: black;">&#125;</span>
    <span style="color: #66cc66;">&lt;</span>li<span style="color: #66cc66;">&gt;&lt;</span>a href=<span style="color: #483d8b;">&quot;{% url main.views.profile a.author.pk %}&quot;</span><span style="color: #66cc66;">&gt;</span><span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> a.<span style="color: black;">author</span>.<span style="color: black;">name</span> <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span><span style="color: #66cc66;">&lt;</span>/a<span style="color: #66cc66;">&gt;</span> <span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> a.<span style="color: black;">message</span> <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span><span style="color: #66cc66;">&lt;</span>/li<span style="color: #66cc66;">&gt;</span>
<span style="color: black;">&#123;</span><span style="color: #66cc66;">%</span> endfor <span style="color: #66cc66;">%</span><span style="color: black;">&#125;</span>
<span style="color: #66cc66;">&lt;</span>/ul<span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>I&#8217;ve used the user&#8217;s mySQL primary key to construct his profile URL.</p>
<p>This is a very basic example but hopefully you can see the advantage of offloading some of the data storage to Mongo. You may ask &#8220;but what if the user changes his name? won&#8217;t the data in the activity remain out of sync?&#8221;. Yes, it will, but you can very easily add a simple method in your Django user model to update Mongo records whenever the user&#8217;s details are updated.</p>
<p>Good luck.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.givp.org/blog/2011/11/30/mongodb-in-django/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Amazon S3 expiring URLs with Boto</title>
		<link>http://www.givp.org/blog/2011/08/01/amazon-s3-expiring-urls-with-boto/</link>
		<comments>http://www.givp.org/blog/2011/08/01/amazon-s3-expiring-urls-with-boto/#comments</comments>
		<pubDate>Mon, 01 Aug 2011 16:37:47 +0000</pubDate>
		<dc:creator>Giv</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[s3]]></category>

		<guid isPermaLink="false">http://www.givp.org/blog/?p=287</guid>
		<description><![CDATA[This is a short post. I spent too long working this out so hopefully this post will help a future Google search. If you&#8217;re using the Boto python wrapper for the Amazon S3 service, you can quickly generate temporary URLs for your private files. 1 2 3 4 from boto.s3.connection import S3Connection &#160; s3 = [...]]]></description>
			<content:encoded><![CDATA[<p>This is a short post. I spent too long working this out so hopefully this post will help a future Google search.</p>
<p>If you&#8217;re using the <a href="http://boto.s3.amazonaws.com/index.html" onclick="pageTracker._trackPageview('/outgoing/boto.s3.amazonaws.com/index.html?referer=');">Boto</a> python wrapper for the Amazon S3 service, you can quickly generate temporary URLs for your private files.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> boto.<span style="color: black;">s3</span>.<span style="color: black;">connection</span> <span style="color: #ff7700;font-weight:bold;">import</span> S3Connection
&nbsp;
s3 = S3Connection<span style="color: black;">&#40;</span><span style="color: #483d8b;">'YOUR_KEY'</span>, <span style="color: #483d8b;">'YOUR_SECRET'</span>, is_secure=<span style="color: #008000;">False</span><span style="color: black;">&#41;</span>
url = s3.<span style="color: black;">generate_url</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">60</span>, <span style="color: #483d8b;">'GET'</span>, bucket=<span style="color: #483d8b;">'YOUR_BUCKET'</span>, key=<span style="color: #483d8b;">'YOUR_FILE_KEY'</span>, force_http=<span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>This will give you a URL to your private file on S3 that will only work for 60 seconds. It will look something like this:</p>
<pre>

http://mycoolbucket.s3.amazonaws.com/myfile.jpg?

Signature=ABC123DEF456&#038;
Expires=1312216031&#038;
AWSAccessKeyId=ABCDEFGHIJKLMNOP
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.givp.org/blog/2011/08/01/amazon-s3-expiring-urls-with-boto/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Image cropping and face detection</title>
		<link>http://www.givp.org/blog/2011/06/13/image-cropping-and-face-detection/</link>
		<comments>http://www.givp.org/blog/2011/06/13/image-cropping-and-face-detection/#comments</comments>
		<pubDate>Mon, 13 Jun 2011 16:07:03 +0000</pubDate>
		<dc:creator>Giv</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[PIL]]></category>

		<guid isPermaLink="false">http://www.givp.org/blog/?p=264</guid>
		<description><![CDATA[The project I&#8217;m currently working on requires cropping of hundreds of portraits from the First World War archives at the Imperial War Museum. Running a batch script on a directory of images is straight forward except my script is pretty dumb and tries to do a centre crop to create a square image. Unfortunately some [...]]]></description>
			<content:encoded><![CDATA[<p>The project I&#8217;m currently working on requires cropping of hundreds of portraits from the First World War archives at the Imperial War Museum.</p>
<p>Running a batch script on a directory of images is straight forward except my script is pretty dumb and tries to do a centre crop to create a square image. Unfortunately some of these images are not suitable for centre cropping:</p>
<p><a href="http://www.givp.org/blog/wp-content/uploads/2011/06/HU_93359.jpg"><img src="http://www.givp.org/blog/wp-content/uploads/2011/06/HU_93359.jpg" alt="" title="HU_93359" width="200" height="200" class="alignright size-full wp-image-276" /></a></p>
<p>Some of these portraits are quite long in height so a centre crop often results in the decapitation of the subject!</p>
<p>The logical thing to do here is to have your script first detect where the face is and then make a more intelligent crop to ensure the face remains in the new image. But surely face recognition requires super computers and several PhDs? Yes, it does. But we don&#8217;t really care who the subject is, we just need to know where the face is (or at least something that looks like a face). What we need is face detection, not recognition.</p>
<p>I was surprised to come across this little beauty: <a href="http://opencv.willowgarage.com/wiki/Welcome" onclick="pageTracker._trackPageview('/outgoing/opencv.willowgarage.com/wiki/Welcome?referer=');">OpenCV</a>, an open library for vision processing and luckily there&#8217;s a nice Python binding for it.</p>
<p>I tried out a sample from <a href="http://creatingwithcode.com/howto/face-detection-in-static-images-with-python/" onclick="pageTracker._trackPageview('/outgoing/creatingwithcode.com/howto/face-detection-in-static-images-with-python/?referer=');">Robert Martin McGuire&#8217;s</a> blog and was amazed at how simple and effective it was.</p>
<p>Robert&#8217;s script spits out two coordinates from the image that places a rectangle of where the face is. If your image has more than one person in it (or things that look like faces &#8211; more on that later) it will return two sets for each face.</p>
<p>Here&#8217;s the same image after running it through our face detection script:</p>
<p><a href="http://www.givp.org/blog/wp-content/uploads/2011/06/output2.jpg"><img src="http://www.givp.org/blog/wp-content/uploads/2011/06/output2-643x1024.jpg" alt="" title="output2" width="643" height="1024" class="aligncenter size-large wp-image-273" /></a></p>
<p>Perfect! now we can adjust our cropping script to ensure that the face is within the bounds.</p>
<p>I tried this using really high resolution images and the script detected several faces in the image where there was only one. The problem is that if you have a lot of detail in your image like background artifacts and smudges there is likely to be some pattern that matches those of a face. For best results you may want to work with smaller images.</p>
<p>You can get this script from Robert&#8217;s site but here it is for all you lazy people. Make sure you&#8217;ve installed all necessary libraries. On Debian/Ubuntu you should be able to use this:</p>
<pre>
$ sudo apt-get install python-opencv libcv-dev python-imaging
</pre>
<p>Test out the script like this:</p>
<pre>
$python thescript.py original.jpg output.jpg
</pre>
<p>If you get errors chances are it&#8217;s not finding the XML files. I had to copy these manually to get it to work. Note: this script doesn&#8217;t do any cropping, it just shows you where the face is and you will need to do the cropping yourself with some trial and error.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> opencv.<span style="color: black;">cv</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">from</span> opencv.<span style="color: black;">highgui</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #66cc66;">*</span>
<span style="color: #ff7700;font-weight:bold;">import</span> Image, ImageDraw
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> print_rectangle<span style="color: black;">&#40;</span>x1,y1,x2,y2<span style="color: black;">&#41;</span>: <span style="color: #808080; font-style: italic;">#function to modify the img</span>
    im = Image.<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    draw = ImageDraw.<span style="color: black;">Draw</span><span style="color: black;">&#40;</span>im<span style="color: black;">&#41;</span>
    draw.<span style="color: black;">rectangle</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>x1,y1,x2,y2<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    im.<span style="color: black;">save</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> detectObjects<span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Converts an image to grayscale and prints the locations of any
     faces found&quot;&quot;&quot;</span>
    grayscale = cvCreateImage<span style="color: black;">&#40;</span>cvSize<span style="color: black;">&#40;</span>image.<span style="color: black;">width</span>, image.<span style="color: black;">height</span><span style="color: black;">&#41;</span>, <span style="color: #ff4500;">8</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    cvCvtColor<span style="color: black;">&#40;</span>image, grayscale, CV_BGR2GRAY<span style="color: black;">&#41;</span>
&nbsp;
    storage = cvCreateMemStorage<span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
    cvClearMemStorage<span style="color: black;">&#40;</span>storage<span style="color: black;">&#41;</span>
    cvEqualizeHist<span style="color: black;">&#40;</span>grayscale, grayscale<span style="color: black;">&#41;</span>
    cascade = cvLoadHaarClassifierCascade<span style="color: black;">&#40;</span>
                                          <span style="color: #483d8b;">'/usr/share/opencv/haarcascade/haarcascade_frontalface_alt.xml'</span>,
                                          cvSize<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    faces = cvHaarDetectObjects<span style="color: black;">&#40;</span>grayscale, cascade, storage, <span style="color: #ff4500;">1.2</span>, <span style="color: #ff4500;">2</span>,
                                CV_HAAR_DO_CANNY_PRUNING, cvSize<span style="color: black;">&#40;</span><span style="color: #ff4500;">50</span>, <span style="color: #ff4500;">50</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> faces.<span style="color: black;">total</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> faces:
            x1,y1,x2,y2=f.<span style="color: black;">x</span>,f.<span style="color: black;">y</span>,f.<span style="color: black;">x</span>+f.<span style="color: black;">width</span>,f.<span style="color: black;">y</span>+f.<span style="color: black;">height</span>
            <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;[(%d,%d) -&gt; (%d,%d)]&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>f.<span style="color: black;">x</span>, f.<span style="color: black;">y</span>, f.<span style="color: black;">x</span> + f.<span style="color: black;">width</span>, f.<span style="color: black;">y</span> + f.<span style="color: black;">height</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
            print_rectangle<span style="color: black;">&#40;</span>x1,y1,x2,y2<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">#call to a python pil</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    image = cvLoadImage<span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">;</span>
    detectObjects<span style="color: black;">&#40;</span>image<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&quot;__main__&quot;</span>:
  main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://www.givp.org/blog/2011/06/13/image-cropping-and-face-detection/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Test-Driven Development &#8211; How Do I Start?</title>
		<link>http://www.givp.org/blog/2010/07/22/test-driven-development-how-do-i-start/</link>
		<comments>http://www.givp.org/blog/2010/07/22/test-driven-development-how-do-i-start/#comments</comments>
		<pubDate>Thu, 22 Jul 2010 21:42:12 +0000</pubDate>
		<dc:creator>Giv</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://www.givp.org/blog/?p=188</guid>
		<description><![CDATA[There seem to be a lot of developers who like the idea of Test-Driven Development (TDD) and can clearly see the benefit of having tests written for their code but can&#8217;t seem to get their head around the process. How do you start writing unit tests before writing the actual code? Let&#8217;s start with an [...]]]></description>
			<content:encoded><![CDATA[<p>There seem to be a lot of developers who like the idea of <a href="http://en.wikipedia.org/wiki/Test-driven_development" onclick="pageTracker._trackPageview('/outgoing/en.wikipedia.org/wiki/Test-driven_development?referer=');">Test-Driven Development</a> (TDD) and can clearly see the benefit of having tests written for their code but can&#8217;t seem to get their head around the process. How do you start writing unit tests <em>before</em> writing the actual code?</p>
<p>Let&#8217;s start with an example. You want to write a method that takes a URL as an argument and have it tell you through a boolean return if it&#8217;s the correct domain or not. It seems simple enough. Just write your method, pass the URL through some regular expression and you&#8217;re done.</p>
<p>But you yourself already know which domains are allowed and which are not so before writing the actual code you can run some tests in your head. E.g. I only want www.bbc.co.uk and its sub-domains on http and https. Nothing else should be allowed. So https://beta.bbc.co.uk/iplayer should return TRUE and http://www.bbcbb.com should return FALSE etc.</p>
<blockquote><p>The process behind TDD is that you first write a failing test. Then you write the actual code and adjust until the test passes.</p></blockquote>
<p>So let&#8217;s write some tests for our domain checker. I&#8217;m using Python and Unittest here:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># this is what we're going to be testing</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Utils<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> is_bbc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, val<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span> <span style="color: #808080; font-style: italic;">#placeholder</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># this is the actual test</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TestUtils<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">u</span> = Utils<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_is_bbc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk/iplayer'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk/food'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://www.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://beta.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.com'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
suite = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestLoader</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">loadTestsFromTestCase</span><span style="color: black;">&#40;</span>TestUtils<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>I&#8217;ve created a an empty method where our domain checker is going to live but as you can see it doesn&#8217;t do anything. The tests should immediately make sense. We pass a bunch of domain variations and we know which ones should pass or fail. Naturally, running the test right now will fail:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python sample.py
test_is_bbc <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestUtils<span style="color: #7a0874; font-weight: bold;">&#41;</span> ... FAIL
&nbsp;
======================================================================
FAIL: test_is_bbc <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestUtils<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #660033;">----------------------------------------------------------------------</span>
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
  File <span style="color: #ff0000;">&quot;sample.py&quot;</span>, line <span style="color: #000000;">14</span>, <span style="color: #000000; font-weight: bold;">in</span> test_is_bbc
    self.assertTrue<span style="color: #7a0874; font-weight: bold;">&#40;</span>self.u.is_bbc<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">'http://www.bbc.co.uk/iplayer'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
AssertionError
&nbsp;
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">in</span> 0.000s
&nbsp;
FAILED <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">failures</span>=<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>Now you can start writing the actual code and keep running the same tests until it passes:</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
</pre></td><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># this is what we're going to be testing</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Utils<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> is_bbc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, val<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">re</span>.<span style="color: black;">match</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'^https?://([^/]+)?<span style="color: #000099; font-weight: bold;">\.</span>bbc<span style="color: #000099; font-weight: bold;">\.</span>co<span style="color: #000099; font-weight: bold;">\.</span>uk'</span>, val<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># this is the actual test</span>
<span style="color: #ff7700;font-weight:bold;">class</span> TestUtils<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">u</span> = Utils<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_is_bbc<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk/iplayer'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk/food'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'https://www.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://beta.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbc.com'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://www.bbbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">assertFalse</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">u</span>.<span style="color: black;">is_bbc</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'http://.bbc.co.uk'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;">#this should fail</span>
&nbsp;
suite = <span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestLoader</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">loadTestsFromTestCase</span><span style="color: black;">&#40;</span>TestUtils<span style="color: black;">&#41;</span>
<span style="color: #dc143c;">unittest</span>.<span style="color: black;">TextTestRunner</span><span style="color: black;">&#40;</span>verbosity=<span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>.<span style="color: black;">run</span><span style="color: black;">&#40;</span>suite<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>The regex may look like it&#8217;s correct but running the test will fail again:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ python sample.py
test_is_bbc <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestUtils<span style="color: #7a0874; font-weight: bold;">&#41;</span> ... FAIL
&nbsp;
======================================================================
FAIL: test_is_bbc <span style="color: #7a0874; font-weight: bold;">&#40;</span>__main__.TestUtils<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #660033;">----------------------------------------------------------------------</span>
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
  File <span style="color: #ff0000;">&quot;sample.py&quot;</span>, line <span style="color: #000000;">22</span>, <span style="color: #000000; font-weight: bold;">in</span> test_is_bbc
    self.assertFalse<span style="color: #7a0874; font-weight: bold;">&#40;</span>self.u.is_bbc<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">'http://.bbc.co.uk'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
AssertionError
&nbsp;
<span style="color: #660033;">----------------------------------------------------------------------</span>
Ran <span style="color: #000000;">1</span> <span style="color: #7a0874; font-weight: bold;">test</span> <span style="color: #000000; font-weight: bold;">in</span> 0.001s
&nbsp;
FAILED <span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #007800;">failures</span>=<span style="color: #000000;">1</span><span style="color: #7a0874; font-weight: bold;">&#41;</span></pre></div></div>

<p>It has failed on the final assert because our code will also allow http://.bbc.co.uk and we obviously don&#8217;t want that. But as you can see we&#8217;ve caught this edge case before deploying our app so we can promptly fix our code.</p>
<p>Hopefully this example demonstrates why it&#8217;s a good idea to start with tests. This is obviously a simple example but on bigger projects predicting the outcome of your system can save you a lot of debugging time in the future.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.givp.org/blog/2010/07/22/test-driven-development-how-do-i-start/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>iPhone App Development with Google App Engine</title>
		<link>http://www.givp.org/blog/2010/02/14/iphone-app-dev-google-app-engine/</link>
		<comments>http://www.givp.org/blog/2010/02/14/iphone-app-dev-google-app-engine/#comments</comments>
		<pubDate>Sun, 14 Feb 2010 12:11:04 +0000</pubDate>
		<dc:creator>Giv</dc:creator>
				<category><![CDATA[Google App Engine]]></category>
		<category><![CDATA[Objective-c]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[memcached]]></category>

		<guid isPermaLink="false">http://www.givp.org/blog/?p=138</guid>
		<description><![CDATA[After almost a year of messing around with various iPhone development alternatives such as Phonegap and Titanium, I finally decided to learn Objective-C and do it all properly. I actually think those other frameworks are brilliant as they allow you to use familiar languages like Javascript to quickly create nice apps for both iPhone and [...]]]></description>
			<content:encoded><![CDATA[<p>After almost a year of messing around with various iPhone development alternatives such as <a href="http://phonegap.com/" onclick="pageTracker._trackPageview('/outgoing/phonegap.com/?referer=');">Phonegap</a> and <a href="http://www.appcelerator.com/" onclick="pageTracker._trackPageview('/outgoing/www.appcelerator.com/?referer=');">Titanium</a>, I finally decided to learn Objective-C and do it all properly. I actually think those other frameworks are brilliant as they allow you to use familiar languages like Javascript to quickly create nice apps for both iPhone and Android. But since they rely heavily on the web view element for loading HTML, creating sophisticated apps like Skype would be impossible.</p>
<p>So I set out to create an app for the iPhone with Objective-C. My app is pretty simple. It basically pulls in RSS news, audio podcast and video podcast feeds into a <a href="http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html" onclick="pageTracker._trackPageview('/outgoing/developer.apple.com/iphone/library/documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html?referer=');">UITableView</a> list, allowing the user to read, listen and watch news stories from the <a href="http://www.democracynow.org/" onclick="pageTracker._trackPageview('/outgoing/www.democracynow.org/?referer=');">Democracy Now!</a> website.</p>
<p><img class="alignright" title="Democracy Now! app" src="http://www.givp.org/democracyapp/img/democphone.png" alt="" width="164" height="305" /><br />
I managed to put together the app pretty quickly but I ran into a lot of issues when I tried to parse and massage the XML data. For starters, cocoa does not have native support for regular expressions (but there are several external libraries). I wanted to clean up the content I was getting back before displaying it to the user but I soon realised something that would normally take me a few minutes in Python/PHP/Javascript would take a lot longer in Objective-C. Parsing XML using <a href="http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html" onclick="pageTracker._trackPageview('/outgoing/developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html?referer=');">NSXMLParser</a> was an absolute nightmare and extremely slow. I rarely work with XML these days and find JSON a much easier protocol to deal with. I even tested the app with some sample JSON data using the excellent <a href="http://code.google.com/p/json-framework/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/p/json-framework/?referer=');">json-framework</a> libarary and it was much easier and faster. Alas, I only had RSS feeds to work with.</p>
<p>The other problem I ran into was slow HTTP requests. It would sometimes take up to 20 seconds just to load the first screen. This was due to a combination of slow connection speeds, long response times from the data provider and a slow XML parser.</p>
<p>The solution I came up with was to do as little as possible in the phone app as far as the data was concerned. I decided to use Google App Engine to fetch the data from the source, parse, rejig, massage and beautify in Python, then serialise and return the results in JSON to the phone app to use.</p>
<p>It may sound like this would increase response times even more since the phone would have to first call GAE, then GAE would need to call the data source and then all the way back to the phone. This is true, however, once the data is with GAE we have the luxury of using <a href="http://code.google.com/appengine/docs/python/memcache/usingmemcache.html" onclick="pageTracker._trackPageview('/outgoing/code.google.com/appengine/docs/python/memcache/usingmemcache.html?referer=');">memcache</a> and <a href="http://code.google.com/appengine/docs/python/datastore/" onclick="pageTracker._trackPageview('/outgoing/code.google.com/appengine/docs/python/datastore/?referer=');">datastore</a>. The RSS and podcast feeds are updated once a day so there&#8217;s no reason to request the data from the source every time the user loads the app. Because each time we have to make the HTTP call, parse the data and load it up. This is extremely slow and unnecessary. We can just make one request a day, then parse, cleanup and cache the results for the next user that requests it.</p>
<p>So the app only talks to GAE. GAE first checks memcache to see if we have a cached version. If we don&#8217;t, it will make the HTTP call, fetch the data, parse, serialise, cache and return results. If we do have a cached version, there&#8217;s nothing else to do but to return the data. A cron job will also run every 24 hours to make sure memcache is up to date.</p>
<p><img src="http://givp.mugal.org/blog/wp-content/uploads/2010/02/bloggae.gif" alt="" /></p>
<p>If you really want a solid and reliable app, you need to think about all the edge cases also. What happens if the cache expires and the data provider&#8217;s website is down? At that exact moment a user loads the app only to get an error message saying there&#8217;s nothing to show. An unlikely scenario but not impossible. So the way I got around this issue was to store the serialised JSON output in GAE&#8217;s datastore as well. We always use the data from memcache but should memcache be empty and the data source down, we can switch over to the datastore and load yesterday&#8217;s content instead. Not ideal but better than having a broken app.</p>
<p>This is a bit of an overkill for such a simple app but it&#8217;s super fast and efficient and will work well for almost any app that relies on 3rd-party APIs. To be fair, it was my lack of experience with Objective-C that led me to using GAE. I feel much more comfortable in Python than Objective-C and I&#8217;m sure an experienced cocoa developer would have no problems parsing and massaging data in the app itself.</p>
<p>Of course there is one other edge case &#8211; Google App Engine could go down or worst, the interwebz could break. In which case, a simple error message will suffice.</p>
<p>You can download <a href="http://itunes.apple.com/app/democracy-now-war-peace-report/id353540657" onclick="pageTracker._trackPageview('/outgoing/itunes.apple.com/app/democracy-now-war-peace-report/id353540657?referer=');">Democracy Now! app on iTunes</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.givp.org/blog/2010/02/14/iphone-app-dev-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>
<!-- This Quick Cache file was built for (  www.givp.org/blog/category/python/feed/ ) in 0.48597 seconds, on Feb 4th, 2012 at 4:19 am UTC. -->
<!-- This Quick Cache file will automatically expire ( and be re-built automatically ) on Feb 4th, 2012 at 5:19 am UTC -->
