<?xml version="1.0" encoding="ISO-8859-1" standalone="no"?>
<rss version="2.0">
 <channel>
  <title>Richard Jones' Log</title>
  <link>http://www.mechanicalcat.net/richard/log</link>
  <description>Richard Jones' Log</description>
  <managingEditor>richard@mechanicalcat.net (Richard Jones)</managingEditor>
  <language>en</language>
  
  <item>
   <title>A simple asyncore "echo server" example</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/A_simple_asyncore__echo_server__example</guid>
   <pubDate>Mon, 15 Mar 2010 22:15:30 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/A_simple_asyncore__echo_server__example</link>
   <description>&lt;p&gt;Tonight I wanted a simple &lt;a href="http://docs.python.org/library/asyncore.html"&gt;asyncore&lt;/a&gt; echo server example for my lecture notes and couldn't immediately find one. Doug Helman has a more complex one in his &lt;a href="http://www.doughellmann.com/PyMOTW/asyncore/"&gt;asyncore Module Of The Week&lt;/a&gt; post, but I wanted Just The Basics. So I read up a little and wrote one :-)&lt;/p&gt;

&lt;p&gt;First the server:&lt;/p&gt;
&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="
n"&gt;dispatcher&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;.&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_accept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="c"&gt;# when we get a client connection start a dispatcher for that&lt;/span&gt;
        &lt;span class="c"&gt;# client&lt;/span&gt;
        &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;accept&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Connection by&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;address&lt;/span&gt;
        &lt;span class="n"&gt;EchoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;EchoHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span cl ass="n"&gt;dispatcher_with_send&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="c"&gt;# dispatcher_with_send extends the basic dispatcher to have an output&lt;/span&gt;
    &lt;span class="c"&gt;# buffer that it writes whenever there&amp;#39;s content&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out_buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;.&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out_buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Server&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5007&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;And the client:&lt;/p&gt;
&lt;div class="highlight-python"&gt;&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;socket&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatcher_with_send&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dispatcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create_socket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AF_INET&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;socket&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SOCK_STREAM&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;out_buffer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;print&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Received&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#39;&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;5007&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#39;Hello, world&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;asyncore&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;When run the server should display:&lt;/p&gt;
&lt;div class="highlight-python"&gt;&lt;pre&gt;Connected by ('127.0.0.1', 56757)&lt;/pre&gt;
&lt;/div&gt;&lt;p&gt;(or similar - the port number will vary) and the client should display:&lt;/p&gt;
&lt;div class="highlight-python"&gt;&lt;pre&gt;Received 'Hello, world'&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;It was actually pretty easy to write, and kinda fun.&lt;/p&gt;
</description>
  </item>


  <item>
   <title>10th Python Game Programming Challenge in three weeks</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/10th_Python_Game_Programming_Challenge_in_three_weeks</guid>
   <pubDate>Fri, 05 Mar 2010 19:47:16 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/10th_Python_Game_Programming_Challenge_in_three_weeks</link>
   <description>&lt;a href="http://www.pyweek.org/"&gt;&lt;img border="0" src="http://media.pyweek.org/static/pyweek.png"&gt;&lt;/a&gt;
&lt;p&gt;The &lt;a href="http://www.pyweek.org/10/"&gt;10th Python Game Programming Challenge (PyWeek)&lt;/a&gt; is coming. It'll run from the 28th of March to the 4th of April.&lt;/p&gt;
&lt;p&gt;The PyWeek challenge:&lt;/p&gt; 
&lt;ol&gt; 
&lt;li&gt;Invites entrants to write a game in one week from scratch
  either as an individual or in a team,&lt;/li&gt; 
&lt;li&gt;Is intended to be challenging and fun,&lt;/li&gt; 
&lt;li&gt;Will hopefully increase the public body of game tools, code and
    expertise,&lt;/li&gt; 
&lt;li&gt;Will let a lot of people actually finish a game, and&lt;/li&gt; 
&lt;li&gt;May inspire new projects (with ready made teams!)&lt;/li&gt; 
&lt;/ol&gt; 
&lt;p&gt;In honor of the 10th challenge I've finally brought the website out of the 80s :-) ...&lt;/p&gt;
&lt;table border="0"&gt;
&lt;tr&gt;&lt;th&gt;Before&lt;/th&gt;&lt;th&gt;After&lt;/th&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;img src="http://www.mechanicalcat.net/images/pyweek-before.png"&lt;/td&gt;
&lt;td&gt;&lt;img src="http://www.mechanicalcat.net/images/pyweek-after.png"&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</description>
  </item>


  <item>
   <title>Melbourne Python Users Group</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Melbourne_Python_Users_Group</guid>
   <pubDate>Mon, 22 Feb 2010 15:09:28 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Melbourne_Python_Users_Group</link>
   <description>&lt;p&gt;The next meeting of the Melbourne Python Users Group (MPUG) will be next week, Monday the 1st of March at 6:30PM at Horse Bazaar.&lt;/p&gt;
&lt;p&gt;Full info on the meeting including directions and talks at the &lt;a href="http://wiki.python.org/moin/MelbournePUG"&gt;MPUG wiki page&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;See you there!&lt;/p&gt;</description>
  </item>


  <item>
   <title>PyWeek 10 (10!) is coming</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/PyWeek_10__10___is_coming</guid>
   <pubDate>Fri, 05 Feb 2010 11:08:25 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/PyWeek_10__10___is_coming</link>
   <description>&lt;a href="http://www.pyweek.org/"&gt;&lt;img border="0" src="http://media.pyweek.org/static/pyweek.png"&gt;&lt;/a&gt;
&lt;p&gt;The &lt;a href="http://www.pyweek.org/10/"&gt;10th Python Game Programming Challenge (PyWeek)&lt;/a&gt; is coming. It'll run from the 28th of March to the 4th of April.&lt;/p&gt;
&lt;p&gt;The PyWeek challenge:&lt;/p&gt; 
&lt;ol&gt; 
&lt;li&gt;Invites entrants to write a game in one week from scratch
  either as an individual or in a team,&lt;/li&gt; 
&lt;li&gt;Is intended to be challenging and fun,&lt;/li&gt; 
&lt;li&gt;Will hopefully increase the public body of game tools, code and
    expertise,&lt;/li&gt; 
&lt;li&gt;Will let a lot of people actually finish a game, and&lt;/li&gt; 
&lt;li&gt;May inspire new projects (with ready made teams!)&lt;/li&gt; 
&lt;/ol&gt; 
&lt;p&gt;If you've never written a game before and would like to try things out then perhaps you could try either:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The tutorial I presented at LCA 2010, &lt;a href="http://www.lca2010.org.nz/wiki/Tutorials/Introduction_to_game_programming"&gt;Introduction to Game Programming&lt;/a&gt;, or&lt;/li&gt;
&lt;li&gt;The book &lt;a href="http://inventwithpython.com/"&gt;Invent Your Own Computer Games With Python&lt;/a&gt;&lt;/li&gt; &lt;/ol&gt;</description>
  </item>


  <item>
   <title>Linux.Conf.Au 2010 is done</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Linux_Conf_Au_2010_is_done</guid>
   <pubDate>Sun, 24 Jan 2010 09:31:20 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Linux_Conf_Au_2010_is_done</link>
   <description>&lt;p&gt;What a week. Unlike other week-long conferences I've been to this one had talks every day. Combined with the usual events every night I'm quite tired now :)&lt;/p&gt;
&lt;p&gt;I gave two presentations: a &lt;a href="http://www.slideshare.net/r1chardj0n3s/state-of-python-2010"&gt;State of Python&lt;/a&gt; talk which was a little rambling but otherwise well-received.&lt;/p&gt;
&lt;p&gt;I did the &lt;a href="http://www.twitvid.com/1DCFD"&gt;haka&lt;/a&gt;. Much fun!&lt;/p&gt;
&lt;p&gt;Even better-received was my tutorial &lt;a href="http://www.lca2010.org.nz/wiki/Tutorials/Introduction_to_game_programming"&gt;Introduction to Game Programming&lt;/a&gt; which was attended by both programmers and non-programmers. &lt;a href="http://pipka.org/blog/2010/01/20/linux-conf-au-2010-–-day-3-freedom-games-bruce-campbell/"&gt;Pia Waugh&lt;/a&gt; and &lt;a href="http://bit.ly/92yFkh"&gt;Pamela Fox&lt;/a&gt;*  both have good writeups. A couple of the attendees have come to me afterwards to say again how they enjoyed the tutorial and are continuing to develop their games. Quite a good outcome, I think!&lt;/p&gt;
&lt;a style="float: right; margin-left: 10px;" href="http://www.flickr.com/photos/richard_jones/4290626341/"&gt;&lt;img src="http://farm3.static.flickr.com/2771/4290626341_0e4cbf12d9_t_d.jpg"&gt;&lt;/a&gt;
&lt;p&gt;On Wednesday night I got my solderin' on and put together a &lt;a href="http://www.flickr.com/photos/richard_jones/4290626341/"&gt;Pebble board for my Arduino&lt;/a&gt;. It's a neat invention of &lt;a href="http://twitter.com/lukeweston"&gt;Luke Weston&lt;/a&gt; and the builds were made possible by the folk from the &lt;a href="http://hackmelbourne.org/"&gt;Melbourne Connected Community HackerSpace&lt;/a&gt;.
&lt;p&gt;During the week I set up the &lt;a href="http://pycon-au.org/"&gt;PyCon Au&lt;/a&gt; website with the help of Benno Rice, Tim Ansell and Michael Kedzierski. It's running the PyCon-Tech code which Malcolm Tedinnick has offered to bring into the modern age of Django post-1.0 :)&lt;/p&gt;
&lt;a style="float: right; margin-left: 10px;" href="http://www.flickr.com/photos/malcolmtredinnick/4296820967/"&gt;&lt;img src="http://farm3.static.flickr.com/2784/4296820967_cf7b4929f1_t.jpg"&gt;&lt;/a&gt;&lt;p&gt;Finally on Saturday I organised a Python booth at the Open Day in Wellington Town Hall. I had a lot of great chats with a diverse range of people including some younger boys and girls who were excited by the game programming aspect of Python. Following advice (I've lost a link to) I had a donated external monitor (thanks Nic) which made showing things off much easier. I had a nice 1.8m banner printed (thanks PSF) which looked cool and gave out about 250 stickers :)&lt;/p&gt;

&lt;p class="small"&gt;* Google Wave account required&lt;/p&gt;
</description>
  </item>


  <item>
   <title>withgui finally made public!</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/withgui_finally_made_public</guid>
   <pubDate>Fri, 22 Jan 2010 08:54:58 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/withgui_finally_made_public</link>
   <description>&lt;p&gt;On the heels of the release of the cool &lt;a href="http://pypi.python.org/pypi/withhacks"&gt;withhacks&lt;/a&gt; library, I've finally (thanks Robert Collins for helping) released &lt;a href="https://edge.launchpad.net/withgui"&gt;withgui&lt;/a&gt; on Launchpad. withgui is my experiment in simple GUI creation as mentioned &lt;a href="http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on"&gt;previously&lt;/a&gt; (see &lt;a href="http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.7"&gt;also&lt;/a&gt;.)&lt;/p&gt;
&lt;p&gt;I'll be looking at incorporating withhacks to replace my less-elegant (and fragile) namespace hackery. Feel free to take the code, branch and run. Contact me if you're interested in contributing (no comments on this blog but you'll figure out how to.)&lt;/p&gt;
&lt;p&gt;Thanks also to Brianna Laugher who tried to help me release to Launchpad a couple of months ago - the failure then was in my available time.&lt;/p&gt;</description>
  </item>


  <item>
   <title>New "html" module release, 1.8</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/New__html__module_release__1_8</guid>
   <pubDate>Fri, 15 Jan 2010 10:55:14 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/New__html__module_release__1_8</link>
   <description>&lt;p&gt;I just had a query regarding my Python &lt;a href="http://pypi.python.org/pypi/html"&gt;html generation&lt;/a&gt; module, asking whether I could a) upload a ZIP file and b) whether it was Python 3 compatible. I made one change (&lt;code class="code"&gt;map(...)&lt;/code&gt; &amp;rarr; &lt;code class="code"&gt;list(map(...))&lt;/code&gt;) and have released version 1.8 on PyPI.</description>
  </item>


  <item>
   <title>Python module statement ordering ... wart?</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Python_module_statement_ordering_____wart</guid>
   <pubDate>Fri, 15 Jan 2010 10:48:27 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Python_module_statement_ordering_____wart</link>
   <description>&lt;p&gt;Can't call this one a "wart" because it's present in Python 3 and &lt;i&gt;we all know Python 3 got rid of all the warts&lt;/i&gt; &amp;lt;wink&amp;gt;.&lt;/p&gt;
&lt;p&gt;It has to do with the very specific ordering of statements at the top of your Python source. Specifically if you have any of the following they must appear in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Top-of-file comments (Typically "# /usr/bin/env python", file encoding or source control revision ID string), then&lt;/li&gt;
&lt;li&gt;Module documentation string, then&lt;/li&gt;
&lt;li&gt;"from __future__ import ..." statement(s), then&lt;/li&gt;
&lt;li&gt;The rest of your module.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Failure to order them precisely like this will result in one of a couple of things: either your docstring will not be created correctly (as the __doc__ attribute) &lt;i&gt;or&lt;/i&gt; you'll get a SyntaxError because your "from __future__ import ..." statements aren't "at the beginning of the file" (even though they &lt;b&gt;can't&lt;/b&gt; be at the beginning of the file.) If the docstring appears after the "from __future__" imports it won't be used as __doc__.&lt;/p&gt;
</description>
  </item>


  <item>
   <title>New Year's Python meme</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/New_Year_s_Python_meme</guid>
   <pubDate>Tue, 05 Jan 2010 09:21:45 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/New_Year_s_Python_meme</link>
   <description>&lt;ol&gt;
&lt;li&gt;&lt;b&gt;What’s the coolest Python application, framework or library you have discovered in 2009 ? &lt;/b&gt;
&lt;br&gt;&lt;a href="http://pypi.python.org/pypi/promise"&gt;promise&lt;/a&gt; - just too cool :)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;What new programming technique did you learn in 2009?&lt;/b&gt;
&lt;br&gt;I learnt how to use some of the new features in Python 2.6 and 3.1 but mostly I was just refining my knowledge of Twisted and SMS protocols.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;What’s the name of the open source project you contributed the most in 2009? What did you do? &lt;/b&gt;
&lt;br&gt;&lt;a href="http://www.roundup-tracker.org/"&gt;Roundup&lt;/a&gt; - I still lead development of the project even though there's usually one or two other code contributors. I also released &lt;a href="http://pypi.python.org/pypi/html"&gt;html&lt;/a&gt; and failed to release &lt;a href="http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.7"&gt;withgui&lt;/a&gt; ;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;What was the Python blog or website you read the most in 2009? &lt;/b&gt;
&lt;br&gt;&lt;a href="http://planet.python.org/"&gt;Planet Python&lt;/a&gt;.&lt;/li&gt; 
&lt;li&gt;&lt;b&gt;What are the three top things you want to learn in 2010 ?&lt;/b&gt;
&lt;br&gt;For my day job I have to learn about &lt;a href="http://en.wikipedia.org/wiki/Signaling_System_7"&gt;SS7&lt;/a&gt; and &lt;a href="http://en.wikipedia.org/wiki/Mobile_Application_Part"&gt;MAP&lt;/a&gt;. I imagine I won't have much room for anything else, though I do look forward to random presentations at the &lt;a href="http://wiki.python.org/moin/MelbournePUG"&gt;Melbourne Python Users' Group&lt;/a&gt; :)&lt;/li&gt;
&lt;/ol&gt;</description>
  </item>


  <item>
   <title>Python's Deficient Generators</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Python_s_Deficient_Generators</guid>
   <pubDate>Tue, 22 Dec 2009 10:50:30 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Python_s_Deficient_Generators</link>
   <description>&lt;p&gt;I've had people try to &lt;a href="http://www.pyweek.org/d/2965/"&gt;explain why Python's generators are deficient before&lt;/a&gt; and the light just went off. To flatten an arbitrarily deep (though stack-limited) nested iterator structure, I wrote:&lt;/p&gt;
&lt;pre class="code"&gt;&gt;&gt;&gt; def flatten(iterable):
...  for elem in iterable:
...   if hasattr(elem, '__iter__'):
...    for sub in flatten(elem): yield sub
...   else:
...    yield elem
... 
&gt;&gt;&gt; list(flatten([[1,2,3],[[2,3],4],[4,5,6]]))
[1, 2, 3, 2, 3, 4, 4, 5, 6]&lt;/pre&gt;
&lt;p&gt;The key failing is that inner "for" loop. It's called "trampolining" as described by &lt;a href="http://www.dabeaz.com/coroutines/"&gt;David Beazley&lt;/a&gt;. If I could somehow yield to the top of the generator stack it'd be unnecessary. It'd look something like &lt;a href="http://www.python.org/dev/peps/pep-0380/"&gt;PEP 380&lt;/a&gt;:&lt;/p&gt;
&lt;pre class="code"&gt;&gt;&gt;&gt; def flatten(iterable):
...  for elem in iterable:
...   if hasattr(elem, '__iter__'):
...    yield from flatten(elem)
...   else:
...    yield elem
... 
&gt;&gt;&gt; list(flatten([[1,2,3],[[2,3],4],[4,5,6]]))
[1, 2, 3, 2, 3, 4, 4, 5, 6]&lt;/pre&gt;
&lt;p&gt;Too bad there's a &lt;a href="http://python.org/dev/peps/pep-3003/"&gt;moratorium on changes&lt;/a&gt; :)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Updated&lt;/b&gt; to include the PEP, thanks ulrik!&lt;/p&gt;</description>
  </item>


  <item>
   <title>Sharing my "What's New In Python" presentations</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Sharing_my__What_s_New_In_Python__presentations</guid>
   <pubDate>Tue, 15 Dec 2009 15:19:17 +1100</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Sharing_my__What_s_New_In_Python__presentations</link>
   <description>&lt;p&gt;I've put together &lt;a href="http://www.slideshare.net/r1chardj0n3s"&gt;presentations for describing the new features in Python versions 2.4, 2.5 and 2.6&lt;/a&gt;. I did this because my employer, like many companies using Python, has only just installed 2.6 - previously almost all development was done using 2.3 (with just a little 2.4, hence I included that version's information as a refresher.)&lt;/p&gt;
&lt;p&gt;The slides are on &lt;a href="http://www.slideshare.net/r1chardj0n3s"&gt;slideshare&lt;/a&gt;. Download the Keynote originals though 'cos slideshare burnt the presenter notes onto the slides.&lt;/p&gt;
&lt;p&gt;I'll be uploading "What's new in Python 3" some time in late January.&lt;/p&gt;
</description>
  </item>


  <item>
   <title>Simple, elegant HTML generation, released</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Simple__elegant_HTML_generation__released</guid>
   <pubDate>Thu, 17 Sep 2009 11:42:11 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Simple__elegant_HTML_generation__released</link>
   <description>&lt;p&gt;I've just released my "&lt;a href="http://pypi.python.org/pypi/html"&gt;simple, elegant HTML generation&lt;/a&gt;" module, "&lt;a href="http://pypi.python.org/pypi/html"&gt;html.py&lt;/a&gt;"
&lt;/p&gt;
&lt;p&gt;See, I do release stuff :)&lt;/p&gt;
&lt;p&gt;And astute readers might notice I've "released often" as well :)&lt;/p&gt;</description>
  </item>


  <item>
   <title>Simple, elegant HTML generation</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Simple__elegant_HTML_generation</guid>
   <pubDate>Wed, 16 Sep 2009 17:38:14 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Simple__elegant_HTML_generation</link>
   <description>&lt;p&gt;OK, I looked. I searched. I didn't find. So here you go...&lt;/p&gt;
&lt;pre class="code"&gt;from cgi import escape
class HTML(object):
    '''Easily generate HTML.

        &gt;&gt;&gt; h = HTML()
        &gt;&gt;&gt; p = h.p('hello, world!')
        &gt;&gt;&gt; p.text('more text')
        &gt;&gt;&gt; with h.table(border='1', newlines=True):
        ...     for i in range(2):
        ...         with h.tr:
        ...             h.td('he&amp;lt;l&amp;gt;lo', a='"foo"')
        ...             h.td('there')
        ... 
        &gt;&gt;&gt; print h
        &amp;lt;p&amp;gt;hello, world!more text&amp;lt;/p&amp;gt;
        &amp;lt;table border="1"&amp;gt;
        &amp;lt;tr&amp;gt;&amp;lt;td a="&amp;amp;quot;foo&amp;amp;quot;"&amp;gt;he&amp;amp;lt;l&amp;amp;gt;lo&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;there&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
        &amp;lt;tr&amp;gt;&amp;lt;td a="&amp;amp;quot;foo&amp;amp;quot;"&amp;gt;he&amp;amp;lt;l&amp;amp;gt;lo&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;there&amp;lt;/td&amp;gt;&amp;lt;/tr&amp;gt;
        &amp;lt;/table&amp;gt;

    '''
    def __init__(self, name=None, stack=None):
        self.name = name
        self.content = []
        self.attrs = {}
        # insert newlines between content?
        self.newlines = False
        if stack is None:
            stack = [self]
        self.stack = stack
    def __getattr__(self, name):
        # adding a new tag or newline
        if name == 'newline':
            e = '\n'
        else:
            e = HTML(name, self.stack)
        self.stack[-1].content.append(e)
        return e
    def text(self, text):
        # adding text
        self.content.append(escape(text))
    def __call__(self, *content, **kw):
        # customising a tag with content or attributes
        if content:
            self.content = map(escape, content)
        if 'newlines' in kw:
            # special-case to allow control over newlines
            self.newlines = kw.pop('newlines')
        for k in kw:
            self.attrs[k] = escape(kw[k]).replace('"', '&amp;quot;')
        return self
    def __enter__(self):
        # we're now adding tags to me!
        self.stack.append(self)
        return self
    def __exit__(self, exc_type, exc_value, exc_tb):
        # we're done adding tags to me!
        self.stack.pop()
    def __str__(self):
        # turn me and my content into text
        join = '\n' if self.newlines else ''
        if self.name is None:
            return join.join(map(str, self.content))
        a = ['%s="%s"'%i for i in self.attrs.items()]
        l = [self.name] + a
        s = '&amp;lt;%s&amp;gt;%s'%(' '.join(l), join)
        if self.content:
            s += join.join(map(str, self.content))
            s += join + '&amp;lt;/%s&amp;gt;'%self.name
        return s
&lt;/pre&gt;
&lt;p class="small"&gt;There was an escaping error in this blog post (the &amp;lt; and &amp;gt; around the "l" first in "hello") which I didn't catch before Planet Python grabbed my feed, so it's wrong on there but correct here. Hrm.&lt;/p&gt;
&lt;p class="small"&gt;Also, look, ma! A ternary expression! My first in Python!&lt;/p&gt;
&lt;p class="small"&gt;Did you like "join.join"? Heh. I know...&lt;/p&gt;</description>
  </item>


  <item>
   <title>Python's 9th write-a-game-in-a-week challenge</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Python_s_9th_write_a_game_in_a_week_challenge</guid>
   <pubDate>Sun, 23 Aug 2009 10:18:23 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Python_s_9th_write_a_game_in_a_week_challenge</link>
   <description>&lt;p&gt;Theme voting for the &lt;a href="http://www.pyweek.org/9/"&gt;latest (9th!) write-a-game-in-a-week PyWeek challenge&lt;/a&gt; is on!&lt;/p&gt;
&lt;p&gt;Everyone should write a game and this is the perfect venue for doing so - you've only got a week (a lot of game ideas can be written in a weekend) and there's lots of help available. And it's a lot of fun!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.pyweek.org/9/"&gt;So get to it!&lt;/a&gt;
</description>
  </item>


  <item>
   <title>Something I'm working on...</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.7</guid>
   <pubDate>Wed, 19 Aug 2009 17:23:14 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.7</link>
   <description>&lt;p&gt;This will probably be the last of these posts before I make the project public. It has two code parts. The first is model:&lt;/p&gt;
&lt;pre class="code"&gt;import random
            
class Cell(object):
    def __init__(self, i, j, has_bomb):
        self.i, self.j = i, j
        self.has_bomb = has_bomb
class Board(list):
    def __init__(self, size, chance=.2): 
        self.size = size
        self[:] = [[Cell(i, j, random.random() &amp;lt; chance)
            for i in range(size)] for j in range(size)]
    def count(self, cell):
        '''Count the number of bombs near the cell.'''
        return sum(self[j][i].has_bomb
            for i in range(max(0, cell.i-1), min(self.size, cell.i+2))
                for j in range(max(0, cell.j-1), min(self.size, cell.j+2)))
    
board = Board(20)&lt;/pre&gt;
&lt;p&gt;And the second is the withgui code:&lt;/p&gt;
&lt;pre class="code"&gt;with gui.canvas(width=320, height=320) as canvas:
    for column in board:
        for cell in column:
            @canvas.image('cover.png', x=cell.i*16, y=cell.j*16)
            def on_mouse(image, mouse, cell=cell):
                count = board.count(cell)
                if cell.has_bomb:
                    image.value = 'bomb.png'
                    print 'GAME OVER!'
                elif count:
                    image.destroy()
                    canvas.label(str(count), x=cell.i*16+8, y=cell.j*16+8, 
                        anchor=center)
                else:
                    image.destroy()&lt;/pre&gt;
&lt;p&gt;Resulting in (youtube vid, sorry about the quality I'm new to this):&lt;/p&gt;
&lt;object width="560" height="340"&gt;&lt;param name="movie" value="http://www.youtube.com/v/1mzCc-4wCwk&amp;hl=en&amp;fs=1&amp;"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/1mzCc-4wCwk&amp;hl=en&amp;fs=1&amp;" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="560" height="340"&gt;&lt;/embed&gt;&lt;/object&gt;
&lt;br&gt;</description>
  </item>


  <item>
   <title>Something I'm working on...</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.6</guid>
   <pubDate>Tue, 18 Aug 2009 19:20:24 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.6</link>
   <description>&lt;p&gt;with &lt;a href="http://code.google.com/p/kytten/"&gt;kytten&lt;/a&gt;...&lt;/p&gt;
&lt;img src="http://www.mechanicalcat.net/images/withkytten.png"&gt;</description>
  </item>


  <item>
   <title>More pausing</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/More_pausing</guid>
   <pubDate>Mon, 17 Aug 2009 22:12:15 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/More_pausing</link>
   <description>&lt;p&gt;I got distracted mucking about with Python 3.1.1 and Tcl/Tk 8.5 today -- withgui works with both (only had to make very minor edits to get it working under Python 3000.)&lt;/p&gt;
&lt;p&gt;More interesting update tomorrow, I hope :)&lt;/p&gt;</description>
  </item>


  <item>
   <title>Brief pause</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Brief_pause</guid>
   <pubDate>Fri, 14 Aug 2009 22:29:51 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Brief_pause</link>
   <description>&lt;p&gt;Today was a day of rest so naturally I spent it refactoring the heck out of withgui*.&lt;/p&gt;
&lt;p&gt;The upshot is that a couple of artificial restrictions have been removed and the Tkinter reference implementation is now significantly clearer.&lt;/p&gt;
&lt;p class="small"&gt;&lt;i&gt;* still a working title; no final title yet ("gui", "show", "pomp" and "fjord" are candidates)&lt;/i&gt;&lt;/p&gt;
</description>
  </item>


  <item>
   <title>Something I'm working on...</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.5</guid>
   <pubDate>Thu, 13 Aug 2009 20:24:53 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.5</link>
   <description>&lt;object width="580" height="360"&gt;&lt;param name="movie" value="http://www.youtube.com/v/4Q0PfdSsYj0&amp;hl=en&amp;fs=1&amp;rel=0&amp;border=1"&gt;&lt;/param&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;/param&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;/param&gt;&lt;embed src="http://www.youtube.com/v/4Q0PfdSsYj0&amp;hl=en&amp;fs=1&amp;rel=0&amp;border=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="580" height="360"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;pre class="code"&gt;with gui.canvas(background='antigravity.png') as canvas:
    with canvas.image('smiley.png', x=0, y=20):
        def animate(image):
            while image.x &amp;lt; 200:
                dt = yield
                image.x += 20*dt
        def on_mouse(image, mouse):
            print 'Got me!'&lt;/pre&gt;
&lt;p class="small"&gt;Screen capture at 10 frames per second; original animation runs smoother.&lt;/p&gt;
&lt;p class="small"&gt;Comic fragment taken from &lt;a href="http://xkcd.com/353/"&gt;XKCD #353 "Python"&lt;/a&gt;. Smiley is all original art ;)&lt;/p&gt;</description>
  </item>


  <item>
   <title>Something I'm working on...</title>
   <guid>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.4</guid>
   <pubDate>Wed, 12 Aug 2009 20:17:40 +1000</pubDate> 
   <link>http://www.mechanicalcat.net/richard/log/Python/Something_I_m_working_on.4</link>
   <description>&lt;p&gt;No update yesterday because I was at &lt;a href="http://bit.ly/mpug"&gt;MPUG&lt;/a&gt; giving a presentation about this stuff...&lt;/p&gt;
&lt;img src="http://www.mechanicalcat.net/images/form.png"&gt;
&lt;pre class="code"&gt;with gui.form() as form:
    name = gui.row('Name', gui.text())
    skill = gui.row('Skill level', gui.selection(['Awesome', 'Radical', 'Understated']))
    @gui.submit('OK')
    def on_click(button):
        print 'Got name=%r'%name.value
        print 'Got skill=%r'%form['skill'].value
        gui.stop(0)
    @gui.cancel('Cancel')
    def on_click(button):
        gui.stop(1)&lt;/pre&gt;</description>
  </item>

 </channel>
</rss>
