<?xml version="1.0" encoding="iso-8859-1"?>
<rss version="2.0"><channel><title>Fredrik Håård's Blaag</title><link>http://blaag.haard.se/</link><description>YAB</description><lastBuildDate>Wed, 03 Apr 2013 05:50:12 GMT</lastBuildDate><generator>PyRSS2Gen-1.0.0</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>See you in Florence this summer?</title><link>http://blaag.haard.se/See-you-in-Florence-this-summer</link><description>&lt;div class="document" id="see-you-in-florence-this-summer"&gt;
&lt;h1 class="title"&gt;See you in Florence this summer?&lt;/h1&gt;
&lt;p&gt;I'll be in Florence for &lt;a class="reference external" href="http://ep2013.europython.eu/"&gt;EuroPython 2013&lt;/a&gt; and do (more or less) a follow-up to the training session I held last year - a very hands-on venture into Python lanugage and standard library features that will allow you to implement your bad ideas in awesome hacks and good ideas with beautiful magic. This is how fun we had last year!&lt;/p&gt;
&lt;blockquote&gt;
&lt;img alt="/static/ep2012dcsl.jpg" src="/static/ep2012dcsl.jpg" style="width: 500px;" /&gt;
&lt;/blockquote&gt;
&lt;p&gt;Ok, so they're all looking at their screens, but that's kind of the point with a training session in my opinion, hands on keyboards as much as possible.&lt;/p&gt;
&lt;p&gt;In other news, I have created a &lt;a class="reference external" href="https://gist.github.com/haard/5295600"&gt;gist&lt;/a&gt; with a cleaned up version of my fetch/unpack/csvparse &lt;a class="reference external" href="http://blaag.haard.se/Batteries-included--Download--unzip-and-parse-in-13-lines/"&gt;code&lt;/a&gt; incorporating some of the suggestions I got here and on Reddit.&lt;/p&gt;
&lt;blockquote&gt;
&lt;!-- keywords: python europython --&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>n</category><guid isPermaLink="true">http://blaag.haard.se/See-you-in-Florence-this-summer</guid><pubDate>Wed, 03 Apr 2013 05:50:00 GMT</pubDate></item><item><title>Batteries included: Download, unzip and parse in 13 lines</title><link>http://blaag.haard.se/Batteries-included--Download--unzip-and-parse-in-13-lines</link><description>&lt;div class="document" id="batteries-included-download-unzip-and-parse-in-13-lines"&gt;
&lt;h1 class="title"&gt;Batteries included: Download, unzip and parse in 13 lines&lt;/h1&gt;
&lt;p&gt;The other day I needed to download some zip files, unpack them, parse the CSV files in them, and return the data as dicts. I did the very same thing a couple of years ago, and although the source is lost, I recall having a Python (2.4?) script of about two screens to do the download - so a hundred lines.
When re-implementing the solution now that I know Python and the standard library better, I ended up with 12 lines written in just a few minutes - edited for blogging clarity it clocks in at 13 lines:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;zipfile&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;csv&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_items&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;urllib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;urlretrieve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;zipfile&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ZipFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;csvfiles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;namelist&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                 &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;endswith&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.csv'&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;csvfiles&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;zf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;reader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;csv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DictReader&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;line&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'iso-8859-1'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                                  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
          &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;
  &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;unlink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;As trivial as it is, I think it is a nice example of just how much you can do with very little (coding) effort.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Edit&lt;/em&gt;: I created a &lt;a class="reference external" href="https://gist.github.com/haard/5295600"&gt;gist&lt;/a&gt; with a cleaned up version using codecs.getreader. I'll be leaving this version as it is though.&lt;/p&gt;
&lt;!-- keywords: python zip zipfile csv urllib terse --&gt;
&lt;/div&gt;
</description><category>b</category><guid isPermaLink="true">http://blaag.haard.se/Batteries-included--Download--unzip-and-parse-in-13-lines</guid><pubDate>Sun, 31 Mar 2013 10:12:11 GMT</pubDate></item><item><title>WGS-84 distance calculations at the speed of C</title><link>http://blaag.haard.se/WGS-84-distance-calculations-at-the-speed-of-C</link><description>&lt;div class="document" id="wgs-84-distance-calculations-at-the-speed-of-c"&gt;
&lt;h1 class="title"&gt;WGS-84 distance calculations at the speed of C&lt;/h1&gt;
&lt;p&gt;When we started out doing fleet management at Visual Units, one thing was really hard to get right - distance calculations. There was no end of information available, but most-to-all of it was on a level of mathematics far beyond a poor developer who feels that anything beyond discrete mathematics and basic geometry and statistics really should be somebody else's problem. The implementations that could be found were closed-source licensed version we really could not afford at that stage.&lt;/p&gt;
&lt;p&gt;For a while we got by using a solution that relied on having a variant of Lambert conformal conic projection coordinates - it was sufficiently exact if not perfect, and our maps used the same projection, so it worked - although there was the added burden of transforming our stored (WGS-84) coordinates to Lambert every time we needed calculations done. A couple of years ago, however, we switched to &lt;a class="reference external" href="https://developers.google.com/maps/"&gt;Google Maps API&lt;/a&gt; and so we really had no use for Lambert - and increased load and precision demands made using the current solution a worse and worse choice.&lt;/p&gt;
&lt;p&gt;Enter &lt;a class="reference external" href="http://www.movable-type.co.uk/"&gt;Chris Veness&lt;/a&gt;. Or rather, enter his &lt;a class="reference external" href="http://www.movable-type.co.uk/scripts/latlong-vincenty.html"&gt;implementation&lt;/a&gt; of the &lt;a class="reference external" href="http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf"&gt;Vincenty inverse formula&lt;/a&gt; (pdf). Even though the math is beyond me, porting the Javascript implementation to Python was straightforward, and some testing showed that &lt;a class="reference external" href="https://bitbucket.org/visualunits/vutools/src/e18fdfb9eed5f5b33c00c715a2a18ca888cfe559/distance/distance.py"&gt;the result&lt;/a&gt; was both faster and had better precision than the previous solution.&lt;/p&gt;
&lt;p&gt;Fast-forward to a few months ago, suddenly the performance is starting to look like something that could become a problem. We have many reasons for doing distance calculations, and while the batch jobs were not a problem, any amount of time that can be shaved off user-initiated actions is welcome.&lt;/p&gt;
&lt;p&gt;So, I thought to myself, I've ported it once, how hard can it be to do it again? After all, when raw speed becomes the issue, the Python programmer reaches for C. Porting it was once again straightforward, mapping the Python function&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;into&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code c literal-block"&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The &lt;a class="reference external" href="https://bitbucket.org/visualunits/vutools/src/e18fdfb9eed5/distance/distance.c"&gt;resulting C code&lt;/a&gt; is almost identical to he Python (and Javascript) implementations but runs about 6 times faster than the Python implementation. Allowing batch submission of calculations instead of calling once for every calculation, eliminating some FFI overhead, would increase the speed further.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code literal-block"&gt;
$ python2.7 -m tests.test_distance
Time elapsed for 100000 calculations in
    Python: 1952.70
    C: 300.46
    Factor: 6.50
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Wrapping the C and calling it was simple enough using ctypes, and I've added fallback to the Python implementation if the C shared library cannot be found; a small __init__.py in the package hooks up the correct version:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;.distance&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;_py_distance&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;ctypes&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;cdll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_double&lt;/span&gt;
    &lt;span class="n"&gt;dll&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cdll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadLibrary&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'cDistance.so'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;dll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;restype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c_double&lt;/span&gt;
    &lt;span class="n"&gt;dll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;argtypes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_double&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;
    &lt;span class="n"&gt;_c_distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dll&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;distance&lt;/span&gt;
&lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="ne"&gt;OSError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="c"&gt;#Fall back to Python implementation&lt;/span&gt;
    &lt;span class="n"&gt;distance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_py_distance&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Of course, this depends on the C code being compiled into cDistance.so and that file being available for linking - and it keeps the .so hardcoded so a windows DLL wont work. I really did intend to clean it up more before making it open source, but since I've been meaning to start open sourcing some of our tools for years now and never really found the time, I thought it would be better to thow it out there, and postpone making it pretty instead. I hope someone can find some use in this, and I'll try to get it cleaned upp and packaged Real Soon Now.&lt;/p&gt;
&lt;!-- keywords: python coordinates google maps c ctypes ffi --&gt;
&lt;/div&gt;
</description><category>s</category><guid isPermaLink="true">http://blaag.haard.se/WGS-84-distance-calculations-at-the-speed-of-C</guid><pubDate>Thu, 21 Feb 2013 18:46:57 GMT</pubDate></item><item><title>pyRest part 5: You can actually use this</title><link>http://blaag.haard.se/pyRest-part-5--You-can-actually-use-this</link><description>&lt;div class="document" id="pyrest-part-5-you-can-actually-use-this"&gt;
&lt;h1 class="title"&gt;pyRest part 5: You can actually use this&lt;/h1&gt;
&lt;p&gt;(&lt;a class="reference external" href="http://blaag.haard.se/Simple-REST-ful---ish--exposure-of-Python-APIs"&gt;part 1&lt;/a&gt;, &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-2--Hooking-the-API/"&gt;part 2&lt;/a&gt;, &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-3--Routing-and-responsibilities"&gt;part 3&lt;/a&gt;, &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-4--Separating-the-parts/"&gt;part 4&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I'm almost done with the parts to make this project PyPI ready - it can now work on your application as long as you implement the actual code to route calls to the right part of your API - this works:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code literal-block"&gt;
python -m pyrest.launcher  --server pyrest.integration.cherry \
       --api=pyrest.examples.hg
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Configuration can also be done using a config file instead of or together with command-line arguments. This means that if you can describe your API's usage using modules (representing resources) and post/put/get/delete functions in those modules, you can then pretty much just copy the line above and have a REST interface as long as you return data that the json library can understand how to serialize.&lt;/p&gt;
&lt;p&gt;The magic is all in the new &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/src/77878107e5f2e126802678664824ebc7f607d442/pyrest/launcher.py?at=default"&gt;launcher.py&lt;/a&gt;, which reads configuration, instantiates pyrest, an appserver interface, and hooks up the specified API. Very little other changes needed to be made - none to pyrest.py, and for &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/src/77878107e5f2/pyrest/integration/cherry.py?at=default"&gt;cherry.py&lt;/a&gt; the only changes was to move functionality from the 'if dunder main' to a new start() function.&lt;/p&gt;
&lt;p&gt;Time for a goal check!&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Create a tool that can expose a Python API in a RESTish fashion&lt;/li&gt;
&lt;li&gt;The API itself must not have to know about the tool&lt;/li&gt;
&lt;li&gt;It must handle HTTP errors&lt;/li&gt;
&lt;li&gt;It must run on Python 3.2+&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
These are all done, with the new launcher module taking care of reading configuration/arguments and wiring up the correct backend server - although right now, there's only the CherryPy version available.&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;It must run on at least CherryPy and two other webapp frameworks TBD (no, not Django)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
Not OK, just CherryPy implemented.&lt;/blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;It must be able to encode data into JSON before returning it&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
Partially OK, but there's no clean way of specializing the serialization if you send data that is not handled by the standard library json module.&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;p&gt;In addition to those goals, I'll also have to create a setup.py to make the tool installable before I can call version 1.0.0&lt;/p&gt;
&lt;p&gt;I'd also like to take the time to give a huge thanks to the people over at &lt;a class="reference external" href="http://www.dzone.com"&gt;DZone&lt;/a&gt; - not only did they ask if they could repost my blogs (which they don't have to since I allow anyone to do anything with it as long as they don't blame me for damage done...), but they actually sent me goodies all the way over the Atlantic! They actually sent me nerf guns (and a t-shirt and other stuff) &lt;em&gt;halfway across the globe&lt;/em&gt; just because they like my blog. Crazy. If everyone who likes this blog did that I'd probably have, like, &lt;em&gt;three&lt;/em&gt; nerf guns!&lt;/p&gt;
&lt;p&gt;That being said, code is as always available at &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest"&gt;Bitbucket&lt;/a&gt;.&lt;/p&gt;
&lt;!-- keywords: python api hgapi cherrypy rest --&gt;
&lt;/div&gt;
</description><category>y</category><guid isPermaLink="true">http://blaag.haard.se/pyRest-part-5--You-can-actually-use-this</guid><pubDate>Mon, 11 Feb 2013 22:30:06 GMT</pubDate></item><item><title>pyRest part 4: Separating the parts</title><link>http://blaag.haard.se/pyRest-part-4--Separating-the-parts</link><description>&lt;div class="document" id="pyrest-part-4-separating-the-parts"&gt;
&lt;h1 class="title"&gt;pyRest part 4: Separating the parts&lt;/h1&gt;
&lt;p&gt;(&lt;a class="reference external" href="http://blaag.haard.se/Simple-REST-ful---ish--exposure-of-Python-APIs"&gt;part 1&lt;/a&gt;, &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-2--Hooking-the-API/"&gt;part 2&lt;/a&gt;, &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-3--Routing-and-responsibilities"&gt;part 3&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I've now split the code into separate parts - &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/src/faa29b2729f481ba069038ce0a63d9651c15fadf/pyrest/pyrest.py?at=default"&gt;pyrest.py&lt;/a&gt; now only has generic functionality for hooking and routing, along with a bunch of helpers to create responses with HTTP response types. In fact, it's only 35 lines of code, and that's the entire 'core' of pyRest so far.&lt;/p&gt;
&lt;p&gt;The CherryPy integration has moved to the pyrest.integration package as &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/src/faa29b2729f4/pyrest/integration/cherry.py?at=default"&gt;cherry.py&lt;/a&gt; - it's still pretty clumsy to use (&lt;em&gt;python -m pyrest.integration.cherry&lt;/em&gt; can _only_ hook up the hgapi example code), and the hgapi implementation has been moved into the pyrest.examples.hg package.
The CherryPy parts have not changed much beyond always expecting a &lt;em&gt;Response&lt;/em&gt; tuple and using it to set response status and content, but the hgapi integration now sports a &lt;em&gt;post&lt;/em&gt; function, allowing me to commit the code just written using itself! &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/src/faa29b2729f481ba069038ce0a63d9651c15fadf/pyrest/examples/hg/changeset.py?at=default"&gt;changeset.py&lt;/a&gt; also uses the new Response helpers to create the return values.&lt;/p&gt;
&lt;p&gt;The code was committed using a POST request to &lt;em&gt;/api/changeset?message=Comitting via pyrest&lt;/em&gt;. Next, I'm planning to make the Mercurial integration useful, and/or the CherryPy integration a bit more robust.&lt;/p&gt;
&lt;p&gt;Code is as always available at &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest"&gt;Bitbucket&lt;/a&gt;.&lt;/p&gt;
&lt;!-- keywords: python api hgapi cherrypy rest --&gt;
&lt;/div&gt;
</description><category>y</category><guid isPermaLink="true">http://blaag.haard.se/pyRest-part-4--Separating-the-parts</guid><pubDate>Thu, 20 Dec 2012 12:44:09 GMT</pubDate></item><item><title>pyRest part 3: Routing and responsibilities</title><link>http://blaag.haard.se/pyRest-part-3--Routing-and-responsibilities</link><description>&lt;div class="document" id="pyrest-part-3-routing-and-responsibilities"&gt;
&lt;h1 class="title"&gt;pyRest part 3: Routing and responsibilities&lt;/h1&gt;
&lt;p&gt;In &lt;a class="reference external" href="http://blaag.haard.se/pyRest-part-2--Hooking-the-API/"&gt;part 2&lt;/a&gt;, I hooked up the API to CherryPy in a very crude fashion, and this time we'll look at how we can add handlers for resources in a less clumsy way. I decided to keep handlers on one 'level' only - that is, /sketch/parrot and /sketch will both be handled by the /sketch handler. This is because I find that the same sub-resource often is present in several places (what about &lt;em&gt;/props/parrot&lt;/em&gt;?) and having handlers like this simplifies stuff and makes the magic more readable.&lt;/p&gt;
&lt;p&gt;That magic looks like this - it is passed a package, find all modules that has at least one of get/post/put/delete implemented, and stores them in a name-&amp;gt;module dict.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_handlers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;handlers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;member_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt;
        &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getmembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;package&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ismodule&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;])]:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;inspect&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;getmembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;member&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
               &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'get'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'post'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'put'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'delete'&lt;/span&gt;&lt;span class="p"&gt;)]:&lt;/span&gt;
            &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Adding handler &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;member_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;member_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;member&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Later, when we get a request, we interpret the first part of the path as resource name (although I mounted it at /api, so it becomed /api/&amp;lt;resource&amp;gt;), and then use that string to get the correct module, check for a handler for the specific method, and call it if it exists.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;requesthandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Main dispatch for calls to PyRest; no framework specific
    code to be present after this point&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;resource&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'404 Not Found'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'No such resource'&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="nb"&gt;hasattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'405 Method Not Allowed'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="s"&gt;'Unsupported method for resource'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;return_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;getattr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handlers&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;resource&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
                          &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'200 OK'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return_data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Right now, there's nothing exciting going on in the API, so the routing logic just calls hgapi and assumes everything will be in order:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="n"&gt;rev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hgapi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="s"&gt;'node'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
       &lt;span class="s"&gt;'desc'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rev&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;desc&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, when we GET /api/changeset/1, the requesthandler will be passed this: ({'changeset': &amp;lt;module&amp;gt;}, 'get', 'changeset', ('1',)). It will lookup 'changeset' to get the module, and then retrieve and call 'get' using getattr and pass in the '1'. changeset.get() will then call hgapi, stick it into a map, and requesthandler encodes it as json and returns it. Since none of the parts involved actually cares what the arguments are, you can just as well use /api/changeset/tip or /api/changeset/default.&lt;/p&gt;
&lt;p&gt;As it looks now, the next part _should_ probably be adding some tests, but since I'm not totally decided on how I want to write my tests, I'll push ahead with separating the code instead - the current PyRest class and everything that has to do with CherryPy should go into a pyrest.cherrypy package or something similar, the requesthandler and get_handler functions should stay as part of pyRest proper, and the backend package should probably end up in an example package.&lt;/p&gt;
&lt;p&gt;Code is as always available at &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest"&gt;Bitbucket&lt;/a&gt;.&lt;/p&gt;
&lt;!-- keywords: python api hgapi cherrypy rest --&gt;
&lt;/div&gt;
</description><category>y</category><guid isPermaLink="true">http://blaag.haard.se/pyRest-part-3--Routing-and-responsibilities</guid><pubDate>Fri, 14 Dec 2012 17:24:16 GMT</pubDate></item><item><title>pyRest part 2: Hooking the API</title><link>http://blaag.haard.se/pyRest-part-2--Hooking-the-API</link><description>&lt;div class="document" id="pyrest-part-2-hooking-the-api"&gt;
&lt;h1 class="title"&gt;pyRest part 2: Hooking the API&lt;/h1&gt;
&lt;p&gt;In &lt;a class="reference external" href="http://blaag.haard.se/Simple-REST-ful---ish--exposure-of-Python-APIs/"&gt;part 1&lt;/a&gt;, a very unexciting base CherryPy implementation was all we had, but now it's time to hook up something real!
Instead of creating a mock API to work against as example code, I've decided to use &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt; to access the pyrest repo itself as example implementation - very meta!&lt;/p&gt;
&lt;p&gt;I've decided to hook the API in before I refactor the code to separate the web framework from pyRest, since I firmly belive in getting things working first and cleaning up after. I did create a namedtuple to hold basic response values so that the &lt;em&gt;requesthandler&lt;/em&gt; function can be extracted later.&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;The 'interesting' part looks like this&lt;/dt&gt;
&lt;dd&gt;&lt;pre class="code python first last literal-block"&gt;
&lt;span class="n"&gt;Response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;namedtuple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'response'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'status content'&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;requesthandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Main dispatch for calls to PyRest; no framework specific
    code to be present after this point&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'get'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'500 Server Error'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Not implemented'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hgapi&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Repo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'.'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'200 Ok'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hg_id&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;...not much yet, but it responds to any GET request with the current Mercurial node id.&lt;/p&gt;
&lt;p&gt;My intention is that the final result will be three separate parts - a routing/domain specific part that uses hgapi, pyRest proper which handles requests and autohooks up the routing, a CherryPy part which integrates with CherryPy and will need to be reimplemented for every web framework supported.&lt;/p&gt;
&lt;p&gt;That will be at at least one update before that though, because next will be &amp;quot;autowiring&amp;quot; the routing logic. Code for the project is available at &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest"&gt;Bitbucket&lt;/a&gt;&lt;/p&gt;
&lt;!-- keywords: python api hgapi cherrypy rest --&gt;
&lt;/div&gt;
</description><category>y</category><guid isPermaLink="true">http://blaag.haard.se/pyRest-part-2--Hooking-the-API</guid><pubDate>Sun, 09 Dec 2012 12:47:42 GMT</pubDate></item><item><title>Simple REST-ful (-ish) exposure of Python APIs</title><link>http://blaag.haard.se/Simple-REST-ful---ish--exposure-of-Python-APIs</link><description>&lt;div class="document" id="simple-rest-ful-ish-exposure-of-python-apis"&gt;
&lt;h1 class="title"&gt;Simple REST-ful (-ish) exposure of Python APIs&lt;/h1&gt;
&lt;p&gt;After having written code to expose APIs through RESTful web services a couple of times, I've decided to do it once more, only this time I won't get paid, I won't have deadlines, I'll write it so I'll never have to write it again, and I'll make it available as open source.&lt;/p&gt;
&lt;p&gt;Problem is, I'm a lazy, lazy person, and have not been able to muster the energy to actually get writing, which leads me to this blog post - since I've not been updating the blog as I should either, I'll kill two projects with one meeting and make the actual development process open as well, as a series of blog posts and a repository at BitBucket.&lt;/p&gt;
&lt;p&gt;For someone else to be able to follow the work, I obviously have to nail down what the goal of this exercise is:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
* Create a tool that can expose a Python API in a RESTish fashion
* The API itself must not have to know about the tool
* It must run on at least CherryPy and two other webapp frameworks TBD (no, not Django)
* It must handle HTTP errors
* It must be able to encode data into JSON before returning it
* It must run on Python 3.2+
* It must not care what the proper definition of RESTful is
&lt;/pre&gt;
&lt;p&gt;In addition, some good-to-haves:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
* It may make linking between resources easier (if feasible)
* It may be able to use other data formats than JSON
* It may run on Python 2.7
&lt;/pre&gt;
&lt;p&gt;Because I enjoy working with CherryPy since it's very good at staying out of my way, I'll start out writing for CherryPy and then generalize from there.
Just to get started, I have created a minimal CherryPy app to work from, even though I'll split the tool from the framwork (or the REST framework from the web framework?) later. The entire code looks like &lt;a class="reference external" href="https://bitbucket.org/haard/pyrest/commits/65e2c578a85c4d81948a5f9b8cf8989a1b05a760"&gt;this&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;cherrypy&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;requesthandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pathargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;cherrypy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;500 Server Error&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;Not implemented&amp;quot;&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PyRest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&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;index&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;requesthandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exposed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;


&lt;span class="n"&gt;CONF&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;'global'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s"&gt;'server.socket_host'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'0.0.0.0'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s"&gt;'server.socket_port'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;'__main__'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ROOT&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;PyRest&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;cherrypy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;quickstart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CONF&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;application&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_response&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;cherrypy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;mount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PyRest&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;cherrypy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start_response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;!-- keywords: python rest http cherrypy tornado twisted --&gt;
&lt;/div&gt;
</description><category>o</category><guid isPermaLink="true">http://blaag.haard.se/Simple-REST-ful---ish--exposure-of-Python-APIs</guid><pubDate>Thu, 06 Dec 2012 20:25:04 GMT</pubDate></item><item><title>Sending non-valid names as arguments</title><link>http://blaag.haard.se/Sending-non-valid-names-as-arguments</link><description>&lt;div class="document" id="sending-non-valid-names-as-arguments"&gt;
&lt;h1 class="title"&gt;Sending non-valid names as arguments&lt;/h1&gt;
&lt;p&gt;I got a &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi/issue/14/hg_log-cannot-filter-by-branch"&gt;feature request&lt;/a&gt;  on &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt; the other day, pointing out that it was not possible to filter
the Mercurial log using the API, since there is no dedicated way to do it and the fallback method - sending
keyword arguments that will be passed to the command line - does not work. The signature of the method in
question is&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hg_log&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;identifier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;template&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;with kwargs accepting any keyword arguments and passing them to the command line. So, for getting
a log by branch, trying&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hg_log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mybranch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;seems like a good idea, until you realize that '-b' is not a valid identifier, and so this code is
invalid. However, almost &lt;em&gt;all&lt;/em&gt; Mercurial options you might want to send like this starts with a dash,
so what is the point of using kwargs at all?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Notice: Entering bad practice land!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;It is totally possible to send keyword arguments to a function in Python that are not valid identifiers,
by using argument unpacking. Given a function like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;myfunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;positional&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwarg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'Hello'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;positional&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kwarg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;     &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]))&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;you can send any dict in like this:&lt;/p&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;myfunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;'-1-'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'dash-one-dash'&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;Hello&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;dash&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;one&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;dash&lt;/span&gt;
&lt;/pre&gt;
&lt;p&gt;Not a very nice way of doing things, but can be handy in - for example - a fallback case where you,
want to support future arguments, obscure arguments, and generally just anything.&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;(hgapi 1.3.1a3 was just uploaded to the cheeseshop; hg_log now takes a 'branch' argument)&lt;/dt&gt;
&lt;dd&gt;&lt;!-- keywords: mercurial python hg hgapi --&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;/div&gt;
</description><category>g</category><guid isPermaLink="true">http://blaag.haard.se/Sending-non-valid-names-as-arguments</guid><pubDate>Fri, 02 Nov 2012 17:29:17 GMT</pubDate></item><item><title>See me on an island!</title><link>http://blaag.haard.se/See-me-on-an-island</link><description>&lt;div class="document" id="see-me-on-an-island"&gt;
&lt;h1 class="title"&gt;See me on an island!&lt;/h1&gt;
&lt;p&gt;I've really neglected to update the blog lately, but that's at least
in part because I've been busy doing preparations for talks - so you
could &lt;em&gt;see&lt;/em&gt; me instead of read my blog! I'll be speaking both at &lt;a class="reference external" href="http://2012.pyconuk.net/"&gt;PyCon
UK&lt;/a&gt; and &lt;a class="reference external" href="http://python.ie/pycon/2012/"&gt;PyCon Ireland&lt;/a&gt;, so if you're going to either come chat with
me! And, you know, maybe see my talks...&lt;/p&gt;
&lt;p&gt;Also, I &lt;strong&gt;do&lt;/strong&gt; have a proper blog post with actual content a-brewing, and I
promise it will be done Real Soon Now (tm).&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/See-me-on-an-island</guid><pubDate>Sun, 16 Sep 2012 19:40:16 GMT</pubDate></item><item><title>You should send a presentation proposal to PyCon</title><link>http://blaag.haard.se/You-should-send-a-presentation-proposal-to-PyCon</link><description>&lt;div class="document" id="you-should-send-a-presentation-proposal-to-pycon"&gt;
&lt;h1 class="title"&gt;You should send a presentation proposal to PyCon&lt;/h1&gt;
&lt;p&gt;Next year, in March, I will be at PyCon. It will be the third time I
attend PyCon - ever since I attended my first, not going has not
really been an option.&lt;/p&gt;
&lt;p&gt;There are lots of good things about PyCon - meeting interesting
people, seeing San Francisco, beating off recruiters with a stick,
hanging out in the hotel bar and chill in the evenings - but the best
part is that the talks are so many, and so good. Now, the only way
there'll be lots of good talks next year is if there are a lot of good
proposals to choose from!&lt;/p&gt;
&lt;p&gt;You might think it scary to propose a talk to such a large conference,
but I can promise you that the Program Committee are really nice
people and that unless you're a professional speaker, the feedback you get is
bound to make your next proposal - and your next talk - better.&lt;/p&gt;
&lt;p&gt;Besides, if you're employed - what better argument to make your boss
send you to California than that you are going to present a talk at
_the_ conference for Python?&lt;/p&gt;
&lt;p&gt;So check the &lt;a class="reference external" href="http://pycon.blogspot.se/2012/08/spacepug-sample-talk-proposal.html"&gt;example proposal&lt;/a&gt;. Read the &lt;a class="reference external" href="https://us.pycon.org/2013/speaking/cfp/"&gt;call for papers&lt;/a&gt;. And
send your proposal before the 28th September, so we can get another
awesome PyCon next year.&lt;/p&gt;
&lt;p&gt;I've done my part, have you done yours?&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/You-should-send-a-presentation-proposal-to-PyCon</guid><pubDate>Wed, 05 Sep 2012 17:59:39 GMT</pubDate></item><item><title>Using the AST to hack constants into Python</title><link>http://blaag.haard.se/Using-the-AST-to-hack-constants-into-Python</link><description>&lt;div class="document" id="using-the-ast-to-hack-constants-into-python"&gt;
&lt;h1 class="title"&gt;Using the AST to hack constants into Python&lt;/h1&gt;
&lt;p&gt;During EuroPython 2012, after my training and talks, I really needed
to do some coding, so I started hacking on a 'practical' application
of the AST - making (some) constants faster than local variables,
instead of slower by inlining them on import.&lt;/p&gt;
&lt;p&gt;To do this, I use a custom importer on &lt;em&gt;meta_path&lt;/em&gt; to intercept the
import, and find any assignments  look like constants - that is, any
module-level variable in ALL_CAPS that is a simple string or a number.&lt;/p&gt;
&lt;p&gt;I store those names and values, and then simply replace any attempt to load
the name with the stored value instead. (Yes - this can go wrong in
many horrible ways!)&lt;/p&gt;
&lt;p&gt;For those who don't know the AST - Abstract Syntax Tree - is a tree
representation of the syntactic structure of your program. Python
lets you look at and modify the AST before compiling it, which in
effect allows you to rewrite the very structure of a program long
before it runs. For a good introduction to the AST I heartily
recommend &lt;a class="reference external" href="http://pyvideo.org/video/419/pycon-2011--what-would-you-do-with-an-ast"&gt;What would you do with an AST&lt;/a&gt; by Matthew Desmarais.&lt;/p&gt;
&lt;p&gt;To do this, I first need to intercept the import - the importer itself
is not very interesting, but what it does is that it tries to find the
source file for any imported module (if, for example, a .pyc file is
found, it simply strips the 'c' and tries to load the file.&lt;/p&gt;
&lt;p&gt;With the source file found and read, the importer just calls the
transformer, compiles the result, and sticks it into sys.modules:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;module&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ModuleType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;inlined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;compile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inlined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'exec'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sys&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;modules&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;module&lt;/span&gt;
&lt;span class="k"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__dict__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The transform method parses the source, creates the NodeTransformer
that will modify the AST, and passes the parsed AST to it.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Transforms the given source and return the AST&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;tree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;cm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ConstantMaker&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;newtree&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cm&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tree&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;newtree&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Our NodeTransformer is equally simple, and overloads &lt;em&gt;visit_Module&lt;/em&gt; (to
find the constants), and &lt;em&gt;visit_Name&lt;/em&gt; (to replace uses of the names with
the value). &lt;em&gt;visit_Module&lt;/em&gt; starts with building a list of all
assignments in the module body, and then filters out assignments that
fulfill our criteria for constants: they should be numbers or strings,
and they should be named in ALL_CAPS. Any such assignments are stored
in a name-&amp;gt;value map that can then be used by &lt;em&gt;visit_Name&lt;/em&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visit_Module&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;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Find eglible variables to be inlined and store
    the Name-&amp;gt;value mapping in self._constants for later use&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;

    &lt;span class="n"&gt;assigns&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt;
               &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;_ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assign&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;assign&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;assigns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Num&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_ast&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;targets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;RE_CONSTANT&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&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;_constants&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assign&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;

    &lt;span class="k"&gt;return&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;generic_visit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The parsing of assignments must be done before the call to
generic_visit, or we'll not have the mapping until after the rest of
the module has already been visited. The mapping makes the work of
&lt;em&gt;visit_Name&lt;/em&gt; extremely simple:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;visit_Name&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;node&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;If node.id is in self._constants, replace the
    loading of the node with the actual value&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="k"&gt;return&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;_constants&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;And that's all we need to do! A simple (simplistic?) benchmark shows
that it works as expected for simple cases - given the following
source that mixes constant access with some other 'work':&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;ONE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="n"&gt;TWO&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;two&amp;quot;&lt;/span&gt;
&lt;span class="n"&gt;THREE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;FOUR&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;4.0&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;costly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
   &lt;span class="n"&gt;tempstr&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;quot;&lt;/span&gt;
   &lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
     &lt;span class="n"&gt;tempstr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;ONE&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;TWO&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;THREE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;change&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="n"&gt;tempstr&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;eturn&lt;/span&gt; &lt;span class="n"&gt;tempstr&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&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="bp"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;THREE&lt;/span&gt;

   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;change&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;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FOUR&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;...a transformed version runs 15-20% faster than the
untransformed version. Of course, my first benchmark which did
&lt;strong&gt;only&lt;/strong&gt; loading of constants was a bazillion times faster, but also
not very interesting.&lt;/p&gt;
&lt;p&gt;This is of course a very limited implementation - a 'proper'
implementation would have to prevent writing to constants (right now
writes will be silently ignored by code in the current module),
in-module writes to a constant should be detected, the transform
should fallback to return the untransformed tree if it fails, and
maybe, just maybe, it's just not a very good idea at all.&lt;/p&gt;
&lt;p&gt;It was, however, great fun to write!
The code is available at the blog &lt;a class="reference external" href="https://bitbucket.org/haard/blaag.haard.se/src/tip/code/constants"&gt;repository&lt;/a&gt; - the timer I use for
the benchmarks is written by &lt;a class="reference external" href="https://github.com/BaltoRouberol/timer-context-manager"&gt;&amp;#64;BaltoRouberol&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Next experiment will be inlining of functions, I think, or maybe lazy
evaluation of function parameters.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Using-the-AST-to-hack-constants-into-Python</guid><pubDate>Thu, 26 Jul 2012 18:57:22 GMT</pubDate></item><item><title>EuroPython impressions</title><link>http://blaag.haard.se/EuroPython-impressions</link><description>&lt;div class="document" id="europython-impressions"&gt;
&lt;h1 class="title"&gt;EuroPython impressions&lt;/h1&gt;
&lt;p&gt;I had a blast at &lt;a class="reference external" href="https://ep2012.europython.eu/"&gt;Europython&lt;/a&gt; - I made new friends, went to a
couple of talks that gave me some ideas for the future, and my own
talks seemed to go down well.&lt;/p&gt;
&lt;p&gt;All in all, the EP2012 organization was great, the food was way
beyond 'normal' conference fare, and the venue was good  - although
finding a place to sit down during lunch was hard.&lt;/p&gt;
&lt;p&gt;I would have liked some kind of feedback mechanism in place for the
talks - had I known there would be none I'd have arranged one for my
own talks and especially the training session I held. I also feel that
the conference was a bit too long; perhaps it was not necessary to
give me the opportunity to take the stage thrice? Overall, I felt that
the quality of talks did not hold up for five days, and would have
preferred a shorter but more consistently high quality program (even if
some or all of my own sessions had been cut). By the end of the week,
I was worn out and going to talks I'd been excited about before the
conference almost became a chore. In addition, I attended no BoF:s,
and I'm not sure if there were any; either there needs to be BoF:s or
the information about them needs to be obvious enough that even I get it.&lt;/p&gt;
&lt;p&gt;However, as I started out saying, EP2012 was a great conference
overall, and I will definitely go again next year, and recommend
anyone else to do so as well. There were some amazing talks, great
discussions, and &lt;a class="reference external" href="https://twitter.com/pythonitalia"&gt;&amp;#64;PythonItalia&lt;/a&gt; did a wonderful job organizing it
all. I really felt that the volunteers were there to help me and they
made me feel welcome both as a speaker and attendee.&lt;/p&gt;
&lt;p&gt;If you did attend any of my talks or my training session, and have any
comments at all, &lt;em&gt;please&lt;/em&gt; comment on this post, ping me at &lt;a class="reference external" href="https://twitter.com/fhaard"&gt;&amp;#64;fhaard&lt;/a&gt;,
and/or mail me at fredrik (at) haard (dot) se.&lt;/p&gt;
&lt;p&gt;Also: Kernel failure during presentation does not have to
be end of the world, but seriously? The one time I &lt;em&gt;dont&lt;/em&gt; have index
cards?&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/EuroPython-impressions</guid><pubDate>Sat, 14 Jul 2012 15:02:03 GMT</pubDate></item><item><title>You deserve practice</title><link>http://blaag.haard.se/You-deserve-practice</link><description>&lt;div class="document" id="you-deserve-practice"&gt;
&lt;h1 class="title"&gt;You deserve practice&lt;/h1&gt;
&lt;p&gt;I enjoyed &lt;a class="reference external" href="http://amzn.to/Ig1nyw"&gt;The Clean Coder&lt;/a&gt; by &lt;a class="reference external" href="http://www.objectmentor.com/omTeam/martin_r.html"&gt;Uncle Bob&lt;/a&gt;, and would recommend it
to any serious developer. I agree with almost everything in it, but
there is one jarring exception - I disagree strongly with his view
that because it's your own responsibility to practice, you should not
do it on paid time.&lt;/p&gt;
&lt;p&gt;Under the headline &amp;quot;&lt;em&gt;Practice Ethics&lt;/em&gt;&amp;quot;, he states: &amp;quot;&lt;em&gt;Professional
programmers practice on their own time. It is not your employer&#8217;s job
to help you keep your skills sharp for you [...] Football fans do not
(usually) pay to see players run through tires. Concert-goers do not
pay to hear musicians play scales. And employers of programmers don&#8217;t
have to pay you for your practice time.&lt;/em&gt;&amp;quot;&lt;/p&gt;
&lt;p&gt;But the best football clubs do pay players for training time, and the
best orchestras pay their musicians to practice. I agree with one
thing, and that is that an employer doesn't &lt;em&gt;have&lt;/em&gt; to pay you for
practice time, but an employer that does not want to pay for
programmer training time does not deserve the best programmers.&lt;/p&gt;
&lt;p&gt;I believe, that if you have ambitions of being a great programmer you
should find an employer that lets you become great. If you want to be
among the best, you should find an employer that understands that
hiring and keeping the best programmers means that they will need to
spend time honing their skills. This is by no means black and white,
but there are not that many great programmers out there, and it's a
sellers market. The first step in taking responsibility for your own
career is to make sure that you have an employer that deserves you.&lt;/p&gt;
&lt;p&gt;Besides, a common trait of almost all great - or, indeed,
professional - programmers I&#8217;ve met is that programming is not their
only passion; and most of them work enough that doing a significant
amount of training outside of work would kill their ability to pursue
other interests in a meaningful way. I know that my own quality of
work degrades rapidly when the workload is high enough that I have to
cut down on other interests, simply because I need real down time to
solve hard problems, and anything related to programming is &lt;em&gt;not&lt;/em&gt; down
time.&lt;/p&gt;
&lt;blockquote&gt;
&lt;!-- python --&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/You-deserve-practice</guid><pubDate>Mon, 23 Apr 2012 08:42:26 GMT</pubDate></item><item><title>Version 1.2.0 of hgapi released</title><link>http://blaag.haard.se/Version-1-2-0-of-hgapi-released</link><description>&lt;div class="document" id="version-1-2-0-of-hgapi-released"&gt;
&lt;h1 class="title"&gt;Version 1.2.0 of hgapi released&lt;/h1&gt;
&lt;p&gt;&lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt; is a pure-Python API for Mercurial, which uses the command-line
interface for maximum compatibility. It is tested for Python 2.7 and
3.2.&lt;/p&gt;
&lt;p&gt;Version 1.2.0 fixes a few bugs, and allows iterating over a repository
as well as using slices ( i.e. repo[0:'tip']) to get a set of
changesets. API &lt;a class="reference external" href="http://packages.python.org/hgapi/hgapi.html"&gt;documentation&lt;/a&gt; is also slightly improved.&lt;/p&gt;
&lt;p&gt;Special thanks to &lt;a class="reference external" href="http://www.silverbucket.net/"&gt;Nick Jennings&lt;/a&gt; and &lt;a class="reference external" href="https://bitbucket.org/adamkg"&gt;Adam Gomaa&lt;/a&gt; who contributed patches.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Version-1-2-0-of-hgapi-released</guid><pubDate>Fri, 13 Apr 2012 12:40:16 GMT</pubDate></item><item><title>Protocol specifications written in Python</title><link>http://blaag.haard.se/Protocol-specifications-written-in-Python</link><description>&lt;div class="document" id="protocol-specifications-written-in-python"&gt;
&lt;h1 class="title"&gt;Protocol specifications written in Python&lt;/h1&gt;
&lt;p&gt;This is a writeup of a talk I did recently at Software Passion Summit
in Gothenburg, Sweden. For more background info, see the &lt;a class="reference external" href="/Using-Python-to-get-rid-of--doc"&gt;post&lt;/a&gt; I did
prior to the conference.&lt;/p&gt;
&lt;p&gt;Writing a specification in a full-blown programming language like
Python has upsides and downsides. On the downside, Python is not
designed as a declarative language, so any attempt to make it
declarative (apart from just listing native data types) will require
some kind of customization and/or tooling to work. On the upside,
having a declaration in the language you write your servers in, you
can use the specification itself, rather than a generated derivative of
that specification, and writing custom - in this case minimal -
generators for other languages is simple, since you can you Python
introspection to traverse your specification, and the templating logic
of your choice to generate source - this makes it possible, for
example, to target a J2ME terminal that just won't accept existing
solutions, and where dropping a 150K jar file for protocol
implementation is not an alternative.&lt;/p&gt;
&lt;p&gt;For me, this journey started around 2006 when I started to lose control over
protocol documentation and protocol versions for the protocol used
between terminals and servers in the fleet management solution
&lt;a class="reference external" href="http://www.visualunits.se"&gt;Visual Units Logistics&lt;/a&gt;. After looking for, and discarding, several existing
tools, and after being inspired by the fact that we usually configure
Javascript in Javascript, I started to sketch (as in, ink on paper)
on what a protocol specification in Python would look like. This is
a transcription of what I came up with at the time:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;imei&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;
&lt;span class="n"&gt;log_message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;
&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;long&lt;/span&gt;
&lt;span class="n"&gt;voltage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;

&lt;span class="n"&gt;log&lt;/span&gt; &lt;span class="o"&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;imei&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
           &lt;span class="n"&gt;log_message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;voltage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;With this as a target, I created the first version of a protocol
implementation. It looked similar to the target version, but suffered
from an abundance of repetition:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c"&gt;#protocol.py&lt;/span&gt;
&lt;span class="n"&gt;LOG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x023&lt;/span&gt;
&lt;span class="n"&gt;ALIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mh"&gt;0x021&lt;/span&gt;

&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'String'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'X'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'timestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'q'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'signal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'short'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'h'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;voltage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'voltage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'short'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'h'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;msg_log&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'LOG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;LOG&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;voltage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;msg_alive&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'ALIVE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ALIVE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;msg_log&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;msg_alive&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="c"&gt;#usage&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;protocol&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;
&lt;span class="n"&gt;parsed_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Protocol.java&#8217;,'&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="s"&gt;').write(protocol.java_protocol())&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;The implementation around this is simple; the Token class knows how to
parse a part of a message, the Message class knows which Tokens to use
(and in which order), and the Protocol class selects the correct
Message instance using a mapping of marker bytes to Message instances.&lt;/p&gt;
&lt;p&gt;However, no support is given for handling multiple versions of the
protocol, and the amount of name duplication makes it really
cumbersome - so I set out to create a better version.&lt;/p&gt;
&lt;p&gt;Some things complicated the creation of a better version. The worst
problem of them all proved to be me, myself and I. At this time I had
used Python for a couple of years, and started to get interested in
the more sophisticated tools available. I had just taught myself
about metaclasses, and thought they were an ingenious application of
object orientation - and having found a shiny new hammer, I was
itching to find a nail.&lt;/p&gt;
&lt;p&gt;Unfortunately, I had no pressing need for using metaclasses, so I
invented one - I wanted to avoid some assignments in the protocol
specification, so I used metaclasses to rip out the init (constructor)
method and replace it with a version that registered the instance in a global map
and then called the original init method. This is wrong in at least
three ways - since it was not generic, it could have been done in the
init method directly, if it would have been general it would have been
a job for a decorator, and it is a really great way to obfuscate the
code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="n"&gt;__MSG_MAPPING__&lt;/span&gt; &lt;span class="o"&gt;=&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;msg_initizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;old_init&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;new_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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;__MSG_MAPPING__get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{})[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&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;__MSG_MAPPING__&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;struct&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;pack&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!B&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;)]&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;old_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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;marker&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_init&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RegisterMeta&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;type&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;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'__init__'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;msg_initizer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                         &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'__init__'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RegisterMeta&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__new__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                      &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bases&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attrs&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;Message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;__metaclass__&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RegisterMeta&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This is the kind of code I'm not &lt;a class="reference external" href="/rant--Dare-to-show-your-code/"&gt;proud&lt;/a&gt; of, by the way. The worst part? It didn't even remove the duplication, although it
lowered it somewhat - and the global registration of messages when
loading a protocol really messed up any attempt of multiple version
support. This was not the only problem; I also went overboard and wanted to support specifying protocol syntax, using a Flow class that defined legal ordering of messages. This might have been a good idea had we actually had any such requirements in our protocols; since they are &#8220;authenticate, do anything&#8221;, adding support for this just expanded the codebase and made the protocol specification more complex for extremely little gain (especially since we authenticate in different ways depending on the client). Adding insult to injury, this is even more verbose than the very first try.&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c"&gt;#In protocol.py&lt;/span&gt;
&lt;span class="n"&gt;imei&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'imei'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'String'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;timestamp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'timestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'long'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'signal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'short'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;voltage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'voltage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'short'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;auth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'auth'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'String'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;Markers&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s"&gt;'LOG'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0x023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'ALIVE'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0x021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s"&gt;'AUTH'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mh"&gt;0x028&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="s"&gt;'LOG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imei&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;voltage&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="s"&gt;'ALIVE'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imei&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&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="s"&gt;'AUTH'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;imei&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;auth&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Flow&lt;/span&gt;&lt;span class="p"&gt;([(&lt;/span&gt;&lt;span class="s"&gt;'AUTH'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'LOG'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'ALIVE'&lt;/span&gt;&lt;span class="p"&gt;)])&lt;/span&gt;

&lt;span class="c"&gt;#Usage&lt;/span&gt;
&lt;span class="n"&gt;protocol&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Protocol&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parsed_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;#error if not auth parsed&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;This entire attempt became a warning example - it shows the danger of finding new and interesting technology and applying it before grokking it, and it shows the danger of over engineering and feature creep. Luckily, once I got a good look on what I had created, even me-a-few-years-back could see that this was an abomination, which was subsequently quietly taken out back and put down without even making it as far as integration tests.&lt;/p&gt;
&lt;p&gt;Finally, and ongoing, I decided to apply a carefully measured amount of standard library magic to make the specifications more terse, and remove stuff that we did not need. This made the specification look something like this instead:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c"&gt;#In protocol_4.2.py:&lt;/span&gt;
&lt;span class="c"&gt;#Tokens&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'message'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'timestamp'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="n"&gt;i64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'signal'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'voltage'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;#Messages&lt;/span&gt;
&lt;span class="n"&gt;LOG&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'A log message containing some debug info'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="mh"&gt;0x023&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&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;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;voltage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;ALIVE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'A message to signal that the terminal alive'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="mh"&gt;0x021&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;#Usage&lt;/span&gt;
&lt;span class="n"&gt;protocols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;load_protocols&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'protocols'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;protocols&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;4.2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;protocols&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;4.2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;write_java&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c"&gt;#Writes to Protocol42.java&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;At one time, it was even terser (as in the earlier blog &lt;a class="reference external" href="/Using-Python-to-get-rid-of--doc"&gt;post&lt;/a&gt;), but that version didn&#8217;t really pan out, and the version in production is very similar to this one. Name duplication is avoided using two different techniques - the tokens are defined by calling a method &lt;tt class="docutils literal"&gt;t&lt;/tt&gt; that creates the Token instance and injects it back into the calling namespace using the supplied name:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="c"&gt;#In types.py&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;inspect&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;currentframe&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_type&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="sd"&gt;&amp;quot;&amp;quot;&amp;quot;Inserts name = (name, data_type) in locals()
    of calling scope&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span class="n"&gt;currentframe&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_back&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f_locals&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data_type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;To some, this may seem like blasphemy, but consider this - the implementation is extremely simple in concept, it gets the work done, and it is easy to explain. Another change is that the messages are created solely by using &lt;tt class="docutils literal"&gt;inspect&lt;/tt&gt; to extract members of the module that look like messages - name in all caps, and a tuple. Worth noting might be that there was error handling initially, but I removed that to make parsing fail, rather than accept a specification that may or may not have contained errors.&lt;/p&gt;
&lt;p&gt;Finally, java source and html documentation is created by traversing the protocol instance, and feeding the information into simple templates - experiments were made using literate programming using ReST to create documentation, but in the end that tended to obfuscate rather than the reverse. This may be an effect of naive implementation, or that the problem does not lend itself well to literate programming, but either way it was not worth it in this case.&lt;/p&gt;
&lt;p&gt;There is a working and slightly generalized version available at
&lt;a class="reference external" href="https://bitbucket.org/haard/protocol-example"&gt;bitbucket&lt;/a&gt;, and it you would like to hear more about this (and more
details about Python magic used), you can buy a ticket to
&lt;a class="reference external" href="https://ep2012.europython.eu/"&gt;EuroPython&lt;/a&gt; - you&#8217;ll have until Sunday to vote for my proposals (and
others).&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Protocol-specifications-written-in-Python</guid><pubDate>Thu, 29 Mar 2012 10:22:27 GMT</pubDate></item><item><title>PyCon 2012 - the other stuff</title><link>http://blaag.haard.se/PyCon-2012---the-other-stuff</link><description>&lt;div class="document" id="pycon-2012-the-other-stuff"&gt;
&lt;h1 class="title"&gt;PyCon 2012 - the other stuff&lt;/h1&gt;
&lt;p&gt;I have tried to do a full writeup of my PyCon experience this year, and failed miserably, so this is what I&#8217;ll do: This post will focus only on the conference experience - lessons learned, sessions attended, and projects discovered will have their own posts; this is the other stuff.&lt;/p&gt;
&lt;p&gt;So what about the conference as a whole? It was, just like Atlanta last year, an overwhelmingly positive experience. This was the first time I volunteered, and I really felt that that was a given win - from getting to have a say in the program by joining the program committee, through doing a session as a session runner and getting to see all the work that goes on behind the scenes, to responding to a just-in-time tweet to join the swag-packing party. Just standing somewhere and looking confused would prompt someone more experienced to help you out, and people were just so genuinely &lt;em&gt;nice&lt;/em&gt;. Will definitely do again.&lt;/p&gt;
&lt;p&gt;The venue was good, although as others have already remarked, the open spaces were too far away from the main rooms - I believe this made both the BoFs and the hallway track a bit less exciting than last year.&lt;/p&gt;
&lt;p&gt;Food was acceptable, and lunch was served in a timely fashion - breakfast was awesome the first day, and good the following days.&lt;/p&gt;
&lt;p&gt;The swag was good, apart from the orange bottle opener - you know who
you are. Also, so many t-shirts!&lt;/p&gt;
&lt;p&gt;(I really need to fix proper tags for posts so that I don't have to
hack a post on PyCon into the Python rss feed used by Planet Python...))&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/PyCon-2012---the-other-stuff</guid><pubDate>Thu, 22 Mar 2012 21:30:31 GMT</pubDate></item><item><title>[rant] Dare to show your code</title><link>http://blaag.haard.se/rant--Dare-to-show-your-code</link><description>&lt;div class="document" id="rant-dare-to-show-your-code"&gt;
&lt;h1 class="title"&gt;[rant] Dare to show your code&lt;/h1&gt;
&lt;p&gt;My name is Fredrik, and sometimes I write code I&#8217;m not that proud of.&lt;/p&gt;
&lt;p&gt;A friend of mine started on a Python project recently, and when I
asked him to put it up on Bitbucket his response was an immediate and
not-quite-mock &#8220;But then people will see my code!&#8221;. I believe this
fear of showing one&#8217;s code is common, and I believe that it is a
problem. Not so much for open source, or anything like that, but for
the individual - it suggests a belief that your code isn&#8217;t good
enough, that other people&#8217;s code is better, and/or that offering my
code up for others to see will lead to rejection and ridicule. I know
I was wary before suggesting a patch to Python, because I feared it
was not good enough (it was, but the tests weren&#8217;t - nobody was mean
in telling me they needed work to conform). I had over ten
repositories at &lt;a class="reference external" href="https://bitbucket.org/haard"&gt;Bitbucket&lt;/a&gt; before I open sourced the first one, and I
spent too much time worrying over the &lt;a class="reference external" href="https://bitbucket.org/haard/autohook"&gt;autohook&lt;/a&gt; source before daring
to make it public... for no good reason at all.&lt;/p&gt;
&lt;p&gt;Sometimes I&#8217;m not proud of my code; I was in a hurry, I was new to the
tools or the domain, I was lazy, I did not know better at the time,
there were customer demands I could not fulfill in any other way, or
any other reason or excuse. Sometimes somebody tells me I should clean
up my code - and that is good. Having others critique your code is one
of the best ways of getting better, and knowing that others will look
at your code will make you (at least it makes me) write better
code. This is why code review is such a powerful tool - even if the
reviews seldom find serious errors, people tend to write better code
when they know somebody will read it &lt;em&gt;right now&lt;/em&gt;, as opposed to that
someone will be forced to read it when maintaining the code base some
time in the future.&lt;/p&gt;
&lt;p&gt;Added to this is, as much as we feel bad when showing our own code, so
does everybody else, from time to time. Not all code will be perfect -
I&#8217;d argue that if we spent the time to make all code perfect, we&#8217;d
never get anything done. Besides, not everyone will agree on what
perfect code entails, so it&#8217;s a fools errand - someone will always
think there are things about your code that are imperfect. And that&#8217;s
OK. Showing off my code online (some of it really ugly, like the
&lt;a class="reference external" href="https://bitbucket.org/haard/blaag"&gt;Blaag source code&lt;/a&gt;, has netted me all of two immature flames, but
also some clever insights, pull requests with bug fixes, and in one
case even someone to discuss the code with (thanks Martijn!).&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/rant--Dare-to-show-your-code</guid><pubDate>Fri, 02 Mar 2012 14:01:54 GMT</pubDate></item><item><title>Python Closures and Decorators (Pt. 2)</title><link>http://blaag.haard.se/Python-Closures-and-Decorators--Pt--2</link><description>&lt;div class="document" id="python-closures-and-decorators-pt-2"&gt;
&lt;h1 class="title"&gt;Python Closures and Decorators (Pt. 2)&lt;/h1&gt;
&lt;p&gt;Edit: got complaints that code was hard to read, trying out &lt;a class="reference external" href="http://pygments.org/"&gt;Pygments&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In &lt;a class="reference external" href="/Python-Closures-and-Decorators--Pt--1"&gt;part 1&lt;/a&gt;, we looked at sending functions as arguments to other
functions, at nesting functinons, and finally we wrapped a function in
another function. We'll begin this part by giving an example
implementation on the exercise I gave in &lt;a class="reference external" href="/Python-Closures-and-Decorators--Pt--1"&gt;part 1&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn_wrap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Calling &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; with arguments: &lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s"&gt;args: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="se"&gt;\n\t&lt;/span&gt;&lt;span class="s"&gt;kwargs:&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;            &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;retval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; returning '&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;'&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;retval&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;retval&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="n"&gt;fn_wrap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;func_name&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fn_wrap&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'world'&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;!&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Hi'&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
     &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:{}&lt;/span&gt;
&lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="s"&gt;'Hi world!'&lt;/span&gt;
&lt;span class="s"&gt;'Hi world!'&lt;/span&gt;

&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Hi&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Python&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Hi'&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
     &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="s"&gt;'what'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'Python'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;greeter&lt;/span&gt; &lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="s"&gt;'Hi Python!'&lt;/span&gt;
&lt;span class="s"&gt;'Hi Python!'&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, this is at least mildly useful, but it'll get better! You may or
may not have heard of &lt;em&gt;closures&lt;/em&gt;, and you may have heard any of a
large number of defenitions of what a closure is - I won't go into
nitpicking, but just say that a closure is a block of code (for
example a function) that captures (or &lt;em&gt;closes over&lt;/em&gt;) non-local (free)
variables. If this is all gibberish to you, you're probably in need of
a CS refresher, but fear not - I'll show by example, and the concept
is easy enough to understand: a function can reference variables that
are defined in the function's enclosing scope.&lt;/p&gt;
&lt;p&gt;For example, take a look at this code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_a&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_a&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_a&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;As you can see, the function &lt;tt class="docutils literal"&gt;get_a&lt;/tt&gt; can get the value of &lt;tt class="docutils literal"&gt;a&lt;/tt&gt;, and
will be able to read the updated value. However, there is a
limitation - a captured variable cannot be written to:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;set_a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;
&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;What happened here? Since a closure cannot write to any captured
variables, &lt;tt class="docutils literal"&gt;a = val&lt;/tt&gt; actually writes to a local variable a that
shadows the module-level &lt;tt class="docutils literal"&gt;a&lt;/tt&gt; that we wanted to write to. To get
around this limitation (which may or may not be a good idea), we can
use a container type:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;object&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;pass&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;set_a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;val&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;val&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;set_a&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;So, with the knowledge that a function captures variables from it's
enclosing scope, we're finally approaching something interesting, and
we'll start by implementing a &lt;em&gt;partial&lt;/em&gt;. A partial is an instance of
a function where you have already filled in some or all of the
arguments; let's say, for example that you have a session with
username and password stored, and a function that queries some
backend layer which takes different arguments but &lt;em&gt;always&lt;/em&gt; require
credentials. Instead of passing the credentials manually every time,
we can use a partial to pre-fill those values:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;#Our 'backend' function&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stuff_id&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="s"&gt;&amp;quot;&amp;quot;&amp;quot;Here we would presumably fetch data using the supplied
...   credentials and id&amp;quot;&amp;quot;&amp;quot;&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;get_stuff called with user: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;, pw: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;, stuff_id: &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stuff_id&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fn_part&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fn_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;fn_kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn_kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fn_args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fn_part&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;my_stuff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;partial&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;get_stuff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'myuser'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'mypwd'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;my_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;get_stuff&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;myuser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mypwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stuff_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;my_stuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;67&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;get_stuff&lt;/span&gt; &lt;span class="n"&gt;called&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;myuser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pw&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;mypwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stuff_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;67&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Partials can be used in numerous places to remove code duplication
where a function is called in different places with the same, or
almost the same, arguments. Of course, you don't &lt;em&gt;have&lt;/em&gt; to implement it
yourself; just do &lt;tt class="docutils literal"&gt;from functools import partial&lt;/tt&gt;.&lt;/p&gt;
&lt;p&gt;Finally, we'll take a look at function decorators (there may be a post
on class decorators in the future). A function decorator is (&lt;em&gt;can be
implemented as&lt;/em&gt;) a function that takes a function as parameter and
returns a new function. Sounds familiar? It should, because we've
already implemented a working decorator: our &lt;tt class="docutils literal"&gt;print_call&lt;/tt&gt; function
is ready to be used as-is:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;&amp;#64;print_call&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;will_be_logged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;will_be_logged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Calling&lt;/span&gt; &lt;span class="n"&gt;will_be_logged&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
     &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'!'&lt;/span&gt;&lt;span class="p"&gt;,)&lt;/span&gt;
     &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;:{}&lt;/span&gt;
&lt;span class="n"&gt;will_be_logged&lt;/span&gt; &lt;span class="n"&gt;returning&lt;/span&gt; &lt;span class="s"&gt;'!!!!!'&lt;/span&gt;
&lt;span class="s"&gt;'!!!!!'&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;Using the &amp;#64;-notation is simply a convenient shorthand to doing:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;will_be_logged&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;will_be_logged&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;print_call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;will_be_logged&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;But what if we want to be able to parameterize the decorator? In this
case, the function used as a decorator will received the arguments,
and will be expected to return a function that wraps
the decorated function:&lt;/p&gt;
&lt;blockquote&gt;
&lt;pre class="code python literal-block"&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;wrapper&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;new_fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&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="n"&gt;role&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'roles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt; not in &lt;/span&gt;&lt;span class="si"&gt;%s&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;role&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'roles'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])))&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;         &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Unauthorized&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;new_fn&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;wrapper&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;&amp;#64;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="o"&gt;...&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;new_fn&lt;/span&gt;
&lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="n"&gt;admin&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'editor'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Traceback&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;most&lt;/span&gt; &lt;span class="n"&gt;recent&lt;/span&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;module&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;&amp;lt;stdin&amp;gt;&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;line&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;new_fn&lt;/span&gt;
&lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Unauthorized&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;get_users&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;roles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;'user'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;'Alice'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;'Bob'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;...and there you have it. You are now ready to write decorators, and
perhaps use them to write aspect-oriented Python; adding &amp;#64;cache,
&amp;#64;trace, &amp;#64;throttle are all trivial (and before you add &amp;#64;cache, do check
functools once more if you're using Python 3!).&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Python-Closures-and-Decorators--Pt--2</guid><pubDate>Thu, 01 Mar 2012 19:04:34 GMT</pubDate></item><item><title>Python Closures and Decorators (Pt. 1)</title><link>http://blaag.haard.se/Python-Closures-and-Decorators--Pt--1</link><description>&lt;div class="document" id="python-closures-and-decorators-pt-1"&gt;
&lt;h1 class="title"&gt;Python Closures and Decorators (Pt. 1)&lt;/h1&gt;
&lt;p&gt;Since I, in retrospect, made the wrong choice when cutting down a Python course to four hours and messed up the decorator exercise, I promised the attendants that I'd make a post about closures and decorators and explain it better - this is my attempt to do so.&lt;/p&gt;
&lt;p&gt;Functions are objects, too. In fact, in Python they are First Class Objects - that is, they can be handled like any other object with no special restrictions. This gives us some interesting options, and I'll try to move through them from the bottom up.&lt;/p&gt;
&lt;p&gt;A very basic case of using the fact that functions are objects is to use them as you would a function pointer in C; pass it into another function that will use it. To illustrate this, we'll take a look at the implementation of a repeat function - that is, a function that accepts another function as argument together with a number, and then calls the passed function the specified number of times:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;&amp;gt;&amp;gt; #A very simple function
&amp;gt;&amp;gt;&amp;gt; def greeter():
...   print(&amp;quot;Hello&amp;quot;)
...
&amp;gt;&amp;gt;&amp;gt; #An implementation of a repeat function
&amp;gt;&amp;gt;&amp;gt; def repeat(fn, times):
...   for i in range(times):
...     fn()
...
&amp;gt;&amp;gt;&amp;gt; repeat(greeter, 3)
Hello
Hello
Hello
&amp;gt;&amp;gt;&amp;gt;
&lt;/pre&gt;
&lt;p&gt;This pattern is used in a large number of ways - passing a comparison function to a sorting algorithm, passing a decoder function to a parser, and in general &lt;em&gt;specializing&lt;/em&gt; the behaviour of a function, or passing a specific parts of a job to be done into a function that abstracts the work flow (i.e. &lt;tt class="docutils literal"&gt;sort()&lt;/tt&gt; knows how to sort lists, &lt;tt class="docutils literal"&gt;compare()&lt;/tt&gt; knows how to compare elements).&lt;/p&gt;
&lt;p&gt;Functions can also be declared in the body of another function, which gives us another important tool. In the most basic case, this can be used to &amp;quot;hide&amp;quot; utility functions in the scope of the function that uses them:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;&amp;gt;&amp;gt; def print_integers(values):
...   def is_integer(value):
...     try:
...       return value == int(value)
...     except:
...       return False
...   for v in values:
...     if is_integer(v):
...       print(v)
...
&amp;gt;&amp;gt;&amp;gt; print_integers([1,2,3,&amp;quot;4&amp;quot;, &amp;quot;parrot&amp;quot;, 3.14])
1
2
3
&lt;/pre&gt;
&lt;p&gt;This may be useful, but is hardly in itself a very powerful tool. Compared with the fact that functions can be passed as arguments however, we can add behaviours to function after they are constructed, by wrapping them in another function. A simple example would be to add a trace output to a function:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;&amp;gt;&amp;gt; def print_call(fn):
...   def fn_wrap(*args, **kwargs): #take any arguments
...     print(&amp;quot;Calling %s&amp;quot; % (fn.func_name))
...     return fn(*args, **kwargs) #pass any arguments to fn()
...   return fn_wrap
...
&amp;gt;&amp;gt;&amp;gt; greeter = print_call(greeter) #wrap greeter
&amp;gt;&amp;gt;&amp;gt; repeat(greeter, 3)
Calling fn_wrap
Hello
Calling fn_wrap
Hello
Calling fn_wrap
Hello
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; greeter.func_name
'fn_wrap'
&lt;/pre&gt;
&lt;p&gt;As you can see, we can replace the &lt;tt class="docutils literal"&gt;greeter&lt;/tt&gt; function with a new function that uses &lt;tt class="docutils literal"&gt;print&lt;/tt&gt; to log the call, and then calls the original function. As seen on the last two rows of the example, the function name of the function reflects that it has been replaced, which may or may not be what we wanted. If we want to wrap a function while keeping the original name, we can do so by adding a row to our &lt;tt class="docutils literal"&gt;print_call&lt;/tt&gt; function:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;&amp;gt;&amp;gt; def print_call(fn):
...   def fn_wrap(*args, **kwargs): #take any arguments
...     print(&amp;quot;Calling %s&amp;quot; % (fn.func_name))
...     return fn(*args, **kwargs) #pass any arguments to fn()
...   fn_wrap.func_name = fn.func_name #Copy the original name
...   return fn_wrap
&lt;/pre&gt;
&lt;p&gt;Since this is rapidly turning into a very long post, I'll stop here and return tomorrow with part two, where we'll look at closures, partials, and (finally) decorators.&lt;/p&gt;
&lt;p&gt;Until then, if this is all new to you, use &lt;tt class="docutils literal"&gt;print_call&lt;/tt&gt; as a base to create a function that will print function name and arguments passed before calling the wrapped function, and the function name and return value before returning.&lt;/p&gt;
&lt;p&gt;Update: &lt;a class="reference external" href="/Python-Closures-and-Decorators--Pt--2"&gt;part 2&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Python-Closures-and-Decorators--Pt--1</guid><pubDate>Wed, 29 Feb 2012 20:36:29 GMT</pubDate></item><item><title>Blaag using Genshi, greedy bloggers adding ads, and demographics. Also ranting.</title><link>http://blaag.haard.se/Blaag-using-Genshi--greedy-bloggers-adding-ads--and-demographics--Also-ranting</link><description>&lt;div class="document" id="blaag-using-genshi-greedy-bloggers-adding-ads-and-demographics-also-ranting"&gt;
&lt;h1 class="title"&gt;Blaag using Genshi, greedy bloggers adding ads, and demographics. Also ranting.&lt;/h1&gt;
&lt;p&gt;(There will be very little techical content here; if that's what you
are looking for, move along)&lt;/p&gt;
&lt;p&gt;So, I updated &lt;a class="reference external" href="https://bitbucket.org/haard/blaag"&gt;Blaag&lt;/a&gt; to use &lt;a class="reference external" href="http://genshi.edgewall.org"&gt;Genshi&lt;/a&gt; for templating (still in it's own
branch), which was a pretty pleasant experience; I cleared out some of
the worst code from blaag.py and ended up with a single html template
instead of a host of snippets.&lt;/p&gt;
&lt;p&gt;I also added a left column to the template (should probably make it
optional) so that only blog links live in the right column. This made
me go over the 960px with that I used to have, but a quick look at my
visitor statistics claim that most of the visitors won't be adversly
affected by that - I still intend to add a lite/mobile alternate
style, since I do want anyone to be able to read the blog.&lt;/p&gt;
&lt;p&gt;On the topic of visitors, you are a curious bunch, but perhaps what
could be expected of readers of a tech blog: 50% use Chrome, 21%
Firefox, 12% Safari, 6% Android browser, 6% 'Mozilla Compatible',
2% Opera, 1.5% IE, and then a gaggle of uncommon browsers. 31% use
Windows, 30% OSX, 18% Linux of some sort, and the rest are mainly
mobile OSes. About 10% of users block Google Analytics, accoring to
the server logs.&lt;/p&gt;
&lt;p&gt;Also on the topic of visitors, I thought that hey, I have a lot of
visiors, I should be able to get some cash out of the hours spent and
maybe make hosting break-even (rather, move haard.se to a host of it's
own)! I figure that any readers that take offense at ads are in the
10% that block Analytics, and will block the ads, so nothing is
stopping me.&lt;/p&gt;
&lt;p&gt;Well, I tried to read up a bit on ad
programs and ads on tech blogs, but there's not a whole lot of
signal in all the noise that turns up; mainly it advertising for ad
programs, and 'this works/does not work, because I say so'. Figures,
or even mildly solid-looking arguments are missing. Right now I tossed
a AdSense add there just because it was quick and I could force a look
and feel; I suspect it will attract about zero clicks. I could allow a
banner, but AFAIK I cannot then preemtively block ugly, animated or
just wrong ads. In addition, it seems that the AdSense ads are synchronous,
slowing down the site to show ads which is wrong in itself.; nobody
visits the site to view ads, after all.&lt;/p&gt;
&lt;p&gt;So, I'll probably have to look
for another program (or just not have ads), but I have no idea what
that would be, since everyone is so damn secret about their
figures. Right now belive I have about 50K visitors a month who does
not block javascript in general or Google in particular (50K since 8th of
february, when the blog went live for 'real'), but I have no idea
whatsovever where that puts me in the great scheme of things since
people don't seem to talk about their visitor numbers, and I have no idea
where I should look for ads that a) are at least somewhat interesting
to developers b) does not slow down page loading c) Pays enough to
make it worth the overhead of maintaining them for a non-webmaster.&lt;/p&gt;
&lt;p&gt;Meh.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Blaag-using-Genshi--greedy-bloggers-adding-ads--and-demographics--Also-ranting</guid><pubDate>Mon, 27 Feb 2012 17:53:12 GMT</pubDate></item><item><title>Your favourite programming language is not good enough</title><link>http://blaag.haard.se/Your-favourite-programming-language-is-not-good-enough</link><description>&lt;div class="document" id="your-favourite-programming-language-is-not-good-enough"&gt;
&lt;h1 class="title"&gt;Your favourite programming language is not good enough&lt;/h1&gt;
&lt;p&gt;I was blown away by the amount of response - mostly positive - on my &lt;a class="reference external" href="http://blaag.haard.se/Why-Python-is-important-for-you/"&gt;Python is important&lt;/a&gt; post. However, a lot of the replies, both positive and... slightly less positive, really highlighted an issue I have with how a lot developers seem to approach programming languages: the search for the Perfect Language to Love and Protect. Why are so many developers so very emotional when it comes to their favourite programming language? Considering that no language can (yet) magically translate the perfect idea in your head into machine code, all of them exist on a scale of badness - they all limit you more than your own thoughts &lt;em&gt;or&lt;/em&gt; the hardware does.&lt;/p&gt;
&lt;p&gt;I believe that the primary reason people feel the need to vehemently defend a particular language is that they are lazy. Of course, good programmers are always lazy (why else automate?), but this is a specific and very bad laziness - being too lazy to learn. If my favourite language is better than anything else, or maybe at least just as good as anything else, I don't have to spend time and effort learning new languages.&lt;/p&gt;
&lt;p&gt;The main problem with this is not only that you won't find the perfect language, but that when you're only comfortable in one or two languages, the way you solve problems become limited by whats possible to do in those languages - and if the languages you know are similar and from the same paradigm, the problem gets worse.&lt;/p&gt;
&lt;p&gt;When you choose a language to solve a problem, by all means, use the language you feel you will solve it best in - the more powerful, more productive, most comfortable, the one with the most libraries... but if you want to be a serious programmer or developer, rather than someone who dabbles a bit in programming, you need to learn new languages, and you &lt;em&gt;need&lt;/em&gt; to stop believing that you found that one language that is better than the rest. All programming languages have made trade-offs, and none is perfect. I would argue that some languages &lt;em&gt;are&lt;/em&gt; better than others, but no language is the best at everything, and no language got everything right.  Python has it's own problems (its not that it is dynamically typed), so has the different Lisp dialects (its not that it has too many parenthesis), and so has Haskell (its the indisputable fact that it is weird*).&lt;/p&gt;
&lt;p&gt;Learn new languages. Learn not to be partisan and defend 'your' language against any criticism. If you haven't already, read &lt;a class="reference external" href="http://mitpress.mit.edu/sicp/full-text/book/book.html"&gt;Structure and Interpretation of Computer Programs&lt;/a&gt;, and learn some form of Lisp - it will make you see and &lt;em&gt;feel&lt;/em&gt; the limitations of other languages, and the pain will make you a better programmer, whatever language you use.&lt;/p&gt;
&lt;p&gt;* No, I'm not being serious. Haskell is next on my list of languages to learn.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Your-favourite-programming-language-is-not-good-enough</guid><pubDate>Fri, 24 Feb 2012 16:30:26 GMT</pubDate></item><item><title>Python API to git: gitapi</title><link>http://blaag.haard.se/Python-API-to-git--gitapi</link><description>&lt;div class="document" id="python-api-to-git-gitapi"&gt;
&lt;h1 class="title"&gt;Python API to git: gitapi&lt;/h1&gt;
&lt;p&gt;Train rides can be good - if not creativity, then at least
boredom-induced productivity. I had planned to make a &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt; fork that
worked against git instead of Mercurial, and during the ride back from
holding a Python workshop in Malmö (a three-hour trip back to Karlskrona; I still have
another hour to go...), I finally did. &lt;a class="reference external" href="https://bitbucket.org/haard/gitapi"&gt;gitapi&lt;/a&gt; is born, and even
though its in it's infancy, it supports a large number of common
operations. Fair warning - I basically just swiched hg-&amp;gt;git and then fixed the test
cases that still made sense, so there's bound to be some kinks left to
iron out. Either way, the test suite passes on both Python 2.7 and
3.2, so there's something.&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Python-API-to-git--gitapi</guid><pubDate>Tue, 21 Feb 2012 21:24:35 GMT</pubDate></item><item><title>Explaining comprehensions to programmers</title><link>http://blaag.haard.se/Explaining-comprehensions-to-programmers</link><description>&lt;div class="document" id="explaining-comprehensions-to-programmers"&gt;
&lt;h1 class="title"&gt;Explaining comprehensions to programmers&lt;/h1&gt;
&lt;p&gt;For the first year or two programming Python, I never used list
comprehensions (at the time, those were the only comprehensions). I
read about them, I kinda figured out how they worked, and then I stuck
to &lt;tt class="docutils literal"&gt;map()&lt;/tt&gt; and &lt;tt class="docutils literal"&gt;filter()&lt;/tt&gt;, which I understood. Looking back, I
think that this has a lot to do with the fact that explanations of
comprehensions are done using their origin - mathematics - rather than
the domain we use them in - programming.&lt;/p&gt;
&lt;p&gt;A quick &lt;a class="reference external" href="http://duckduckgo.com"&gt;duckduckgo&lt;/a&gt; search tells me this is still the case -
&lt;a class="reference external" href="http://en.wikipedia.org/wiki/List_comprehension#Overview"&gt;Wikipedia&lt;/a&gt; asks us to consider something like this: &lt;span class="math"&gt;
\(S = \{2 \cdot x | x \epsilon N |
x &amp;gt; 3\}\)&lt;/span&gt;
, and other sources also seem to start out with &#8216;this is how its
done in math, so...&#8217; (a notable exception is the &lt;a class="reference external" href="http://docs.python.org/tutorial/datastructures.html#list-comprehensions"&gt;tutorial&lt;/a&gt; on
&lt;a class="reference external" href="http://python.org"&gt;python.org&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;When talking to programmers, I&#8217;d like to explain comprehensions
differently, because not all programmers have a background in
mathematics. For a programmer, a list comprehension is simply a
for loops for constructing lists, using a more declarative notation
than your usual for loop. For those of us used to &lt;tt class="docutils literal"&gt;map()&lt;/tt&gt; and
&lt;tt class="docutils literal"&gt;filter()&lt;/tt&gt;, list comprehensions are both of those as well.&lt;/p&gt;
&lt;p&gt;Consider:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
def loop(my_list):
  result = []
  for x in my_list:
      if x &amp;gt; 3:
          result.append(x*2)
  return result
&lt;/pre&gt;
&lt;p&gt;Ever written code like this? This is code that explicitly states which
steps should be taken to construct your list; but you don&#8217;t have to -
you can instead state what you want:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
def compr(my_list):
  return [x*2 for x in my_list if x &amp;gt; 3]
&lt;/pre&gt;
&lt;p&gt;This translates to &lt;em&gt;give me value*2 for every value in my_list, but
only if that value is more than three&lt;/em&gt;. Note also that this expression
does the work of both &lt;cite&gt;map&lt;/cite&gt; (multiply by two) and &lt;cite&gt;filter&lt;/cite&gt; (take only
values that are less than two). The general case would be [add
something to the list &lt;tt class="docutils literal"&gt;for&lt;/tt&gt; each value in an iterable, optionally
only &lt;tt class="docutils literal"&gt;if&lt;/tt&gt; a condition is True for that value]&lt;/p&gt;
&lt;p&gt;Comprehensions also work nested - consider this simple but ugly code:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
def create_matrix_loop(size, default):
  new_matrix = []
  for y in range(size):
    row = []
    for x in range(size):
      row.append(default)
    new_matrix.append(row)
return new_matrix
&lt;/pre&gt;
&lt;p&gt;Sample output:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;create_matrix_loop(3, None)
[[None, None, None],
 [None, None, None],
 [None, None, None]]
&lt;/pre&gt;
&lt;p&gt;Since comprehensions can be nested, this can be replaced with:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
def create_matrix_compr(size, default):
  return [[default for x in range(size)] for x in range(size)]
&lt;/pre&gt;
&lt;p&gt;As an added bonus, when we don&#8217;t tell the compiler how we want to do
something, but rather what we want done, it can generate better -
faster - bytecode for us. The loop version of create_matrix is
translated into 35 bytecode instructions, and the version using a list
comprehension is only 20 (try &lt;tt class="docutils literal"&gt;import dis; dis.dis(func)&lt;/tt&gt; to see
what &lt;tt class="docutils literal"&gt;func&lt;/tt&gt; looks like in bytecode) and in reality, you will often
avoid making a function at all when using comprehensions since they&#8217;re
terse enough on their own, making this difference even bigger. Timing
the implementations, the difference is evident:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
&amp;gt;timeit -n100 create_matrix_loop(1000, None)
100 loops, best of 3: 113 ms per loop

&amp;gt;timeit -n100 create_matrix_compr(1000, None)
100 loops, best of 3: 49.1 ms per loop
&lt;/pre&gt;
&lt;p&gt;That's right: less code, declarative syntax, &lt;em&gt;and&lt;/em&gt; faster execution!
(Note: I used &lt;a class="reference external" href="http://ipython.org/"&gt;iPython&lt;/a&gt; when creating and timing the examples - it's awesome
and you should try it)&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Explaining-comprehensions-to-programmers</guid><pubDate>Thu, 16 Feb 2012 11:10:39 GMT</pubDate></item><item><title>Why Python is important for you</title><link>http://blaag.haard.se/Why-Python-is-important-for-you</link><description>&lt;div class="document" id="why-python-is-important-for-you"&gt;
&lt;h1 class="title"&gt;Why Python is important for you&lt;/h1&gt;
&lt;p&gt;I believe that Python is important for software development. While
there are more powerful languages (e.g. Lisp), faster languages
(e.g. C), more used languages (e.g. Java), and weirder languages
(e.g. Haskell), Python gets a lot of different things &lt;em&gt;right&lt;/em&gt;, and
right in a combination that no other language I know of has done so
far.&lt;/p&gt;
&lt;p&gt;It recognises that you&#8217;ll spend a lot more time reading code than
writing it, and focuses on guiding developers to write readable
code. It&#8217;s possible to write obfuscated code in Python, but the
easiest way to write the code (assuming you know Python) is almost
always a way that is reasonable terse, and more importantly: code that
clearly signals intent. If you know Python, you can work with almost
any Python with little effort. Even libraries that add &#8220;magic&#8221;
functionality can be written in perfectly readable Python (compare
this to understanding the implementation of a framework such as Spring
in Java).&lt;/p&gt;
&lt;p&gt;Python also acknowledges that speed of development is
important. Readable and terse code is part of this, and so is access
to powerful constructs that avoid tedious repetition of
code. Maintainability also ties into this - LoC may be a all but
useless metric, but it does say something about how much code you have
to scan, read and/or understand to troubleshoot problems or tweak
behaviours.&lt;/p&gt;
&lt;p&gt;This speed of development, the ease with which a programmer of other
languages can pick up basic Python skills, and the huge standard
library is key to another area where Python excels - toolmaking. Any
project of size will have tasks to automate, and automating them in
Python is in my experience orders of magnitude faster than using more
mainstream languages - in fact, that was how I started out with
Python, creating a tool to automate configuring Rational Purify for a
project where it before was such a chore that it was never run (and
memory leaks were not fixed). I&#8217;ve since created tools to extract
information from ticket systems and presenting them in a way useful to
the team, tools to check poms in a Maven project, Trac integration,
custom monitoring tools... and a whole lot more. All of those tools
have been quick to implement, saved a lot of time, and several of them
has later been patched and updated by people &lt;em&gt;with no Python
background&lt;/em&gt; - without breaking.&lt;/p&gt;
&lt;p&gt;That building custom tools is easy hints at another strength -
building and maintaining custom software is easy, period. This is why,
while the quite huge &lt;a class="reference external" href="http://djangoproject.com"&gt;Django&lt;/a&gt; framework might be the most famous Python
web framework, there is also a host of successful small and
micro-frameworks. When working in a powerful programming language with
a wide array of standard and third-party libraries, you often don&#8217;t
&lt;em&gt;need&lt;/em&gt; to accept the trade-offs that are necessary when using any
large off-the-shelf framework. This means that you can build &lt;em&gt;exactly&lt;/em&gt;
the software your customers want, rather than telling them that &lt;em&gt;&#8221;this
is how it&#8217;s done, sorry&#8221;&lt;/em&gt;. To me, this is a huge difference. I feel
&lt;strong&gt;ashamed&lt;/strong&gt; when I have to tell a customer that no, sorry, this
&lt;em&gt;seems&lt;/em&gt; like a simple requirement, but the framework we use makes it
impossible or prohibitively expensive to implement. Whenever this
happens, you have failed. Writing software that fits into the
customer&#8217;s model rather than into a framework is &lt;em&gt;important&lt;/em&gt;, and I
for one feel that a lot of developers today has lost sight of that
simple fact. A lot of programmers now spend more time being
configurators of frameworks and makíng excuses for their shortcomings,
rather than actual programming.&lt;/p&gt;
&lt;p&gt;Finally, if you&#8217;re a boss-wo/man or general manager, using Python has a final benefit - Python programmers run into less frustration*, which makes them happier, and even more productive!&lt;/p&gt;
&lt;p&gt;(*may not be true when installing source-distributed C extensions on
Windows)&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Why-Python-is-important-for-you</guid><pubDate>Sat, 11 Feb 2012 10:26:03 GMT</pubDate></item><item><title>Using Python to get rid of .doc</title><link>http://blaag.haard.se/Using-Python-to-get-rid-of--doc</link><description>&lt;div class="document" id="using-python-to-get-rid-of-doc"&gt;
&lt;h1 class="title"&gt;Using Python to get rid of .doc&lt;/h1&gt;
&lt;p&gt;I'll be appearing att &lt;a class="reference external" href="http://softwarepassion.se/"&gt;Software Passion&lt;/a&gt;  to speak about using Python
for protocol specifications, instead of using an external document to
write the specification, and then try to implement it from there (or,
perhaps more common, implementing it and then trying to keep the
document up-to-date).&lt;/p&gt;
&lt;p&gt;A while ago at &lt;a class="reference external" href="http://www.visualunits.se"&gt;Visual Units&lt;/a&gt;, the situation was this: There was a
protocol to transfer data over TCP from fleet management black boxes running J2ME to a
server running Python, which then stored that data so interesting
things could be done with it. Accompanying the protocol was a
ever-slightly-out-of-date protocol specification, and a client
implementation in Python used for testing the server.&lt;/p&gt;
&lt;p&gt;This means that we had four different implementations of the protocol:
one in Java, two in Python, and one in English. If one of those was
not updated when the others were, the system was no longer consistent,
and might break in interesting ways.&lt;/p&gt;
&lt;p&gt;Since this created a lot of work for me, I set out to change
things. First, I searched for viable existing solutions, but the need
to keep the protocol compact (telematics data transfer is expensive),
and J2ME support meant I did not find anything to use off the shelf.&lt;/p&gt;
&lt;p&gt;Instead I started to implement my own solution, with a vision that I
would implement the protocol once, and use it everywhere - Java,
Python, and English. In the end, using a couple of hundred of rows of
Python, we can now specify a protocol thus:&lt;/p&gt;
&lt;pre class="literal-block"&gt;
message = string
timestamp = i64
timediff = i32

ping = (&amp;quot;A ping, with a time and message&amp;quot;,
         timestamp, message)

pong = (&amp;quot;A pong, with message, timestamp and perceived lag&amp;quot;,
        timestamp, timediff, message)
&lt;/pre&gt;
&lt;p&gt;...and from this, we create Java source code for the terminals, the
Python clients and servers use it directly when packing and parsing
messages, and the documentation for the poor souls who might want to
read English instead of Python is generated.&lt;/p&gt;
&lt;p&gt;Want to know how this was made possible, see some code, and point and
laugh at my miserable attempts that failed? Want to know why
meta-classes were absolutely vital - or not? &lt;a class="reference external" href="http://softwarepassion.se/register.do"&gt;Register&lt;/a&gt; for &lt;a class="reference external" href="http://softwarepassion.se/"&gt;Software
Passion&lt;/a&gt; where I'll be talking about this - if you use the promontion
code 'BLAAG' when registering, you'll even get a 10% discount!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Using-Python-to-get-rid-of--doc</guid><pubDate>Tue, 07 Feb 2012 18:36:26 GMT</pubDate></item><item><title>Mercurial in Python 3: promoting hgapi</title><link>http://blaag.haard.se/Mercurial-in-Python-3--promoting-hgapi</link><description>&lt;div class="document" id="mercurial-in-python-3-promoting-hgapi"&gt;
&lt;h1 class="title"&gt;Mercurial in Python 3: promoting hgapi&lt;/h1&gt;
&lt;p&gt;When I took a look at the &lt;a class="reference external" href="http://www.python.org"&gt;python.org&lt;/a&gt; &lt;a class="reference external" href="http://python.org/3kpoll"&gt;Py3k poll&lt;/a&gt;, I saw that Mercurial was on the top list of things people wanted ported (though far behind the likes of Django). Now, I don't know why others want to tie into Mercurial from code, but if a little performance overhead from using the CLI isn't critical - such as when writing &lt;a class="reference external" href="https://bitbucket.org/haard/autohook"&gt;hooks&lt;/a&gt;, or just integrating version control in some &lt;a class="reference external" href="https://bitbucket.org/haard/blaag"&gt;tool&lt;/a&gt; or another, you might want to consider &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;hgapi uses only the command line interface, and was created to be able to release &lt;a class="reference external" href="https://bitbucket.org/haard/autohook"&gt;autohook&lt;/a&gt; under a more permissive license than the GPL - and it's tested against both Python 2.7 and Python 3.2. It now supports most (for a given computation of 'most') operations in Mercurial, and as a bonus there are no open feature requests - so if there is something you miss, this is the time to request it!&lt;/p&gt;
&lt;p&gt;Also, don't forget to register for &lt;a class="reference external" href="https://us.pycon.org/2012/registration/"&gt;PyCon&lt;/a&gt;, early bird rates until 25/1!&lt;/p&gt;
&lt;blockquote&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Mercurial-in-Python-3--promoting-hgapi</guid><pubDate>Thu, 19 Jan 2012 17:00:00 GMT</pubDate></item><item><title>What's the point of properties in Python?</title><link>http://blaag.haard.se/What-s-the-point-of-properties-in-Python</link><description>&lt;div class="document" id="what-s-the-point-of-properties-in-python"&gt;
&lt;h1 class="title"&gt;What's the point of properties in Python?&lt;/h1&gt;
&lt;p&gt;A few days ago I was asked by a collegaue what the point of properties
in Python is. After all, writing properties is as much text as
writing getters and setters, and they don't really add any
functionality except from not having to write '()' on access.&lt;/p&gt;
&lt;p&gt;On the surface, this argument holds as we can see by comparing a
simple class implemented with getters and setters, and with properties.&lt;/p&gt;
&lt;div class="section" id="implemented-with-getters-and-setters"&gt;
&lt;h1&gt;Implemented with getters and setters:&lt;/h1&gt;
&lt;pre class="doctest-block"&gt;
&amp;gt;&amp;gt;&amp;gt; class GetSet(object):
...   x = 0
...   def set_x(self, x):
...     self.x = x
...   def get_x(self):
...     return self.x
...
&lt;/pre&gt;
&lt;pre class="doctest-block"&gt;
&amp;gt;&amp;gt;&amp;gt; getset = GetSet()
&amp;gt;&amp;gt;&amp;gt; getset.set_x(3)
&amp;gt;&amp;gt;&amp;gt; getset.get_x()
3
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="and-implemented-with-properties"&gt;
&lt;h1&gt;And implemented with properties:&lt;/h1&gt;
&lt;pre class="doctest-block"&gt;
&amp;gt;&amp;gt;&amp;gt; class Props(object):
...   _x = 0
...   &amp;#64;property
...   def x(self):
...     return self._x
...   &amp;#64;x.setter
...   def x(self, x):
...     self._x = x
...
&amp;gt;&amp;gt;&amp;gt; props = Props()
&amp;gt;&amp;gt;&amp;gt; props.x = 5
&amp;gt;&amp;gt;&amp;gt; props.x
5
&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="section" id="the-point"&gt;
&lt;h1&gt;The point&lt;/h1&gt;
&lt;p&gt;In fact, we've gone from 196 to 208 chars in this simple use case - so
why would we use properties at all?&lt;/p&gt;
&lt;p&gt;The answer is, that in this use case we would not. In fact, we would
write thus:&lt;/p&gt;
&lt;pre class="doctest-block"&gt;
&amp;gt;&amp;gt;&amp;gt; class MyClass(object):
...   x = 0
...
&amp;gt;&amp;gt;&amp;gt; my = MyClass()
&amp;gt;&amp;gt;&amp;gt; my.x = 4
&amp;gt;&amp;gt;&amp;gt; my.x
4
&lt;/pre&gt;
&lt;p&gt;'But!', I can hear you scream, 'there's no encapsulation!'. What will
we do if we need to control access to x, make it read-only or do
something else to it? Won't we have to refactor everything to the
getters and setters that we avoided?&lt;/p&gt;
&lt;p&gt;No - we just switch to the property version, add whatever we want, and
have not changed the interface one iota! The great thing about
properties is not that they replace getters and setters, its that you
don't have to write them to future-proof your code. You can start out
by writing the simplest implementation imaginable, and if you later
need to change the implementation you can still do so without changing
the interface. Neat, huh?&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/What-s-the-point-of-properties-in-Python</guid><pubDate>Sun, 15 Jan 2012 13:03:16 GMT</pubDate></item><item><title>hgapi 1.1.0</title><link>http://blaag.haard.se/hgapi-1-1-0</link><description>&lt;div class="document" id="hgapi-1-1-0"&gt;
&lt;h1 class="title"&gt;hgapi 1.1.0&lt;/h1&gt;
&lt;p&gt;As a belated christmas gift, I just released &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt; version 1.1.0. New
since 1.0.1 is support for hg status, merge and revert. This means
that I right now have no firm plans for the future, as the tool does
what I need it to do. If you have other requirements, add them to the
issue tracker.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/hgapi-1-1-0</guid><pubDate>Thu, 29 Dec 2011 13:21:16 GMT</pubDate></item><item><title>Jenkins</title><link>http://blaag.haard.se/Jenkins</link><description>&lt;div class="document" id="jenkins"&gt;
&lt;h1 class="title"&gt;Jenkins&lt;/h1&gt;
&lt;p&gt;Recently, I wanted to migrate some lightweight services from a virtual
host to an account at &lt;a class="reference external" href="http://www.webfaction.com/"&gt;Webfaction&lt;/a&gt;, since running a wiki/issue tracker
(&lt;a class="reference external" href="http://trac.edgewall.org/"&gt;Trac&lt;/a&gt;) and CI server (&lt;a class="reference external" href="http://jenkins-ci.org/"&gt;Jenkins&lt;/a&gt;) for a couple of low-volume projects
really shouldn&#8217;t take a whole machine of it&#8217;s own. Or should it?&lt;/p&gt;
&lt;p&gt;This is when I realized that Jenkins is heavyweight in a world of
cloud and shared hosts. I already kinda knew, since I've been
administrating a Jenkins installation that claims several gigs of RAM,
but that's with over thirty Maven projects and a pretty high load.&lt;/p&gt;
&lt;p&gt;Firing Jenkins up and configuring two (Ant) projects, it claims ~150Mb
RAM - for doing nothing. On a shared host, that&#8217;s unacceptable. Under
the old RAM limits on Webfaction, it&#8217;d be impossible to run, now its
just claiming 3/5 of my total memory allotment.&lt;/p&gt;
&lt;p&gt;So yesterday I set up continuous integration using a Python script
that runs the build, determines fail or success, and publishes the log
and/or artifacts; it took a bit less than an hour to get working from
scratch (admittedly using my own Mercurial lib for integration).&lt;/p&gt;
&lt;p&gt;Now I'm thinking of maybe creating something useful out of this. Right
now, I publish logs as static web pages, but I could just post them as
wiki pages to Trac via &lt;a class="reference external" href="http://trac-hacks.org/wiki/XmlRpcPlugin"&gt;RPC&lt;/a&gt;. That would allow logs to tie into the
ticket system and source browser, and I could show build status right
there on the Kanban-ish-board next to the tickets.&lt;/p&gt;
&lt;p&gt;I've got no firm design done yet, but I'm thinking about what the
requirements for a minimalistic CI tool should be:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;Take no resources apart from disk space when idle&lt;/li&gt;
&lt;li&gt;Be able to publish fail and success logs in a useful format&lt;ul&gt;
&lt;li&gt;It should be trivial (for real) to implement support for new targets for result publishing&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Ability to limit resource usage (number of concurrent builds)&lt;/li&gt;
&lt;li&gt;Jobs can trigger each other&lt;/li&gt;
&lt;li&gt;more?&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Jenkins</guid><pubDate>Wed, 28 Dec 2011 13:21:44 GMT</pubDate></item><item><title>Problem exist between chair and keyboard</title><link>http://blaag.haard.se/Problem-exist-between-chair-and-keyboard</link><description>&lt;div class="document" id="problem-exist-between-chair-and-keyboard"&gt;
&lt;h1 class="title"&gt;Problem exist between chair and keyboard&lt;/h1&gt;
&lt;p&gt;It was pointed out to me that a entry was missing. My initial
reaction was &amp;quot;No, its not!&amp;quot;, but then had to confess that yes, an entry
that had been posted was missing. This was because I've developed (and
written) for blaag on several computers, and I'd accidently made a
closed head tip and lost an update. Maybe I need to add some
functionality to make sure that existing posts do not disappear.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Problem-exist-between-chair-and-keyboard</guid><pubDate>Wed, 28 Dec 2011 13:04:19 GMT</pubDate></item><item><title>Autohook updated</title><link>http://blaag.haard.se/Autohook-updated</link><description>&lt;div class="document" id="autohook-updated"&gt;
&lt;h1 class="title"&gt;Autohook updated&lt;/h1&gt;
&lt;p&gt;When I linked to autohook the other day, I was not prepared that
somebody would actually try it, and tell me that it did not work.&lt;/p&gt;
&lt;p&gt;So, eating my own dogfood I set up the released version of &lt;a class="reference external" href="https://bitbucket.org/haard/autohook"&gt;autohook&lt;/a&gt;,
to run Blaag generation, and realized that it did, indeed, not
work. This is fixed now in version 1.1.0, which also does away with
using &amp;quot;&lt;em&gt;if __name__ ...&lt;/em&gt;&amp;quot; and instead uses setuptools magic to create
runnable scripts.&lt;/p&gt;
&lt;p&gt;In addition, I realized that setting up hooks for a single repo was
kind of a pain, so I simplified the configuration for that use case.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Autohook-updated</guid><pubDate>Wed, 21 Dec 2011 13:48:51 GMT</pubDate></item><item><title>Tools for better Python</title><link>http://blaag.haard.se/Tools-for-better-Python</link><description>&lt;div class="document" id="tools-for-better-python"&gt;
&lt;h1 class="title"&gt;Tools for better Python&lt;/h1&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/dt&gt;
&lt;dd&gt;pip install virtualenv pylint ipython autohook&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;Tools I use every day to write better Python, to make it more fun, or just easier:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;A good editor: I prefer &lt;a class="reference external" href="http://www.gnu.org/s/emacs/"&gt;Emacs&lt;/a&gt;, you might like something else, but trust me on this - it&#8217;ll be a humongous project that forces you to use a full IDE. If you stay clear of large web frameworks, you might never need it. I started out using PyDev since I was used to Eclipse, but now I just don&#8217;t think its worth the complexity and overhead.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://pypi.python.org/pypi/virtualenv"&gt;virtualenv&lt;/a&gt;: I use my virtualenvs for more than just Python these days, and setting a new environment up is the first thing I do when starting a new project.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://www.logilab.org/project/pylint"&gt;pylint&lt;/a&gt;: Not only does it tell you what you might want to fix in your code, it tells you if your code gets better or worse. The more unsure you are, the more you should use pylint.&lt;/li&gt;
&lt;li&gt;&lt;a class="reference external" href="http://ipython.org/"&gt;ipython&lt;/a&gt;: While REPL is nice, iPython is truly awesome for testing and prototyping. For me, its gradually replacing bash as well.&lt;/li&gt;
&lt;li&gt;unittest/unittest2: Python comes with built-in unit test support - use it (where appropriate)!&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;These are the tools I use in almost any project, and recently I&#8217;ve added one of my own:&lt;/p&gt;
&lt;blockquote&gt;
&lt;ul class="simple"&gt;
&lt;li&gt;&lt;a class="reference external" href="https://bitbucket.org/haard/autohook"&gt;autohook&lt;/a&gt;, to run pylint/unit tests on commit to Mercurial&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Finally, I&#8217;d like to point anyone starting out with Python to the excellent introduction set up by Mir Nazim at &lt;a class="reference external" href="http://mirnazim.org/writings/python-ecosystem-introduction/"&gt;his site&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Tools-for-better-Python</guid><pubDate>Tue, 20 Dec 2011 09:13:44 GMT</pubDate></item><item><title>On useless testing</title><link>http://blaag.haard.se/On-useless-testing</link><description>&lt;div class="document" id="on-useless-testing"&gt;
&lt;h1 class="title"&gt;On useless testing&lt;/h1&gt;
&lt;p&gt;All testing is not valuable. There. I said it.&lt;/p&gt;
&lt;p&gt;If you take a look at the &lt;a class="reference external" href="https://bitbucket.org/haard/blaag/src"&gt;source&lt;/a&gt; of Blaag, you might notice a certain
lack of tests. No unit test, no tests at all in fact. Does this mean I
do not believe in unit tests, TDD and testing in general? No! If you
take a look at &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt;, for example, I wrote almost all code using TDD
since that was the only way to know I got it right.&lt;/p&gt;
&lt;p&gt;When starting on Blaag (which did at the time not have a name), I
began by creating testblaag.py, writing &lt;tt class="docutils literal"&gt;import unittest&lt;/tt&gt; - and then
I froze. I had no idea what a test for Blaag would look
like. Everything Blaag does, is glue code. It fetches data, feeds it
to &lt;a class="reference external" href="http://docutils.sourceforge.net"&gt;docutils&lt;/a&gt;, collects some additional data from &lt;a class="reference external" href="http://mercurial.selenic.com"&gt;Mercurial&lt;/a&gt;,
creates documents using &lt;a class="reference external" href="http://docs.python.org/library/string.html#template-strings"&gt;string.Template&lt;/a&gt; and a RSS feed using
&lt;a class="reference external" href="http://www.dalkescientific.com/Python/PyRSS2Gen.html"&gt;PyRSS2Gen&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There are some utility functions (implemented as functions or not)
that I could have created unit tests for, but what information would I
draw from writing a test for &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;sum([int(i)&lt;/span&gt; for i in
&lt;span class="pre"&gt;hgdate_string.split()])&lt;/span&gt;&lt;/tt&gt;? I write this code for me, and for me this
code is obvious. So how do I &lt;em&gt;know&lt;/em&gt; it works? I test it. Manually,
since generating the entire html source is the &lt;em&gt;only&lt;/em&gt; way for me to
know that Blaag works as I intend it to work.&lt;/p&gt;
&lt;p&gt;Whereas when writing &lt;a class="reference external" href="https://bitbucket.org/haard/hgapi"&gt;hgapi&lt;/a&gt;, I wrote a tool for others to use and
adapt, and a tool that I could not easily look at and see if the
result was correct, Blaag is &lt;em&gt;easy&lt;/em&gt; to verify: I look at the rendered
site, in my browser. If it does not look OK, I have a bug. If it
works, I have NO bugs. I might have potential bugs, like the fact that
the &lt;tt class="docutils literal"&gt;&lt;span class="pre"&gt;-f&lt;/span&gt;&lt;/tt&gt; option is currently required when updating, but if the code
generates the result I want, consistently, and in reasonable time,
Blaag performs perfectly.&lt;/p&gt;
&lt;p&gt;Any test would simply be more code that did not add information or
value - and there is a name for that kind of code: bloat. And while in
the case of Blaag this is easy to see, I believe that more care should
be taken generally when writing tests, just as when writing
functionality - the question you should always ask yourself when
producing code is simply: &lt;em&gt;what value does this code add?&lt;/em&gt; If you
cannot answer that question, you probably should not write the code,
whether it's a test or not.&lt;/p&gt;
&lt;p&gt;Because code unwritten never breaks.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/On-useless-testing</guid><pubDate>Sun, 18 Dec 2011 17:46:46 GMT</pubDate></item><item><title>Styling</title><link>http://blaag.haard.se/Styling</link><description>&lt;div class="document" id="styling"&gt;
&lt;h1 class="title"&gt;Styling&lt;/h1&gt;
&lt;p&gt;New style thanks to &lt;a class="reference external" href="http://twitter.com/#!/markuseliasson"&gt;&amp;#64;markuseliasson&lt;/a&gt; - anything ugly is because of my
adaptions, anything looking great is his work. Since the main parts,
are done (still to be done: Mercurial hook, optional
disqus/analytics), the next post may actually have
other content than the Blaag itself!&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Styling</guid><pubDate>Sun, 18 Dec 2011 11:03:07 GMT</pubDate></item><item><title>RSS support is go!</title><link>http://blaag.haard.se/RSS-support-is-go</link><description>&lt;div class="document" id="rss-support-is-go"&gt;
&lt;h1 class="title"&gt;RSS support is go!&lt;/h1&gt;
&lt;p&gt;There's no reason to roll my own when the guys over at &lt;a class="reference external" href="http://www.dalkescientific.com"&gt;Dalke Scientific Software&lt;/a&gt;
have created the awesome &lt;a class="reference external" href="http://www.dalkescientific.com/Python/PyRSS2Gen.html"&gt;PyRSS2Gen&lt;/a&gt;. It's everything I want from a
utility library - it's simple, documented by example, it does one
thing, and it does it well. Thanks to them, this Blaag now sports a
&lt;a class="reference external" href="http://blaag.haard.se/rss.xml"&gt;RSS&lt;/a&gt; feed!&lt;/p&gt;
&lt;p&gt;Also some bug fixes and minor tweaks done.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/RSS-support-is-go</guid><pubDate>Sat, 17 Dec 2011 22:36:06 GMT</pubDate></item><item><title>Progress is made</title><link>http://blaag.haard.se/Progress-is-made</link><description>&lt;div class="document" id="progress-is-made"&gt;
&lt;h1 class="title"&gt;Progress is made&lt;/h1&gt;
&lt;p&gt;Timestamps from Mercurial is now used to insert creation and
modification times for posts in Blaag. I've also done some code
cleanup and documentation, although there is still work to be done.&lt;/p&gt;
&lt;p&gt;Next up is RSS or Atom feed generation, just have to decide if I
should use an existing library or just generate the XML. Knowing
myself, I'll probably roll my own, yet again.&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/Progress-is-made</guid><pubDate>Sat, 17 Dec 2011 20:17:23 GMT</pubDate></item><item><title>&#65279;It's alive!</title><link>http://blaag.haard.se/It-s-alive</link><description>&lt;div class="document" id="it-s-alive"&gt;
&lt;h1 class="title"&gt;&#65279;It's alive!&lt;/h1&gt;
&lt;p&gt;After &lt;span class="strike"&gt;almost&lt;/span&gt; more than four hours of &lt;em&gt;grueling&lt;/em&gt; work, my blogging platform codenamed &amp;quot;&lt;a class="reference external" href="https://bitbucket.org/haard/blaag"&gt;blaag&lt;/a&gt;&amp;quot; works.&lt;/p&gt;
&lt;p&gt;I created blaag since I've been thinking about blogging, but didn't like the blogging platforms I found, because they were made of bloat with a little functionality hidden deep within. I did, however, like the idea behind &lt;a class="reference external" href="https://github.com/codekoala/hgblog"&gt;hgblog&lt;/a&gt; - especially that it's based around generating the blog from &lt;a class="reference external" href="http://docutils.sourceforge.net"&gt;rst&lt;/a&gt; using &lt;a class="reference external" href="http://mercurial.selenic.com/"&gt;Mercurial&lt;/a&gt; hooks, allowing blogging from the comfort of Emacs. In the end, I decided to roll my own.&lt;/p&gt;
&lt;p&gt;The code for blaag and the entries for this instance of blaag coexists at Bitbucket, so you can view the source code and the source for the entries themselves there.&lt;/p&gt;
&lt;dl class="docutils"&gt;
&lt;dt&gt;The goals of blaag are, in order of priority:&lt;/dt&gt;
&lt;dd&gt;&lt;ol class="first last arabic simple"&gt;
&lt;li&gt;Nicer color scheme&lt;/li&gt;
&lt;li&gt;Time/Datestamp posts&lt;/li&gt;
&lt;li&gt;RSS support&lt;/li&gt;
&lt;li&gt;Add example of Mercurial hooks to repo&lt;/li&gt;
&lt;/ol&gt;
&lt;/dd&gt;
&lt;/dl&gt;
&lt;p&gt;I guess documentation should be somewhere up top as well. Suggestions on what color scheme I should use are welcome! (assuming the Disqus integration works)&lt;/p&gt;
&lt;/div&gt;
</description><category>uncategorized</category><guid isPermaLink="true">http://blaag.haard.se/It-s-alive</guid><pubDate>Fri, 16 Dec 2011 22:08:57 GMT</pubDate></item></channel></rss>