<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>California Dreams &#187; Python</title>
	<atom:link href="http://www.heikkitoivonen.net/blog/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.heikkitoivonen.net/blog</link>
	<description>A Finn in Silicon Valley - Adventures in Technology</description>
	<lastBuildDate>Wed, 09 Feb 2011 05:57:43 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Beware of cPickle</title>
		<link>http://www.heikkitoivonen.net/blog/2011/02/08/beware-of-cpickle/</link>
		<comments>http://www.heikkitoivonen.net/blog/2011/02/08/beware-of-cpickle/#comments</comments>
		<pubDate>Wed, 09 Feb 2011 04:59:34 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1163</guid>
		<description><![CDATA[The Python pickle module provides a way to serialize and deserialize Python objects. A large downside of the pickle format is that it is not secure, meaning you should not deserialize pickles received from untrusted sources. There is also a cPickle version of the pickle module which implements the algorithm in C and is much [...]]]></description>
			<content:encoded><![CDATA[<p>The Python <a href="http://docs.python.org/library/pickle.html">pickle</a> module provides a way to serialize and deserialize Python objects.  A large downside of the pickle format is that it is not secure, meaning you should not deserialize pickles received from untrusted sources. </p>
<p>There is also a <code>cPickle</code> version of the pickle module which implements the algorithm in C and is much faster than the pure Python module. This provides somewhat surprising use cases for the <code>cPickle</code> module besides the obvious application save format: it turns out <code>cPickle</code> can be the <a href="http://stackoverflow.com/questions/1410615/copy-deepcopy-vs-pickle">fastest way to make a copy</a> of nested structures. Due to speed, using <code>cPickle</code> can also be attractive as a data format between trusted servers.</p>
<p>There is an issue that you need to watch out for in the <code>cPickle</code> module, though. When you are serializing to or deserializing from string using the <code>dumps</code> and <code>loads</code> functions respectively, the functions do not release the <a href="http://wiki.python.org/moin/GlobalInterpreterLock">GIL</a>! This took me by surprise: I did not expect anything in the stdlib to hold on to the GIL for anything that could potentially take a long time. You can try this out easily by creating a multithreaded application where one thread tries to use <code>cPickle.dumps</code> on multimegabyte data structure while the other treads are printing to screen for example. You will see that while <code>dumps</code> is running, the other threads are stopped.</p>
<p>Luckily there is an easy workaround: you can use the <a href="http://docs.python.org/library/pickle.html#pickle.load"><code>load</code></a> and <a href="http://docs.python.org/library/pickle.html#pickle.dump"><code>dump</code></a> functions with <a href="http://docs.python.org/library/stringio.html#module-cStringIO">cStringIO</a> buffer or other file-like objects.</p>
<p>Note that I haven&#8217;t checked if this problem applies to Python 3.x.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2011/02/08/beware-of-cpickle/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Decorator to Log Slow Calls</title>
		<link>http://www.heikkitoivonen.net/blog/2011/02/02/decorator-to-log-slow-calls/</link>
		<comments>http://www.heikkitoivonen.net/blog/2011/02/02/decorator-to-log-slow-calls/#comments</comments>
		<pubDate>Thu, 03 Feb 2011 06:33:07 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1153</guid>
		<description><![CDATA[One of the most common examples given for Python decorators is a decorator that tracks how long the execution of the wrapped function took. While this is very useful in and of itself, it can cause issues when you want to apply that into production usage. The issue I faced was that when I was [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most common examples given for Python decorators is a decorator that tracks how long the execution of the wrapped function took. While this is very useful in and of itself, it can cause issues when you want to apply that into production usage.</p>
<p>The issue I faced was that when I was trying to find out why my servers were too slow (only under production loads), I first added the simple timing decorators to everything I thought might be slow in the hopes of catching all the slow calls and maybe finding some patterns. Well, this approach worked in the sense that I did find the slow parts quickly, but it was producing much more logs than before, and I wasn&#8217;t really interested in most of this timing information.</p>
<p>What I really wanted was a timing decorator that would log only when the wrapped callable took too long to execute. But there were still some calls that I wanted to log always for accurate statistical purposes. I figured the best way was to make my decorator take a threshold argument with some reasonable default that I could override if I wanted.</p>
<p>Now while I have written decorators before, this was the first decorator that called for optional arguments. Python treats decorators that don&#8217;t take any arguments slightly differently from those that require arguments, so this complicates things a bit. The sample in <a href="http://wiki.python.org/moin/PythonDecoratorLibrary#Creatingdecoratorwithoptionalarguments">Python decorator library</a> is almost scary! I think my approach is nice and simple yet fairly sophisticated:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">logging</span>
<span style="color: #ff7700;font-weight:bold;">import</span> functools
&nbsp;
log = <span style="color: #dc143c;">logging</span>.<span style="color: black;">getLogger</span><span style="color: black;">&#40;</span>__name__<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> time_slow<span style="color: black;">&#40;</span>f=<span style="color: #008000;">None</span>, logger=log, threshold=<span style="color: #ff4500;">0.01</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> decorated<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>:
        @functools.<span style="color: black;">wraps</span><span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">def</span> wrapper<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kw<span style="color: black;">&#41;</span>:
            start = <span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                ret = f<span style="color: black;">&#40;</span><span style="color: #66cc66;">*</span>args, <span style="color: #66cc66;">**</span>kw<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">finally</span>:
                duration = <span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> - start
                <span style="color: #ff7700;font-weight:bold;">if</span> duration <span style="color: #66cc66;">&gt;</span> threshold:
                    logger.<span style="color: black;">info</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'slow: %s %.9f seconds'</span>, f.__name__, duration<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">return</span> ret
        <span style="color: #ff7700;font-weight:bold;">return</span> wrapper
    <span style="color: #ff7700;font-weight:bold;">if</span> f <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> decorated<span style="color: black;">&#40;</span>f<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> decorated</pre></div></div>

<p>This decorator can be placed on a callable without any arguments, or with a custom logger or threshold value. In other words, both of these would work:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">@time_slow
<span style="color: #ff7700;font-weight:bold;">def</span> myfast<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
@time_slow<span style="color: black;">&#40;</span>threshold=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> myslow<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">time</span> <span style="color: #ff7700;font-weight:bold;">import</span> sleep
    sleep<span style="color: black;">&#40;</span><span style="color: #ff4500;">0.001</span><span style="color: black;">&#41;</span></pre></div></div>

<p>and typically calling <code>myslow</code> only would produce log output. I chose 0.01 as a reasonable default threshold, but this of course depends a lot on the use case. The log includes the slow function&#8217;s name, as well as the time formatted with 9 decimals in order to avoid the exponential notation, which makes it easier to work with the log output (<a href="http://linux.die.net/man/1/sort"><code>sort -n</code></a>, for example). I have just used a single threshold, but an easy improvement would be to pass a list of thresholds and log at different <a href="http://docs.python.org/library/logging.html#logging-levels">levels</a> depending on the duration.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2011/02/02/decorator-to-log-slow-calls/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>M2Crypto Supports OpenSSL 1.0.x</title>
		<link>http://www.heikkitoivonen.net/blog/2011/01/16/m2crypto-supports-openssl-1-0-x/</link>
		<comments>http://www.heikkitoivonen.net/blog/2011/01/16/m2crypto-supports-openssl-1-0-x/#comments</comments>
		<pubDate>Mon, 17 Jan 2011 05:32:40 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[m2crypto]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1149</guid>
		<description><![CDATA[I was supposed to release new M2Crypto version in the summer of 2010 but &#8220;real life&#8221; got in the way, and this extended all the way until this week. I finally decided that I&#8217;d better push out a new release even though there was just one significant change: OpenSSL 1.0.x support. However, I felt this [...]]]></description>
			<content:encoded><![CDATA[<p>I was supposed to release new <a href="http://chandlerproject.org/Projects/MeTooCrypto">M2Crypto</a> version in the summer of 2010 but &#8220;real life&#8221; got in the way, and this extended all the way until this week. I finally decided that I&#8217;d better push out a new release even though there was just one significant change: <a href="http://www.openssl.org/">OpenSSL</a> 1.0.x support. However, I felt this was really important since OpenSSL 1.0.x has been out for almost a year now, and it is starting to get difficult to deal with software that does not work with pre-1.0.x.</p>
<p>Unfortunately I made a mistake in my first release to <a href="http://pypi.python.org/pypi/M2Crypto">PyPI</a>: I used the <code>setup.py</code> commands to build, sign and upload a source distribution, but I did this from a tree I had <code>svn export</code>ed. Due to the way the M2Crypto <code>setup.py</code> was constructed this meant that the tarball was lacking vital files. Yesterday I did a new 0.21.1 release from the Subversion checkout, so the tarball now includes everything.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2011/01/16/m2crypto-supports-openssl-1-0-x/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>SSL in Python 2.7</title>
		<link>http://www.heikkitoivonen.net/blog/2010/08/23/ssl-in-python-2-7/</link>
		<comments>http://www.heikkitoivonen.net/blog/2010/08/23/ssl-in-python-2-7/#comments</comments>
		<pubDate>Tue, 24 Aug 2010 04:20:24 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[m2crypto]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1109</guid>
		<description><![CDATA[It has been almost two years since I wrote about the state of SSL in Python 2.6. If you haven&#8217;t read that yet, I suggest you read that first and then continue here, since I will mostly just be talking about things that have changed since then, or things that I have discovered since then. [...]]]></description>
			<content:encoded><![CDATA[<p>It has been almost two years since I wrote about the state of <a href="http://www.heikkitoivonen.net/blog/2008/10/14/ssl-in-python-26/">SSL in Python 2.6</a>. If you haven&#8217;t read that yet, I suggest you read that first and then continue here, since I will mostly just be talking about things that have changed since then, or things that I have discovered since then.</p>
<p>The good news is that things have improved in the stdlib <a href="http://docs.python.org/library/ssl.html">ssl</a> module. The bad news is that it is still missing some critical pieces to make SSL secure. </p>
<p>Python 2.7 enables you to specify ciphers to use explicitly, rather than just relying on what comes default with the SSL version selection. Additionally, if you compile the <code>ssl</code> module with OpenSSL 1.0 and later, using <code>ssl.PROTOCOL_SSLv23</code> is safe (as in, it will not pick the insecure SSLv2 protocol) as long as you don&#8217;t enable SSLv2 specific ciphers (see the ssl module documentation for details).</p>
<h3>Servers</h3>
<p>With that out of the way, there isn&#8217;t really much difference to how you would write a simple SSL server with Python 2.7 compared to what I wrote in 2008. If you know your <code>ssl</code> module was compiled with OpenSSL 1.0 you can pick <code>ssl.PROTOCOL_SSLv23</code> for maximum compatibility. Otherwise you should stick with an explicit version other than v2.</p>
<p>The documentation for the ssl module in 2.7 has improved a lot, and includes good sample code for servers <a href="http://docs.python.org/library/ssl.html#server-side-operation">here</a>.</p>
<p>The <a href="http://chandlerproject.org/Projects/MeTooCrypto">M2Crypto</a> code hasn&#8217;t changed. The next M2Crypto release will add support for 0penSSL 1.0.</p>
<h3>Clients</h3>
<p>Checking the peer certificate&#8217;s hostname is still the weak point of the <code>ssl</code> module. The SSL version selection situation has improved slightly like I explained above. Othewise follow the example I wrote in 2008.</p>
<p>Again, the M2Crypto API hasn&#8217;t changed.</p>
<p>Lately I have been working with <a href="http://pycurl.sourceforge.net/">pycurl</a> at <a href="http://egnyte.com/">Egnyte</a>, so I decided to give a client example using that module.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> pycurl
&nbsp;
c = pycurl.<span style="color: black;">Curl</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">setopt</span><span style="color: black;">&#40;</span>pycurl.<span style="color: black;">URL</span>, <span style="color: #483d8b;">'https://www.google.com'</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">setopt</span><span style="color: black;">&#40;</span>pycurl.<span style="color: black;">HTTPGET</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">setopt</span><span style="color: black;">&#40;</span>pycurl.<span style="color: black;">SSL_VERIFYPEER</span>, <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">setopt</span><span style="color: black;">&#40;</span>pycurl.<span style="color: black;">CAINFO</span>, <span style="color: #483d8b;">'ca.pem'</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">setopt</span><span style="color: black;">&#40;</span>pycurl.<span style="color: black;">SSL_VERIFYHOST</span>, <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    c.<span style="color: black;">perform</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">finally</span>:
    c.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p>I am not a big fan of pycurl due to difficulties getting it compiled and the non-Pythonic API. But it is based on the very powerful curl library, so it comes full featured out of the box.</p>
<h3>Other Resources</h3>
<p>Besides the Python crypto libraries capable of doing SSL that I mentioned in my <a href="http://www.heikkitoivonen.net/blog/2008/10/14/ssl-in-python-26/">SSL in Python 2.6</a> article, I have found pycurl. Another find in the Python crypto front is <a href="http://www.cryptlib.com/">cryptlib</a>. </p>
<p><a href="http://www.mikeivanov.com/">Mike Ivanov</a> wrote a great series about crypto in Python: <a href="http://www.activestate.com/blog/2010/03/python-crypto-state-art-part-2">part 2</a>, <a href="http://www.activestate.com/blog/2010/05/python-crypto-state-art-part-3">part 3</a> (link to part 1 seems to have rotted). Mike also produced a <a href="http://mikeivanov.com/pc/python-crypto.pdf">comparison of different Python crypto libraries</a> (PDF).</p>
<p>The future is also looking bright for the <code>ssl</code> module. Already the upcoming <a href="http://docs.python.org/dev/library/ssl.html">Python 3.2 ssl module</a> will include support for <code>SSLContext</code>s so that you can set options for multiple SSL connections at once, allows you to selectively disable SSL versions, and it allows you to check the OpenSSL version as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2010/08/23/ssl-in-python-2-7/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>baconrank.com Powered by Turbogears 2</title>
		<link>http://www.heikkitoivonen.net/blog/2010/05/11/baconrank-com-powered-by-turbogears-2/</link>
		<comments>http://www.heikkitoivonen.net/blog/2010/05/11/baconrank-com-powered-by-turbogears-2/#comments</comments>
		<pubDate>Wed, 12 May 2010 05:22:42 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1085</guid>
		<description><![CDATA[The baconrank.com website was written with the Turbogears 2 web application framework. It is pretty lightly modified from the quickstart project. In the UI front the quickstart project used a lot of images to make rounded corners and so on to make everything look good in cross-platform way. I dislike this practice, so I decided [...]]]></description>
			<content:encoded><![CDATA[<p>The <a href="http://baconrank.com/">baconrank.com</a> website was written with the <a href="http://www.turbogears.org/2.0/docs/">Turbogears 2</a> web application framework. It is pretty lightly modified from the <a href="http://www.turbogears.org/2.0/docs/main/QuickStart.html">quickstart</a> project.</p>
<p>In the UI front the quickstart project used a lot of images to make rounded corners and so on to make everything look good in cross-platform way. I dislike this practice, so I decided to see if I could take the basic layout and not use any images for corners and backgrounds and the like. I think the result looks pretty good in modern browsers, including the default browser in Android 2.1. <code>border-radius</code> and <code>-moz-linear-gradient</code> did the bulk of the work. Which reminds me that I forgot to look for the equivalent of <code>-moz-linear-gradient</code> for other browsers&#8230;</p>
<p>The template language I used was <a href="http://genshi.edgewall.org/">Genshi</a>, both because it is the default that comes with TG2 and the quickstart project, but also because I wanted to try out another template language as well. The thing I like about Genshi is that it guarantees I get well-formed output. However, its use of XPath can be a pretty steep learning curve to someone who doesn&#8217;t know XPath (like me). I did not see how to control the whitespace around elements: in some cases I have elements one on each row, other times they end up on the same row. I think I also could not get a comment to appear at the end of the document (to put in page rendering time, for example, although it turned out you&#8217;d need to hack tg2 itself to get the rendering time &#8211; unfortunately I lost the link).</p>
<p>I originally had bigger plans for the application, including forum, password recovery and so on, but canned those plans for now because I realized I could not find enough time to do all those and ship something before the summer. Part of that I did get in, although it is only exposed to the admin user. Being the security-minded geek that I am, I hacked the <a href="http://www.heikkitoivonen.net/blog/2009/12/01/secure-password-scheme-for-turbogears2-application-with-repoze-who-and-bcrypt/">auth code to use bcrypt</a>. I also learned about doing <a href="http://rdist.root.org/2009/05/28/timing-attack-in-google-keyczar-library/">password comparison</a> in a way that does not leak information due to timing.</p>
<p>I designed the small protocol that the Android client uses to communicate with the server. Most operations are covered by the following:</p>
<p>Initial sync:</p>
<pre>
>>>request<<<
POST /users
@JSON@

>>>response<<<
201
Location: /users/123

>>>request<<<
GET /users/123

>>>request<<<
200
@JSON@
</pre>
<p>Add bacon:</p>
<pre>
>>>request<<<
POST /users/123
@JSON@

>>>response<<<
200
@JSON@
</pre>
<p>Incidentally, if you'd like to write another client (iPhone anyone?), let me know...</p>
<p>I wanted to wrap the client API in its own class, but could not get that to work as  a separate class so had to just settle with a method that does way too too much. Something I hope I can visit later.</p>
<p>I really wanted to like Turbogears 2 since it is based on my favorite, Pylons, but I actually felt that TG2 was getting in my way almost as often as it was helping me. I am happy that I did not have to write the auth code from scratch, and having the admin area almost as easy as in Django were big wins, but since I did not yet implement the forum (where I think I could really have used more of tg2's strengths) I would probably have been better off with plain Pylons. The documentation has been in flux the whole time I've been working on my app, some things working, some broken, and I had to resort to comments at the end of docs and doing web searches to try and figure things out. There were periods of time when the dependent packages were out of sync, and you could not even get a working quickstart project without setting version limits. I think that the controller methods not returning the actual string to render can be potentially big headache (for me, I just could not get the timing information output into the end of the returned HTML). I'd say TG2 has potential to be great, but right now things feel a little bit too unfinished. I know 2.1 will fix some of the issues I run into, but I don't know if anyone is looking at checking and cleaning up the documentation.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2010/05/11/baconrank-com-powered-by-turbogears-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Bacon Rank Released</title>
		<link>http://www.heikkitoivonen.net/blog/2010/05/10/bacon-rank-released/</link>
		<comments>http://www.heikkitoivonen.net/blog/2010/05/10/bacon-rank-released/#comments</comments>
		<pubDate>Tue, 11 May 2010 05:28:49 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[android]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1074</guid>
		<description><![CDATA[I am pleased to release Bacon Rank, the application you have been waiting for to count your bacon! (You may not have realized this, of course. I forgive you.) I&#8217;ve been working on this application combo since last November, a few hours here and there. The server piece is a Turbogears 2 application, while the [...]]]></description>
			<content:encoded><![CDATA[<p>I am pleased to release <a href="http://baconrank.com/">Bacon Rank</a>, the application you have been waiting for to count your bacon! (You may not have realized this, of course. I forgive you.)</p>
<p>I&#8217;ve been working on this application combo since last November, a few hours here and there. The server piece is a Turbogears 2 application, while the client piece is an Android application. As a whole, they form the Bacon Rank application ecosystem. The idea is that whenever you eat bacon, you submit the number of strips of bacon you ate, using the Android client, to the server. The server returns your statistics, including your rank compared to other users of the system. It is clearly a not very serious application, but it presented some interesting programming challenges.</p>
<p>I&#8217;ve been going through various Python web frameworks, and this time I wanted to learn about Turbogears 2. There isn&#8217;t anything especially groundbreaking about it, but I think it marks the first time I am actually running a real service. Of course it is also tied to the Android application, which makes it interesting.</p>
<p>The Android application is a bit more ambitious from engineering point of view. In the UI the trickiest piece was a customized SeekBar: uncooked bacon that becomes cooked as you move a skillet over it. I was also able to finally figure out how to make a background network request survive screen orientation change gracefully.</p>
<p>I am also experimenting with Twitter for the first time as a communications channel for the project.</p>
<p>In the next two posts I will explore the server and client pieces in more detail.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2010/05/10/bacon-rank-released/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>New Adventures</title>
		<link>http://www.heikkitoivonen.net/blog/2010/04/07/new-adventures/</link>
		<comments>http://www.heikkitoivonen.net/blog/2010/04/07/new-adventures/#comments</comments>
		<pubDate>Thu, 08 Apr 2010 05:17:29 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1065</guid>
		<description><![CDATA[This news is a couple of weeks old, but I thought better late than never&#8230; For the past couple of years I was working at SpikeSource, on a variety of things ranging from Pylons and CherryPy applications to designing RESTful APIs and client libraries and even CakePHP and Java web applications (horror of horrors ). [...]]]></description>
			<content:encoded><![CDATA[<p>This news is a couple of weeks old, but I thought better late than never&#8230; For the past couple of years I was working at <a href="http://www.spikesource.com/">SpikeSource</a>, on a variety of things ranging from <a href="http://pylonshq.com/">Pylons</a> and <a href="http://cherrypy.org/">CherryPy</a> applications to designing RESTful APIs and client libraries and even <a href="http://cakephp.org/">CakePHP</a> and Java web applications (horror of horrors <img src='http://www.heikkitoivonen.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ). It was never a good fit culturally, though, so just before my two year anniversary came around I decided I needed a change.</p>
<p>I decided to be very focused on my search: Python web application development, startups, and ideally located from Sunnyvale to Palo Alto. I used mostly <a href="http://craigslist.org/">craigslist.org</a> and <a href="http://startuply.com/">startuply.com</a> for my search, with a couple of hints from friends. I applied to eight jobs, and got five interviews. I was quite surprised that there were so many companies matching my preferences within such a small area hiring at the time when I was looking! I was also pleasantly surprised that I got into as many interviews as I did; last time around I had a bit worse success rate. Hint: requirements aren&#8217;t necessarily requirements in job postings.</p>
<p>Unfortunately I learned I am bad at interviews aimed at Python web application developers. For some reason I find coding questions a lot easier to answer  when they are in C. I was also badly prepared to answer a few questions related to web development; having not thought about something for a while makes a bad interview impression. Note to my future self: start practicing at least a week before interviews, practice in Python on problems designed to be solved in Python (maybe <a href="http://www.pythonchallenge.com/">Python challenge</a>s, <a href="http://www.facebook.com/careers/puzzles.php">Facebook programming puzzles</a> and the like), and check with friends for some common web developer questions. Assuming I were to look for that kind of job next time around, of course.</p>
<p>To make long story short, I decided to join <a href="http://www.pythoncraft.com/">Aahz</a> at <a href="http://egnyte.com/">Egnyte</a>. Egnyte provides cloud storage, backup and sharing services. My first task involves integrating new UI design to a CherryPy application using Cheetah templates. I am also working on a Mac after many years on Linux.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2010/04/07/new-adventures/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Pulling Android Market Sales Data Programmatically</title>
		<link>http://www.heikkitoivonen.net/blog/2010/02/08/pulling-android-market-sales-data-programmatically/</link>
		<comments>http://www.heikkitoivonen.net/blog/2010/02/08/pulling-android-market-sales-data-programmatically/#comments</comments>
		<pubDate>Tue, 09 Feb 2010 04:48:51 +0000</pubDate>
		<dc:creator>Heikki Toivonen</dc:creator>
				<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[m2crypto]]></category>

		<guid isPermaLink="false">http://www.heikkitoivonen.net/blog/?p=1023</guid>
		<description><![CDATA[Android Market handles sales through Google Checkout. I haven&#8217;t tried selling anything else online before, but what this setup provides for me as the seller leaves a lot to be desired. One issue you will have trouble with is getting the data needed to file taxes. Google provides a Google Checkout Notification History API that [...]]]></description>
			<content:encoded><![CDATA[<p>Android Market handles sales through Google Checkout. I haven&#8217;t tried selling anything else online before, but what this setup provides for me as the seller leaves a lot to be desired. One issue you will have trouble with is getting the data needed to file taxes.</p>
<p>Google provides a <a href="http://code.google.com/apis/checkout/developer/Google_Checkout_XML_API_Notification_History_API.html">Google Checkout Notification History API</a> that lets you programmatically query sales data. For my purposes the API requests are really simple: just post a small XML document with the date range I am interested in, get back XML documents that contain my data. If there is more data that fits in a single response, look for an element that specifies the token for the next page and keep pulling until you get all data.</p>
<p>Below is a really simple Python script that uses <a href="http://chandlerproject.org/Projects/MeTooCrypto">M2Crypto</a> to handle the SSL parts for the connection (needed since <a href="http://www.heikkitoivonen.net/blog/2008/10/14/ssl-in-python-26/">Python doesn&#8217;t do secure SSL out of the box</a>). You will also need to <a href="http://www.heikkitoivonen.net/blog/2008/09/30/root-certificates-for-python-programs-using-python/">grab certificates</a>. You should save the script as <code>gnotif.py</code>, save the certificates as <code>cacert.pem</code> and create <code>gnotif.ini</code> as described in the script below all in the same directory. When you execute it, it will ask for start and end date (in <code>YYYY-MM-DD</code> format) and then fetch all the data, saving them in response-N.xml files, where N is a number.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># Script to query Google Checkout Notification History</span>
<span style="color: #808080; font-style: italic;"># http://code.google.com/apis/checkout/developer/Google_Checkout_XML_API_Notification_History_API.html</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Supporting file gnotif.ini:</span>
<span style="color: #808080; font-style: italic;">#[gnotif]</span>
<span style="color: #808080; font-style: italic;"># merchant_id = YOUR_MERCHANT_ID_HERE</span>
<span style="color: #808080; font-style: italic;"># merchant_key = YOUR_MERCHANT_KEY_HERE</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">base64</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">ConfigParser</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">ConfigParser</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> M2Crypto <span style="color: #ff7700;font-weight:bold;">import</span> SSL, httpslib
&nbsp;
ENVIRONMENT = <span style="color: #483d8b;">&quot;https://checkout.google.com/api/checkout/v2/reports/Merchant/&quot;</span>
XML = <span style="color: #483d8b;">&quot;&quot;&quot;<span style="color: #000099; font-weight: bold;">\</span>
&lt;notification-history-request xmlns=&quot;http://checkout.google.com/schema/2&quot;&gt;
%(query)s
&lt;/notification-history-request&gt;
&quot;&quot;&quot;</span>
&nbsp;
config = <span style="color: #dc143c;">ConfigParser</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
config.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gnotif.ini'</span><span style="color: black;">&#41;</span>
MERCHANT_ID = config.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gnotif'</span>, <span style="color: #483d8b;">'merchant_id'</span><span style="color: black;">&#41;</span>
MERCHANT_KEY = config.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'gnotif'</span>, <span style="color: #483d8b;">'merchant_key'</span><span style="color: black;">&#41;</span>
&nbsp;
rawstr = r<span style="color: #483d8b;">&quot;&quot;&quot;&lt;next-page-token&gt;(.*)&lt;/next-page-token&gt;&quot;&quot;&quot;</span>
compile_obj = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>rawstr, <span style="color: #dc143c;">re</span>.<span style="color: black;">MULTILINE</span><span style="color: black;">&#41;</span>
&nbsp;
auth = <span style="color: #dc143c;">base64</span>.<span style="color: black;">encodestring</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'%s:%s'</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>MERCHANT_ID, MERCHANT_KEY<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
&nbsp;
ctx = SSL.<span style="color: black;">Context</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'sslv3'</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># If you comment out the next 2 lines, the connection won't be secure</span>
ctx.<span style="color: black;">set_verify</span><span style="color: black;">&#40;</span>SSL.<span style="color: black;">verify_peer</span> | SSL.<span style="color: black;">verify_fail_if_no_peer_cert</span>, depth=<span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> ctx.<span style="color: black;">load_verify_locations</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'cacert.pem'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">1</span>: <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">Exception</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'No CA certs'</span><span style="color: black;">&#41;</span>
&nbsp;
start = <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Start date: '</span><span style="color: black;">&#41;</span>
end = <span style="color: #008000;">raw_input</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'End date: '</span><span style="color: black;">&#41;</span>
&nbsp;
data = XML <span style="color: #66cc66;">%</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'query'</span>: <span style="color: #483d8b;">&quot;&quot;&quot;&lt;start-time&gt;%(start)s&lt;/start-time&gt;
&lt;end-time&gt;%(end)s&lt;/end-time&gt;&quot;&quot;&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'start'</span>: start, <span style="color: #483d8b;">'end'</span>: end<span style="color: black;">&#125;</span><span style="color: black;">&#125;</span>
&nbsp;
i = <span style="color: #ff4500;">0</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
    c = httpslib.<span style="color: black;">HTTPSConnection</span><span style="color: black;">&#40;</span>host=<span style="color: #483d8b;">'checkout.google.com'</span>, port=<span style="color: #ff4500;">443</span>, ssl_context=ctx<span style="color: black;">&#41;</span>
    c.<span style="color: black;">request</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'POST'</span>, ENVIRONMENT + MERCHANT_ID, data,
             <span style="color: black;">&#123;</span><span style="color: #483d8b;">'content-type'</span>: <span style="color: #483d8b;">'application/xml; charset=UTF-8'</span>,
              <span style="color: #483d8b;">'accept'</span>: <span style="color: #483d8b;">'application/xml; charset=UTF-8'</span>,
              <span style="color: #483d8b;">'authorization'</span>: <span style="color: #483d8b;">'Basic '</span> + auth<span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
&nbsp;
    r = c.<span style="color: black;">getresponse</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    f=<span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'response-%d.xml'</span> <span style="color: #66cc66;">%</span> i, <span style="color: #483d8b;">'w'</span><span style="color: black;">&#41;</span>
    result = r.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    f.<span style="color: black;">write</span><span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span>
    f.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">print</span> i, r.<span style="color: black;">status</span>
&nbsp;
    c.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    match_obj = compile_obj.<span style="color: black;">search</span><span style="color: black;">&#40;</span>result<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> match_obj:
        i += <span style="color: #ff4500;">1</span>
        data = XML <span style="color: #66cc66;">%</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">'query'</span>: <span style="color: #483d8b;">&quot;&quot;&quot;&lt;next-page-token&gt;%s&lt;/next-page-token&gt;&quot;&quot;&quot;</span> <span style="color: #66cc66;">%</span> match_obj.<span style="color: black;">group</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span><span style="color: black;">&#125;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #ff7700;font-weight:bold;">break</span></pre></div></div>

<p>As you take a look at the data you will probably notice that you are only getting the sale price information, but no information about the fees that Google is deducting. Officially it is a flat 30%, but I have found out a number of my sales have the fee as 5%. So we need to get this information somehow. Luckily you can <a href="http://googlecheckout.blogspot.com/2009/09/transaction-fee-information-now.html">toggle a checkbox in your Google Checkout Merchant Settings</a>. Unfortunately there is a bug, and the transaction fee shows as $0 for Android Market sales. I have reported this to Google, and they acknowledged it, but there is no ETA on when this will be fixed.</p>
<p>I also haven&#8217;t found any way to programmatically query when and how much did Google Checkout actually pay me. (I can get this info from my bank, but it would be nice to query for that with the Checkout API as well.)</p>
<p>Last but certainly not least, working with the monster XML files returned from Google Checkout API is a real pain. If someone has a script to turn those into a format that could be imported into a spreadsheet or database that would be nice&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.heikkitoivonen.net/blog/2010/02/08/pulling-android-market-sales-data-programmatically/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
	</channel>
</rss>

