<?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>Open Source Hacker &#187; python</title>
	<atom:link href="http://opensourcehacker.com/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://opensourcehacker.com</link>
	<description>Pushing the boundaries of free technology</description>
	<lastBuildDate>Wed, 01 Feb 2012 09:06:57 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>readthedocs.org, GitHub edit backlink and short history of Plone documentation</title>
		<link>http://opensourcehacker.com/2012/01/08/readthedocs-org-github-edit-backlink-and-short-history-of-plone-documentation/</link>
		<comments>http://opensourcehacker.com/2012/01/08/readthedocs-org-github-edit-backlink-and-short-history-of-plone-documentation/#comments</comments>
		<pubDate>Sun, 08 Jan 2012 15:57:24 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ace]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[disqus]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[gpl]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[readthedocs.org]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1733</guid>
		<description><![CDATA[TL; DR: To encourage contributions to developer documentation you can maintain Sphinx based documentation on GitHub, deploy and it via readthedocs.org and have this nice &#8220;Edit this document&#8221; pop-up note on the deployed docs. The source code for the edit &#8230; <a href="http://opensourcehacker.com/2012/01/08/readthedocs-org-github-edit-backlink-and-short-history-of-plone-documentation/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.urbandictionary.com/define.php?term=tl%3Bdr">TL; DR</a>: To encourage contributions to developer documentation you can maintain <a href="http://sphinx.pocoo.org/">Sphinx based</a> documentation <a href="https://github.com/collective/collective.developermanual">on GitHub</a>, deploy and it via <a href="http://readthedocs.org/">readthedocs.org</a> and have this nice &#8220;<a href="http://collective-docs.readthedocs.org/en/latest/index.html">Edit this document</a>&#8221; pop-up note on the deployed docs.</p>
<p><a href="http://opensourcehacker.com/wp-content/uploads/2012/01/Screen-shot-2012-01-08-at-4.35.33-PM.png"><img class="alignnone size-full wp-image-1734" title="Screen shot 2012-01-08 at 4.35.33 PM" src="http://opensourcehacker.com/wp-content/uploads/2012/01/Screen-shot-2012-01-08-at-4.35.33-PM.png" alt="" width="568" height="252" /></a></p>
<p><a href="https://github.com/collective/collective.developermanual/blob/master/source/_templates/page.html">The source code for the edit pop-up is here</a>. I hope you can see my cool CSS3 effects!</p>
<p>Also this blog post is a story how you gain 180k words worth of developer documentation almost from the scratch for your favorite Python project. A Story worth of telling, I hope.</p>
<h2>History</h2>
<p>To understand the context and the level of complexity.</p>
<p><a href="http://plone.org">Plone CMS</a>, mature (as in your great-great-great-grand-aunt) Python based content management system, has not been very developer  friendly. The goal of &#8220;to make it easy to customize and extend&#8221; has never appeared in Plone roadmap or conference keynotes. Instead, the most of the developers have generally been busy of doing more interesting stuff and pushing the technology forward.</p>
<p>Plone is also geared toward more heterogeneous end of codebases out there, due to its long history (&gt;10 years &#8211; a long time for a Python product) and adoption of many third party-ish packages in the codebase (248 Python packages) . All these packages, including critical packages you should understand for extending Plone for your own purpose, come with <a href="http://pypi.python.org/pypi/plone.app.folder/">less</a> or <a href="http://pypi.python.org/pypi/plone.app.layout">even less</a> documentation. Sometimes packages are <a href="http://pypi.python.org/pypi/zope.configuration/3">not Plone related</a> and authors may not be interested how to apply the re-usable components in the context of Plone.</p>
<p>It&#8217;s all sucks if you are a developer and simply want to get your little customization done into Plone. You need to drill through a stack and try to guess which piece of history to apply in which point of source code.</p>
<h2>From closed official documentation to open-ended unofficial documentation</h2>
<p>There exists <a href="http://plone.org/documentation/manual/developer-manual">an official Plone developer documentation</a> &#8211; official in the sense Plone Foundation has copyright over it. However this level of ownership, right to relicense, comes with a price: it&#8217;s &#8220;hard&#8221; to contribute for it &#8211; you need to sign a contribution agreement (by hand) and snailmail it somewhere. Due to lack of content and contributions, the official documentation does not carry you far.</p>
<p>Somewhere in the past &#8220;unofficial&#8221; Plone developer documentation was started. The goal of this project was to have more open-ended documentation process to get some developer documentation for Plone in the first place and the fix some of the problems mentioned before. The spirit was &#8220;wiki-style&#8221; though the tools were different. The community went through some mailing list wars about the future of the documentation. This was the future then (and now is the current past):</p>
<ul>
<li>First the unofficial documentation was bunch of Plone pages (WYSIWYG) managed in plone.org. We were living the time when Sphinx was still a dream in its authors minds.</li>
<li>Then it was converted to reStructured Text pages, still managed in plone.org</li>
<li>Then it was pulled out from plone.org, converted to Sphinx, put into Plone &#8220;collective&#8221; Subversion control (no contrib agreement needed). We were living the time when first Sphinx release was put out into PyPi.</li>
<li>Sphinx becomes de facto method of creating Python developer documentation</li>
<li>Then it was hosted as standalone HTML files, under <a href="https://github.com/collective/collective.developermanual">collective.developermanual</a> Python package, on random hosts</li>
<li>Then it was hosted on plone.org again. This time Sphinx generated HTML was imported to plone.org using a tool called <a href="http://pypi.python.org/pypi/funnelweb">Funnelweb</a>. Funnelweb was originally created for importing arbitary sites into Plone as Plone content (it has been known to work for Liferay, WordPress, Drupal, etc.) Howver, this was still bad idea as Funnelweb does not have really have a concept of updating docs &#8211; just one time imports and data dumps.</li>
<li>And, da-da, it&#8217;s 2010s, <a href="http://readthedocs.org/">readthedocs.org</a> is launched. The documentation management is moved to GitHub as, with readthedocs.org, this solves the need for automatic documentation deployments after a commit.</li>
<li>GitHub creates a button <em>Fork and edit this file</em></li>
<li>readthedocs.org gains edit back link when <a href="https://github.com/rtfd/readthedocs.org/issues/152#issuecomment-3401888">issue 152 </a>is worked around</li>
<li>The documentation title is renamed from <em>Plone community maintained blaablaablaa</em> to more simple <em>Plone Developer Documentation</em> (as opposite to official Plone Developer Manual)</li>
<li>This blog post is written &#8211; hoping to encourage even more open-ended developer documentation contributions</li>
</ul>
<p>Plone Developer Documentation now contains 183 792 words. It is comprehensive, but not coherent. It also crucially <a href="http://collective-docs.readthedocs.org/en/latest/tutorials/addon.html">lacks polished, hand holding, Hello world tutorial</a> needed to lure in new developers (someone please take a ball on this). Even with these little hindrances, based on the readers&#8217; comments, it&#8217;s slowly becoming really really good.</p>
<p>The unofficial documentation is licensed under GPL license. The rationale for this is simply the fact that when collective.developermanual package was created this was the default license coming in Paster templates. Also, Plone Foundation&#8217;s official stance is that <a href="http://plone.org/foundation/copyrights/license-faq">when you import code from Plone your product should be GPL</a>. The documentation contains a lot of code starting with import plone&#8230; This little gem does not have any practical impact, but I wish to live to see some arguments about this.</p>
<h2>Fork and edit this file</h2>
<p>I love GitHub; I hate Git. Git is the anti-thesis of user interfaces &#8211; what a version control system would look like if it were developed by persons knowing only C and Perl and who&#8217;d love to scare away all other developers how are not equally smart. But luckily with GitHub, everyone, even without theoretical version management course studies, can work with Git.</p>
<p>One of GitHub&#8217;s recent innovations is <em>Fork and edit this file</em> button. It allows anyone to suggest changes to source file. No prior relationship between the author and the contributor is needed &#8211; the suggestion goes to the pull request queue and you&#8217;ll get a notification about the contribution.</p>
<p><a href="http://opensourcehacker.com/wp-content/uploads/2012/01/Screen-shot-2012-01-08-at-5.21.56-PM.png"><img class="alignnone size-full wp-image-1735" title="Screen shot 2012-01-08 at 5.21.56 PM" src="http://opensourcehacker.com/wp-content/uploads/2012/01/Screen-shot-2012-01-08-at-5.21.56-PM.png" alt="" width="424" height="181" /></a></p>
<p>This was a holy grail for me who cares less about politics and more about getting in more contributions.</p>
<ul>
<li>Any person can edit the file, as Git/SVN checkout is not needed</li>
<li>You don&#8217;t need to maintain user list of &#8220;authored editors&#8221;</li>
<li>The GitHub editor itself (<a href="https://github.com/ajaxorg/ace">ACE based</a>?) is actually nice: selecting text and hitting Tab key actually indents a block of text. It&#8217;s way beyond crappy &lt;TEXTAREA&gt;.</li>
<li>You get pull request notifications</li>
<li>You can post-edit proposed changes easily and communicate with the contributor</li>
</ul>
<h2> Linking it back</h2>
<p>A perfect documentation update workflow would be that when you want to edit a piece of text you simply click it in the place, edit in place and press Save. This is what Wikipedia was before it grew too large.</p>
<p>With readthedocs.org, GitHub and Javascript  magic we cannot reach such fidelity yet. We</p>
<ul>
<li>Don&#8217;t know if user is logged into GitHub, or his/her GitHub username</li>
<li>Cannot edit individual Sphinx paragraphs in ACE</li>
<li>Don&#8217;t have GitHub Javascript API to push in commits/pull requets</li>
</ul>
<p>(Please correct me if I am wrong)</p>
<p>But someday we&#8217;ll be there.</p>
<p>Meanwhile, we have something what we call in Finnish a &#8220;fur cap solution&#8221; (karvalakkiratkaisu). It means solving the problem in the least complex way, but still achieving the solution somehow. (If someone would like to clarify the etymology of this proverb or has a translation for it I&#8217;d like to hear that also)</p>
<p>In Sphinx HTML templates we simply include backlinks to the source code file on GitHub and have bulleted instructions how to edit the file:</p>
<div id="editor-trap">
<h3 style="padding-left: 60px;"><em>Edit this document</em></h3>
<p style="padding-left: 60px;"><em>The source code of this file is hosted on GitHub. Everyone can update and fix errors in this document with few clicks &#8211; no downloads needed.</em></p>
<ol style="padding-left: 60px;">
<li><em>Go to <a href="https://github.com/collective/collective.developermanual/blob/master/source/index.txt"> Plone Developer Documentation </a> on GitHub.</em></li>
<li><em>Press <strong>Fork and edit this file</strong> button</em></li>
<li><em>Edit file contents using GitHub&#8217;s text editor in your web browser</em></li>
<li><em>Press <strong>Propose file change</strong> at the bottom of the page</em></li>
</ol>
<p style="padding-left: 60px;"><em>For basic information about updating this manual and Sphinx format please see <a href="http://collective-docs.readthedocs.org/en/latest/introduction/writing.html"> Writing and updating the manual</a> guide.</em></p>
</div>
<h2>Future future</h2>
<p>After struggling several years of getting any developer documentation for Plone I am think I am finally quite happy and my work here is done. It&#8217;s not perfect, but compared to other CMS&#8217;s we are not definitely the worst anymore.</p>
<p>What still is needed is more interactivity &#8211; where people can ask questions in the context of documentation, like happens on php.net API documentation. Then store the question and the answer in the context, so the future generations do not need to wonder the same thing again. This far I have been manually linking stackoverflow.com questions direcly to the documentation when I am too <del>lazy</del> busy to start writing anything. Sadly, the orignal plone.org documentation had discussion feature until it was disabled, due to lack of good notification system. Maybe we could do something akin the lines using DISQUS and Sphinx and post questions to the mailing list?</p>
<h2>Ps.</h2>
<p>The edit pop-up note text, due to CSS3 rotation, looks like crap on Firefox 10 / OSX. Chrome does not suffer from this. A bug in FF text rendering?</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2012/01/08/readthedocs-org-github-edit-backlink-and-short-history-of-plone-documentation/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Migrating from BIND DNS servers to Amazon Route 53 by using cli53</title>
		<link>http://opensourcehacker.com/2011/11/23/migrating-from-bind-dns-servers-to-amazon-route-53-by-using-cli53/</link>
		<comments>http://opensourcehacker.com/2011/11/23/migrating-from-bind-dns-servers-to-amazon-route-53-by-using-cli53/#comments</comments>
		<pubDate>Tue, 22 Nov 2011 23:17:26 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[aws]]></category>
		<category><![CDATA[bind]]></category>
		<category><![CDATA[buildout]]></category>
		<category><![CDATA[cli53]]></category>
		<category><![CDATA[dig]]></category>
		<category><![CDATA[dns]]></category>
		<category><![CDATA[domain names]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[route 53]]></category>
		<category><![CDATA[zone]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1680</guid>
		<description><![CDATA[Amazon Route 53 offers DNS as a hosted service. They maintain robust DNS service for you with easy to user web interface and API. Name servers are part of any serious hosting infrastructure. They have been traditionally run on BIND &#8230; <a href="http://opensourcehacker.com/2011/11/23/migrating-from-bind-dns-servers-to-amazon-route-53-by-using-cli53/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Amazon Route 53 offers DNS as a hosted service. They maintain robust DNS service for you with easy to user web interface and API.</p>
<p>Name servers are part of any serious hosting infrastructure. They have been traditionally run on BIND or similar UNIX daemons. The usual hosting tasks including mapping domain names and subdomains (A, CNAME, et. al records) to servers and delivering email (MX and SPF records).</p>
<p>Usually a basic hosting plan is only good for setting A records for few subdomains like www, but on the instant you need something more advanced like routing MX records to Google Apps email you need to start considering a real DNS service. GoDaddy and other big name registrants provide tools for this, but they are usually specific only for top level domains (TLDs) the registrant supports. If you come from a cold country like .fi you cannot centralize your DNS management to big popular domain registrants.</p>
<p>The bad thing with running your own name servers is that when the service goes down the whole your infrastructure becomes virtually inaccessible &#8211; web sites, email, anything. Thus you usually run at least two BIND daemons on two physically separated servers just in case one blows up the other can still keep DNS records running. Also DNS, being core part of internet infrastructure, is subject for many kind of attacks and keeping your skills and knowledge up-to-date with BIND may be time consuming.</p>
<p>Like with email servers, hosting name servers is a thing you really don&#8217;t want to do. Enter Amazon Route 53. (tha name Route 53 probably comes from the famous U.S. road  Route 67 and DNS port 53?).</p>
<p>Route 53 is ridiculous easy to use. Just go to the site and register one for yourself. However if you have legacy BIND servers running around there exist ways to import data automatically instead of manually reading through zone files and typing them in to Route 53 by hand.</p>
<h2>Setting up cli53</h2>
<p><a href="https://github.com/barnybug/cli53">cli53</a> is a Python based command line interface for Route 53. It uses <a href="http://www.buildout.org">buildout</a> for installation (of Python package dependencies).</p>
<p>These instructions have been tested with Ubuntu 8.04 server. Prerequisitements for using this stuff is knowing basic Ubuntu server management from the command line.</p>
<p>Run everything as root.</p>
<p>Install <em>wget</em> and <em>unzip</em></p>
<pre>apt-get install wget unzip</pre>
<p>Download ZIP copy of cli53 from Github (we don&#8217;t do git clone here &#8211; no need to install git on the server):</p>
<pre>wget --no-check-certificate https://github.com/barnybug/cli53/zipball/master</pre>
<p>Extract</p>
<pre>unzip master</pre>
<p>Install as user local under the extracted folder (note that the folder varies across GitHub exports)</p>
<pre>cd barnybug-cli53-3b468b7
python bootstrap.py
bin/buildout</pre>
<p>This will generate the local <em>bin/cli53</em> command.</p>
<p>Now you need to set up AWS credentials. Route 53, and other AWS service, are operated using access keys which you can get from <em>Security Credentials</em> page in AWS web console. Set the access keys for your shell/SSH session using enviroment variables:</p>
<pre>export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=XXXXXXXXXXXXXXXXXXXXXXXXXXXXX</pre>
<p>Side note: as this point you need to check that your server clock is in correct time your AWS remote operations will fail (300 seconds thresold).. Use <em>date</em> command to see the server clock time and correct it with the same date command <a href="http://codeghar.wordpress.com/2007/12/06/manage-time-in-ubuntu-through-command-line/">using this obscure date command syntax</a>.</p>
<p>Now you can run a test by listing your Amazon Route 53 Hosted Zones (Hosted Zone = zonefile = one per top level domain usually) using list command:</p>
<pre>bin/cli53 list</pre>
<p>The proper output for one domain which has been created throught-the-web in Route 53 control panel is something like:</p>
<pre>HostedZones:
  - CallerReference: 9265CCC3-9C41-98CE-8820-E26C0356C478
    Config:
      Comment: test
    Id: /hostedzone/Z2L3NT0WCS8OWA
    Name: xxx.fi.</pre>
<h2>Importing zone files</h2>
<p>Now when cli53 is running and working it <a href="http://www.youtube.com/watch?v=AOfiziY-htU">is time to rock&#8217;n'roll</a>.</p>
<p>On our server configuration BIND zonefiles lived in <em>/srv/dns/zones</em> though this is not the default location for Ubuntu BIND. There is one file per each zone and the filename is the domain name.</p>
<pre>[root@foobar][23:02][/srv/dns/zones]# ls -l
total 176
-rw-r--r-- 1 root root  425 Dec 30  2008 abc.com
-rw-r--r-- 1 root root 1713 Dec 30  2008 abcabc.com
-rw-r--r-- 1 root root 1719 Dec 30  2008 abcabcabc.com</pre>
<p>We can simple create an one-liner shell script which will loop through all the files and import them to Amazon Route 53. However &#8211; there is a trick. You&#8217;ll get unknown origin exception if your zone files lack a certain line:</p>
<pre>Traceback (most recent call last):
  File "/root/barnybug-cli53-3b468b7/bin/cli53", line 22, in &lt;module&gt;
    cli53.cli53.main()
  File "/root/barnybug-cli53-3b468b7/src/cli53/cli53.py", line 495, in main
    args.func(args)
  File "/root/barnybug-cli53-3b468b7/src/cli53/cli53.py", line 268, in cmd_import
    raise Exception, 'Could not find origin'
Exception: Could not find origin</pre>
<p>This is because the zone file doesn&#8217;t have <a href="http://www.zytrax.com/books/dns/ch8/origin.html">$ORIGIN</a> directive. it&#8217;s optional with BIND as BIND uses the filename as $ORIGIN if it&#8217;s not defined, but the directive is mandatory  for cli53 (cli53 doesn&#8217;t yet synthetize $ORIGIN).</p>
<p>You can simple add $ORIGIN to the beginning of each file and copy files to a working directory with the following shell one-liner (it&#8217;s always safe to make copies of processed files than try to fix them in place):</p>
<pre>mkdir ../transfer
for i in * ; do echo "\$ORIGIN $i." &gt; ../transfer/$i ; cat $i &gt;&gt; ../transfer/$i ; done</pre>
<p>Then do a test run for one import:</p>
<pre>~/barnybug-cli53-3b468b7/bin/cli53 create xxx.fi
~/barnybug-cli53-3b468b7/bin/cli53 import xxx.fi --file xxx.fi --replace --wait</pre>
<p>Note: deleting zones in Route 53 control panel is painful difficult, so make sure you import zones you only really need.</p>
<p>If everything looks good we are ok to upload everything to Route 53. Again, a shell one-liner does the trick for us:</p>
<pre>for i in * ; do ~/barnybug-cli53-3b468b7/bin/cli53 create $i ; ~/barnybug-cli53-3b468b7/bin/cli53 import $i --file $i --wait ; done</pre>
<p>This will take abour 15-20 seconds per domain.</p>
<p>Note: if you need to re-import add &#8211;replace flag.</p>
<h2>The ugly part</h2>
<p>Each zone has<em> Source of Authority</em> record with authoritative nameserves (NS records). These will be change from your BIND server IP addresses to Amazon ones. Route 53 will re-assign its own name servers for each imported Hosted Zone. However, you cannot know beforehand what name servers the dice has chosen for your Hosted Zone, so automatizing this process is little bit difficult. NS records servers are overriden when the zone file is uploaded to Route 53.</p>
<p>You can see new SOA and NS records when you choose the domain in Route 53 control panel and press <em>Go to Record Set</em>s.</p>
<p>To make things easier later on here is a script which will dump all the name servers of all domains you have in Route 53 and collect are info to <em>domain-info.txt</em> file:</p>
<pre>for i in * ; do ~/barnybug-cli53-3b468b7/bin/cli53 info $i &gt;&gt; /tmp/domain-info.txt ; done</pre>
<h2>Testing Route 53 DNS</h2>
<p>Browser through imported domain records in Route 53 control panel and see if they look ok.</p>
<p>You can also test the actual DNS functionality. When you use <em>ping</em> command, your web browser or any other &#8220;normal&#8221; mean which queries DNS records they use the Source of Authority name servers as set by in your domain registrant settings. When in the middle of migration to Route 53, the authorative name servers are still pointing to the old name servers in this point.</p>
<p><em>dig</em> command can be used to query a specific name server for DNS records.</p>
<ul>
<li>In Route 53 control panel pick any domain and any of its name servers</li>
<li>Use dig command to query the records of this domain</li>
</ul>
<p>Example:</p>
<pre>dig -t ANY @ns-1340.awsdns-39.org yourdomainname.com</pre>
<p>Output should be something like this:</p>
<pre>; &lt;&lt;&gt;&gt; DiG 9.4.2-P1 &lt;&lt;&gt;&gt; -t ANY @ns-1340.awsdns-39.org yourdomain.com
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NOERROR, id: 9352
;; flags: qr aa rd; QUERY: 1, ANSWER: 10, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;yourdomain.com.            IN    ANY

;; ANSWER SECTION:
yourdomain.com.        172800    IN    NS    ns-470.awsdns-58.com.
yourdomain.com.        172800    IN    NS    ns-553.awsdns-05.net.
yourdomain.com.        172800    IN    NS    ns-1340.awsdns-39.org.
yourdomain.com.        172800    IN    NS    ns-1706.awsdns-21.co.uk.
yourdomain.com.        900    IN    SOA    ns-1340.awsdns-39.org. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400
yourdomain.com.        0    IN    MX    10 aspmx.l.google.com.
yourdomain.com.        0    IN    MX    20 alt1.aspmx.l.google.com.
yourdomain.com.        0    IN    MX    20 alt2.aspmx.l.google.com.
yourdomain.com.        0    IN    TXT    "v=spf1 a mx a:smtp.something.fi a:auth-smtp.something.fi include:aspmx.googlemail.com ~all"
yourdomain.com.        0    IN    A    84.20.128.49

;; Query time: 32 msec
;; SERVER: 205.251.197.60#53(205.251.197.60)
;; WHEN: Wed Nov 23 00:04:53 2011
;; MSG SIZE  rcvd: 413</pre>
<p>(subdomains are not listed)</p>
<h2>Finalizing it</h2>
<p>Go to your domain name registrant and update the domain name servers point to your Route 53 servers.</p>
<ul>
<li>For each domain in <em>domain-info.txt</em></li>
<ul>
<li>Go to the corresponding registrant from whom you obtained the domain (e.g. <em>domain.ficora.fi</em>)</li>
<li>Update the authoritative name servers to be as stated in the file</li>
</ul>
<li>Wait 24-48 hours or whatever time-to-live time you have for your name servers &#8211; usually this is longish period</li>
<li>See that your services still run</li>
<li>Take down your old name servers</li>
</ul>
<h2>More info</h2>
<ul>
<li><a href="http://hathology.com/2011/02/how-to-import-bind-zone-files-into-amazon-route-53/">http://hathology.com/2011/02/how-to-import-bind-zone-files-into-amazon-route-53/</a></li>
<li><a href="http://docs.amazonwebservices.com/Route53/latest/DeveloperGuide/index.html?MigratingDNS.html#Step_UpdateRegistrar">http://docs.amazonwebservices.com/Route53/latest/DeveloperGuide/index.html?MigratingDNS.html#Step_UpdateRegistrar</a></li>
</ul>
<p>&nbsp;</p>
<p>&nbsp;
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/11/23/migrating-from-bind-dns-servers-to-amazon-route-53-by-using-cli53/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>sauna.reload &#8211; the most awesomely named Python package ever</title>
		<link>http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named-python-package-ever/</link>
		<comments>http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named-python-package-ever/#comments</comments>
		<pubDate>Mon, 07 Nov 2011 22:53:16 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[egg]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[fork]]></category>
		<category><![CDATA[maemo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sprint]]></category>
		<category><![CDATA[symbian]]></category>
		<category><![CDATA[unexec]]></category>
		<category><![CDATA[watchdog]]></category>
		<category><![CDATA[zodb]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1660</guid>
		<description><![CDATA[This blog post is about sauna.reload which is a Python package adding an automatic reload feature to Plone CMS. The short history of reloading The web developer community takes reload-code-on-development as granted. You edit your source file, hit refresh and &#8230; <a href="http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named-python-package-ever/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This blog post is about <a href="http://plone.org">sauna.reload</a> which is a Python package adding an automatic reload feature to <a href="http://plone.org">Plone CMS</a>.</p>
<h2>The short history of reloading</h2>
<p>The web developer community takes reload-code-on-development as granted. You edit your source file, hit refresh and poof: your changed are there. It is a good way and the only real web development way and one of the sane things PHP community has taught to us. Things could be different: for example if you are developing an embedded code on mobile platforms you might need to build the ROM image for hours before you see your changed source code line in the action.</p>
<p><em>Side note: To check your code changes it is often faster the hit enter on the browsee address bar line as this does not reload CSS and JS files for the HTTP request</em></p>
<p>For PHP the reloading is easy as the software stack parses every PHP file again on every request. There is no reload &#8211; only load. <a href="https://en.wikipedia.org/wiki/PHP_accelerator">In fact there is a whole &#8220;optimizer&#8221; open source business model spawned around PHP just to make it faster</a>. PHP processes are stateless.</p>
<p>For Python the things are not so simple. Python web frameworks have separate process lifespan and HTTP request handling lifespans. Often a server process is started, it spawns N threads and each thread handles one HTTP request at a time. Python processes are stateful.</p>
<p>As being stateful, Python processes may start slowly. You need to parse all source code and create initial memory objects, etc. Frameworks do not optimize for fast start-up because it really doesn&#8217;t matter on the production service as you spawn Python processes only once, when the server is booted.</p>
<p>Plone CMS, coming with choking 250 MB of source code (Linux kernel has 400-500 MB) is the extreme of this slow initialization. Plone CMS is the biggest open source Python project out there (does anyone dare to challenge my clain?).  When Plone starts it loads most of source code to memory and parsing and initializing Python itself, plus various XML files, is quite an achievement.</p>
<p>What Tornado, Django, Paster etc. Python frameworks do that when they reload they simply zap the process dead and reinitialize 100% virgin process. This is ok as these low level frameworks have little overhead. Though it becomes painful slow too when your Django service grows for many applications and the code starts piling up&#8230;</p>
<p>For Plone 100% start up this is no go. Plone people care about the start up time, but there is not much they can do about it&#8230; even the smallest sites have start up times of dozens of seconds.</p>
<h2>Python and module reload</h2>
<p>Plone used to have (has) a helper package called <a href="http://pypi.python.org/pypi/plone.reload">plone.reload</a>. It works by reloading Python modules. Python interpreter allows you to reload a module again in the memory. The code is actually based on <cite>xreload.py</cite> written by Guido van Rossum himself.</p>
<p>However, there is a catch. Naive code reload does not work. <a href="http://svn.python.org/projects/sandbox/trunk/xreload/xreload.py">As xreload.py comments state there are issues</a>. Global stateful objects, other initialization specific code paths, etc. are ignored. So with <em>plone.reload</em> you ended up with a broken Python process as many times you ended up with a successful reload. It&#8217;s so frustrating to use that you don&#8217;t actually want to use it.</p>
<h2>From Finland with Love</h2>
<p>sauna.reload was initially created in <a href="http://opensourcehacker.com/2011/07/25/sauna-sprint-day-1-sunday-technical-motivational/">Sauna Sprint 2011</a> event, arranged by EESTEC and Plone Community. The event name comes from the abundance of sauna in Finland and the package name comes from the fact that a lot of sauna was put into the effort of creating it.</p>
<h2> Going trident</h2>
<p><img title="195771045_cb4ab353f1_o" src="http://opensourcehacker.com/wp-content/uploads/2011/11/195771045_cb4ab353f1_o-300x195.jpg" alt="" width="300" height="195" /></p>
<p>A fork. (<a href="http://www.flickr.com/photos/malinky/195771045/">The orignal image</a>)</p>
<p><a href="http://www.youtube.com/watch?v=ju1Gp2ez-Nc&amp;feature=related"><img title="576247738_5c67399780_o" src="http://opensourcehacker.com/wp-content/uploads/2011/11/576247738_5c67399780_o-300x200.jpg" alt="" width="300" height="200" /></a></p>
<p>A spoon (<a href="http://www.flickr.com/photos/sizima/576247738/">The orignal image</a>)</p>
<p>sauna.reload takes a different strategy of reloading</p>
<p>The idea behind sauna.reload goes back to the days as I was working with Python for Nokia Series 60 phones. Symbian seriously sucks, peace on its memory (though not sure if it&#8217;s dead yet or just a walking corpse). If you did any Symbian development you saw how it could never fly &#8211; such a monster it was.</p>
<p>One of the issues was start-up time of the apps, especially Python start up time. Symbian IO was slow and simple fact to running the application to the point where all <em>imports</em> had been run took several seconds. For all of this time you could just show some happy loading screen for the user. It was very difficult to deliver a Python application which would have acceptable user experience on Symbian.</p>
<p>Far back in the day I chatted with <a href="https://twitter.com/#%21/jlaurila">Jukka Laurila</a> who gave me some tips. Emacs used to have <a href="http://mail.python.org/pipermail/python-dev/2003-May/035727.html">unexec() command</a> which simply dumped the application state to the disk and resumed later. This works nicely if your application is an isolated binary and does not have any references to DLLs, so it doesn&#8217;t work so nicely on any contemporary platform.</p>
<p>On the other hand, Maemo folks had something called <a href="http://pylauncher.garage.maemo.org/">PyLauncher</a>. PyLauncher loaded a daemon to memory and this daemon had Python interpreter and pygtk library loaded. When Python script had to be run, the PyLauncher daemon simply <a href="https://en.wikipedia.org/wiki/Fork_%28operating_system%29">fork()&#8217;ed</a> a new child and this new child inherited already loaded Python interpreter and pygtk for free. Fork() is a copy-on-write operation on modern operating systems.</p>
<p>This gave me a cunning idea.</p>
<h2>Taking a shortcut</h2>
<p>When you develop a web application and you want to reload changes you usually don&#8217;t want to reload the whole stack. In fact, your custom code tends to sit up on the top of the framework stack and unless you are a framework core developers yourself, you never poke into those files.</p>
<p>What if we run Plone initialization process to the point it is just about to load your custom code, freeze the process and then just always go back to this point when we want to load our (changed) code?</p>
<p>Plone process is in fact a series of Python egg loads. Your custom eggs are loaded last.</p>
<h2>With sofware only your imagination is the limit</h2>
<p>So I presented the idea to <a href="https://twitter.com/#%21/datakurre">Asko Soukka</a> and <a href="https://twitter.com/#%21/esamatti">Esa-Matti Suuronen</a> from University of Jyväskylä (one of the largest Plone users in Finland) in Sauna Sprint 2011. If I recall correctly their first reaction was &#8220;wow dude that definitely is not going to work&#8221;.</p>
<p>But at the end of the tunnel was the freedom of Plone web developers &#8211; being released from the chains of Zope start-up times forever. Even if it had turned out sauna.reload was not possible we would have been stranded in the middle of the forest having nothing to do. So the guys decided to give it a crack. All the time they spent to develop sauna.reload would be paid back later with gracious multiplier.</p>
<p>sauna.reload is using <a href="http://pypi.python.org/pypi/watchdog">awesome cross-platform Watchdog Python package to monitor the source code files</a>. Plone is frozen in the start-up process before any custom source code eggs from src/ folder are being loaded. When there is a file-system change event sauna.reload kills the forked child process and reforks a new child from the frozen parent process, effectively continuing the loading from the clean table where none of your source code files were present.</p>
<h2>Going uphill</h2>
<p>San Francisco, where we are hosting Plone Conference 2011 and sprints, is a city of hills. They feel quite steep for a person who comes from a place where maps don&#8217;t have countours.</p>
<p>With Zope 2, the technology the ancients left to us, things were not that straightforward.</p>
<p>ZODB, the database used in Plone, happens in-process for the development instances (single process mode). When you go back to the orignal frozen copy of Plone process you&#8217;ll also travel back in append-only database time.</p>
<p><a href="https://github.com/collective/sauna.reload/blob/master/sauna/reload/db.py">The sauna.reload devs managed to fix this</a>. However this code is prone to ZODB internal changes as happened with Plone 4.1.</p>
<p>Another funky issues were <a href="https://github.com/collective/sauna.reload/blob/master/sauna/reload/monkeypatcher.py">how to monkey-patch Zope loading process early enough</a> and <a href="https://github.com/collective/sauna.reload/blob/master/sauna/reload/fiveconfigure.py">reordering egg loading process so that we hold loading the custom code till very end</a>.</p>
<h2>For The Win</h2>
<p>sauna.reload works on all Python packages which declare <a href="http://plone.org/products/plone/roadmap/247">z3c.autoinclude loading in setup.py</a>. <a href="http://pypi.python.org/pypi/sauna.reload/">Just go and use it</a>. This, of course, is based on the assumption you use an operating system which supports fork() operation and unfortunately Windows is not privileged for this.</p>
<p><a href="http://pypi.python.org/pypi/sauna.reload/0.3.3#osx-special-notes"><strong>Note: OSX users <em>might</em> need to use trunk version of Watchdog until a bug fix is released</strong></a></p>
<p>Your Plone restart time goes down to 1 second from 40 seconds. Also, the restart happens automatically every time you save your files. It works with Grok, Zope component architecture, everything&#8230; ZCML is reloaded too. You should feel an unsurmountable boost in your productivity.</p>
<p>We still have some quirks in sauna.reload. If you try hard enough you rarely might be able to corrupt database. <a href="https://github.com/collective/sauna.reload">We don&#8217;t know how, so keep trying and report your findings pack to GitHub issue tracker</a>.  Also as sauna.reload is meant for the development only you shouldn&#8217;t really worry about breaking  things. We also have an <strong>old</strong> <a href="https://github.com/epeli/sauna.reload/issues">issue tracker</a> which was not migrated to collective &#8211; how one can migrate a issue tracker on Github?</p>
<h2>The Future</h2>
<p>Who knows? Maybe someone gets inspiration of this work and ports it to other Python frameworks.</p>
<p>Our plan is to release a <a href="http://opensourcehacker.com/2011/11/07/plone-ide-the-future-of-plone-development/">Plone developer distribution </a>which comes with sauna.reload and other goodies by default. This way new Plone developers could instantly start hacking their code by just copy-pasting examples and keep hitting refresh.</p>
<p>&nbsp;
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named-python-package-ever/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Javascript &#8211; How to avoid the bad parts</title>
		<link>http://opensourcehacker.com/2011/11/05/javascript-how-to-avoid-the-bad-parts/</link>
		<comments>http://opensourcehacker.com/2011/11/05/javascript-how-to-avoid-the-bad-parts/#comments</comments>
		<pubDate>Sat, 05 Nov 2011 17:37:23 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[crockford]]></category>
		<category><![CDATA[ecmascript5]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[jshint]]></category>
		<category><![CDATA[jslint]]></category>
		<category><![CDATA[requirejs]]></category>
		<category><![CDATA[strict]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1643</guid>
		<description><![CDATA[This is my five minutes lighting talk presentation in Plone Confrence 2011. It&#8217;s a crash course how to write Javascript by following the modern best practices and not in that crappy way when you where still studying web development circa &#8230; <a href="http://opensourcehacker.com/2011/11/05/javascript-how-to-avoid-the-bad-parts/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>This is my five minutes lighting talk presentation in Plone Confrence 2011. It&#8217;s a crash course how to write Javascript by following the modern best practices and not in that crappy way when you where still studying web development circa HTML3.</p>
<p>The presentation was originally aimed for Python developers, but suits for anyone with some programming experience and not much Javascript experience.</p>
<p>Discussed topics include: require.js, ECMAScript 5, strict mode, JSLint, this scoping and bind(), binding event handlers using jQuery</p>
<div id="__ss_10040915" style="width: 425px;"><strong style="display: block; margin: 12px 0 4px;"><a title="Javascript - How to avoid the bad parts" href="http://www.slideshare.net/miohtama/javascript-how-to-avoid-the-bad-parts" target="_blank">Javascript &#8211; How to avoid the bad parts</a></strong> <iframe src="http://www.slideshare.net/slideshow/embed_code/10040915" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" width="425" height="355"></iframe></p>
<div style="padding: 5px 0 12px;">View more <a href="http://www.slideshare.net/" target="_blank">presentations</a> from <a href="http://www.slideshare.net/miohtama" target="_blank">Mikko Ohtamaa</a></div>
</div>
<p>Ps. Always when searching Javascript related information in Google et. al. use <a href="https://developer.mozilla.org/en-US/">MDN</a> (Mozilla Developer Network) prefix as otherwise you&#8217;ll get misinformation and spammy results. E.g. search &#8220;MDN javascript bind&#8221; instead of &#8220;javascript bind&#8221;.</p>
<p>Pps. Put w3cschool.com domain on the black list in your search engine. It&#8217;s <em>bad</em>.</p>
<p>Ppps. <a href="http://opensourcehacker.com/wp-content/uploads/2011/11/JS-Lighting-talk.pdf">PDF is available here</a>.
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/11/05/javascript-how-to-avoid-the-bad-parts/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
		<item>
		<title>How does it do a date picker widget?</title>
		<link>http://opensourcehacker.com/2011/10/30/how-does-it-do-a-date-picker-widget/</link>
		<comments>http://opensourcehacker.com/2011/10/30/how-does-it-do-a-date-picker-widget/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 20:39:05 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[chuck norris]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[joomla]]></category>
		<category><![CDATA[phat]]></category>
		<category><![CDATA[pointy haired boss]]></category>
		<category><![CDATA[software quality]]></category>
		<category><![CDATA[web development]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1630</guid>
		<description><![CDATA[Python folks love frameworks. They put framework in your framework so that you can create a framework. A friend of mine was involved yet another of these framework ventures and was seriously excited when he was trying to explain to &#8230; <a href="http://opensourcehacker.com/2011/10/30/how-does-it-do-a-date-picker-widget/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Python folks love frameworks. They put framework in your framework so that you can create a framework. A friend of mine was involved yet another of these framework ventures and was seriously excited when he was trying to explain to me how good the new web framework was and what problems it solves.</p>
<p>This blog post is a long flow of mind try to pinpoint how to define if a framework is helpful for you or not. Though I use a Python framework as an example these thoughts can be applied for any programming language, framework, CMS, etc. out there. I&#8217;d be especially interest how Joomla!, Drupal etc. popular PHP platforms solve problems mentioned here.</p>
<p>The framework in the discussion was towards high level of web development, contentish things. To make tailored CMS, and stuff. This framework was on higher level than Pyramid, little bit higher than Django. It is named after an egyptian god and because Egyptian gods have difficult names spelled with symbols, my Finnish mind already lost it.</p>
<p>So the friend of mine was trying to convince me about the need and superiority of this new frame and asked the question: “Do you like it?”</p>
<p>And I answered: “Does it help me to get my work done?”</p>
<p>My question was the right question, but wrong in so many ways. We were discussing about the same thing, but from different viewpoints…. and in this point, the discussion got off the rail. My friend tried to justify the existence of the new framework and I was trying to help him understand what kind of needs I hope a framework would solve for me.</p>
<p>As we put a lot of energy in seemingly fruitless conversation, I become sad. This discussion and thoughts about it keep me awake during the night and I tried to come up a simple way to measure the usefulness of a high level web framework.</p>
<p>Now I have a new question, which in the end is the same question as above, but more communicative. This question was inspired by <a href="http://www.youtube.com/watch?v=HrFpqmgv2DY">Douglas Crockford’s talk about Javascript metaperformance</a> and especially the part where he tells that there are a lot of smart people doing web &#8211; sometimes they focus on wrong things, but  if you give them a proper target to shoot at they can get amazing things done.</p>
<p>Next time, when someones needs my opinion about a web framework, I&#8217;ll ask “How does it do a date picker widget?”</p>
<h2><a href="http://en.wikipedia.org/wiki/Modern_Times_%28film%29">Modern Times</a></h2>
<p>To see how my little question works you need to dive into the history of web development a bit.  The web user interaction is much about forms. The forms have input fields and these input fields are wrapped into user interact-able widgets which have additional properties besides simply handling punching of keyboard keys: input validation, typing auto completion, mouse interaction, nice bling bling decoration and effects  and so on… especially when creating things like CMS where the users are expected to input stuff through the browser you need to pay careful attention for the user interaction details.</p>
<p>The purpose of a software development framework is to make the life of a software developer simple and <em>get the thing done</em>.  Because web is much about forms a lot of effort has been put to make form development simple. My question could have been a less form specific; I chose a date picker because it is familiar and everyone has come across one e.g. when booking flight tickets. Thus we should have quite unified idea what we are discussing about. The date picker also tends to be one of the most complex form widgets available in your toolbox, so were are not setting the bar too low here.</p>
<h2><a href="http://www.imdb.com/title/tt0070849/">Last Tango in Paris</a></h2>
<p>Web itself was not originally designed to have or to do rich widgets for easy user interaction. We have a HTML mark-up language which tries to separate content from the presentation. We have a layout language, CSS,  which tries to separate layout from the content, but in the end fails doing so. Then we have a Javascript programming language which pulls strings in your web browser to make HTML and CSS co-operate and  do the widgets using Document Object Model. A model, which was not designed Javascript programing language in mind.</p>
<p>(sidenote: on the day I see bbc.co.uk level site delivering both web and mobile version from the same HTML code  just using different CSS stylesheets I can say that CSS actually delivers it promise to separate the layout from the content)</p>
<p>Now is now and web is steering more and more to the direction where it can do more <em>for</em> the user… or the interaction is more efficient because of richer controls and paradigms, enabled by Javascript and HTML5, can be applied to solve the same old problems. In this world if you do a modern web framework for and expect it to remain on the isolation on the server-side from all the gory details of Javascript and CSS you are doing it wrong.</p>
<p>Doing a web widget is like a dance of several participants who need to co-ordinate their actions so that the individual performances are in harmony and the actors are not stepping on each other toes. A web framework is like premade step guide telling you how to execute your dance. The result is magnificent performance of  0.5 seconds of your site visitor time when he or she subconsciously picks a date in the web form by clickety-clicky, or as on the mobile era, by thumbity-thumbly.</p>
<h2><a href="http://www.imdb.com/title/tt0087727/">Missing in Action</a></h2>
<p>Now, I could have asked “Does it do a date picker widget?” The answer would probably be “yes”, as of course you can put a date picker widget on every HTML page out there. Then I could asked “how?” and then the answer would be something like:</p>
<ul>
<li>Download your favorite Javascript widget library (e.g. JQuery UI)</li>
<li>Toss CSS files somewhere, Javascript files somewhere in your project</li>
<li>Edit your  main template &lt;head&gt; to have these files included &#8211; if you are smart include them only on the pages where the user interaction is actually needed</li>
<li>Bootstrap &lt;input&gt; fields doing date picking using a CSS class markers or similar markers in the source code somewhere, or have a bootstrap JS running by &lt;input&gt; ids</li>
<li>Convert between Javascript widget framework date model and your web framework date model in somewhere of the form layers</li>
<li>etc. etc.</li>
</ul>
<p>This is what I call a blunt approach. It&#8217;s solving the problem of dancing like this:</p>
<p><iframe src="http://www.youtube.com/embed/2bS9DFXw4WA" frameborder="0" width="420" height="315"></iframe></p>
<p>This all is tolerable if you do it once for your web appy. But what about if you need different widgets on the page too? How about checkbox groups with internal dependencies? Time picker?  Yoyo? Again you need to toss files somewhere, edit head, etc.</p>
<p>When your web application grows this all quickly leads to a mess where you have tens of different files included in the main template. Different modules start to clash with their CSS classes and you need to start resolving the issues by your own hand written CSS overrides. Suddenly the page load times are through the roof, because you are doing too many HTTP requests per page. You need to start thinking about the cache. You need to think about merging static media files. Which leads you to think solving dependency orders between media files.</p>
<p>Does the framework help you solve the problems like above to get the thing done?</p>
<h2><a href="http://www.imdb.com/title/tt0125439/">Notting HIll</a></h2>
<p>I studied industrial engineering and management in University of Oulu (<a href="http://en.wikipedia.org/wiki/Internet_Relay_Chat#History">home of IRC</a> &#8211; never forget to mention this when I have a chance).  We had a course called Quality which was about quality. You can study subjects like this from very broad perspective especially if your plan is to become <a href="https://en.wikipedia.org/wiki/Pointy-haired_Boss">a pointy haired boss</a> who doesn’t know crap about what he or she is doing.</p>
<p>The definition of quality is simple. Quality is not the same thing as high value brand (e.g. Mercedes Benz). Quality is not the same thing as faultiness (no bugs in the delivered software). Quality is about whether the customer is satisfied what he or she gets.</p>
<p>The customer of a software framework is a developer. What the developer is buying is a tool to make delivering software more easy &#8211; to get the thing done by the end of the day.</p>
<p>My friend was telling how high test coverage the framework has. This is a nice trait for a framework. Higher the test coverage, the less  bugs you are likely to encounter. Essentially this is faultiness.</p>
<p>Now a bad, but thoughtful, analogue: in industrial engineering faultiness comes with a price. On your production line you’ll pay a high cost of 100% faultiness products. You usually want to do testing by sampling and simply let few bad products slip through instead of having the high cost of testing every single manufactured item. In the end, the testing cost of the product is away from the other areas of product development and manufacturing (features, delivery options, etc.)</p>
<p>Faultiness is important, but it does not make high quality software framework alone. Inspired by <a href="http://tech.slashdot.org/comments.pl?sid=2473136&amp;cid=37695990">the leaked rant of Steve Yegge</a> if you dial test coverage 100% but have no accessibility you have no product.</p>
<p>Which brings me to the punch line of software framework quality: accessibility. To enable developers get the thing done with the framework it must have documentation telling how you get the thing done.</p>
<p>Django folks get it. Django has always had very detailed documentation and no surprise it won the most of the hearts of Python developers back in 2006ish when the framework situation was different with Turbogears et. al. being still in their strength.  Anti examples would be packages <a href="http://pypi.python.org/pypi/z3c.form">z3c.form</a> or <a href="http://pypi.python.org/pypi/plone.portlets">plone.portlets</a> (<a href="http://www.xkcd.com/221/">chosen by a fair dice roll &#8211; guaranteed to be random</a>). Both the packages are frameworkish and have near perfect test coverage. Too bad it seems that only 0.0001% of people are smart enough to use these packages and mostly get frustrated whilst trying to get the thing done.</p>
<p>(sidenote: even though z3c.form has plentiful documentation does not primarily address the needs of the framework users)</p>
<h2><a href="http://www.imdb.com/title/tt0066995/">Diamonds are forever</a></h2>
<p>Another trait of quality is that it must be measurable.  The absolute measurement of the quality is the customer satisfaction: how happy people are with your product. However the level of satisfaction is difficult to measure directly. Indirect, easy numbers, are measured instead.</p>
<p>One easy quality measurement  is that you go around and ask random users whether they are happy with the framework. If you do not know any of these developers users yet you can simply follow the chat on a related IRC channel:  friendlier atmosphere usually correlates with happiness which correlates with quality.</p>
<p>But being an engineer I hope we could use something more tangible than random chat around a pint or two.</p>
<p>The most important indirect number of your framework quality could be API documentation coverage. How many of the functions of your API have sane helpful documentation or documentation in the first place? As this number  translates to how easily people can pick up your framework and simply read how to get things done with it. <a href="http://opensourcehacker.com/2011/03/29/when-python-sucks-how-you-call-a-function-and-document-it/">Especially with Python a good API documentation (parameters in, results out) is important because Python has poor statistical code analysis or auto-completion support, something  what Java and C# IDEs enjoy</a>.</p>
<h2><a href="http://en.wikipedia.org/wiki/I_Am_Legend_%28film%29">I Am Legend</a></h2>
<p>The another nice thing you can learn about the quality on the university courses is that less numbers you need express the quality of your product the better. It’s over simplifying of things to say how good or bad your product ultimately is. Your pointy haired boss might be able to process few percent scale numbers a day, but less he needs to think anything besides golf, the better. You suggest a new framework to be used for the new software project and the boss takes a decision if it’s good or not, essentially the boolean value or quality. On the rare day the PHB is on his/her brightest the PHB might think one step forward and ask why the framework is any good and then you can answer that the goodness has been tested with the scientific method found from a random blog in the internets.</p>
<p>.. and to shine at the very end of quality simplification spectrum I came up with the following objective decision tree to measure the quality of a web framework:</p>
<p>Is a web framework, CMS, tool etc. any good for modern development needs? <span style="text-decoration: underline;"><em>Yes</em> / <em>No</em></span></p>
<p>Yes if…</p>
<ul>
<li>You take one average developer, like me, who has wide general programming experience, but not yet insight how the framework works (don’t pick any super smart guy like the framework developer itself might be).</li>
<li>You give the developer four hours of time (I am generous about my time today), a hello world style tutorial and API reference manual.</li>
<li>The developer is able to create a simple form / content type / page  containing a date picker widget with some customizations like template changes or non-default options. The customizations are important because that’s what you eventually will do &#8211; you won&#8217;t be mass producing hello world applications from the conveyor belt with the framework.</li>
<li>The resulting Javascript and CSS widget bindings to HTML are handled in maintainable manner and media files are merged, compressed and HTTP cache headers are set  properly.</li>
</ul>
<p>…else no.</p>
<p>This is just a litmus test. It doesn’t necessary tell how good a framework is, but if the test fails then it might be a sign that the framework is either not a developer friendly or is not solving the needs of modern web frameworks. The most possible failure mode is that there are no API documentation at all -  which means that the project is not disciplined to communicate what problems the framework should be solving in the first place and is worth as much as any random bunch of code you can find from the open source archives.</p>
<p>Also, this blog post is just <a href="http://www.youtube.com/watch?v=bplEuBjppTw">guidelining</a>: no need to nitpick the details unless they advance the humankind somehow. As mentioned before, the blog post tries to give a good target to shoot at and highlights what kind of facts you might need to communicate out to success as a software development framework. Please feel free to challenge me, but as far as I am aware, <em>none</em> of current web frameworks or CMSs passes this test.</p>
<p>Finally, how the proper dance of HTML, CSS and Javascript should look like, Chuck Norris style:
<iframe src="http://www.youtube.com/embed/TYHZEu7Y7DU" frameborder="0" width="420" height="315"></iframe>
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/10/30/how-does-it-do-a-date-picker-widget/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>PyCon Finland live streams running</title>
		<link>http://opensourcehacker.com/2011/10/17/pycon-finland-live-streams-running/</link>
		<comments>http://opensourcehacker.com/2011/10/17/pycon-finland-live-streams-running/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 07:11:25 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[cpython]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[scalability]]></category>
		<category><![CDATA[spotify]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1612</guid>
		<description><![CDATA[Here, today! Track 1, auditorium Lambda 9:45 Opening notes 10:00 “from __magic__ import wtf” by Tommie Gannert from Spotify 11:00 “Replacing Spreadsheets with Django” by Teemu Kurppa from Huikea Experience 12:00 Lunch 13:00 “High-Performance Computing with Python” by Jussi Enkovaara &#8230; <a href="http://opensourcehacker.com/2011/10/17/pycon-finland-live-streams-running/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://fi.pycon.org/2011/stream1.html">Here,</a> today!</p>
<p><strong>Track 1, auditorium Lambda</strong>
9:45 Opening notes
10:00 “from __magic__ import wtf” by Tommie Gannert from Spotify
11:00 “Replacing Spreadsheets with Django” by Teemu Kurppa from Huikea Experience
12:00 Lunch
13:00 “High-Performance Computing with Python” by Jussi Enkovaara from CSC
14:00 “Understanding Encodings” by Ezio Melotti, a CPython core developer
15:00 Lightning talks
16:00 Keynote by Mike Bradshaw
Closing notes</p>
<p><strong>Track 2, classroom B2033</strong>
11:00 “Python for Data Science” by Harri Hämäläinen, a semantic data scientist
12:00 Lunch
13:00 “Building Your Own Cloud” by Andy Smith from OpenStack
14:00 “Non-blocking QA” by Anthony Long
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/10/17/pycon-finland-live-streams-running/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Top level domains .py and .js</title>
		<link>http://opensourcehacker.com/2011/09/22/top-level-domains-py-and-js/</link>
		<comments>http://opensourcehacker.com/2011/09/22/top-level-domains-py-and-js/#comments</comments>
		<pubDate>Thu, 22 Sep 2011 07:48:07 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[gtld]]></category>
		<category><![CDATA[icann]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[such-a-great-idea]]></category>
		<category><![CDATA[top level domain]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1589</guid>
		<description><![CDATA[Now when ICANN has freed the top level domain names for the allocation I hope we could register .py and .js domains for the open source framework uses. They already have io. We just need a sponsor organization and some &#8230; <a href="http://opensourcehacker.com/2011/09/22/top-level-domains-py-and-js/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Now when <a href="http://www.icann.org/en/announcements/announcement-4-19sep11-en.htm">ICANN has freed the top level domain names</a> for the allocation I hope we could register <em>.py</em> and <em>.js</em> domains for the open source framework uses. They already have <a href="http://io">io</a>.</p>
<p>We just need a sponsor organization and <a href="http://newgtlds.icann.org/applicants/faqs/faqs-en">some 200 000 USD for the evaluation fee</a>.</p>
<p>Anyone?</p>
<p>I know you want __init__.py (<a href="http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names">though underscore is not an allowed character in home name</a>).</p>
<p>(thanks for Petri for the orignal idea)
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/09/22/top-level-domains-py-and-js/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Fix Linux filename encodings with Python</title>
		<link>http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/</link>
		<comments>http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 10:22:09 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[accents]]></category>
		<category><![CDATA[decoding]]></category>
		<category><![CDATA[encoding]]></category>
		<category><![CDATA[finnish]]></category>
		<category><![CDATA[latin-1]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[path]]></category>
		<category><![CDATA[red hat]]></category>
		<category><![CDATA[subversion]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[unicode]]></category>
		<category><![CDATA[utf-8]]></category>
		<category><![CDATA[windows]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1551</guid>
		<description><![CDATA[We recently deployed a web based system to old Red Hat installation still using latin-1 as primary encoding for its filesystem. This caused headscratching as we were using Ubuntu during the development which uses UTF-8 encoding for filenames. Files were &#8230; <a href="http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>We recently deployed a web based system to old Red Hat installation still using <a href="http://en.wikipedia.org/wiki/Latin-1">latin-1</a> as primary encoding for its filesystem. This caused headscratching as we were using Ubuntu during the development which uses <a href="http://en.wikipedia.org/wiki/Utf-8">UTF-8</a> encoding for filenames. Files were copied to the production server using rsync. When <em>ls</em> command was used in a terminal everything seemed be fine, because terminal itself was configured to UTF-8 and thus decoded the filenames when outputted to the terminal. However the web server was unable to serve images containing Finnish ä and ö characters in filenames.</p>
<p>After the headscratching was over we had figured out that renaming filenames to use latin-1 encoding makes the web server serve them fine. If it were a fresh start I&#8217;d rather configure the server itself to use now prevailent UTF-8, but because the infrastructure was shared with other, older, projects this was out of the question.</p>
<p>Thus, the script below was created to address the filename encoding problem (<a href="http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/">syntax highlighting available on the orignal publication</a>):</p>
<pre class="prettyprint lang-py">#!/usr/bin/python
"""

    Recursively fix filename encoding problems

    http://www.opensourcehacker.com, MIT licensed

"""

import os

# Source filename encoding
FROM="utf-8"

# Target filename encoding
TO="latin-1"

# Current working directory
PATH=os.getcwd()

for root, dirs, files in os.walk(PATH):

    # Assume files are 8-bit strings in the native encoding
    # of the system which we cannot know
    for f in files:
        try:
            decoded = f.decode(FROM)
        except UnicodeDecodeError:
            print "Cannot decode:" + f
            continue

        fullpath = os.path.join(root, f)

        newpath = os.path.join(root, decoded.encode(TO))

        if newpath != fullpath:
            print "Renaming:" + fullpath + " to:" + newpath
            os.rename(fullpath, newpath)</pre>
<p>I still don&#8217;t know how to verify / check / guess which encoding Linux file systems are using (if not UTF-8&#8230;), so someone please enlight me. In this case we learnt this by a smart guess and testing: we created two filenames, one name encoded with UTF-8 and one encoded with Latin-1 and see which file the web server was giving for us. I am also unsure whether the fact that files were orignally kept in Subversion repository and committed there from Windows had anything to do with the problem.
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/09/16/fix-linux-filename-encodings-with-python/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>3 reasons why you should send your corporate representative to PyCon (Finland)</title>
		<link>http://opensourcehacker.com/2011/09/15/3-reasons-why-you-should-send-your-corporate-representative-to-pycon-finland/</link>
		<comments>http://opensourcehacker.com/2011/09/15/3-reasons-why-you-should-send-your-corporate-representative-to-pycon-finland/#comments</comments>
		<pubDate>Thu, 15 Sep 2011 14:07:46 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[finland]]></category>
		<category><![CDATA[hire]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[pycon]]></category>
		<category><![CDATA[recruit]]></category>
		<category><![CDATA[spotify]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1545</guid>
		<description><![CDATA[PyCon is a network of conferences around the globe related to Python programming language and technologies. PyCon Finland is now arranged for the second time (two weeks to the registration deadline!) I am writing this blog post in hope to &#8230; <a href="http://opensourcehacker.com/2011/09/15/3-reasons-why-you-should-send-your-corporate-representative-to-pycon-finland/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://pycon.org">PyCon</a> is a network of conferences around the globe related to Python programming language and technologies. <a href="http://fi.pycon.org">PyCon Finland</a> is now arranged for the second time <strong>(two weeks to the registration deadline!)</strong> I am writing this blog post in hope to encourage and inspire companies and organizations to participate in this wonderful event and also see the business benefits of doing so. As a disclaimer I am one of the event organizers and thus this post is also a non-paid advertisement of the event.</p>
<h1>1. For constant innovation choose Python</h1>
<p>To stay competitive it&#8217;s not enough for you to do the same thing as yesterday. It&#8217;s a deceivingly comfortable choice: no one has been fired for doing the same choices as done on the year before. But we have learn something dearly in Finland: the comfortability of no change comes with a terrible price. You&#8217;ll soon follow the fate of 00s mobile operating system: when you keep clinging on the old way the competitors will soon show the better way.</p>
<p>Python has proven its reputation as an agile technology platform. How about doing a small or medium sized project with Python instead of using (too) heavy enterprise tools? Think about if you could get all the time saved back in your next annual bonus? Here is a good related essay &#8220;<a href="http://www.paulgraham.com/avg.html">Beating the Averages</a>&#8221; from Paul Graham.</p>
<p>PyCon is the best place to see and learn the latest secret weapons Python has to offer. Many of open souce hackers, who write the development tools, are present in person. For example, in PyCon Finland we have Andy Smith from Rackspace (cloooouds). Be at the event and pump all the knowledge out of the brains of the masterminds.</p>
<h1>2. Be global, act local</h1>
<p><a href="http://www.spotify.com">Spotify</a> will be present with a considerable delegation. For those who live in a barrel (no offense US) Spotify is (was?) a real hot Swedish start-up which seeks to dethrone iTunes in the game of global digital music consumption.</p>
<p>Besides Spotify from Sweden, we have plenty of other international guests. The window of new opportunities is open when organizations having similar competency background meet (read: Python). I have been personally participating in ventures which started as  chit-chat in a conference and later developed into full blown businesses just because people and companies with the same mindset where given a chance.</p>
<p>SMEs might have developed technologies for which they seek new channels of marketing. A trending website might need a new localization. You can find new clients for whom to subcontract your Python talent.. or anything in between. When you are dealing with international people already familiar with the core technology you have much more trust for being able to work together. There is no fear of conflict of interest as market area geographies are isolated (especially true in EU).</p>
<p>3. <a href="http://www.imdb.com/title/tt0096913/">Best of the best</a></p>
<p>I have heard rumors that there is a shortage of Python programmers in Finland to hire. There exists a simple explanation: The Python programmers are the best programmers out there and thus they already have the best jobs.</p>
<p>PyCon Finland is <em>the</em> place to meet Python programmers as they have been nicely gathered into one place for you to pick. This is your once in a year chance to verify the fact whether all the best programmers are already hired. (note: if you manage to disprove me I am not offering beer prize or anything)</p>
<p>&nbsp;</p>
<p>&nbsp;
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/09/15/3-reasons-why-you-should-send-your-corporate-representative-to-pycon-finland/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generating Apache redirects from sitemap.xml for WordPress using Python</title>
		<link>http://opensourcehacker.com/2011/09/10/generating-apache-redirects-from-sitemap-xml-for-wordpress-using-python/</link>
		<comments>http://opensourcehacker.com/2011/09/10/generating-apache-redirects-from-sitemap-xml-for-wordpress-using-python/#comments</comments>
		<pubDate>Fri, 09 Sep 2011 23:22:58 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[export]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[import]]></category>
		<category><![CDATA[lxml]]></category>
		<category><![CDATA[migration]]></category>
		<category><![CDATA[moved permanently]]></category>
		<category><![CDATA[redirect]]></category>
		<category><![CDATA[requests]]></category>
		<category><![CDATA[seo]]></category>
		<category><![CDATA[sitemap]]></category>
		<category><![CDATA[sitemap.xml]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://opensourcehacker.com/?p=1541</guid>
		<description><![CDATA[Sitemap.xml (Sitemaps) is a protocol exposing website pages for the search engines. Beyond hinting crawler bots you can find some creative uses for it. I was migrating blog posts from one WordPress site to another. I wanted to have the &#8230; <a href="http://opensourcehacker.com/2011/09/10/generating-apache-redirects-from-sitemap-xml-for-wordpress-using-python/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><a href="http://en.wikipedia.org/wiki/Sitemaps">Sitemap.xml (Sitemaps)</a> is a protocol exposing website pages for the search engines. Beyond hinting crawler bots you can find some creative uses for it.</p>
<p>I was migrating blog posts from <a href="http://mobilizejs.com">one WordPress site</a> to <a href="http://opensourcehacker.com">another</a>. I wanted to have the old site still run the front page and few other static pages and I wanted to move the blog posts only. A best practice for content migrations is set HTTP 301 Moved Permantently redirects on the orignal web server so that users and search engines following old links will automatically find the new content.</p>
<p>WordPress sites were and are hosted on Apache web server. Since writing Apache .htaccess redirects by hand is something no living soul wants to do, I wrote a little Python script using <a href="http://pypi.python.org/pypi/requests">Requests</a> (a.k.a. urllib done right) and <a href="http://pypi.python.org/pypi/lxml">lxml</a> libraries.</p>
<p>This script will</p>
<ul>
<li>Read sitemap.xml.gz file</li>
<li>Extract page URLs out of it</li>
<li>(add optional filtering step here)</li>
<li>Output Apache .htaccess redirect rules so that old links will point to the new site</li>
</ul>
<p>The beauty of scraping the information from sitemap.xml: Even though this script was written for WordPress it is valid for any CMS supporting Sitemaps protocol. (hint: <a href="http://plone.org">Plone</a>, Drupal, Joomla!, you name it.. they all support it)</p>
<p>In theory one could run this script in cron so that all new WordPress content gets automatically redirected continuously.</p>
<p>In additional for setting up .htaccess WordPress provides easy export and import tool for blog posts through its admin interface.</p>
<p>And the script:</p>
<pre># Python stdlib
from StringIO import StringIO
import urlparse

# 3rd party
import requests
from lxml import etree

# Sitemap of the source site
SITEMAP_URL = "http://mobilizejs.com/wp-content/plugins/simple-google-sitemap-xml/sitemap.xml"

# Where posts will be moved
NEW_DOMAIN="http://opensourcehacker.com"

# Apache .htaccess line template
# http://httpd.apache.org/docs/2.0/mod/mod_alias.html#redirectmatch
REDIRECT_TEMPLATE="RedirectMatch permanent %(path)s$ %(new_domain)s%(path)s"

response = requests.get(SITEMAP_URL)

def create_apache_redirect_to_other_domain(url, new_domain):
    """
    Creates .htaccess redirect entry.

    Create HTTP 301 Permanent Redirect.

    Output is something along lines::

        RedirectMatch permanent /tag/cache-control/$ http://opensourcehacker.com/tag/cache-control/

    """
    parts = urlparse.urlparse(url)

    vars = {
        "new_domain" : new_domain,
        "path" : parts.path          
    }    

    # Simple Python string template substituion
    return REDIRECT_TEMPLATE % vars

# Parse sitemap
tree = etree.parse(StringIO(response.content))
root = tree.getroot()

locs = root.xpath("//*[name()='loc']")

# Iterate through each sitemap &lt;loc&gt; entry and creating corresponding redirect
for loc in locs:
    url = loc.text
    redirect_line = create_apache_redirect_to_other_domain(url, NEW_DOMAIN)
    print redirect_line</pre>
<p>&nbsp;
<p class="signature">
 <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="border:0"/></a> <a href="http://feeds.feedburner.com/OpenSourceHacker" rel="alternate" type="application/rss+xml">Subscribe to this blog in a reader</a> <a href="http://twitter.com/moo9000"> <img valign="middle"  style="border:0" src="http://opensourcehacker.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a> </p>
]]></content:encoded>
			<wfw:commentRss>http://opensourcehacker.com/2011/09/10/generating-apache-redirects-from-sitemap-xml-for-wordpress-using-python/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

