<?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/"
	xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule"
>

<channel>
	<title>Aral Balkan &#187; Python</title>
	<atom:link href="http://aralbalkan.com/category/development/python/feed" rel="self" type="application/rss+xml" />
	<link>http://aralbalkan.com</link>
	<description>Passionate geekisms.</description>
	<lastBuildDate>Wed, 01 Feb 2012 18:53:09 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
		<item>
		<title>Gaebar Beta 3 (version 0.3) released</title>
		<link>http://aralbalkan.com/1907</link>
		<comments>http://aralbalkan.com/1907#comments</comments>
		<pubDate>Wed, 21 Jan 2009 13:01:09 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1907</guid>
		<description><![CDATA[I've just tagged Gaebar Beta 3 (version 0.3) in GitHub. This is a bugfix release, with changes almost entirely submitted by or suggested by the community. Thanks go to gumptionthomas, Martin Kleppmann, Tony Andrews, Rafal Jonca, and, of course, Guido van Rossum, for your patches and feedback. Changes in Beta 3 Merged gumptionthomas's pull request [...]]]></description>
			<content:encoded><![CDATA[<p id="top" /><a href="http://github.com/aral/gaebar/tree/0.3" title="aral's gaebar at 0.3 - GitHub"><img src="http://aralbalkan.com/wp-content/uploads/2009/01/gaebar-beta-3-release.jpg" alt="Gaebar Beta 3 Release" height="190" width="295" style="float:right; margin-left:2em;"></a></p>
<p>I've just tagged <a href="http://github.com/aral/gaebar/tree/0.3" title="aral's gaebar at 0.3 - GitHub">Gaebar Beta 3 (version 0.3)</a> in GitHub.</p>
<p><span id="more-1907"></span></p>
<p>This is a bugfix release, with changes almost entirely submitted by or suggested by the community. </p>
<p>Thanks go to gumptionthomas, Martin Kleppmann, Tony Andrews, Rafal Jonca, and, of course, Guido van Rossum, for your patches and feedback.</p>
<h3>Changes in Beta 3</h3>
<ul>
<li>Merged gumptionthomas's pull request (<a href="http://github.com/aral/gaebar/commit/98415f1f988139987b71522e2f97ccd23ba8a68e" title="Commit 98415f1f988139987b71522e2f97ccd23ba8a68e to aral's gaebar - GitHub">commit</a>)
<ul>
<li>Fixed unicode and escape string issues with key_names</li>
<li>Properly reference InternalError as db.InternalError</li>
</ul>
</li>
<li>Applied patch by Martin Kleppmann (<a href="http://github.com/aral/gaebar/commit/7cb964e36c44be0190d1413ad71030a9b916ff63" title="Commit 7cb964e36c44be0190d1413ad71030a9b916ff63 to aral's gaebar - GitHub">commit</a>)</li>
<ul>
<li>Backup doesn't blow up when there are non-backup files/folders in the backups folder. (e.g., if your project uses SVN)</li>
</ul>
<li>Updated the readme.txt based on Guido's feedback (<a href="http://github.com/aral/gaebar/commit/95a4b99c85c9d0724f21627616248bb23922d680" title="Commit 95a4b99c85c9d0724f21627616248bb23922d680 to aral's gaebar - GitHub">commit</a>)</li>
<li>Added note to readme.txt regarding getting more detailed exceptions (thanks to Tony Andrews; <a href="http://github.com/aral/gaebar/commit/5a9d40a0cf77c14b08f2cdcf673ab7bf9ecef42d" title="Commit 5a9d40a0cf77c14b08f2cdcf673ab7bf9ecef42d to aral's gaebar - GitHub">commit</a>).</li>
<li>Applied patch by Rafal Jonca (<a href="http://github.com/aral/gaebar/commit/95ed388f6d871913ca94f4fd37698262d762fbda" title="Commit 95ed388f6d871913ca94f4fd37698262d762fbda to aral's gaebar - GitHub">commit</a>):
<ul>
<li>Key names may now contain unicode</li>
<li>ReferenceProperties can now be created with keys of parents, not just model instances</li>
<li>Now using global datastore's delete, put, and get methods instead of model's</li>
</ul>
</li>
</ul>
<p><a href="http://aralbalkan.com/1784">See the original announcement</a> for a screencast and general information on Gaebar.</p>
<p>Please do keep your feedback coming and, of course, if you have pull requests, patches, or suggestions, please send them my way (and thank you!)</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1907/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Real-world Google App Engine</title>
		<link>http://aralbalkan.com/1903</link>
		<comments>http://aralbalkan.com/1903#comments</comments>
		<pubDate>Tue, 20 Jan 2009 13:06:47 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1903</guid>
		<description><![CDATA[Real World Google App Engine Aral Balkan Jan 2009 View more presentations or upload your own. (tags: google app) I just posted my slides from last night's talk at the London Django User Group on SlideShare (and you can view them above). A big thank you to Rob and the DJUGL team for organizing the [...]]]></description>
			<content:encoded><![CDATA[<p id="top" />
<div style="width:425px;text-align:left" id="__ss_934238"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/aralbalkan/real-world-google-app-engine-aral-balkan-jan-2009-presentation?type=presentation" title="Real World Google App Engine   Aral Balkan   Jan 2009">Real World Google App Engine   Aral Balkan   Jan 2009</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slideshare.net/swf/ssplayer2.swf?doc=real-world-google-app-engine-aral-balkan-jan-2009-1232455652197054-1&stripped_title=real-world-google-app-engine-aral-balkan-jan-2009-presentation" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slideshare.net/swf/ssplayer2.swf?doc=real-world-google-app-engine-aral-balkan-jan-2009-1232455652197054-1&stripped_title=real-world-google-app-engine-aral-balkan-jan-2009-presentation" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> or <a style="text-decoration:underline;" href="http://www.slideshare.net/upload?type=presentation">upload</a> your own. (tags: <a style="text-decoration:underline;" href="http://slideshare.net/tag/google">google</a> <a style="text-decoration:underline;" href="http://slideshare.net/tag/app">app</a>)</div>
<p><span id="more-1903"></span></p>
</div>
<p>I just posted my slides from last night's talk at the London Django User Group on SlideShare (and you can view them above). </p>
<p>A big thank you to <a href="http://www.siudesign.co.uk/" title="Home | Siu Design | Passionate about design">Rob</a> and the DJUGL team for organizing the event and kindly inviting me over to speak. I had a great time and it seems like the audience enjoyed it too! :)</p>
<p><img src="http://aralbalkan.com/wp-content/uploads/2009/01/google-app-engine-fake-it-slide-small.jpg" alt="Google app Engine Fake it Slide Small" height="190" width="295" style="display:none;"></p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1903/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Gaebar Beta 2 Released</title>
		<link>http://aralbalkan.com/1837</link>
		<comments>http://aralbalkan.com/1837#comments</comments>
		<pubDate>Wed, 31 Dec 2008 21:24:57 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1837</guid>
		<description><![CDATA[I'm happy to announce that there's quite an important update to Gaebar that brings with it some essential bug fixes and should help shave quite a bit of time off of your restores. I've also created a new project called gaebar-gaed-skeleton on GitHub that gives you an empty Google App Engine Django (Helper) project with [...]]]></description>
			<content:encoded><![CDATA[<p id="top" /><img src="http://aralbalkan.com/wp-content/uploads/2008/12/gaebar-beta-2-release.jpg" alt="Gaebar Beta 2 Release" height="190" width="295" style="float:left; margin-right:2em;"></p>
<p>I'm happy to announce that there's quite an important update to <a href="http://aralbalkan.com/1784" title="Aral Balkan - Google App Engine Backup and Restore (Gaebar) released">Gaebar</a> that brings with it some essential bug fixes and should help shave quite a bit of time off of your restores.</p>
<p><span id="more-1837"></span></p>
<p>I've also created a new project called <a href="https://github.com/aral/gaebar-gaed-skeleton/tree/master">gaebar-gaed-skeleton</a> on GitHub that gives you an empty Google App Engine Django (Helper) project with Gaebar pre-installed to start you off when creating your own applications.</p>
<p>Here's a list of changes in Beta 2:</p>
<ul>
<li><strong>Fixed:</strong> All required properties, including references should work correctly now. Required properties would raise an exception during the restore process in Beta 1.</li>
<li><strong>Refactored:</strong> We are no longer using actual entity references (which was unnecessary) but keys to create reference properties. This means that creation order of references doesn’t matter any more (thanks to Pete Koomen who explained all this to me in an email ages ago; it only just sunk in, Pete!)</li>
<li><strong>New feature:</strong> Due to above changes, the restore process is now one-pass, not two. This means that restores should now take considerably less time.</li>
<li><strong>Refactored:</strong> I moved the functional tests out to their own GitHub module since they were being shared by both the gaebar-gaed and gaebar-aep test apps. This will make maintaining them much easier.</li>
</ul>
<p>I want to thank Jonathan Ricketson for alerting me in the comments earlier today that the Beta 1 release was not handling required properties correctly (thanks, Jonathan). I also want to thank Thomas Bohmbach, Jr. for providing feedback and helping me test.</p>
<p>You can <a href="http://github.com/aral/" title="aral's Profile &mdash; GitHub">download Gaebar Beta 2 and the other Gaebar projects from my GitHub account</a>.</p>
<p>If you'd like to learn more about Gaebar, <a href="http://aralbalkan.com/1784" title="Aral Balkan - Google App Engine Backup and Restore (Gaebar) released">please see my original announcement</a>, which contains a screencast showing Gaebar (albeit Beta 1) in use.</p>
<p>As always, I value your bug reports, comments, and suggestions so please feel free to leave a comment and let me know of your experiences with Gaebar.</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1837/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Google App Engine Backup and Restore (Gaebar) released</title>
		<link>http://aralbalkan.com/1784</link>
		<comments>http://aralbalkan.com/1784#comments</comments>
		<pubDate>Thu, 25 Dec 2008 01:26:52 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Community]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Tools and Utilities]]></category>
		<category><![CDATA[app]]></category>
		<category><![CDATA[app engine]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[gaebar]]></category>
		<category><![CDATA[project]]></category>
		<category><![CDATA[restore]]></category>
		<category><![CDATA[utility]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/?p=1784</guid>
		<description><![CDATA[Update: Beta 2 Released! See the Gaebar Beta 2 announcement. Here's my Christmas present for the Google App Engine community: Google App Engine Backup and Restore (or Gaebar, for short). Gaebar is an easy-to-use, standalone Django application that you can plug in to your existing Google App Engine Django or app-engine-patch-based Django applications on Google [...]]]></description>
			<content:encoded><![CDATA[<p id="top" /><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="512" height="426" id="viddler_fed9d8b6"><param name="movie" value="http://www.viddler.com/player/fed9d8b6/" /><param name="allowScriptAccess" value="always" /><param name="allowFullScreen" value="true" /><embed src="http://www.viddler.com/player/fed9d8b6/" width="512" height="426" type="application/x-shockwave-flash" allowScriptAccess="always" allowFullScreen="true" name="viddler_fed9d8b6" ></embed></object></p>
<p><strong>Update: Beta 2 Released!</strong> <a href="http://aralbalkan.com/1837" title="Gaebar Beta 2 release announcement">See the Gaebar Beta 2 announcement</a>.</p>
<p><span id="more-1784"></span></p>
<p>Here's my Christmas present for the Google App Engine community: Google App Engine Backup and Restore (or Gaebar, for short).</p>
<p>Gaebar is an easy-to-use, standalone Django application that you can plug in to your existing <a href="http://code.google.com/p/google-app-engine-django/" title="google-app-engine-django -</p>
<p> Google Code">Google App Engine Django</a> or <a href="http://code.google.com/p/app-engine-patch/" title="app-engine-patch -</p>
<p>  Google Code">app-engine-patch</a>-based Django applications on Google App Engine to give them datastore backup and restore functionality. </p>
<p>For a quick overview of Gaebar, watch the screencast, above. For the impatient, links to the project pages where you can download Gaebar follow.</p>
<h3>Downloads</h3>
<p>Gaebar is hosted on GitHub. You can either download archives or clone the repository (or install Gaebar as a git submodule) via git. Alongside the Gaebar project itself are two sample applications &mdash; one built on Google App Engine Django and the other on app-engine-patch &mdash; that contain the Gaebar functional test suite. The functional test suite tests every datatype supported by Google App Engine as well as references, Expandos, and ancestor relationships.</p>
<p>Please make sure you read the readme files after downloading the projects for installation and usage instructions.</p>
<ul>
<li>Gaebar: <a href="http://github.com/aral/gaebar/tree/master">http://github.com/aral/gaebar/tree/master</a></li>
<li>Gaebar-gaed: <a href="http://github.com/aral/gaebar-gaed/tree/master">http://github.com/aral/gaebar-gaed/tree/master</a></li>
<li>Gaebar-aep: <a href="http://github.com/aral/gaebar-aep/tree/master">http://github.com/aral/gaebar-aep/tree/master</a></li>
</ul>
<h3>What you can do with Gaebar</h3>
<ul>
<li>Backup your deployment application's datastore for safekeeping.</li>
<li>Restore that backup on your local development server for testing with real data during development.</li>
<li>Restore that backup to a <em>different</em> Google App Engine application and use that application as a <strong>staging application</strong> much in the same way you would use a staging server in traditional development.</li>
</ul>
<p>(You can, of course, also backup and restore your local development datastore as well as your staging application, etc.)</p>
<h3>I've got a huge datastore, will Gaebar work for me?</h3>
<p>Congratulations on the impressive size of your datastore! The answer should be "yes!" The largest datastore I've tested it with is the <a href="http://www.headconference.com">&lt;head&gt; web conference</a> datastore. The latest backup had 18, 969 rows from 14 models backed up into 225 code shards.</p>
<h3>What's a staging application?</h3>
<p>A staging application is a new Google App Engine concept made possible by Gaebar. Basically, if your application is <em>myapp.appspot.com</em>, you can use a separate application (say, <em>myapp-staging.appspot.com</em>) in the same way as you would use a staging server in traditional development. </p>
<p>Your staging application can let you try out new features and test with real data without having your users see your changes until you are ready to deploy to your main application.</p>
<p>In fact, it's a perfect staging environment since it is identical to your deployment environment. For an example of this, see the screencast.</p>
<h3>How Gaebar works</h3>
<p>Gaebar backs up the data in your datastore to Python code. It restores your data by running the generated Python code.</p>
<p>Since a backup is a long running process, and since Google App Engine doesn't support long-running processes, Gaebar fakes a long running process by breaking up the backup and restore processes into bite-sized chunks and repeatedly hitting the server via Ajax calls. </p>
<p>By default, Gaebar backs up 5 rows at a time to avoid the short term CPU and 10-second call duration quotas and splits the generated code into code shards of approx. 300KB to avoid the 1MB limit on objects. You can change these defaults in the views.py file if your app has higher quotas and you want faster backups and restores.</p>
<p>Once a backup of a remote server is complete, Gaebar automatically hits your local development server. From there on, the local development server makes a series of calls to the remote server to download the backup files (code shards) from the remote server. Once the backup is complete, you will see a new backup folder in <em>gaebar/backups</em> with the contents of your backup. </p>
<p>Here's an example of some generated backup code from the Google App Engine Django test application <strong>(updated for the upcoming Beta 2 release)</strong>:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pickle</span>
<span style="color: #ff7700;font-weight:bold;">from</span> google.<span style="color: black;">appengine</span>.<span style="color: black;">api</span>.<span style="color: black;">datastore</span> <span style="color: #ff7700;font-weight:bold;">import</span> datastore_types
<span style="color: #ff7700;font-weight:bold;">from</span> app1.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> *
<span style="color: #ff7700;font-weight:bold;">from</span> app2.<span style="color: black;">models</span> <span style="color: #ff7700;font-weight:bold;">import</span> *
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> row_0<span style="color: black;">&#40;</span>app_name<span style="color: black;">&#41;</span>:
	existing_entity = Profile.<span style="color: black;">get</span><span style="color: black;">&#40;</span>datastore_types.<span style="color: black;">Key</span>.<span style="color: black;">from_path</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Profile'</span>, <span style="color: #ff4500;">1</span>, _app=app_name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> existing_entity:
		existing_entity.<span style="color: black;">delete</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	profile_0 = Profile<span style="color: black;">&#40;</span>key_name=<span style="color: #483d8b;">&quot;id1&quot;</span>, friends = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'(lp0<span style="color: #000099; font-weight: bold;">\n</span>.'</span><span style="color: black;">&#41;</span>, in_relationship_with = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'N.'</span><span style="color: black;">&#41;</span>, full_name = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'VPaul Booth<span style="color: #000099; font-weight: bold;">\n</span>p0<span style="color: #000099; font-weight: bold;">\n</span>.'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	profile_0.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> row_1<span style="color: black;">&#40;</span>app_name<span style="color: black;">&#41;</span>:
	existing_entity = Profile.<span style="color: black;">get</span><span style="color: black;">&#40;</span>datastore_types.<span style="color: black;">Key</span>.<span style="color: black;">from_path</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Profile'</span>, <span style="color: #ff4500;">2</span>, _app=app_name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	<span style="color: #ff7700;font-weight:bold;">if</span> existing_entity:
		existing_entity.<span style="color: black;">delete</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
	profile_1 = Profile<span style="color: black;">&#40;</span>key_name=<span style="color: #483d8b;">&quot;id2&quot;</span>, full_name = <span style="color: #dc143c;">pickle</span>.<span style="color: black;">loads</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'VAral Balkan<span style="color: #000099; font-weight: bold;">\n</span>p0<span style="color: #000099; font-weight: bold;">\n</span>.'</span><span style="color: black;">&#41;</span>, friends = <span style="color: black;">&#91;</span>datastore_types.<span style="color: black;">Key</span>.<span style="color: black;">from_path</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Profile'</span>, u<span style="color: #483d8b;">'stephalicious'</span>, _app=app_name<span style="color: black;">&#41;</span>, datastore_types.<span style="color: black;">Key</span>.<span style="color: black;">from_path</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Profile'</span>, <span style="color: #483d8b;">'id1'</span>, _app=app_name<span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>, in_relationship_with = datastore_types.<span style="color: black;">Key</span>.<span style="color: black;">from_path</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Profile'</span>, u<span style="color: #483d8b;">'stephalicious'</span>, _app=app_name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
	profile_1.<span style="color: black;">put</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre>
<p>To restore, you simply deploy your application, along with the backup folder, to your deployment environment and hit the Restore button in Gaebar. (If you have a large datastore both the backup and restore processes will take a long time, especially when restoring to a local development server.)</p>
<p>The restore process simply calls each of the generated row functions and each row function restores a single row into the datastore. </p>
<h3>A note on the screencast</h3>
<p>When mentioning how to install Gaebar, I left out that you also need to add the URL mapping for Gaebar to your application's urls.py. That, along with the rest of the installation instructions are in the readme.txt file, which I highly recommend that you peruse.</p>
<h3>Have your say!</h3>
<p>As in all things, my approach to blog posts is that they should evolve over time and your feedback is invaluable in achieving this by helping me fix factual errors, fill in details, and expand the original post. </p>
<p>What do you think of Gaebar? Have you run into any issues that need fixing? Do you have other suggestions on how to improve it? Or do you, perhaps, have a patch to send me that adds Webapp support or some other feature? Leave me a comment and let me know!</p>
<p><em>Gaebar is a Naklab™ production released under GNU GPL v3 and sponsored by the <a href="http://www.headconference.com">&lt;head&gt; web conference</a>.</em></p>
<p><img src="http://aralbalkan.com/wp-content/uploads/2008/12/gaebar-logo.jpg" alt="Gaebar Logo" height="190" width="295" style="display:none;"></p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1784/feed</wfw:commentRss>
		<slash:comments>56</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Running Google App Engine Helper trunk with Django trunk (zipimport)</title>
		<link>http://aralbalkan.com/1757</link>
		<comments>http://aralbalkan.com/1757#comments</comments>
		<pubDate>Sat, 20 Dec 2008 09:16:42 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Apple]]></category>
		<category><![CDATA[Articles]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1757</guid>
		<description><![CDATA[Dan Sanderson has a good article on Google Code on Using Django 1.0 on App Engine with Zipimport, however it misses two steps in preparing the django.zip file if you want to use the latest Django trunk with the latest Google App Engine Helper. To create a new Django application for Google App Engine using [...]]]></description>
			<content:encoded><![CDATA[<p id="top" />Dan Sanderson has a good article on Google Code on <a href="http://code.google.com/appengine/articles/django10_zipimport.html">Using Django 1.0 on App Engine with Zipimport</a>, however it misses two steps in preparing the django.zip file if you want to use the latest Django trunk with the latest <a href="http://code.google.com/p/google-app-engine-django/">Google App Engine Helper</a>.</p>
<p>To create a new Django application for Google App Engine using Google App Engine Helper, start by exporting the latest Google App Engine Helper:</p>
<p><span id="more-1757"></span></p>
<pre>svn export http://google-app-engine-django.googlecode.com/svn/trunk/ ~/myapp</pre>
<p>To create a django.zip file to use with the latest Google App Engine:</p>
<ol>
<li>Export the latest Django trunk
<pre>svn export http://code.djangoproject.com/svn/django/trunk/ django</pre>
</li>
<li>Follow steps #2 and #3 in <a href="http://code.google.com/appengine/articles/django10_zipimport.html">Dan's instructions</a> under the "Archiving Django 1.0" section of his article</li>
<li>Add contrib/auth:
<pre>zip -r django.zip django/contrib/__init__.py \
	                  django/contrib/auth</pre>
</li>
<li>Add contrib/sessions:
<pre>zip -r django.zip django/contrib/__init__.py \
	                  django/contrib/sessions</pre>
</li>
<li>Copy the django.zip file into the root folder of your new app:
<pre>cp django.zip ~/myapp</pre>
</li>
<li>Uncomment the sessions middleware or auth middleware lines in settings.py file  in your app so that it looks like:
<pre>MIDDLEWARE_CLASSES = (
	    'django.middleware.common.CommonMiddleware',
	    'django.contrib.sessions.middleware.SessionMiddleware',
	    'django.contrib.auth.middleware.AuthenticationMiddleware',
	#    'django.middleware.doc.XViewMiddleware',
	)</pre>
</li>
</ol>
<p>That's it! To test it out:</p>
<pre>./manage.py runserver</pre>
<p>Hit http://localhost:8000/ and you should see the default Django welcome page.</p>
<p><strong>Update:</strong> Don't make the mistake of adding django.contrib.auth or django.contrib.sessions to your INSTALLED_APPS, even though you are including those apps in the django.zip file. If you do, ./manage.py runserver will work but ./manage.py shell and ./manage.py flush will return errors.</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1757/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>How to make standalone OS X application bundles from PyQt apps using py2app</title>
		<link>http://aralbalkan.com/1675</link>
		<comments>http://aralbalkan.com/1675#comments</comments>
		<pubDate>Mon, 01 Dec 2008 19:35:15 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Featured]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1675</guid>
		<description><![CDATA[You can build cross-platform GUI applications in Python using a library called PyQt, a set of Python bindings for Nokia's Qt application framework. Using PyQt, you can create Python applications that look and feel like native applications regardless of whether they happen to be running on Linux, OS X, or Windows. The application files themselves, [...]]]></description>
			<content:encoded><![CDATA[<p id="top" /><img src="http://aralbalkan.com/wp-content/uploads/2008/12/py2app-pyqt.jpg" alt="Py2app Pyqt" height="190" width="295" style="float:right; margin-left:1.5em; margin-bottom:1.5em;"></p>
<p>You can build cross-platform GUI applications in Python using a library called <a href="http://wiki.python.org/moin/PyQt" title="PyQt - PythonInfo Wiki">PyQt</a>, a set of Python bindings for <a href="http://trolltech.com/" title="Qt Software - Code Less. Create More. Deploy Everywhere.">Nokia's Qt application framework</a>. Using PyQt, you can create Python applications that look and feel like native applications regardless of whether they happen to be running on Linux, OS X, or Windows. </p>
<p><span id="more-1675"></span></p>
<p>The application files themselves, however, do not look like native executables; they are simply Python files and require Python, PyQt, and other dependencies to be installed to run. Needless to say, you cannot distribute your applications in this manner unless your target audience is entirely comprised of alpha geeks. To provide a usable user experience that is consistent with native applications, you can bundle PyQt applications into native executables for each of the platforms you're supporting. When deploying on OS X, for example, you can bundle your PyQt application into a standalone OS X application bundle. This process, which involves the use of the excellent <a href="http://undefined.org/python/" title="Python Stuff">py2app</a> application, comes with several gotchas that I hadn't bargained on. </p>
<p>Specifically, you cannot build standalone application bundles with the system python in OS X using py2app. If you want to build standalone PyQt apps, I recommend setting up Python, PyQt, etc., under <a href="http://www.macports.org/" title="The MacPorts Project -- Home">MacPorts</a>.</p>
<p>If you're comfortable with Terminal and don't need to be spoon fed, here's a quick overview of how to get your system in shape to compile standalone OS X application bundles from PyQt apps using py2app on Leopard 10.5.5 (which happens to be the only operating system version I've tested this on; this may work on other versions of OS X but <a href="http://www.urbandictionary.com/define.php?term=YMMV" title="Urban Dictionary: YMMV">YMMV</a>).</p>
<p>(If you need step-by-step instructions, see the <a href="#macports-details">Macports installation details</a> section, below).</p>
<h3>Setting up MacPorts</h3>
<ol>
<li><a href="http://www.macports.org/install.php" title="The MacPorts Project -- Download &amp; Installation">Install MacPorts</a>. You will be installing Python, PyQt, py2app and everything else you need under MacPorts and using that environment for everything.</li>
<li>Install the following portfiles: python25, py25-macholib-devel, py25-sip, py25-pyqt4, py25-py2app-devel, py25-pyqt, python_select.</li>
</ol>
<p>Note that I am installing the <em>-devel</em> version of <em>py25-py2app</em>, as well as <em>py25-macholib-devel</em> on purpose. I couldn't get it to work with the stable versions. You may have to deactivate <em>py25-macholib</em> if it gets installed automatically as a dependency for <em>py25-py2app-devel</em> (this is what I did, but I'm assuming that installing <em>py25-macholib-devel</em> before <em>py25-py2app-devel</em> should mean that you won't have to).</p>
<h3>Deploying a PyQt application as a Mac OS X application bundle</h3>
<p>Once you've successfully installed everything under MacPorts, change your environment to use the version of Python in Macports via python_select:</p>
<pre>sudo python_select python25</pre>
<p>Once you're done, create a <em>setup.py</em> file for py2app. Something along the lines of the following example:</p>
<pre class="python"><span style="color: #ff7700;font-weight:bold;">from</span> setuptools <span style="color: #ff7700;font-weight:bold;">import</span> setup
&nbsp;
APP = <span style="color: black;">&#91;</span><span style="color: #483d8b;">'myapp.pyw'</span><span style="color: black;">&#93;</span>
OPTIONS = <span style="color: black;">&#123;</span><span style="color: #483d8b;">'argv_emulation'</span>: <span style="color: #008000;">True</span>, <span style="color: #483d8b;">'includes'</span>: <span style="color: black;">&#91;</span><span style="color: #483d8b;">'sip'</span>, <span style="color: #483d8b;">'PyQt4._qt'</span><span style="color: black;">&#93;</span><span style="color: black;">&#125;</span>
&nbsp;
setup<span style="color: black;">&#40;</span>
    app=APP,
    options=<span style="color: black;">&#123;</span><span style="color: #483d8b;">'py2app'</span>: OPTIONS<span style="color: black;">&#125;</span>,
    setup_requires=<span style="color: black;">&#91;</span><span style="color: #483d8b;">'py2app'</span><span style="color: black;">&#93;</span>,
<span style="color: black;">&#41;</span></pre>
<p>Note that the includes array contains <code>sip</code> and <code>PyQt4._qt</code>. Those two entries are essential if you're bundling a PyQt app.</p>
<p>Finally, issue the following command to create a standalone OS X application bundle from your application:</p>
<pre>python setup.py py2app</pre>
<p>That's it. Double click on your app, which you can find in the <em>dist</em> folder and it should run.</p>
<p>If you run into any problems, see the <a href="#macports-setup">My Macports setup</a> section, below, for an exact dump of my Macports portfiles that you can use to compare (obtained using <code>port installed</code>). </p>
<p>Read on if you want to the full story and details of how I got my system up and running with MacPorts to deploy OS X app bundles using PyQt and py2app. I'm including this with as much information (error messages, etc., as possible so that others may find this post if they're similarly stuck.) Or, if you're not interested, you can jump to the <a href="#reference">Reference section</a>.</p>
<h3>The gory details</h3>
<p>My initial attempt at creating a standalone PyQt app with py2app resulted in the app crashing on launch. </p>
<p>The error message:</p>
<blockquote><p>Fatal Python error: Interpreter not initialized (version mismatch?)</p></blockquote>
<p>Judging by the error message, and emboldened by <a href="http://www.nabble.com/py2app-version-mismatch-while-including-a-library-built-with-Pyrex-td18071149.html" title="Nabble - Python - pythonmac-sig - py2app version mismatch while including a library built with Pyrex">a forum exchange between Derrick Hendricks and Christopher Baker</a> I guessed that the conflict was due to my having two versions of Python installed (the System python and a 2.5 through MacPorts). So I removed MacPorts completely, ran py2app again and the app launched but with a different error:</p>
<blockquote><p>ImportError: '/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/lib-dynload/PyQt4/QtCore.so' not found</p></blockquote>
<p>Searching for a solution, <a href="http://www.nabble.com/Py2App-and-PyQT-td20175194.html" title="Nabble - Python - pythonmac-sig - Py2App and PyQT">I stumbled upon a thread</a> where someone who ran into the same issue suggested adding the following line to __boot__.py in the Contents/Resources folder of the application bundle:</p>
<pre class="python"><span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span> = <span style="color: black;">&#91;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'RESOURCEPATH'</span><span style="color: black;">&#93;</span>, <span style="color: #483d8b;">'lib'</span>, <span style="color: #483d8b;">'python2.5'</span>, <span style="color: #483d8b;">'lib-dynload'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> + <span style="color: #dc143c;">sys</span>.<span style="color: black;">path</span></pre>
<p>Unfortunately, doing that caused the app to crash at launch.</p>
<p>It was only when I actually read the output from py2app that I noticed that it appeared to be creating a semi-standalone app instead of the standalone app that I asked it to create. In retrospect, I should have realized this from the very first error since I should not have gotten a version mismatch error on the Python interpreter if it had been correctly embedded in the app bundle.</p>
<p>The message in the py2app log read: </p>
<pre>creating . . ./bdist.macosx-10.5-i386/python2.5-semi_standalone/app/collect/PyQt4</pre>
<p>A Google search later, I had a thread where <a href="http://www.mail-archive.com/pythonmac-sig%40python.org/msg04376.html">someone else was having the same problem</a> and I found a definitive answer from <a href="http://bob.pythonmac.org/" title="from __future__ import *">Bob Ippolito</a>, one of my Python heroes and the author of py2app, stating the following:</p>
<blockquote><p>[py2app] refuses to build a standalone bundle out of the system framework.</p></blockquote>
<p>OK, that's something that should be in the docs page on H1! (I couldn't find any mention of it in the docs at all.)</p>
<p>This makes sense, as <a href="http://mail.python.org/pipermail/pythonmac-sig/2008-August/020413.html" title="[Pythonmac-SIG] &quot;Best&quot; Mac Python under Leopard?">David Warde-Farley states</a> in a forum posting:</p>
<blockquote><p>First of all, if you want to build bundle .app's that are redistributable, it's a good idea not to use the system Python, especially if you want to support Tiger (10.4). There are things in Apple's Python (i.e. DTrace support) that I imagine won't play nicely on an older OS.</p></blockquote>
<p>At this point, I knew that I had to install a separate Python and decided to use MacPorts. It did take a while to install everything but that approach paid off in the end. </p>
<h3 name="reference">Reference</h3>
<h4 name="macports-setup">My Macports setup</h4>
<p>Here's a full list of my MacPorts setup (which I set up specifically to compile PyQt apps with py2app, so there aren't any superfluous packages in there) which you can compare to yours if something isn't working:</p>
<ul>
<li>autoconf @2.63_0 (active)</li>
<li>automake @1.10.1_0 (active)</li>
<li>dbus @1.2.4_2 (active)</li>
<li>expat @2.0.1_0 (active)</li>
<li>gettext @0.17_3 (active)</li>
<li>gperf @3.0.3_0 (active)</li>
<li>help2man @1.36.4_1 (active)</li>
<li>jpeg @6b_3 (active)</li>
<li>lcms @1.17_0 (active)</li>
<li>libiconv @1.12_0 (active)</li>
<li>libmng @1.0.10_0 (active)</li>
<li>libpng @1.2.33_0 (active)</li>
<li>libtool @1.5.26_0 (active)</li>
<li>m4 @1.4.12_1 (active)</li>
<li>ncurses @5.7_0 (active)</li>
<li>ncursesw @5.7_0 (active)</li>
<li>openssl @0.9.8i_0 (active)</li>
<li>p5-locale-gettext @1.05_0 (active)</li>
<li>perl5 @5.8.8_0+darwin_9</li>
<li>perl5.8 @5.8.8_3+darwin_9 (active)</li>
<li>pkgconfig @0.23_1 (active)</li>
<li>py25-altgraph @0.6.7_0 (active)</li>
<li>py25-bdist_mpkg @0.4.3_0 (active)</li>
<li>py25-hashlib @2.5.2_0 (active)</li>
<li>py25-macholib @1.1_0</li>
<li>py25-macholib-devel @1.2_0 (active)</li>
<li>py25-modulegraph-devel @0.7.2_0 (active)</li>
<li>py25-py2app-devel @0.4.2_0 (active)</li>
<li>py25-pyqt4 @4.4.3_0 (active)</li>
<li>py25-setuptools @0.6c9_0 (active)</li>
<li>py25-sip @4.7.6_0 (active)</li>
<li>py25-zlib @2.5.2_0 (active)</li>
<li>python25 @2.5.2_5+darwin_9 (active)</li>
<li>python_select @0.1_4+darwin_9 (active)</li>
<li>qt4-mac @4.4.3_0+dbus+docs (active)</li>
<li>tiff @3.8.2_2+darwin_9+macosx (active)</li>
<li>zlib @1.2.3_2 (active)</li>
</ul>
<h4 name="macports-details">Macports installation details</h4>
<p>Here are step-by-step instructions on how I got things working:</p>
<ol>
<li><a href="http://www.macports.org/install.php" title="The MacPorts Project -- Download &amp; Installation">Install MacPorts</a></li>
<li><code>sudo port install python25</code></li>
<li><code>sudo port install py25-macholib-devel</code></li>
<li><code>sudo port install py25-sip</code></li>
<li><code>sudo port install py25-pyqt4</code></li>
<li><code>sudo port install py25-py2app-devel</code></li>
<li><code>sudo port -v install py25-pyqt</code></li>
<li><code>sudo port install python_select</code></li>
</ol>
<p>Note that at one point during the PyQt installation, MacPorts aborted with:</p>
<blockquote><p>Target org.macports.activate returned: Image error: /opt/local/bin/a2p is being used by the active perl5.8 port.  Please deactivate this port first, or use the -f flag to force the activation.</p></blockquote>
<p>It appears that there were two versions of PERL installed. I simply restarted the installation (<code>sudo port install py25-pyqt</code>) and, after waiting a long while, and having to restart it once more, it completed successfully in installing Qt and PyQt.</p>
<p>(Note that the PyQt installation will take seemingly forever so it might be an idea to (a) start it in verbose mode, as shown above, so you know it's still doing something and hasn't hung, and (b) <a href="http://growl.info/documentation/growlnotify.php" title="growlnotify documentation">set up a growlnotify message</a> to let you know when the process is complete.)</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1675/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Python Launcher doesn&#8217;t work with OS X Leopard</title>
		<link>http://aralbalkan.com/1671</link>
		<comments>http://aralbalkan.com/1671#comments</comments>
		<pubDate>Sun, 30 Nov 2008 23:33:21 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[Apple]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1671</guid>
		<description><![CDATA[It appears that Python Launcher doesn't work under OS X Leopard. Python Launcher is used to launch Python apps by double-clicking on them in the Finder, and is thus useful when testing GUI Python apps. I wasted a bit of time trying to track down where exactly I had done something wrong in configuring my [...]]]></description>
			<content:encoded><![CDATA[<p id="top" />It appears that Python Launcher doesn't work under OS X Leopard. </p>
<p>Python Launcher is used to launch Python apps by double-clicking on them in the Finder, and is thus useful when testing GUI Python apps. </p>
<p>I wasted a bit of time trying to track down where exactly I had done something wrong in configuring my system so I hope this simple post keeps someone else from the same fate! :) </p>
<p><span id="more-1671"></span></p>
<p>Based on the <a href="http://bugs.python.org/issue1905" title="Issue 1905: PythonLauncher not working correctly on OS X 10.5/Leopad - Python tracker">issue ticket at python.org</a>, the bug appears to be fixed but I'm not sure which version it will be/was released in (I'm running Python 2.5.1 and experiencing the issue).</p>
<h3>Related links:</h3>
<ul>
<li><a href="http://bugs.python.org/issue1905" title="Issue 1905: PythonLauncher not working correctly on OS X 10.5/Leopad - Python tracker">PythonLauncher not working correctly on OS X 10.5/Leopard</a></li>
<li><a href="http://discussions.apple.com/thread.jspa?threadID=1784938&amp;tstart=0">Topic : Python Launcher Broken</a></li>
<li><a href="http://groups.google.com/group/comp.lang.python/browse_thread/thread/4b2954b2ae8ca261/7ba3be15934ac723" title="Python launcher not working on Mac after Leopard upgrade? -<br />
	  comp.lang.python |<br />
	  Google Groups">Python launcher not working on Mac after Leopard upgrade?</a></li>
<li><a href="http://www.macintouch.com/readerreports/leopard/topic4381.html" title="Leopard: Experiences">http://www.macintouch.com/readerreports/leopard/topic4381.html</a> (search for "Python Launcher" in the page).</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1671/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Running the PyAMF shell with Django 1.0 and app-engine-patch</title>
		<link>http://aralbalkan.com/1503</link>
		<comments>http://aralbalkan.com/1503#comments</comments>
		<pubDate>Thu, 02 Oct 2008 13:04:17 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[App Engine]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Flash]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[app engine]]></category>
		<category><![CDATA[app-engine-patch]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[pyamf]]></category>
		<category><![CDATA[shell]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1503</guid>
		<description><![CDATA[I lost quite a bit of time trying to get the PyAMF shell up and running on the &#60;head&#62; web site this week. I started out by downloading the source for the shell app via a link on a post on the PyAMF blog. Unfortunately, the link was to the wrong version of the shell [...]]]></description>
			<content:encoded><![CDATA[<p id="top" />I lost quite a bit of time trying to get the <a href="http://blog.pyamf.org/archives/interactive-python-shell-with-flex" title="PyAMF blog  &raquo; Blog Archive   &raquo; Interactive Python shell with Flex">PyAMF shell</a> up and running on the <a href="http://www.headconference.com">&lt;head&gt; web site</a> this week. </p>
<p>I started out by downloading the source for the shell app via a link <a href="http://blog.pyamf.org/archives/interactive-python-shell-with-flex" title="PyAMF blog  &raquo; Blog Archive   &raquo; Interactive Python shell with Flex">on a post on the PyAMF blog</a>. Unfortunately, the link was to the wrong version of the shell app (I've since informed the PyAMF team and Nick's fixed the link.)</p>
<p><span id="more-1503"></span></p>
<p>Seeing that the example used sessions, I decided to port the site from Google App Engine Helper to app-engine-patch, which has support for sessions in Google App Engine. Porting to app-engine-patch meant that I had to port the site to Django 1.0 also. <a href="http://aralbalkan.com/1502" title="Dictionary lookup removed for request object in Django 1.0 and other fun facts. at Aral Balkan">I've chronicled my experience with this previously</a>. </p>
<p>Today, I pinged the PyAMF folks on IRC and realized that there was a Google App Engine-specific version available. Unfortunately, that didn't work out of the box either due to a clash between its sessions implementation and the sessions implementation in app-engine-patch. That, however, was simple enough to fix.</p>
<p>If you're running app-enginge-patch and want to run the PyAMF shell, refactor the gateway.py module to rename the <code>Sessions</code> class to <code>ShellSessions</code> and Bob's your uncle. (It might be an idea for the PyAMF team to modify the example so that it works out of the box with app-engine-shell.)</p>
<p>Also, make sure that you protect the shell by only allowing admin access to it.</p>
<p>I can't begin to express how empowering it is to have shell access to your app on Google App Engine and I have no idea how I got by without it for so long. A big thank-you to the PyAMF team for making the shell app and releasing it. Great job, guys!</p>
<p>I would love to see a standalone Django app of the shell that you can simply plug in to your existing apps. Unfortunately, this is currently not possible since the app has static files and you need to add static folders manually to your application's app.yaml file. <a href="http://code.google.com/p/googleappengine/issues/detail?id=662&amp;can=1&amp;q=standalone&amp;colspec=ID%20Type%20Status%20Priority%20Stars%20Owner%20Summary%20Log" title="Issue 662 - googleappengine - Google Code">I've filed an ECR on this</a> -- star it if you'd like that feature.</p>
<p><strong>Update:</strong> Scratch that, I keep running into the 1MB limit for datastructures while trying to run queries, etc., through the shell, making it practically useless.</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1503/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Dictionary lookup removed for request object in Django 1.0 and other fun facts.</title>
		<link>http://aralbalkan.com/1502</link>
		<comments>http://aralbalkan.com/1502#comments</comments>
		<pubDate>Wed, 01 Oct 2008 14:50:33 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1502</guid>
		<description><![CDATA[Porting pre 1.0 Django to 1.0 is apparently not a walk in the park. For one thing django.core.validators, which I was using, was removed. The fix: copy it back from the earlier version. Not sure if it was a bad practice or not but I was also doing dictionary lookups on the request object and [...]]]></description>
			<content:encoded><![CDATA[<p id="top" />Porting pre 1.0 Django to 1.0 is apparently not a walk in the park.</p>
<p>For one thing django.core.validators, which I was using, was removed. The fix: copy it back from the earlier version. </p>
<p>Not sure if it was a bad practice or not but I was also doing dictionary lookups on the request object and <a href="http://code.djangoproject.com/wiki/BackwardsIncompatibleChanges#Removeddictionaryaccesstorequestobject" title="BackwardsIncompatibleChanges - Django - Trac">that's been removed now</a>. </p>
<p><span id="more-1502"></span></p>
<p>The errors you will get are:</p>
<ul>
<li>'WSGIRequest' object is not iterable</li>
<li>'WSGIRequest' object is unsubscriptable</li>
</ul>
<p>If you're in the same boat, here's the regular expressions you need to find/replace in TextMate: </p>
<h4>Fix 'WSGIRequest' object is not iterable:</h4>
<p>Find: </p>
<pre>' in request(?!\.)</pre>
<p>Replace:</p>
<pre>' in request.REQUEST</pre>
<h4>'WSGIRequest' object is unsubscriptable:</h4>
<p>Find: </p>
<pre>request\['</pre>
<p>Replace:</p>
<pre>request.REQUEST['</pre>
<p>Also, I switched from using <a href="http://code.google.com/p/google-app-engine-django/" title="google-app-engine-django - Google Code">Google App Engine Helper for Django</a> to <a href="http://code.google.com/p/app-engine-patch/" title="app-engine-patch - Google Code">app-engine-patch</a>. The main reason? So I could have the sessions middleware and run the <a href="http://blog.pyamf.org/archives/interactive-python-shell-with-flex" title="PyAMF blog &raquo; Blog Archive &raquo; Interactive Python shell with Flex">PyAMF Shell</a>. (And, of course, it's good to be running Django 1.0 now.)</p>
<p>App-engine-patch supports Django's mail feature so I stopped using google.appengine.api.mail.EmailMessage and replaced it with django.core.mail.EmailMessage. One thing to note if you do this is that you need to change the <code>to</code> properties on your EmailMessage instances to be lists, not strings, lest you end up trying to email each letter in the email address separately. </p>
<p>(Also, on my local server, I keep getting a Broken Pipe (error 32) since I upgraded to Django 1.0. I set fail_silently to True on my <code>send()</code> calls and that's fixed it. I don't have any issues on the deployment server. Looking into that one but it's a hairy one to track down.)</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1502/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
		<item>
		<title>Dr. Woohoo, Generating Artwork, and some Python code to massage user submitted content (specifically, images).</title>
		<link>http://aralbalkan.com/1458</link>
		<comments>http://aralbalkan.com/1458#comments</comments>
		<pubDate>Wed, 20 Aug 2008 22:48:23 +0000</pubDate>
		<dc:creator>Aral</dc:creator>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Conferences]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[dr.woohoo]]></category>
		<category><![CDATA[generating artwork]]></category>
		<category><![CDATA[regular expressions]]></category>
		<category><![CDATA[Singularity]]></category>
		<category><![CDATA[web conference]]></category>

		<guid isPermaLink="false">http://aralbalkan.com/1458</guid>
		<description><![CDATA[The cool thing about user submitted content is that you can't always predict what you're going to get. Our speakers at the Singularity Web Conference, for example, submit and update their own bios and session descriptions on the site. Yesterday, I noticed that Dr. Woohoo had put up an image of one of his awesome [...]]]></description>
			<content:encoded><![CDATA[<p id="top" /><a href="http://www.singularity08.com/speakers/dr-woohoo/" title="Speakers: Dr. WooHoo"><img id="image256" width="160" height="207" alt="Cotton Candy Corral Reef" src="http://www.inthemod.com/bps/wp-content/uploads/2008/05/Cotton%20Candy%20Corral%20Reef-blog.png" style="float: right; margin-left: 1em;"/></a>The cool thing about user submitted content is that you can't always predict what you're going to get. Our speakers at the <a href="http://www.singularity08.com/" title="Singularity Web Conference: October 24-26, 2008">Singularity Web Conference</a>, for example, submit and update their own bios and session descriptions on the site. Yesterday, I noticed that <a href="http://www.drwoohoo.com/" title="Dr. Woohoo || 760.889.1247">Dr. Woohoo</a> had put up an image of one of his awesome generative artworks in <a href="http://www.singularity08.com/speakers/dr-woohoo/" title="Speakers: Dr. WooHoo">his session description</a>. </p>
<p>Of course, since I hadn't considered images in session descriptions, this had the side-effect of breaking the layout of the sessions page. </p>
<p><span id="more-1458"></span></p>
<p>(In case you're wondering, yes, this is the way I like to work. Instead of over-engineering things, I like to see how people actually use stuff and then evolve them to meet their needs.)</p>
<p>So tonight I wrote a bit of code to massage and tame how images in session descriptions are displayed and I thought I'd share it with you in case it helps anyone else. (Another, more complicated way to go about things would have been to grab the images using urlfetch, store them in the datastore, and resize them via the image API -- but that would have been overkill for my needs.)</p>
<pre class="python"><span style="color: #808080; font-style: italic;"># Copyright (c) 2008 Aral Balkan, Singularity Web Conference</span>
<span style="color: #808080; font-style: italic;"># http://www.singularity08.com</span>
<span style="color: #808080; font-style: italic;"># Released under the open source MIT license.</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> markdown <span style="color: #ff7700;font-weight:bold;">import</span> Markdown
&nbsp;
image_tag_width_re = r<span style="color: #483d8b;">'(?P&lt;img&gt;&lt;img.*?width=&quot;)(?P&lt;width&gt;<span style="color: #000099; font-weight: bold;">\d</span>*?)&quot;'</span>
image_tag_height_re = r<span style="color: #483d8b;">'(?P&lt;img&gt;&lt;img.*?height=&quot;)(?P&lt;height&gt;<span style="color: #000099; font-weight: bold;">\d</span>*?)&quot;'</span>
image_tag_re = r<span style="color: #483d8b;">'(&lt;img)(.*?)&gt;'</span>
image_tag_src_re = r<span style="color: #483d8b;">'&lt;img.*?src=&quot;(.*?)&quot;'</span>
image_tag_alt_re = r<span style="color: #483d8b;">'&lt;img.*?alt=&quot;(.*?)&quot;'</span>
&nbsp;
image_tag_width_rc = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>image_tag_width_re<span style="color: black;">&#41;</span>
image_tag_height_rc = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>image_tag_height_re<span style="color: black;">&#41;</span>
image_tag_rc = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>image_tag_re<span style="color: black;">&#41;</span>
image_tag_src_rc = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>image_tag_src_re<span style="color: black;">&#41;</span>
image_tag_alt_rc = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>image_tag_alt_re<span style="color: black;">&#41;</span>
&nbsp;
IMAGE_SAFE_WIDTH = <span style="color: #ff4500;">160.0</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> massage_images<span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>:
	<span style="color: #483d8b;">&quot;&quot;</span><span style="color: #483d8b;">&quot;Helper: Alters dimensions of any images in the passed HTML to make them safe for the site's design.&quot;</span><span style="color: #483d8b;">&quot;&quot;</span>
	image_tag_widths = image_tag_width_rc.<span style="color: black;">findall</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>
	image_tag_heights = image_tag_height_rc.<span style="color: black;">findall</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>
	image_tag_srcs = image_tag_src_rc.<span style="color: black;">findall</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>
	image_tag_alts = image_tag_alt_rc.<span style="color: black;">findall</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #008000;">len</span><span style="color: black;">&#40;</span>image_tag_widths<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
		<span style="color: #808080; font-style: italic;"># Reduce the width of any found images to 160px so as not to break the layout</span>
		original_width = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>image_tag_widths<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</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>
&nbsp;
		maintain_aspect_ratio = <span style="color: #008000;">True</span>
		<span style="color: #ff7700;font-weight:bold;">try</span>:
			original_height = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>image_tag_heights<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</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: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">IndexError</span>:
			<span style="color: #808080; font-style: italic;"># Mismatched width/height pairs on image tags. We won't be</span>
			<span style="color: #808080; font-style: italic;"># able to maintain aspect ratio.</span>
			maintain_aspect_ratio = <span style="color: #008000;">False</span>
&nbsp;
		<span style="color: #ff7700;font-weight:bold;">if</span> maintain_aspect_ratio:
&nbsp;
			aspect_ratio = <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>original_width<span style="color: black;">&#41;</span>/<span style="color: #008000;">float</span><span style="color: black;">&#40;</span>original_height<span style="color: black;">&#41;</span>
			new_height = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>IMAGE_SAFE_WIDTH/aspect_ratio<span style="color: black;">&#41;</span>
&nbsp;
			<span style="color: #808080; font-style: italic;"># Substitute the new height</span>
			html = image_tag_height_rc.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\g</span>&lt;img&gt;'</span>+<span style="color: #008000;">repr</span><span style="color: black;">&#40;</span>new_height<span style="color: black;">&#41;</span>+r<span style="color: #483d8b;">'&quot;'</span>, html<span style="color: black;">&#41;</span>
			<span style="color: #dc143c;">logging</span>.<span style="color: black;">info</span><span style="color: black;">&#40;</span>html<span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># Substitute the new width</span>
		html = image_tag_width_rc.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\g</span>&lt;img&gt;'</span>+<span style="color: #008000;">str</span><span style="color: black;">&#40;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>IMAGE_SAFE_WIDTH<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>+<span style="color: #483d8b;">'&quot;'</span>, html<span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># Add float:left and slight margin so that text flows around the image</span>
		html = image_tag_rc.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\1</span> style=&quot;float:left; margin-right:.5em;&quot; <span style="color: #000099; font-weight: bold;">\2</span>&gt;'</span>, html<span style="color: black;">&#41;</span>
&nbsp;
		<span style="color: #808080; font-style: italic;"># Finally, add a link to the original image if people want to see it larger</span>
		html = image_tag_rc.<span style="color: black;">sub</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'&lt;a href=&quot;'</span>+ image_tag_srcs<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span> + <span style="color: #483d8b;">'&quot; title=&quot;'</span>+image_tag_alts<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span>+r<span style="color: #483d8b;">'&quot;&gt;<span style="color: #000099; font-weight: bold;">\1</span><span style="color: #000099; font-weight: bold;">\2</span>&gt;&lt;/a&gt;'</span>, html<span style="color: black;">&#41;</span>
&nbsp;
	<span style="color: #ff7700;font-weight:bold;">return</span> html
&nbsp;</pre>
<p>There are a couple of basic but helpful regular expressions in there and you might find the snippet useful if you want to manipulate image tags generated from user submitted content. </p>
<p>Oh, and before I forget, Dr. Woohoo is going to be talking about <a href="http://www.singularity08.com/speakers/dr-woohoo/" title="Speakers: Dr. WooHoo">Generating Artwork</a> at the Singularity Web Conference. Check out his <a href="http://www.singularity08.com/speakers/dr-woohoo/" title="Speakers: Dr. WooHoo">bio and session</a> and <a href="http://www.singularity08.com/sessions/" title="Sessions at Singularity Web Conference">the other sessions</a> at the conference. </p>
<p>(You can <a href="http://www.drwoohoo.com/" title="Dr. Woohoo || 760.889.1247">find out more about Dr.Woohoo on his web site</a> and take a look at his latest book, <a href="http://www.blurb.com/bookstore/detail/324172" title="Color Visualizations | By Dr. Woohoo! | Category: Arts &amp; Photography | Blurb">Color Visualizations: Exploring the Circle, vol 02</a>.)</p>
<p>If you haven't booked your ticket for Singularity yet, hurry, as the $99 early bird discount ends at the end of this month.</p>
]]></content:encoded>
			<wfw:commentRss>http://aralbalkan.com/1458/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
	<creativeCommons:license>http://creativecommons.org/licenses/by-nc/2.0/uk/</creativeCommons:license>
	</item>
	</channel>
</rss>

