<?xml version="1.0"?>
<rdf:RDF
	xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:foaf="http://xmlns.com/foaf/0.1/"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns="http://purl.org/rss/1.0/"
>
<channel rdf:about="http://planet.python.org/">
	<title>Planet Python</title>
	<link>http://planet.python.org/</link>
	<description>Planet Python - http://planet.python.org/</description>

	<items>
		<rdf:Seq>
			<rdf:li rdf:resource="http://be.groovie.org/post/380320476" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-5702936365231918674.post-8120553126411850327" />
			<rdf:li rdf:resource="http://lericson.blogg.se/code/2010/february/a-little-off-topic.html" />
			<rdf:li rdf:resource="http://lateral.netmanagers.com.ar/weblog/posts/BB867.html" />
			<rdf:li rdf:resource="http://www.logilab.org/blogentry/20290" />
			<rdf:li rdf:resource="http://www.muhuk.com/?p=338" />
			<rdf:li rdf:resource="http://www.blog.pythonlibrary.org/?p=569" />
			<rdf:li rdf:resource="http://www.huyng.com/?p=537" />
			<rdf:li rdf:resource="http://jessenoller.com/?p=752" />
			<rdf:li rdf:resource="tag:the-space-station.com,2010-02-09:/entry;2010/2/9/multi-touch:-pymt-0-4-released" />
			<rdf:li rdf:resource="http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-27648409.post-4167916853613161900" />
			<rdf:li rdf:resource="http://www.heikkitoivonen.net/blog/?p=1023" />
			<rdf:li rdf:resource="http://learnpython.wordpress.com/2010/02/08/get-the-most-out-of-pycon-volunteer/" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-21332048.post-7044502207707423382" />
			<rdf:li rdf:resource="http://www.eflorenzano.com/blog/post/how-do-we-kick-our-synchronous-addiction/" />
			<rdf:li rdf:resource="http://lateral.netmanagers.com.ar/weblog/posts/BB866.html" />
			<rdf:li rdf:resource="http://www.johndcook.com/blog/?p=4483" />
			<rdf:li rdf:resource="http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-11683713.post-1928982814843756737" />
			<rdf:li rdf:resource="http://blog.isotoma.com/?p=560" />
			<rdf:li rdf:resource="http://simonwillison.net/2010/Feb/8/integrate/" />
			<rdf:li rdf:resource="tag:blogger.com,1999:blog-5702936365231918674.post-1630538266823111730" />
			<rdf:li rdf:resource="http://geekscrap.com/?p=588" />
			<rdf:li rdf:resource="http://www.hardcoded.net/articles/embedded-pyobjc.htm" />
		</rdf:Seq>
	</items>
</channel>

<item rdf:about="http://be.groovie.org/post/380320476">
	<title>Ben Bangert: Deploying a Pylons App to Production, Step-by-Step</title>
	<link>http://be.groovie.org/post/380320476</link>
	<content:encoded>&lt;a href=&quot;http://blog.rightbrainnetworks.com/2010/02/deploying-a-pylons-app-to-production-step-by-step-part-1-of-2/?utm_source=web&amp;utm_medium=twitter&quot;&gt;Deploying a Pylons App to Production, Step-by-Step&lt;/a&gt;: &lt;p&gt;One of the many ways to deploy a Pylons application. Hopefully with tools like toppcloud, the Python web world as a whole can start to come to a ‘best practices’ type methodology to ease deployment pains. So far, whether you’re deploying a Pylons, Django, repoze.bfg, Zope, or TurboGears app, many of the same deployment pains will crop up. Since all of them can be deployed as WSGI apps, it would feel like by now we surely could at least have a ‘best practice for deploy Python web app’ type doc that works fine for any Python webapp.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T18:52:00+00:00</dc:date>
</item>
<item rdf:about="http://blog.some-abstract-type.com/2010/02/dont-forget-commit-in-mysql.html">
	<title>Geert Vanderkelen: Don't forget the COMMIT in MySQL</title>
	<link>http://blog.some-abstract-type.com/2010/02/dont-forget-commit-in-mysql.html</link>
	<content:encoded>&lt;p&gt;Yes, &lt;a href=&quot;http://dev.mysql.com&quot;&gt;MySQL&lt;/a&gt; has transactions if you use &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/innodb.html&quot;&gt;InnoDB&lt;/a&gt; or &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster.html&quot;&gt;NDB Cluster&lt;/a&gt; for example. Using these transactional storage engines, you'll have &lt;a href=&quot;http://dev.mysql.com/doc/refman/5.1/en/commit.html&quot;&gt;to commit&lt;/a&gt; (or roll back) your inserts, deletes or updates.&lt;/p&gt;&lt;p&gt;I've seen it a few times now with people being surprised that no data is going into the tables. It's not so a silly problem in the end. If you are used to the defaults in MySQL you don't have to commit anything since it is automatically done for you.&lt;/p&gt;&lt;p&gt;Take the &lt;a href=&quot;http://python.org&quot;&gt;Python&lt;/a&gt; Database Interfaces for MySQL. &lt;a href=&quot;http://www.python.org/dev/peps/pep-0249/&quot;&gt;PEP-249&lt;/a&gt; says that, by default, auto-commit should be turned off. You could turn it back on, but it's good practice to be explicit and commit in your code. Remember &lt;a href=&quot;http://www.python.org/dev/peps/pep-0020/&quot;&gt;the Zen of Python&lt;/a&gt;!&lt;p&gt;Here is just a small example to show it. Uses &lt;a href=&quot;https://launchpad.net/myconnpy&quot;&gt;MySQL Connector/Python&lt;/a&gt;, but it should also work with the other MySQL database interfaces:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;import mysql.connector&lt;br /&gt;cnx = mysql.connector.connect(db='test')&lt;br /&gt;cur = cnx.cursor()&lt;br /&gt;cur.execute(&quot;&quot;&quot;CREATE TABLE innodb_t1 (&lt;br /&gt;  id INT UNSIGNED NOT NULL,&lt;br /&gt;  c1 VARCHAR(128),&lt;br /&gt;  PRIMARY KEY (id)&lt;br /&gt;) ENGINE=InnoDB&quot;&quot;&quot;)&lt;br /&gt;ins = &quot;INSERT INTO innodb_t1 (id,c1) VALUES (%s,%s)&quot;&lt;br /&gt;cur.execute(ins,&lt;br /&gt;  (1,'MySQL Support Team _is_ already the best',))&lt;br /&gt;cnx.commit()&lt;br /&gt;cur.close()&lt;br /&gt;cnx.close()&lt;br /&gt;&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5702936365231918674-8120553126411850327?l=blog.some-abstract-type.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T18:40:49+00:00</dc:date>
</item>
<item rdf:about="http://lericson.blogg.se/code/2010/february/a-little-off-topic.html">
	<title>Ludvig Ericson: A little off-topic</title>
	<link>http://lericson.blogg.se/code/2010/february/a-little-off-topic.html</link>
	<content:encoded>&lt;div class=&quot;document&quot;&gt;
&lt;p&gt;Oh man, this one's great.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;http://asset.soup.io/asset/0502/3216_3574.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p&gt; &lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;http://delicious.com/save?url=http://lericson.blogg.se/http://lericson.blogg.se/code/2010/february/a-little-off-topic.html&amp;title=A little off-topic&quot;&gt;&lt;img src=&quot;http://static.delicious.com/img/delicious.small.gif&quot; height=&quot;10&quot; width=&quot;10&quot; alt=&quot;Save on Delicious&quot; /&gt; delicious.com&lt;/a&gt;&lt;/p&gt;


&lt;img src=&quot;http://stats.blogg.se/?id=1395964&quot; border=&quot;0&quot; width=&quot;0&quot; height=&quot;0&quot; alt=&quot;&quot; /&gt;</content:encoded>
	<dc:date>2010-02-09T16:30:53+00:00</dc:date>
</item>
<item rdf:about="http://lateral.netmanagers.com.ar/weblog/posts/BB867.html">
	<title>Roberto Alsina: Marave 0.4 is out!</title>
	<link>http://lateral.netmanagers.com.ar/weblog/posts/BB867.html</link>
	<content:encoded>&lt;p&gt;Version 0.4 of Marave, a distraction-free fullscreen editor is out at &lt;a class=&quot;reference external&quot; href=&quot;http://marave.googlecode.com&quot;&gt;http://marave.googlecode.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This version includes several bugs fixed and features implemented since 0.4:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;It works better with WindowMaker (dialogs appeared behind main window)&lt;/li&gt;
&lt;li&gt;Works better with some Qt styles (combo boxes were unusable)&lt;/li&gt;
&lt;li&gt;Added support for SVG backgrounds&lt;/li&gt;
&lt;li&gt;Code cleanups&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Marave is free softare released under the GPL, and should work in all major desktop platforms.&lt;/p&gt;
&lt;p&gt;I would love feedback on this release, as well as ideas for Marave's future, so if you want to help, please join the mailing list:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://groups.google.com/group/marave-discuss&quot;&gt;http://groups.google.com/group/marave-discuss&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Of course, if you like Marave, feel free to &lt;a class=&quot;reference external&quot; href=&quot;https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=Q6R5YDDPM2RL6&amp;lc=AR&amp;item_name=rst2pdf&amp;item_number=rst2pdf&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted&quot;&gt;give me money&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T16:04:44+00:00</dc:date>
</item>
<item rdf:about="http://feedproxy.google.com/~r/logilaborg_en/~3/5gYmy9xGhr0/20290">
	<title>Logilab: SCons presentation in 5 minutes</title>
	<link>http://feedproxy.google.com/~r/logilaborg_en/~3/5gYmy9xGhr0/20290</link>
	<content:encoded>&lt;img align=&quot;right&quot; alt=&quot;http://www.scons.org/scons-logo-transparent.png&quot; class=&quot;align-right&quot; src=&quot;http://www.scons.org/scons-logo-transparent.png&quot; /&gt;
&lt;p&gt;Building software with SCons requires to have Python and &lt;a class=&quot;reference&quot; href=&quot;http://www.scons.org&quot;&gt;SCons&lt;/a&gt; installed.&lt;/p&gt;
&lt;p&gt;As SCons is only made of Python modules, the sources may be shipped
with your project if your clients can not install dependencies. All
the following exemples can be downloaded at the end of that blog.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;a-building-tool-for-every-file-extension&quot;&gt;
&lt;h3&gt;&lt;a&gt;A building tool for every file extension&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First a Fortran 77 program will be built made of two files:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;fortran-project
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scons -Q
gfortran -o cfib.o -c cfib.f
gfortran -o fib.o -c fib.f
gfortran -o compute-fib cfib.o fib.o
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./compute-fib
 First 10 Fibonacci numbers:
  0.  1.  1.  2.  3.  5.  8. 13. 21. 34.
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;The '-Q' option tell to Scons to be less verbose. For cleaning the
project, add the '-c' option:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scons -Qc
Removed cfib.o
Removed fib.o
Removed compute-fib
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From this first example, it can been seen that SCons find the 'gfortran'
tool from the file extension. Then have a look at the user's manual
if you want to set a particular tool.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;describing-the-construction-with-python-objects&quot;&gt;
&lt;h3&gt;&lt;a&gt;Describing the construction with Python objects&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A second C program will directly run the execution from the SCons file
by adding a test command:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;c-project
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scons -Q run-test
gcc -o &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;.o -c &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;.c
gcc -o fact.o -c fact.c
ar rc libfact.a fact.o
ranlib libfact.a
gcc -o &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;-fact &lt;span class=&quot;nb&quot;&gt;test&lt;/span&gt;.o libfact.a
run_test&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;run-test&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;test-fact&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
OK
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;However running scons alone builds only the main program:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scons -Q
gcc -o main.o -c main.c
gcc -o compute-fact main.o libfact.a
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;./compute-fact
Computing factorial &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt;: 5
Result: 120
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This second example shows that the construction dependency is described
by passing Python objects. An interesting point is the possibility to
add your own Python functions in the build process.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;hierarchical-build-with-environment&quot;&gt;
&lt;h3&gt;&lt;a&gt;Hierarchical build with environment&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A third C++ program will create a shared library used for two different
programs: the main application and a test suite. The main application
can be built by:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;cd &lt;/span&gt;cxx-project
&lt;span class=&quot;nv&quot;&gt;$ &lt;/span&gt;scons -Q
g++ -o main.o -c -Imbdyn-src main.cxx
g++ -o mbdyn-src/nodes.os -c -fPIC -Imbdyn-src mbdyn-src/nodes.cxx
g++ -o mbdyn-src/solver.os -c -fPIC -Imbdyn-src mbdyn-src/solver.cxx
g++ -o mbdyn-src/libmbdyn.so -shared mbdyn-src/nodes.os mbdyn-src/solver.os
g++ -o mbdyn main.o -Lmbdyn-src -lmbdyn
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;It shows that SCons handles for us the compilation flags for creating a
shared library according to the tool (-fPIC). Moreover extra environment
variables have been given (CPPPATH, LIBPATH, LIBS), which are all
translated for the chosen tool. All those variables can be found
in the user's manual or in the man page.
The building and running of the test suite is made by giving an
extra variable:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span class=&quot;nv&quot;&gt;$ TEST_CMD&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;LD_LIBRARY_PATH=mbdyn-src ./%s&amp;quot;&lt;/span&gt; scons -Q run-tests
g++ -o tests/run_all_tests.o -c -Imbdyn-src tests/run_all_tests.cxx
g++ -o tests/test_solver.o -c -Imbdyn-src tests/test_solver.cxx
g++ -o tests/all-tests tests/run_all_tests.o tests/test_solver.o -Lmbdyn-src -lmbdyn
run_test&lt;span class=&quot;o&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tests/run-tests&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;, &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;tests/all-tests&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;])&lt;/span&gt;
OK
&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;conclusion&quot;&gt;
&lt;h3&gt;&lt;a&gt;Conclusion&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;That is rather convenient to build softwares by manipulating Python
objects, moreover custom actions can be added in the process. SCons has
also a configuration mechanism working like autotools macros that can
be discovered in the user's manual.&lt;/p&gt;
&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-09T15:38:58+00:00</dc:date>
</item>
<item rdf:about="http://www.muhuk.com/2010/02/top-5-untrends-according-to-me/">
	<title>Atamert Olcgen: Top 5 Untrends According To Me</title>
	<link>http://www.muhuk.com/2010/02/top-5-untrends-according-to-me/</link>
	<content:encoded>&lt;p&gt;My dear friend Ochronus posted an article titled &lt;a href=&quot;http://blog.mostof.it/posts/top-5-trends-in-software-development/&quot;&gt;&lt;em&gt;Top 5 trends and technologies in software development&lt;/em&gt;&lt;/a&gt; that got me thinking. My thoughts below. Go check Ochronus&amp;#8217;s blog if you haven&amp;#8217;t, he is the lead developer at &lt;a href=&quot;http://www.arukereso.hu/&quot;&gt;Arukereso.hu&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I agree with the suggestions from the original article. Yet, I would like to change the order a little bit; DVCS and then agile (with lowercase a) and then the rest. None of my points below are cool trends, in fact I can guarantee most of you will find them boring. But I think they are all important. OK, I hope you are all psyched now. Here we go:&lt;/p&gt;

&lt;h3&gt;1. Be Careful With The Buzz&lt;/h3&gt;

&lt;p&gt;Trends are cool. What could be wrong about following cutting edge stuff? We all want to be &lt;em&gt;up to date&lt;/em&gt;, no? I think it&amp;#8217;s good to follow the trends &lt;strong&gt;if&lt;/strong&gt; you have the experience and the ability to filter the BS. I know a young developer who was constantly going back and forth between &lt;a href=&quot;http://railsenvy.com/2007/9/10/ruby-on-rails-vs-django-commercial-7&quot;&gt;Rails/Ruby and Django/Python&lt;/a&gt;. I haven&amp;#8217;t heard from him for a while, but he is probably still doing that same dance. Why? Because his considerations were solely based on buzz, not on simple requirements analysis or technical comparisons or personal experience.&lt;/p&gt;

&lt;h3&gt;2. Learn And Use An Old-Fashioned &lt;del&gt;Modern&lt;/del&gt; Low-Level &lt;del&gt;Scripting&lt;/del&gt; Language&lt;/h3&gt;

&lt;p&gt;To all the &lt;em&gt;scripting&lt;/em&gt; people, like me, out there: you need to have an understanding of what&amp;#8217;s happening under the hood. At the least to appreciate our high-level environments, at the most to become genuinely good programmers. Being a Python person myself, I think the best low-level language to be proficient for me is C. Many other high-level languages have C interfaces. So investing the time to learn C should pay off one way or the other.&lt;/p&gt;

&lt;h3&gt;3. Do Less Web Programming&lt;/h3&gt;

&lt;p&gt;Aren&amp;#8217;t we doing a lot of web programming these days? Actually I think doing X development exclusively is bad for your programming muscles. Web programming, enterprise work or system scripting, it doesn&amp;#8217;t matter. But web programming happens more than anything else. Maybe some of you have only been playing with it, but there are a huge number of us doing nothing but web programming. This is so sad; both in an individual level and for the community at large.&lt;/p&gt;

&lt;h3&gt;4. Learn How To Educate Yourself&lt;/h3&gt;

&lt;p&gt;What is a noob? Here is a definition and disambiguation (from newbie):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Newbs are those who are new to some task and are very beginner at it, possibly a little overconfident about it, but they are willing to learn and fix their errors to move out of that stage. n00bs, on the other hand, know little and have no will to learn any more. They expect people to do the work for them and then expect to get praised about it, and make up a unique species of their own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make an active effort not to be a noob. Learn &lt;a href=&quot;http://catb.org/~esr/faqs/smart-questions.html&quot;&gt;how to ask smart questions&lt;/a&gt;, &lt;a href=&quot;http://www.dtcc.edu/cs/rfc1855.html&quot;&gt;how to communicate others&lt;/a&gt; and seek help. Being polite is good but actually improving and being a valuable member of the community is much, much better.&lt;/p&gt;

&lt;h3&gt;5. Open Source Properly&lt;/h3&gt;

&lt;p&gt;It&amp;#8217;s great to open source your project. But please do it properly. There are already too many unmaintained, undocumented projects out there that noone seem to care. Do you really have to add to that? &lt;em&gt;As is&lt;/em&gt; argument doesn&amp;#8217;t make much sense today. But if you really have to make an open source dead drop, please at least document the status of your project and your intentions clearly.&lt;/p&gt;

&lt;p&gt;I wouldn&amp;#8217;t be surprised if some you think they all are obvious. But if they are so obvious then why are they widely being ignored? Is it because they are under-retweeted, under-reddited and therefore not trendy.&lt;/p&gt;


&lt;p&gt;Related posts:&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://www.muhuk.com/2009/05/django-formfieldset/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: django-formfieldset&quot;&gt;django-formfieldset&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.muhuk.com/2009/05/nominate-qooxdoo-for-sourceforge-community-choice-awards/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: Nominate Qooxdoo for SourceForge Community Choice Awards&quot;&gt;Nominate Qooxdoo for SourceForge Community Choice Awards&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.muhuk.com/2009/05/sad-state-of-web-development-industry-in-turkiye/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: Sad State of Web Development Industry in Türkiye&quot;&gt;Sad State of Web Development Industry in Türkiye&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T15:21:39+00:00</dc:date>
</item>
<item rdf:about="http://www.blog.pythonlibrary.org/2010/02/09/enabling-screen-locking-with-python/">
	<title>Mike Driscoll: Enabling Screen Locking with Python</title>
	<link>http://www.blog.pythonlibrary.org/2010/02/09/enabling-screen-locking-with-python/</link>
	<content:encoded>&lt;p&gt;A few months ago, my employer needed to lock down some of our workstations to be compliant with some new software we were installing from another government organization. We needed to force those machines to lock after so many minutes elapsed and we needed to make it such that the user could not change those settings.  In this article, you&amp;#8217;ll find out how do this and as a bonus, I&amp;#8217;ll also show you how to lock your Windows machine on demand with Python.&lt;span id=&quot;more-569&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;h2&gt;Hacking the Registry to Lock the Machine&lt;/h2&gt;
&lt;p&gt;To start, we&amp;#8217;ll take a look at my original script and then we&amp;#8217;ll refactor it a bit to make the code better:&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; &lt;span&gt;_winreg&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; CreateKey, SetValueEx
&lt;span&gt;from&lt;/span&gt; &lt;span&gt;_winreg&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; HKEY_CURRENT_USER, HKEY_USERS
&lt;span&gt;from&lt;/span&gt; &lt;span&gt;_winreg&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; REG_DWORD, REG_SZ
&amp;nbsp;
&lt;span&gt;try&lt;/span&gt;:
    i = &lt;span&gt;0&lt;/span&gt;
    &lt;span&gt;while&lt;/span&gt; &lt;span&gt;True&lt;/span&gt;:
        subkey = EnumKey&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_USERS, i&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;len&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;subkey&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;30&lt;/span&gt;:
            &lt;span&gt;break&lt;/span&gt;
        i += &lt;span&gt;1&lt;/span&gt;
&lt;span&gt;except&lt;/span&gt; &lt;span&gt;WindowsError&lt;/span&gt;:
    &lt;span&gt;# WindowsError: [Errno 259] No more data is available&lt;/span&gt;
    &lt;span&gt;# looped through all the subkeys without finding the right one&lt;/span&gt;
    &lt;span&gt;raise&lt;/span&gt; &lt;span&gt;WindowsError&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;quot;Could not apply workstation lock settings!&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
keyOne = CreateKey&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_USERS, r&lt;span&gt;'%s&lt;span&gt;\C&lt;/span&gt;ontrol Panel&lt;span&gt;\D&lt;/span&gt;esktop'&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; subkey&lt;span&gt;&amp;#41;&lt;/span&gt;
keyTwo = CreateKey&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_CURRENT_USER, r&lt;span&gt;'Software&lt;span&gt;\M&lt;/span&gt;icrosoft&lt;span&gt;\W&lt;/span&gt;indows&lt;span&gt;\C&lt;/span&gt;urrentVersion&lt;span&gt;\P&lt;/span&gt;olicies&lt;span&gt;\S&lt;/span&gt;ystem'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;# enable screen saver security&lt;/span&gt;
SetValueEx&lt;span&gt;&amp;#40;&lt;/span&gt;keyOne, &lt;span&gt;'ScreenSaverIsSecure'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;, REG_DWORD, &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&lt;span&gt;# set screen saver timeout&lt;/span&gt;
SetValueEx&lt;span&gt;&amp;#40;&lt;/span&gt;keyOne, &lt;span&gt;'ScreenSaveTimeOut'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;, REG_SZ, &lt;span&gt;'420'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&lt;span&gt;# set screen saver&lt;/span&gt;
SetValueEx&lt;span&gt;&amp;#40;&lt;/span&gt;keyOne, &lt;span&gt;'SCRNSAVE.EXE'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;, REG_SZ, &lt;span&gt;'logon.scr'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&lt;span&gt;# disable screen saver tab&lt;/span&gt;
SetValueEx&lt;span&gt;&amp;#40;&lt;/span&gt;keyTwo, &lt;span&gt;'NoDispScrSavPage'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;, REG_DWORD, &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
CloseKey&lt;span&gt;&amp;#40;&lt;/span&gt;keyOne&lt;span&gt;&amp;#41;&lt;/span&gt;
CloseKey&lt;span&gt;&amp;#40;&lt;/span&gt;keyTwo&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;It took a while to discover this, but to set the right key, we need to find the first sub-key that is larger than 30 characters in length under the HKEY_USERS hive. I&amp;#8217;m sure there&amp;#8217;s probably a better way to do this, but I haven&amp;#8217;t found it yet. Anyway, once we&amp;#8217;ve found the long key, we break out of the loop and open the keys we need or create them if they don&amp;#8217;t already exist. This is the reason that we use CreateKey since it will do just that.  Next, we set four values and then we close the keys to apply the new settings. You can read the comments to see what each key does. Now let&amp;#8217;s refine the code a bit to make it into a function:&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; &lt;span&gt;_winreg&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; &lt;span&gt;*&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;def&lt;/span&gt; modifyRegistry&lt;span&gt;&amp;#40;&lt;/span&gt;key, sub_key, valueName, valueType, value&lt;span&gt;&amp;#41;&lt;/span&gt;:
    &lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;quot;
    A simple function used to change values in
    the Windows Registry.
    &amp;quot;&lt;/span&gt;&lt;span&gt;&amp;quot;&amp;quot;&lt;/span&gt;
    &lt;span&gt;try&lt;/span&gt;:
        key_handle = OpenKey&lt;span&gt;&amp;#40;&lt;/span&gt;key, sub_key, &lt;span&gt;0&lt;/span&gt;, KEY_ALL_ACCESS&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;except&lt;/span&gt; &lt;span&gt;WindowsError&lt;/span&gt;:
        key_handle = CreateKey&lt;span&gt;&amp;#40;&lt;/span&gt;key, sub_key&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    SetValueEx&lt;span&gt;&amp;#40;&lt;/span&gt;key_handle, valueName, &lt;span&gt;0&lt;/span&gt;, valueType, value&lt;span&gt;&amp;#41;&lt;/span&gt;
    CloseKey&lt;span&gt;&amp;#40;&lt;/span&gt;key_handle&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;try&lt;/span&gt;:
    i = &lt;span&gt;0&lt;/span&gt;
    &lt;span&gt;while&lt;/span&gt; &lt;span&gt;True&lt;/span&gt;:
        subkey = EnumKey&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_USERS, i&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;len&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;subkey&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;&amp;gt;&lt;/span&gt; &lt;span&gt;30&lt;/span&gt;:
            &lt;span&gt;break&lt;/span&gt;
        i += &lt;span&gt;1&lt;/span&gt;
&lt;span&gt;except&lt;/span&gt; &lt;span&gt;WindowsError&lt;/span&gt;:
    &lt;span&gt;# WindowsError: [Errno 259] No more data is available&lt;/span&gt;
    &lt;span&gt;# looped through all the subkeys without finding the right one&lt;/span&gt;
    &lt;span&gt;raise&lt;/span&gt; &lt;span&gt;WindowsError&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;quot;Could not apply workstation lock settings!&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
subkey = r&lt;span&gt;'%s&lt;span&gt;\C&lt;/span&gt;ontrol Panel&lt;span&gt;\D&lt;/span&gt;esktop'&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; subkey
data= &lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'ScreenSaverIsSecure'&lt;/span&gt;, REG_DWORD, &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;,
              &lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'ScreenSaveTimeOut'&lt;/span&gt;, REG_SZ, &lt;span&gt;'420'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;,
              &lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'SCRNSAVE.EXE'&lt;/span&gt;, REG_SZ, &lt;span&gt;'logon.scr'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;for&lt;/span&gt; valueName, valueType, value &lt;span&gt;in&lt;/span&gt; data:
    modifyRegistry&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_USERS, subkey, valueName,
                   valueType, value&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
modifyRegistry&lt;span&gt;&amp;#40;&lt;/span&gt;HKEY_CURRENT_USER,
               r&lt;span&gt;'Software&lt;span&gt;\M&lt;/span&gt;icrosoft&lt;span&gt;\W&lt;/span&gt;indows&lt;span&gt;\C&lt;/span&gt;urrentVersion&lt;span&gt;\P&lt;/span&gt;olicies&lt;span&gt;\S&lt;/span&gt;ystem'&lt;/span&gt;,
               &lt;span&gt;'NoDispScrSavPage'&lt;/span&gt;, REG_DWORD, &lt;span&gt;1&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;As you can see, first we import everything in the &lt;em&gt;_winreg&lt;/em&gt; module. This isn&amp;#8217;t really recommended as you can accidentally overwrite functions that you&amp;#8217;ve imported, which is why this is sometimes called &amp;#8220;poisoning the namespace&amp;#8221;. However, almost every example I&amp;#8217;ve ever seen that uses the _winreg modules does it that way. See the first example for the correct way to import from it.&lt;/p&gt;
&lt;p&gt;Next, we create a general purpose function that can open the key, or create the key if it&amp;#8217;s not already there. The function will also set the value and close the key for us. After that, we do basically the same thing that we did in the previous example: we loop over the HKEY_USERS hive and break appropriately. To mix things up a bit, we create a &lt;em&gt;data&lt;/em&gt; variable that holds a list of tuples. We loop over that and call our function with the appropriate parameters and for good measure, we demonstrate how to call it outside of a loop.&lt;/p&gt;
&lt;h2&gt;Locking the Machine Programmatically&lt;/h2&gt;
&lt;p&gt;Now you may be thinking that we already covered how to lock the machine programmatically. Well, we did in a sense; but what we really did was set up a timer to lock the machine sometime in the future when the machine has been idle. What if we want to lock the machine now? Some of you are probably thinking we should just hit the Windows key plus &amp;#8220;L&amp;#8221; and that is a good idea. However, the reason I created this script is because I have to remotely connect to my machine with VNC from time-to-time and I need to go through multiple steps to lock the machine when using VNC whereas if you have Python set up correctly, you can just double-click a script file and have it do the locking for you. That&amp;#8217;s what this little script does:&lt;/p&gt;
&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;import&lt;/span&gt; &lt;span&gt;os&lt;/span&gt;
&amp;nbsp;
winpath = &lt;span&gt;os&lt;/span&gt;.&lt;span&gt;environ&lt;/span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;&lt;span&gt;&amp;quot;windir&amp;quot;&lt;/span&gt;&lt;span&gt;&amp;#93;&lt;/span&gt;
&lt;span&gt;os&lt;/span&gt;.&lt;span&gt;system&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;winpath + r&lt;span&gt;'&lt;span&gt;\s&lt;/span&gt;ystem32&lt;span&gt;\r&lt;/span&gt;undll32 user32.dll, LockWorkStation'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;This three line script imports the &lt;em&gt;os&lt;/em&gt; module, grabs the Windows directory using its &lt;em&gt;environ &lt;/em&gt;method and then calls &lt;em&gt;os.system&lt;/em&gt; to lock the machine. If you were to open a DOS window on your machine and type the following into it, you would have the exact same effect:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;
C:\windows\system32\rundll32 user32.dll, LockWorkStation&lt;br /&gt;
&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Wrapping Up&lt;/h2&gt;
&lt;p&gt;Now you know how to lock your machine with Python. If you put the first example in a login script, then you can use it lock down some or all the machines on your network. This is very handy if you have users that like to wander off or go to lots of meetings, but leave their machines logged in. It protects them from snooping and can protect your company from espionage.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T15:11:38+00:00</dc:date>
</item>
<item rdf:about="http://www.huyng.com/archives/537">
	<title>Huy Nguyen: Exceptions are your Friends</title>
	<link>http://www.huyng.com/archives/537</link>
	<content:encoded>Robust code cries often and loudly as soon as something is not right. It does not cower away in corners of obscurity hoping that no one will notice, until one day, shit hits the fan.
Any serious python code contains proper use of exceptions, errors, and asserts. In fact, I would argue that their presence defines [...]</content:encoded>
	<dc:date>2010-02-09T15:00:39+00:00</dc:date>
</item>
<item rdf:about="http://feedproxy.google.com/~r/Jessenollercom/~3/SpQ2iwDU11M/">
	<title>Jesse Noller: Say Hello – Nasuni Launches Today!</title>
	<link>http://feedproxy.google.com/~r/Jessenollercom/~3/SpQ2iwDU11M/</link>
	<content:encoded>&lt;p&gt;&lt;img src=&quot;http://jessenoller.com/wp-content/uploads/2010/02/nasuni_final.png&quot; alt=&quot;nasuni_final.png&quot; border=&quot;0&quot; width=&quot;226&quot; height=&quot;62&quot; align=&quot;right&quot; /&gt; The company I&amp;#8217;ve worked for since July of last year &amp;#8211; &lt;a href=&quot;http://www.nasuni.com&quot; target=&quot;_blank&quot;&gt;Nasuni Corporation&lt;/a&gt; (a startup in Massachusetts) has gone live! This is the culmination of a lot of hard, but exceedingly fun and exciting work over the past months.&lt;/p&gt;
&lt;p&gt;The Nasuni team is an excellent one &amp;#8211; and one I am very, very proud to be a part of. Our product is called the Nasuni Filer &amp;#8211; a simple-to-use, versioned, encrypted and cloud-storage backed virtual NAS (network attached storage) server (click &lt;a href=&quot;http://www.nasuni.com/product/product-overview/&quot; target=&quot;_blank&quot;&gt;here&lt;/a&gt; for more information).&lt;/p&gt;
&lt;p&gt;Without going into all of the features, our goal in making this was to make cloud storage &lt;b&gt;simple&lt;/b&gt;, &lt;b&gt;accessible&lt;/b&gt; and &lt;b&gt;secure&lt;/b&gt; &amp;#8211; and I know we&amp;#8217;ve accomplished all three. All you do is download it, boot it and start using it &amp;#8211; once you do so you have access to truly unlimited storage. It&amp;#8217;s an unlimited filesystem for the cloud. Here&amp;#8217;s the elevator pitch:&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;
Nasuni has developed a virtual file server, called the Nasuni Filer, that delivers unlimited file storage and complete file protection for businesses. Working in partnership with leading cloud storage vendors, the Nasuni Filer leverages the vast capacity of the cloud to store and protect company files offsite, while retaining the local functionality and performance of a traditional NAS.&lt;/p&gt;
&lt;p&gt;This technology allows businesses to use the cloud provider of their choice as a replacement for traditional primary storage. Snapshots, file versioning, and offsite storage are integrated into the file server itself &amp;#8211; ensuring business file are safe and secure at all times. No need to manage complex backup and DR schemes &amp;#8211; if the file server is running, files are protected.
&lt;/p&gt;&lt;/blockquote&gt;
&lt;p&gt;We&amp;#8217;ve launched the &lt;a href=&quot;http://www.nasuni.com/free-trial/free-trial-registration/&quot; target=&quot;_blank&quot;&gt;Beta of the product&lt;/a&gt; today &amp;#8211; anyone can sign up, download and use it. Anyone can give us feedback and suggestions &amp;#8211; I encourage all of you who might need something like this to download and give it a try. If you want &amp;#8211; go check out the videos we&amp;#8217;ve put together &lt;a href=&quot;http://www.nasuni.com/support/how-videos/&quot; target=&quot;_blank&quot;&gt;showcasing the Filer&lt;/a&gt; (and better yet &amp;#8211; check out the awesome animated cartoon we have on the &lt;a href=&quot;http://www.nasuni.com/&quot; target=&quot;_blank&quot;&gt;front page&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;Most of you know that my blog is mainly Python oriented. Suffice it to say, Nasuni &amp;#8211; and the Nasuni Filer make use of Python for a wide range of tasks. We use Python, Django and as much of the Python ecosystem as we can to drive everything from the website, to the GUI on the appliance itself &amp;#8211; Python is part of the DNA of the company, and it has served us well. Without Open Source and Python &amp;#8211; I don&amp;#8217;t think it would have been possible to build what we have built in as little time as we have.&lt;/p&gt;
&lt;p&gt;We have a strong dedication to not just Python, but open source in general (and a fair number of us will be at PyCon this month).  As time progresses, now that we&amp;#8217;re exiting stealth mode we plan on possibly open sourcing stuff we feel would benefit the community. Some of us already push patches back where and when we can, but as I said &amp;#8211; as time progresses this involvement will only increase.&lt;/p&gt;
&lt;p&gt;So not only am I proud to announce the product, be part of this team and to see what we&amp;#8217;ve made, I&amp;#8217;m also happy to thank so many people in the Python and OSS community which have helped us reach this point.&lt;/p&gt;
&lt;p&gt;So go &amp;#8211; &lt;a href=&quot;http://www.nasuni.com/&quot; target=&quot;_blank&quot;&gt;check it out&lt;/a&gt;, let us know what you think.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T13:35:03+00:00</dc:date>
</item>
<item rdf:about="http://the-space-station.com/2010/2/9/multi-touch:-pymt-0-4-released">
	<title>Christopher Denter: Multi-Touch: PyMT 0.4 released</title>
	<link>http://the-space-station.com/2010/2/9/multi-touch:-pymt-0-4-released</link>
	<content:encoded>&lt;img src=&quot;http://the-space-station.com/~dennda/gallery/mt/BoneTouchMarketingSmall.png&quot; alt=&quot;Multi-Touch helps to visualize and interact with medical data (image)&quot; /&gt;

&lt;p&gt;The awesome &lt;a href=&quot;http://the-space-station.com/2009/11/19/pymt-multi-touch-with-python&quot;&gt;PyMT library&lt;/a&gt; has just been released in version 0.4.&lt;/p&gt;

&lt;p&gt;This is a major release that brings a ton of cool new stuff, including a new animation framework, speed &amp;amp; stability improvements and much more.
Take a look at the &lt;a href=&quot;http://pymt.txzone.net/?page=releasenotes&quot;&gt;release notes&lt;/a&gt; to see what’s new in this release.&lt;/p&gt;

&lt;p&gt;I’m using PyMT for my thesis (see picture above) and I love it. Make sure to check the new &lt;a href=&quot;http://pymt.txzone.net/&quot;&gt;website&lt;/a&gt;, too! (There’s also a new demo video in the works. I will update this posting as soon as it’s available.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T13:23:10+00:00</dc:date>
</item>
<item rdf:about="http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html">
	<title>Ned Batchelder: A preventable Python packaging peeve</title>
	<link>http://nedbatchelder.com/blog/201002/a_preventable_python_packaging_peeve.html</link>
	<content:encoded>&lt;p&gt;Python packaging is a common theme on which to complain, and rightly so.
It's no one's first love, so it tends not to get the devoted attention of say,
Numpy.  And it's a hard problem to solve well.  So we have a mish-mash of tools
that each do about 75% of the job.&lt;/p&gt;&lt;p&gt;But there's one small aspect of Python packaging that could easily be solved
well if people just attended to it:  Not enough Python projects clearly state
what versions of Python they run on.&lt;/p&gt;&lt;p&gt;For example, suppose you are in the market for a mock object library for your
tests.  There's no shortage.  Less than a minute at PyPI produces
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/mock/0.6.0&quot;&gt;mock&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/MiniMock/1.2.5&quot;&gt;MiniMock&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/mocktest/0.3.1&quot;&gt;mocktest&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/Mocky/0.2&quot;&gt;Mocky&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/pmock/0.3&quot;&gt;pmock&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/mocker/0.10.1&quot;&gt;mocker&lt;/a&gt;,
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/mockito/0.2.0&quot;&gt;mockito&lt;/a&gt;, and
&lt;a class=&quot;offsite&quot; href=&quot;http://pypi.python.org/pypi/ludibrio/2.0&quot;&gt;ludibrio&lt;/a&gt;.
Some of those PyPI pages have extensive documentation.  Not a single one explicitly
mentions the versions of Python supported.  And I don't mean 2.x vs. 3.x.  I want
to know if it will run on 2.4 or not.  Ludibrio and Mocky offer a slight clue
in that they are available for download as an egg, for 2.5 and 2.4 respectively.
pMock mentions &amp;gt;= 2.3 support on the home page linked from the PyPI page.&lt;/p&gt;&lt;p&gt;On top of all the other well-known difficulties people have with Python
packaging, at the very least, we should be able to manage this: clearly state
what versions of Python you support.  This is a simple three-step process:&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Decide what versions you want to support.&lt;/li&gt;
&lt;li&gt;Test your code on those versions.&lt;/li&gt;
&lt;li&gt;Add a sentence like this to your PyPI documentation: &quot;SpockMocker runs
on Python 2.5 and 2.6&quot;.&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The Python community will thank you.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T12:58:37+00:00</dc:date>
</item>
<item rdf:about="http://posted-stuff.blogspot.com/2010/02/mailman-style-mailing-list-archives.html">
	<title>Richard Tew: Mailman-style mailing list archives</title>
	<link>http://posted-stuff.blogspot.com/2010/02/mailman-style-mailing-list-archives.html</link>
	<content:encoded>I have the posts made to several mailing lists in a variety of non-standard formats.  Converting them to a standard mbox file is a matter of parsing and is a different process for each.  Once I have each parsed, what I would like to do is generate Mailman-style list archives.&lt;br /&gt;&lt;br /&gt;I've downloaded Mailman and tried to get it to take my mbox file, and output the list archives.  But the process is to some degree tied to Unix-style platforms, relying on functionality that is not supported on Windows.  But to a larger degree, it is tied into the quality of being a proper Mailman hosted mailing list.  Even changing the code to address or work around these things is not the cleanest of processes.  There must be a better way.&lt;br /&gt;&lt;br /&gt;Any suggestions?&lt;br /&gt;&lt;br /&gt;Have some hacky code while I am at it:&lt;pre class=&quot;brush: python&quot;&gt;&lt;br /&gt;    WORKING_PATH = r&quot;D:\MailingList&quot;&lt;br /&gt;    MAILMAN_PATH = os.path.join(WORKING_PATH, &quot;mailman-2.1.13&quot;)&lt;br /&gt;&lt;br /&gt;    class MailList:&lt;br /&gt;        def __init__(self, basePath, fileName):&lt;br /&gt;            self.basePath = basePath&lt;br /&gt;            self.fileName = fileName&lt;br /&gt;            self.SetVars()&lt;br /&gt;&lt;br /&gt;        def SetVars(self):&lt;br /&gt;            self._internal_name = &quot;mud-dev&quot;&lt;br /&gt;            self._fullpath = &quot;/resource/MUD-Dev/&quot;&lt;br /&gt;            self.host_name = &quot;localhost&quot;&lt;br /&gt;            self.subject_prefix = &quot;[MUD-Dev] &quot;&lt;br /&gt;            self.real_name = &quot;MUD-Dev&quot;&lt;br /&gt;&lt;br /&gt;        def fullpath(self):&lt;br /&gt;            return self._fullpath&lt;br /&gt;&lt;br /&gt;        def archive_dir(self):&lt;br /&gt;            return self.basePath&lt;br /&gt;&lt;br /&gt;        def internal_name(self):&lt;br /&gt;            return self.fileName&lt;br /&gt;&lt;br /&gt;        def ArchiveFileName(self):&lt;br /&gt;            return os.path.join(self.basePath, self.internal_name() + &quot;.mbox&quot;)&lt;br /&gt;&lt;br /&gt;        def GetScriptURL(self, *args, **kwargs):&lt;br /&gt;            return args[0]&lt;br /&gt;&lt;br /&gt;        def GetListEmail(self):&lt;br /&gt;            return &quot;no-list-email&quot;&lt;br /&gt;&lt;br /&gt;    class SuperDuperArchive(HyperArchive):&lt;br /&gt;        def GetArchLock(self): return 1&lt;br /&gt;&lt;br /&gt;        def DropArchLock(self): pass&lt;br /&gt;        &lt;br /&gt;    def fake_symlink(src, dst):&lt;br /&gt;        if os.path.exists(src):&lt;br /&gt;            open(dst, &quot;w&quot;).write(open(src, &quot;r&quot;).read())&lt;br /&gt;&lt;br /&gt;    os.symlink = fake_symlink&lt;br /&gt;    os.link = fake_symlink&lt;br /&gt;    Mailman.mm_cfg.TEMPLATE_DIR = os.path.join(MAILMAN_PATH, &quot;templates&quot;)&lt;br /&gt;    Mailman.mm_cfg.LIST_DATA_DIR = WORKING_PATH&lt;br /&gt;    Mailman.mm_cfg.PUBLIC_ARCHIVE_FILE_DIR = WORKING_PATH&lt;br /&gt;    Mailman.mm_cfg.PRIVATE_ARCHIVE_FILE_DIR = WORKING_PATH&lt;br /&gt;&lt;br /&gt;    mlist = MailList(os.path.join(filePath, &quot;archives&quot;), &quot;mud-dev&quot;)&lt;br /&gt;    mlist.preferred_language = 'en'&lt;br /&gt;    &lt;br /&gt;    listPath = os.path.join(Mailman.mm_cfg.LIST_DATA_DIR, mlist.internal_name())&lt;br /&gt;    if not os.path.exists(listPath):&lt;br /&gt;        os.makedirs(listPath)&lt;br /&gt;&lt;br /&gt;    class DummyClass:&lt;br /&gt;        def internal_name(self):&lt;br /&gt;            return &quot;mud-dev&quot;&lt;br /&gt;&lt;br /&gt;        def archive_dir(self):&lt;br /&gt;            return Site.get_archpath(self.internal_name())&lt;br /&gt;&lt;br /&gt;        def GetScriptURL(self, *args, **kwargs):&lt;br /&gt;            return args[0]&lt;br /&gt;&lt;br /&gt;        def GetListEmail(self):&lt;br /&gt;            return &quot;no-list-email&quot;&lt;br /&gt;&lt;br /&gt;    instance = DummyClass()&lt;br /&gt;&lt;br /&gt;    Mailman.MailList.MailList.InitVars.im_func(instance, &quot;mud-dev&quot;)&lt;br /&gt;    for baseclass in Mailman.MailList.MailList.__bases__:&lt;br /&gt;        if hasattr(baseclass, 'InitVars'):&lt;br /&gt;            baseclass.InitVars.im_func(instance)&lt;br /&gt;&lt;br /&gt;    MailList.SetVars.im_func(instance)&lt;br /&gt;&lt;br /&gt;    listConfigPath = os.path.join(listPath, &quot;config.pck&quot;)&lt;br /&gt;    if not os.path.exists(listConfigPath):&lt;br /&gt;        cPickle.dump(instance.__dict__, open(listConfigPath, &quot;wb&quot;))&lt;br /&gt;&lt;br /&gt;    archive = SuperDuperArchive(mlist)&lt;br /&gt;    archive.processListArch()&lt;br /&gt;    archive.close()&lt;/pre&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/27648409-4167916853613161900?l=posted-stuff.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-09T06:37:30+00:00</dc:date>
</item>
<item rdf:about="http://www.heikkitoivonen.net/blog/2010/02/08/pulling-android-market-sales-data-programmatically/">
	<title>Heikki Toivonen: Pulling Android Market Sales Data Programmatically</title>
	<link>http://www.heikkitoivonen.net/blog/2010/02/08/pulling-android-market-sales-data-programmatically/</link>
	<content:encoded>&lt;p&gt;Android Market handles sales through Google Checkout. I haven&amp;#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.&lt;/p&gt;
&lt;p&gt;Google provides a &lt;a href=&quot;http://code.google.com/apis/checkout/developer/Google_Checkout_XML_API_Notification_History_API.html&quot;&gt;Google Checkout Notification History API&lt;/a&gt; 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.&lt;/p&gt;
&lt;p&gt;Below is a really simple Python script that uses &lt;a href=&quot;http://chandlerproject.org/Projects/MeTooCrypto&quot;&gt;M2Crypto&lt;/a&gt; to handle the SSL parts for the connection (needed since &lt;a href=&quot;http://www.heikkitoivonen.net/blog/2008/10/14/ssl-in-python-26/&quot;&gt;Python doesn&amp;#8217;t do secure SSL out of the box&lt;/a&gt;). You will also need to &lt;a href=&quot;http://www.heikkitoivonen.net/blog/2008/09/30/root-certificates-for-python-programs-using-python/&quot;&gt;grab certificates&lt;/a&gt;. You should save the script as &lt;code&gt;gnotif.py&lt;/code&gt;, save the certificates as &lt;code&gt;cacert.pem&lt;/code&gt; and create &lt;code&gt;gnotif.ini&lt;/code&gt; as described in the script below all in the same directory. When you execute it, it will ask for start and end date (in &lt;code&gt;YYYY-MM-DD&lt;/code&gt; format) and then fetch all the data, saving them in response-N.xml files, where N is a number.&lt;/p&gt;

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

&lt;p&gt;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 &lt;a href=&quot;http://googlecheckout.blogspot.com/2009/09/transaction-fee-information-now.html&quot;&gt;toggle a checkbox in your Google Checkout Merchant Settings&lt;/a&gt;. 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.&lt;/p&gt;
&lt;p&gt;I also haven&amp;#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.)&lt;/p&gt;
&lt;p&gt;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&amp;#8230;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-09T04:48:51+00:00</dc:date>
</item>
<item rdf:about="">
	<title>Vern Ceder: Get the most out of PyCon – VOLUNTEER</title>
	<link></link>
	<content:encoded>PyCon Atlanta is now less than 2 weeks away, and things are coming together. My big concern, the poster session, is pretty much set to go. Transportation, check. Hotel, check. Conference registration, time off from work, talks I want to catch, tentative open space plans: check, check, check, and check. 
Yesterday I added the final [...]&lt;img alt=&quot;&quot; border=&quot;0&quot; src=&quot;http://stats.wordpress.com/b.gif?host=learnpython.wordpress.com&amp;blog=1158170&amp;post=80&amp;subd=learnpython&amp;ref=&amp;feed=1&quot; /&gt;</content:encoded>
	<dc:date>2010-02-09T04:30:32+00:00</dc:date>
</item>
<item rdf:about="http://techblog.ironfroggy.com/2010/02/deferargs-on-github.html">
	<title>Calvin Spealman: DeferArgs on GitHub</title>
	<link>http://techblog.ironfroggy.com/2010/02/deferargs-on-github.html</link>
	<content:encoded>A time ago I wrote a library called DeferArgs and I used it when I was still in Twisted code every day. I no longer have that fun, but I was reminded of the code and decided to throw it onto GitHub for anyone who cares for it.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;a href=&quot;http://github.com/ironfroggy/DeferArgs&quot;&gt;http://github.com/ironfroggy/DeferArgs&lt;/a&gt;&lt;br /&gt;
&lt;br /&gt;
An example usage, where &lt;span&gt;foo&lt;/span&gt; could take any deferreds and would be called when they all fire.&lt;br /&gt;
 &lt;br /&gt;
 &lt;span&gt;@deferargs&lt;/span&gt;&lt;br /&gt;&lt;span&gt;def foo():&lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; assert False&lt;/span&gt;&lt;br /&gt;&lt;span&gt;@catch(AssertionError)&lt;/span&gt;&lt;br /&gt;&lt;span&gt;def onAssert(error):&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;OOPS&quot;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;@catch()&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;def onOthers(error):&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;I WOULD BE REACHED FOR ANYTHING NOT CAUGHT ABOVE.&quot;&lt;/span&gt;&lt;br /&gt;&lt;span&gt;@cleanup&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;def _(r):&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; print &quot;The result was: &quot;, r&lt;/span&gt;&lt;br /&gt;
&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/21332048-7044502207707423382?l=techblog.ironfroggy.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;div class=&quot;feedflare&quot;&gt;
&lt;a href=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?a=phcA8v1dcNQ:YzCr3yGUjko:yIl2AUoC8zA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?d=yIl2AUoC8zA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?a=phcA8v1dcNQ:YzCr3yGUjko:63t7Ie-LG7Y&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?d=63t7Ie-LG7Y&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?a=phcA8v1dcNQ:YzCr3yGUjko:F7zBnMyn0Lo&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?i=phcA8v1dcNQ:YzCr3yGUjko:F7zBnMyn0Lo&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?a=phcA8v1dcNQ:YzCr3yGUjko:7Q72WNTAKBA&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?d=7Q72WNTAKBA&quot; border=&quot;0&quot; /&gt;&lt;/a&gt; &lt;a href=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?a=phcA8v1dcNQ:YzCr3yGUjko:V_sGLiPBpWU&quot;&gt;&lt;img src=&quot;http://feeds.feedburner.com/~ff/RavingTechnoRant?i=phcA8v1dcNQ:YzCr3yGUjko:V_sGLiPBpWU&quot; border=&quot;0&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-09T03:44:00+00:00</dc:date>
</item>
<item rdf:about="http://www.eflorenzano.com/blog/post/how-do-we-kick-our-synchronous-addiction/">
	<title>Eric Florenzano: How do we kick our synchronous addiction?</title>
	<link>http://www.eflorenzano.com/blog/post/how-do-we-kick-our-synchronous-addiction/</link>
	<content:encoded>&lt;p&gt;Asynchronous programming is superior &lt;a class=&quot;reference external&quot; href=&quot;http://blog.webfaction.com/a-little-holiday-present&quot;&gt;both in memory usage and in overall throughput&lt;/a&gt; when compared to synchronous programming .  We've &lt;a class=&quot;reference external&quot; href=&quot;http://www.kegel.com/c10k.html&quot;&gt;known this fact for years&lt;/a&gt;.  If we look at Django or Ruby on Rails, arguably the two most promising new web application frameworks to emerge in the past few years, both of them are written in such a way that synchronous programming  is assumed. Why is it that even in 2010 we're still writing programs that rely on synchronous programming ?&lt;/p&gt;
&lt;p&gt;The reason that we're stuck on synchronous programming  is twofold.  Firstly, the programming model required for straightforward asynchronous implementations is inconvenient.  Secondly, popular and/or mainstream languages lack the built-in language constructs that are needed to implement a less-straightforward approach to asynchronous programming.&lt;/p&gt;
&lt;div class=&quot;section&quot; id=&quot;asynchronous-programming-is-too-hard&quot;&gt;
&lt;h1&gt;Asynchronous programming is too hard&lt;/h1&gt;
&lt;p&gt;Let's first examine the straightforward implementation: an event loop.  In this programming model, we have a single process with a single loop that runs continuously.  Functionality is achieved by writing functions to execute small tasks quickly, and inserting those functions into that event loop.  One of those functions might read some bytes from a socket, while another function might write a few bytes to a file, and yet another function might do something computational like calculating an XOR on the data that's been buffered from that first socket.&lt;/p&gt;
&lt;p&gt;The most important part about this event loop is that only one thing is ever happening at a time.  That means that you really have to break your logic up into small chunks that can be performed incrementally.  If any one of our functions blocks, it hogs the event loop and nothing else can execute during that time.&lt;/p&gt;
&lt;p&gt;We have some really great frameworks geared towards making this event loop model easier to work with.  In Python, there's &lt;a class=&quot;reference external&quot; href=&quot;http://twistedmatrix.com/trac/&quot;&gt;Twisted&lt;/a&gt; and, more recently, &lt;a class=&quot;reference external&quot; href=&quot;http://www.tornadoweb.org/&quot;&gt;Tornado&lt;/a&gt;.  In Ruby there's &lt;a class=&quot;reference external&quot; href=&quot;http://rubyeventmachine.com/&quot;&gt;EventMachine&lt;/a&gt;.  In PERL there's &lt;a class=&quot;reference external&quot; href=&quot;http://poe.perl.org/&quot;&gt;POE&lt;/a&gt;.  What these frameworks do is twofold: provide constructs for more easily working with an event loop (e.g. &lt;a class=&quot;reference external&quot; href=&quot;http://twistedmatrix.com/documents/current/core/howto/defer.html&quot;&gt;Deferreds&lt;/a&gt; or &lt;a class=&quot;reference external&quot; href=&quot;http://en.wikipedia.org/wiki/Futures_and_promises&quot;&gt;Promises&lt;/a&gt;), and provide asynchronous implementations of common tasks (e.g. HTTP clients and DNS resolution).&lt;/p&gt;
&lt;p&gt;But these frameworks stop very short of making asynchronous programming easy for two reasons.  The first reason is that we really do have to completely change our coding style.  Consider what it would take to render a simple blog web page with comments.  Here's some JavaScript code to demonstrate how this might work in a synchronous framework:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;function&lt;/span&gt; handleBlogPostRequest(request&lt;span&gt;,&lt;/span&gt; response&lt;span&gt;,&lt;/span&gt; postSlug) {
    &lt;span&gt;var&lt;/span&gt; db &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; DBClient();
    &lt;span&gt;var&lt;/span&gt; post &lt;span&gt;=&lt;/span&gt; db.getBlogPost(postSlug);
    &lt;span&gt;var&lt;/span&gt; comments &lt;span&gt;=&lt;/span&gt; db.getComments(post.id);
    &lt;span&gt;var&lt;/span&gt; html &lt;span&gt;=&lt;/span&gt; template.render(&lt;span&gt;'blog/post.html'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;
        {&lt;span&gt;'post'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; post&lt;span&gt;,&lt;/span&gt; &lt;span&gt;'comments'&lt;/span&gt;&lt;span&gt;:&lt;/span&gt; comments});
    response.write(html);
    response.close();
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now here's some JavaScript code to demonstrate how this might look in an asynchronous framework.  Note several things here: We've specifically written this in such a way that it doesn't become nested four levels deep.  We've also written these callback functions inside of the &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;handleBlogPostRequest&lt;/span&gt;&lt;/tt&gt; function to take advantage of closure so as to retain access to the request and response objects, the template context, and the database client. Both the desire to avoid nesting and the closure are things that we need to think about as we write this code, that were not even considerations in the synchronous version:&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;function&lt;/span&gt; handleBlogPostRequest(request&lt;span&gt;,&lt;/span&gt; response&lt;span&gt;,&lt;/span&gt; postSlug) {
    &lt;span&gt;var&lt;/span&gt; context &lt;span&gt;=&lt;/span&gt; {};
    &lt;span&gt;var&lt;/span&gt; db &lt;span&gt;=&lt;/span&gt; &lt;span&gt;new&lt;/span&gt; DBClient();
    &lt;span&gt;function&lt;/span&gt; pageRendered(html) {
        response.write(html);
        response.close();
    }
    &lt;span&gt;function&lt;/span&gt; gotComments(comments) {
        context[&lt;span&gt;'comments'&lt;/span&gt;] &lt;span&gt;=&lt;/span&gt; comments&lt;span&gt;;&lt;/span&gt;
        template.render(&lt;span&gt;'blog/post.html'&lt;/span&gt;&lt;span&gt;,&lt;/span&gt; context).addCallback(pageRendered);
    }
    &lt;span&gt;function&lt;/span&gt; gotBlogPost(post) {
        context[&lt;span&gt;'post'&lt;/span&gt;] &lt;span&gt;=&lt;/span&gt; post&lt;span&gt;;&lt;/span&gt;
        db.getComments(post.id).addCallback(gotComments);
    }
    db.getBlogPost(postSlug).addCallback(gotBlogPost);
}
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;I've chosen JavaScript here to prove a point, by the way.  People are very excited about &lt;a class=&quot;reference external&quot; href=&quot;http://nodejs.org/&quot;&gt;node.js&lt;/a&gt; right now, and it's a very cool framework, but it doesn't hide all of the complexities involved in doing things asynchronously.  It only hides some of the implementation details of the event loop.&lt;/p&gt;
&lt;p&gt;The second reason why these frameworks fall short is because not all IO can be handled properly by a framework, and in these cases we have to resort to bad hacks.  For example, MySQL does not offer an asynchronous database driver, so most of the major frameworks end up using threads to ensure that this communication happens out of band.&lt;/p&gt;
&lt;p&gt;Given the inconvenient API, the added complexity, and the simple fact that most developers haven't switched to using this style of programming, leads us to the conclusion that this type of framework is not a desirable final solution to the problem (even though I do concede that you can get Real Work done today using these techniques, and many people do).  That being the case, what other options do we have for asynchronous programming? Coroutines and lightweight processes, which brings us to our next major problem.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;languages-don-t-support-easier-asynchronous-paradigms&quot;&gt;
&lt;h1&gt;Languages don't support easier asynchronous paradigms&lt;/h1&gt;
&lt;p&gt;There are a few language constructs that, if implemented properly in modern programming languages, could pave the way for alternative methods of doing asynchronous programming that don't have the drawbacks of the event loop.  These constructs are coroutines and lightweight processes.&lt;/p&gt;
&lt;p&gt;A coroutine is a function that can suspend and resume its execution at certain, programmatically specified, locations.  This simple concept can serve to transform blocking-looking code to be non-blocking.  At certain critical points in your IO library code, the low-level functions that are doing IO can choose to &amp;quot;cooperate&amp;quot;.  That is, it can choose to suspend execution in order for another function to resume execution and continue on.&lt;/p&gt;
&lt;p&gt;Here's an example (it's Python, but fairly understandable for all I hope):&lt;/p&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;span&gt;def&lt;/span&gt; &lt;span&gt;download_pages&lt;/span&gt;():
    google &lt;span&gt;=&lt;/span&gt; urlopen(&lt;span&gt;'http://www.google.com/'&lt;/span&gt;)&lt;span&gt;.&lt;/span&gt;read()
    yahoo &lt;span&gt;=&lt;/span&gt; urlopen(&lt;span&gt;'http://www.yahoo.com/'&lt;/span&gt;)&lt;span&gt;.&lt;/span&gt;read()
&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Normally the way this would work is that a socket would be opened, connected to Google, an HTTP request sent, and the full response would be read, buffered, and assigned to the &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;google&lt;/span&gt;&lt;/tt&gt; variable, and then in turn the same series of steps would be taken for the &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;yahoo&lt;/span&gt;&lt;/tt&gt; variable.&lt;/p&gt;
&lt;p&gt;Ok, now imagine that the underlying socket implementation were built using coroutines that cooperated with each other.  This time, just like before, the socket would be opened and a connection would be made to Google, and then a request would be fired off.  This time, however, after sending the request, the socket implementation suspends its own execution.&lt;/p&gt;
&lt;p&gt;Having suspended its execution (but not yet having returned a value), execution continues on to the next line.  The same thing happens on the Yahoo line: once its request has been fired off, the Yahoo line suspends its execution.  But now there's something else to cooperate with--there's actually some data ready to be read on the Google socket--so it resumes execution at that point.  It reads some data from the Gooogle socket, and then suspends its execution again.&lt;/p&gt;
&lt;p&gt;It jumps back and forth between the two coroutines until one has finished.  Let's say that the Yahoo socket has finished, but the Google one has not.  In this case, the Google socket just continues to read from its socket until it has completed, because there are no other coroutines to cooperate with.  Once the Google socket is finally finished, the function returns with all of the buffered data.&lt;/p&gt;
&lt;p&gt;Then the Yahoo line returns with all of its buffered data.&lt;/p&gt;
&lt;p&gt;We've preserved the style of our blocking code, but we've used asynchronous programming to do it.  Best of all, we've preserved our original program flow--the &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;google&lt;/span&gt;&lt;/tt&gt; variable is assigned first, and then the &lt;tt class=&quot;docutils literal&quot;&gt;&lt;span class=&quot;pre&quot;&gt;yahoo&lt;/span&gt;&lt;/tt&gt; variable is assigned.  In truth, we've got a smart event loop going on underneath the covers to control who gets to execute, but it's hidden from us due to the fact that coroutines are in play.&lt;/p&gt;
&lt;p&gt;Languages like PHP, Python, Ruby, and Perl simply don't have built-in coroutines that are robust enough to implement this kind of behind-the-scenes transformation.  So what about these lightweight processes?&lt;/p&gt;
&lt;p&gt;Lightweight processes are what Erlang uses as its main concurrency primitive.  Essentially these are processes that are mostly implemented in the Erlang VM itself.  Each process has approximately 300 words of overhead and its execution is scheduled primarily by the Erlang VM, sharing no state at all amongst processes.  Essentially, we don't have to think twice about spawning a process, as it's essentially free.  The catch is that these processes can only communicate via message passing.&lt;/p&gt;
&lt;p&gt;Implementing these lightweight processes at the VM level gets rid of the memory overhead, the context switching, and the relative sluggishness of interprocess communication provided by the operating system.  Since the VM also has insight into the memory stack of each process, it can freely move or resize those processes and their stacks.  That's something that the OS simply cannot do.&lt;/p&gt;
&lt;p&gt;With this model of lightweight processes, it's possible to again revert back to the convenient model of using a separate process for all of our asynchronous programming needs.  The question becomes this: can this notion of lightweight processes be implemented in languages other than Erlang?  The answer to that is &amp;quot;I don't know.&amp;quot;  To my knowledge, Erlang takes advantage of some features of the language itself (such as having no mutable data structures) in its lightweight process implementation.&lt;/p&gt;
&lt;/div&gt;
&lt;div class=&quot;section&quot; id=&quot;where-do-we-go-from-here&quot;&gt;
&lt;h1&gt;Where do we go from here?&lt;/h1&gt;
&lt;p&gt;The key to moving forward is to drop the notion that developers need to learn to think about all of their code in terms of callbacks and asynchrony, as the asynchronous event loop frameworks require them to do.  Over the past ten years, we can see that most developers, when faced with that decision, simply choose to ignore it.  They continue to use the inferior blocking methodologies of yesteryear.&lt;/p&gt;
&lt;p&gt;We need to look at these alternative implementations like coroutines and lightweight processes, so that we can make asynchronous programming as easy as synchronous programming.  Only then will we be able to kick this synchronous addiction.&lt;/p&gt;
&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-08T22:15:31+00:00</dc:date>
</item>
<item rdf:about="http://lateral.netmanagers.com.ar/weblog/posts/BB866.html">
	<title>Roberto Alsina: Marave 0.3 is out!</title>
	<link>http://lateral.netmanagers.com.ar/weblog/posts/BB866.html</link>
	<content:encoded>&lt;p&gt;Version 0.3 of Marave, a distraction-free fullscreen editor is out at &lt;a class=&quot;reference external&quot; href=&quot;http://marave.googlecode.com&quot;&gt;http://marave.googlecode.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This version includes several bugs fixed and features implemented since 0.2:&lt;/p&gt;
&lt;ul class=&quot;simple&quot;&gt;
&lt;li&gt;New 'Styles' support, you can change the look of Marave
with CSS syntax&lt;/li&gt;
&lt;li&gt;Debugged themes support, a few themes included&lt;/li&gt;
&lt;li&gt;Fixed bug saving text color&lt;/li&gt;
&lt;li&gt;Fixed font changing bug&lt;/li&gt;
&lt;li&gt;Use the document name in window title&lt;/li&gt;
&lt;li&gt;&amp;quot;Now playing&amp;quot; notification&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Marave is free softare released under the GPL, and should work in all major desktop platforms.&lt;/p&gt;
&lt;p&gt;I would love feedback on this release, as well as ideas for Marave's future, so if you want to help, please join the mailing list:&lt;/p&gt;
&lt;p&gt;&lt;a class=&quot;reference external&quot; href=&quot;http://groups.google.com/group/marave-discuss&quot;&gt;http://groups.google.com/group/marave-discuss&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Of course, if you like Marave, feel free to &lt;a class=&quot;reference external&quot; href=&quot;https://www.paypal.com/cgi-bin/webscr?cmd=_donations&amp;business=Q6R5YDDPM2RL6&amp;lc=AR&amp;item_name=rst2pdf&amp;item_number=rst2pdf&amp;currency_code=USD&amp;bn=PP%2dDonationsBF%3abtn_donate_LG%2egif%3aNonHosted&quot;&gt;give me money&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T21:17:12+00:00</dc:date>
</item>
<item rdf:about="http://www.johndcook.com/blog/2010/02/08/twitter-daily-tip-news/">
	<title>John Cook: Twitter daily tip news</title>
	<link>http://www.johndcook.com/blog/2010/02/08/twitter-daily-tip-news/</link>
	<content:encoded>&lt;p&gt;I have five Twitter accounts that send out one tip per day, including a new one I just added last week.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Regular expressions&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/RegexTip&quot;&gt;@RegexTip&lt;/a&gt; started over today. It&amp;#8217;s a cycle of tips for learning regular expressions. It sticks to the regular expression features common to Python, Perl, C#, and many other programming languages. This account posts Monday through Friday.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Keyboard shortcuts&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/SansMouse&quot;&gt;@SansMouse&lt;/a&gt; gives one tip a day on using Windows without a mouse. By practicing one keyboard shortcut a day, you can get into the habit of using your mouse less and your keyboard more. This cycle of tips started over January 29 with the most common and most widely useful shortcuts. I&amp;#8217;m also sprinkling in a few extra tips that are less well known. This account also posts Monday through Friday.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Math&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I have three mathematical accounts. These post seven days a week.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/AlgebraFact&quot;&gt;@AlgebraFact&lt;/a&gt;, just started February 2. It will be a mixture of linear algebra, number theory, group theory, etc.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/ProbFact&quot;&gt;@ProbFact&lt;/a&gt; gives one fact per day from probability. Usually these facts are theorems, but sometimes they include a note on history or applications.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://twitter.com/AnalysisFact&quot;&gt;@AnalysisFact&lt;/a&gt; gives facts from real and complex analysis. The topics range from elementary to advanced.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;What if I don&amp;#8217;t use Twitter?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You can visit the page for a Twitter account just like any other web page. And every Twitter account has an &lt;a href=&quot;http://www.johndcook.com/blog/2008/04/28/60-second-description-of-feeds/&quot;&gt;RSS feed&lt;/a&gt; link allowing you to subscribe just as you would subscribe to a blog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How do you write these?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I write up content for these accounts in bulk. I may sit down on a Saturday and come up with several weeks worth of tips. Then I use HootSuite to schedule the tips weeks in advance. Sometimes I&amp;#8217;ll post something spontaneously, such as link to something relevant, but most of the work is done in advance. I use my &lt;a href=&quot;http://twitter.com/johndcook&quot;&gt;personal Twitter account&lt;/a&gt; for live interaction.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Related links&lt;/strong&gt;:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.johndcook.com/blog/2009/11/09/using-windows-without-a-mouse/&quot;&gt;Using Windows without a mouse&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Regular expressions in&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johndcook.com/python_regex.html&quot;&gt;Python&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johndcook.com/regex.html&quot;&gt;PowerShell&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johndcook.com/mathematica_regex.html&quot;&gt;Mathematica&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johndcook.com/r_language_regex.html&quot;&gt;R&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.johndcook.com/cpp_regex.html&quot;&gt;C++&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;http://www.johndcook.com/distribution_chart.html&quot;&gt;Chart of probability distribution relationships&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T16:26:25+00:00</dc:date>
</item>
<item rdf:about="http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html">
	<title>Ned Batchelder: 21st century life in transition</title>
	<link>http://nedbatchelder.com/blog/201002/21st_century_life_in_transition.html</link>
	<content:encoded>&lt;p&gt;Sitting at the breakfast table, my wife &lt;a class=&quot;offsite&quot; href=&quot;http://susansenator.com&quot;&gt;Susan&lt;/a&gt;
was reading the paper, and when she got to the end of a story, dragged her
finger down the paper to try to scroll the newspaper.&lt;/p&gt;&lt;p&gt;I've sat in a movie theater watching trailers, and glanced at the bottom of
the screen to try to see the progress bar to see how much time was left in the
short clip.&lt;/p&gt;&lt;p&gt;Max said when he's writing on paper with a pencil, and makes a mistake, his
left hand twitches as if to hit cmd-Z.&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T12:44:47+00:00</dc:date>
</item>
<item rdf:about="http://spyced.blogspot.com/2010/02/distributed-deletes-in-cassandra.html">
	<title>Jonathan Ellis: Distributed deletes in the Cassandra database</title>
	<link>http://spyced.blogspot.com/2010/02/distributed-deletes-in-cassandra.html</link>
	<content:encoded>&lt;p&gt;
Handling deletes in a distributed, &lt;a href=&quot;http://www.allthingsdistributed.com/2008/12/eventually_consistent.html&quot;&gt;eventually consistent&lt;/a&gt; system is a little tricky, as demonstrated by the fairly frequent recurrence of the question, &quot;&lt;a href=&quot;http://wiki.apache.org/cassandra/FAQ#i_deleted_what_gives&quot;&gt;Why doesn't disk usage immediately decrease when I remove data in Cassandra&lt;/a&gt;?&quot;

&lt;p&gt;
As background, recall that a &lt;a href=&quot;http://incubator.apache.org/cassandra/&quot;&gt;Cassandra &lt;/a&gt;cluster defines a ReplicationFactor that determines how many nodes each key and associated columns are written to.  In Cassandra (as in &lt;a href=&quot;http://www.allthingsdistributed.com/2007/10/amazons_dynamo.html&quot;&gt;Dynamo&lt;/a&gt;), the client controls how many replicas to block for on writes, which includes deletions.  In particular, the client may (and typically will) specify a ConsistencyLevel of less than the cluster's ReplicationFactor, that is, the coordinating server node should report the write successful even if some replicas are down or otherwise not responsive to the write.

&lt;p&gt;
(Thus, the &quot;eventual&quot; in eventual consistency: if a client reads from a replica that did not get the update with a low enough ConsistencyLevel, it will potentially see old data.  Cassandra uses &lt;a href=&quot;http://wiki.apache.org/cassandra/HintedHandoff&quot;&gt;Hinted Handoff&lt;/a&gt;, &lt;a href=&quot;http://wiki.apache.org/cassandra/ReadRepair&quot;&gt;Read Repair&lt;/a&gt;, and &lt;a href=&quot;http://wiki.apache.org/cassandra/AntiEntropy&quot;&gt;Anti Entropy&lt;/a&gt; to reduce the inconsistency window, as well as offering higher consistency levels such as ConstencyLevel.QUORUM, but it's still something we have to be aware of.)

&lt;p&gt;
Thus, a delete operation can't just wipe out all traces of the data being removed immediately: if we did, and a replica did not receive the delete operation, when it becomes available again it will treat the replicas that &lt;span&gt;did&lt;/span&gt; receive the delete as having missed a write update, and repair them!  So, instead of wiping out data on delete, Cassandra replaces it with a special value called a tombstone.  The tombstone can then be propagated to replicas that missed the initial remove request.

&lt;p&gt;
There's one more piece to the problem: how do we know when it's safe to remove tombstones?  In a fully distributed system, we can't.  We could add a coordinator like &lt;a href=&quot;http://hadoop.apache.org/zookeeper/&quot;&gt;ZooKeeper&lt;/a&gt;, but that would pollute the simplicity of the design, as well as complicating ops -- then you'd essentially have two systems to monitor, instead of one.  (This is not to say ZK is bad software -- I believe it is best in class at what it does -- only that it solves a problem that we do not wish to add to our system.)

&lt;p&gt;
So, Cassandra does what distributed systems designers frequently do when confronted with a problem we don't know how to solve: define some additional constraints that turn it into one that we do. Here, we defined a constant, &lt;em&gt;GCGraceSeconds&lt;/em&gt;, and had each node track tombstone age locally.  Once it has aged past the constant, it can be GC'd.  This means that if you have a node down for longer than &lt;em&gt;GCGraceSeconds&lt;/em&gt;, you should treat it as a failed node and replace it as described in &lt;a href=&quot;http://wiki.apache.org/cassandra/Operations&quot;&gt;Cassandra Operations&lt;/a&gt;.  The default setting is very conservative, at 10 days; you can reduce that once you have Anti Entropy configured to your satisfaction.  And of course if you are only running a single Cassandra node, you can reduce it to zero, and tombstones will be GC'd at the first &lt;a href=&quot;http://wiki.apache.org/cassandra/MemtableSSTable&quot;&gt;compaction&lt;/a&gt;.&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/11683713-1928982814843756737?l=spyced.blogspot.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T12:08:10+00:00</dc:date>
</item>
<item rdf:about="http://blog.isotoma.com/2010/02/beginning-development-with-plone-4-dexterity/">
	<title>Isotoma: Beginning development with Plone 4 &amp;amp; Dexterity</title>
	<link>http://blog.isotoma.com/2010/02/beginning-development-with-plone-4-dexterity/</link>
	<content:encoded>&lt;p&gt;Over the past few days, I&amp;#8217;ve been tinkering with the latest alphas of &lt;a title=&quot;Plone 4.0 alpha downloads&quot; href=&quot;http://plone.org/products/plone/releases/4.0&quot;&gt;Plone 4&lt;/a&gt;, particularly with an eye to trying out &lt;a href=&quot;http://plone.org/products/dexterity&quot;&gt;Dexterity&lt;/a&gt; on the latest version.&lt;/p&gt;
&lt;p&gt;I started out, as many people will, by downloading the unified installer which will install Python 2.6, Zope 2.12 and the Plone 4.0 alpha for you. After &lt;a title=&quot;Universal installer fails when using &quot;&gt;a few teething problems&lt;/a&gt; with multiple versions of Python on my Hardy host, I had my Plone install up and running.&lt;/p&gt;
&lt;p&gt;First impressions among myself and my colleagues here at Isotoma were that firstly, it was a heck of a lot faster than its predecessor. In fact, John Stahl &lt;a title=&quot;Plone 4: three times faster than Drupal, Joomla or Wordpress&quot; href=&quot;http://jstahl.org/archives/2010/01/19/plone-4-three-times-faster-than-drupal-joomla-or-wordpress/&quot;&gt;recently blogged&lt;/a&gt; that Plone 4 is potentially three times faster than Drupal, Joomla and Wordpress. The other main, marked difference was the default theme, which is a lot slicker, though in my own opinion with its blocks of bright colours and rounded corners, a little too overtly &amp;ldquo;&lt;em&gt;Web 2.0&lt;/em&gt;&amp;rdquo; (insert air-quotes here).&lt;/p&gt;
&lt;p&gt;My next stop was Martin Aspeli&amp;#8217;s &lt;a href=&quot;http://plone.org/products/dexterity/documentation/manual/developer-manual/referencemanual-all-pages&quot;&gt;Dexterity developer manual&lt;/a&gt; which whilst up-to-date for the current stable release of Plone, required some tweaking to get going with Plone 4.&lt;/p&gt;
&lt;p&gt;The unified installer, by default, makes use of several config files for buildout, which keeps a lot of the core settings in separate files (&lt;samp&gt;base.cfg&lt;/samp&gt; &amp;amp; &lt;samp&gt;versions.cfg&lt;/samp&gt;). &lt;a title=&quot;Message between Jordan Baker &amp; Martin Aspeli on Twitter&quot; href=&quot;http://twitter.com/hexsprite/statuses/8547484559&quot;&gt;I hear&lt;/a&gt; that &lt;a title=&quot;Roadrunner project homepage&quot; href=&quot;http://hexsprite.lighthouseapp.com/projects/21973-roadrunner&quot;&gt;roadrunner&lt;/a&gt; is almost ready for Plone 4, but it&amp;#8217;ll be a little while before we&amp;#8217;re getting it without checking out the source so that had to be chopped. The &lt;samp&gt;extends&lt;/samp&gt; entry for Dexterity also required updating to the latest alpha.&lt;/p&gt;
&lt;p&gt;Otherwise, things went very straightforwardly. My &lt;samp&gt;buildout.cfg&lt;/samp&gt; for use with the unified installer can be found below the fold.&lt;br /&gt;
&lt;span id=&quot;more-560&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre name=&quot;code&quot;&gt;
[buildout]
extends-cache = extends
extends = http://good-py.appspot.com/release/dexterity/2.0-next
    base.cfg
    versions.cfg

http-address = 8080

eggs =
    Plone
    Products.PDBDebugMode
    Products.LinguaPlone
    plone.reload

zcml =
    plone.reload

develop =
    src/example.project

debug-mode = off

backups-dir=${buildout:directory}/var

user=admin:password

parts =
    productdistros
    instance
    zopepy
    zopeskel
    backup
    unifiedinstaller
    chown
    omelette
    test

extensions =
    mr.developer
    buildout.dumppickedversions

[versions]
Cheetah = 2.2.1
Paste = 1.7.2
PasteScript = 1.7.3
ZopeSkel = 2.15
collective.recipe.backup = 1.3
plone.recipe.command = 1.0
plone.recipe.distros = 1.5
plone.recipe.unifiedinstaller = 4.0a1
PasteDeploy = 1.3.3

[omelette]
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
packages = ./

[test]
recipe = zc.recipe.testrunner
eggs = example.project
extra-paths =
defaults = ['--exit-with-status', '--auto-color', '--auto-progress']
&lt;/pre&gt;</content:encoded>
	<dc:date>2010-02-08T11:18:04+00:00</dc:date>
</item>
<item rdf:about="http://simonwillison.net/2010/Feb/8/integrate/">
	<title>Simon Willison: Integrate Tornado in Django</title>
	<link>http://simonwillison.net/2010/Feb/8/integrate/</link>
	<content:encoded>&lt;div class=&quot;blogmark segment&quot;&gt;&lt;p&gt;&lt;a href=&quot;http://geekscrap.com/2010/02/integrate-tornado-in-django/&quot;&gt;Integrate Tornado in Django&lt;/a&gt;. A handy ./manage.py runtornado management command for firing up a Tornado server that serves your Django application.&lt;/p&gt;
&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-08T11:12:46+00:00</dc:date>
</item>
<item rdf:about="http://blog.some-abstract-type.com/2010/02/python-oursql-and-macos-x-106-snow.html">
	<title>Geert Vanderkelen: Python, oursql and MacOS X 10.6 (Snow Leopard)</title>
	<link>http://blog.some-abstract-type.com/2010/02/python-oursql-and-macos-x-106-snow.html</link>
	<content:encoded>&lt;p&gt;This post explains how to compile &lt;b&gt;&lt;a href=&quot;https://launchpad.net/oursql&quot;&gt;oursql&lt;/a&gt;&lt;/b&gt; and install it on MacOS 10.6. oursql is a Python database interface for MySQL, an alternative to &lt;a href=&quot;http://sourceforge.net/projects/mysql-python/files/&quot;&gt;MySQL for Python&lt;/a&gt; (i.e. &lt;a href=&quot;http://blog.some-abstract-type.com/2009/09/mysql-python-and-mac-os-x-106-snow.html&quot;&gt;MySQLdb&lt;/a&gt;) and &lt;a href=&quot;https://launchpad.net/myconnpy&quot;&gt;MySQL Connector/Python&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;First, &lt;b&gt;find out which MySQL you installed&lt;/b&gt;. This can be either the 32-bit or the 64-bit version. To make sure, find the mysqld (e.g. in /usr/local/mysql/bin) and do the following in a Terminal window:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt;shell&gt; file /usr/local/mysql/bin/mysqld&lt;br /&gt;.../mysqld: Mach-O 64-bit executable &lt;b&gt;x86_64&lt;/b&gt;&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;If you see x86_64, you got 64-bit, otherwise 32-bit. If you see both, then you have a universal build. This is important for specifying the &lt;tt&gt;ARGSFLAG&lt;/tt&gt; when building.&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;https://launchpad.net/oursql/+download&quot;&gt;&lt;b&gt;Download oursql&lt;/b&gt; from Launchpad&lt;/a&gt; and unpack it into some directory. Using the information from above, you'll have to do following for 64-bit platform (or universal build) in a Terminal window:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt; shell&gt; ARCHFLAGS=&quot;-arch x86_64&quot; python setup.py build&lt;br /&gt; shell&gt; sudo python setup.py install&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;For 32-bit, you'll have to do:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt; shell&gt; ARCHFLAGS=&quot;-arch i386&quot; python setup.py build&lt;br /&gt; shell&gt; sudo python setup.py install&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;Following error will be reported when you don't specify the correct &lt;tt&gt;ARCHFLAGS&lt;/tt&gt;:&lt;/p&gt;&lt;pre&gt;&lt;br /&gt; ld: warning: in .../lib/libmysqlclient.dylib,&lt;br /&gt;   file is not of required architecture&lt;br /&gt;&lt;/pre&gt;&lt;p&gt;&lt;b&gt;Tips&lt;/b&gt;:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;When building failed, it is good to remove oursql, unpack it and try again.&lt;/li&gt;&lt;li&gt;If you don't want to compile anything, or run into more troubles, give &lt;a href=&quot;https://launchpad.net/myconnpy/+download&quot;&gt;MySQL Connector/Python a try&lt;/a&gt; (alpha releases). It's a pure Python implementation of the MySQL Client/Server protocol and doesn't need compiling or a MySQL installation.&lt;/li&gt;&lt;li&gt;You can download MySQL from either &lt;a href=&quot;http://www.mysql.com&quot;&gt;www.mysql.com&lt;/a&gt; or &lt;a href=&quot;http://dev.mysql.com&quot;&gt;dev.mysql.com&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class=&quot;blogger-post-footer&quot;&gt;&lt;img width=&quot;1&quot; height=&quot;1&quot; src=&quot;https://blogger.googleusercontent.com/tracker/5702936365231918674-1630538266823111730?l=blog.some-abstract-type.com&quot; alt=&quot;&quot; /&gt;&lt;/div&gt;</content:encoded>
	<dc:date>2010-02-08T11:09:47+00:00</dc:date>
</item>
<item rdf:about="http://geekscrap.com/2010/02/integrate-tornado-in-django/">
	<title>Geek Scrap: Integrate Tornado in Django</title>
	<link>http://geekscrap.com/2010/02/integrate-tornado-in-django/</link>
	<content:encoded>&lt;p&gt;&lt;a href=&quot;http://www.tornadoweb.org/&quot;&gt;Tornado&lt;/a&gt; is a nice python WSGI-compliant web server developed by guys at FriendFeed. It&amp;#8217;s primarily thought as application server for python web frameworks and according to FriendFeed benchmarks, it&amp;#8217;s blazing fast thanks to its non-blocking connections. There are already some how-to&amp;#8217;s on the web on plugging Django web framework into Tornado webserver. A quick recap:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A &lt;a rel=&quot;nofollow&quot; href=&quot;http://www.jeremybowers.com/blog/4/tornado-web-framework-production-django-and-nginx/&quot;&gt;tutorial&lt;/a&gt; on Tornado, Django and nginx by Jeremy Bowers.&lt;/li&gt;
&lt;li&gt;How to &lt;a rel=&quot;nofollow&quot; href=&quot;http://lincolnloop.com/blog/2009/sep/15/using-django-inside-tornado-web-server/&quot;&gt;import django framework&lt;/a&gt; inside a Tornado project by Lincoln Loop.&lt;/li&gt;
&lt;li&gt;A &lt;a rel=&quot;nofollow&quot; href=&quot;http://www.djangosnippets.org/snippets/1748/&quot;&gt;snippet&lt;/a&gt; by lawgon.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;My approach is slightly different as I wanted to run Tornado using Django management command-line interface.&lt;/p&gt;
&lt;p&gt;&lt;span id=&quot;more-588&quot;&gt;&lt;/span&gt;The 3 easy steps are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Add Tornado module to your django setup. If you use buildout, add Tornado git checkout to buildout.cfg using &lt;em&gt;minitage.recipe.fetch&lt;/em&gt; recipe, like this:

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;ini&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;buildout&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;
...
&lt;span&gt;parts&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;
...
    tornado
    django
...
&amp;nbsp;
&lt;span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;tornado&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;recipe&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;&lt;span&gt; minitage.recipe.fetch&lt;/span&gt;
&lt;span&gt;urls&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;&lt;span&gt;&lt;span&gt; git://github.com/facebook/tornado.git | git | | $&lt;span&gt;&amp;#123;&lt;/span&gt;&lt;/span&gt;buildout:parts-directory&lt;span&gt;&amp;#125;&lt;/span&gt;/tornado&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;django&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;
&lt;span&gt;recipe&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;&lt;span&gt; minitage.recipe.scripts&lt;/span&gt;
&lt;span&gt;initialization&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;
    import os
    os.environ&lt;span&gt;&lt;span&gt;&amp;#91;&lt;/span&gt;'DJANGO_SETTINGS_MODULE'&lt;span&gt;&amp;#93;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;'project.settings.development'&lt;/span&gt;
&lt;span&gt;scripts&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;
    django
&lt;span&gt;eggs&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;
    Django
    ...
&lt;span&gt;entry-points&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;
    &lt;span&gt;django&lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt;django.core.management:execute_from_command_line&lt;/span&gt;
&lt;span&gt;extra-paths&lt;/span&gt; &lt;span&gt;=&lt;/span&gt;
    $&lt;span&gt;&amp;#123;&lt;/span&gt;buildout:directory&lt;span&gt;&amp;#125;&lt;/span&gt;
    $&lt;span&gt;&amp;#123;&lt;/span&gt;tornado:location&lt;span&gt;&amp;#125;&lt;/span&gt;
...&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;li&gt;Next, create a command-line extension hierarchy in your project&amp;#8217;s main app:
&lt;pre&gt;$ mkdir project/myapp/management
$ touch project/myapp/management/__init__.py
$ mkdir project/myapp/management/commands
$ touch project/myapp/management/commands/__init__.py&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;Last, add a runtornado.py script in project/myapp/management/commands/ folder with the following content:

&lt;div class=&quot;wp_syntax&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;pre class=&quot;python&quot;&gt;&lt;span&gt;from&lt;/span&gt; django.&lt;span&gt;core&lt;/span&gt;.&lt;span&gt;management&lt;/span&gt;.&lt;span&gt;base&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; BaseCommand, CommandError
&lt;span&gt;from&lt;/span&gt; &lt;span&gt;optparse&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; make_option
&lt;span&gt;import&lt;/span&gt; &lt;span&gt;os&lt;/span&gt;
&lt;span&gt;import&lt;/span&gt; &lt;span&gt;sys&lt;/span&gt;
&amp;nbsp;
&lt;span&gt;class&lt;/span&gt; Command&lt;span&gt;&amp;#40;&lt;/span&gt;BaseCommand&lt;span&gt;&amp;#41;&lt;/span&gt;:
    option_list = BaseCommand.&lt;span&gt;option_list&lt;/span&gt; + &lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
    &lt;span&gt;help&lt;/span&gt; = &lt;span&gt;&amp;quot;Starts a Tornado Web.&amp;quot;&lt;/span&gt;
    args = &lt;span&gt;'[optional port number, or ipaddr:port]'&lt;/span&gt;
&amp;nbsp;
    &lt;span&gt;def&lt;/span&gt; handle&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;self&lt;/span&gt;, addrport=&lt;span&gt;''&lt;/span&gt;, &lt;span&gt;*&lt;/span&gt;args, &lt;span&gt;**&lt;/span&gt;options&lt;span&gt;&amp;#41;&lt;/span&gt;:
        &lt;span&gt;import&lt;/span&gt; django
        &lt;span&gt;from&lt;/span&gt; django.&lt;span&gt;core&lt;/span&gt;.&lt;span&gt;handlers&lt;/span&gt;.&lt;span&gt;wsgi&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; WSGIHandler
        &lt;span&gt;from&lt;/span&gt; tornado &lt;span&gt;import&lt;/span&gt; httpserver, wsgi, ioloop
&amp;nbsp;
	&lt;span&gt;sys&lt;/span&gt;.&lt;span&gt;stdout&lt;/span&gt; = &lt;span&gt;os&lt;/span&gt;.&lt;span&gt;fdopen&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;sys&lt;/span&gt;.&lt;span&gt;stdout&lt;/span&gt;.&lt;span&gt;fileno&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, &lt;span&gt;'w'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
	&lt;span&gt;sys&lt;/span&gt;.&lt;span&gt;stderr&lt;/span&gt; = &lt;span&gt;os&lt;/span&gt;.&lt;span&gt;fdopen&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;sys&lt;/span&gt;.&lt;span&gt;stderr&lt;/span&gt;.&lt;span&gt;fileno&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, &lt;span&gt;'w'&lt;/span&gt;, &lt;span&gt;0&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        &lt;span&gt;if&lt;/span&gt; args:
            &lt;span&gt;raise&lt;/span&gt; CommandError&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;'Usage is runserver %s'&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;args&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;not&lt;/span&gt; addrport:
            addr = &lt;span&gt;''&lt;/span&gt;
            port = &lt;span&gt;'8000'&lt;/span&gt;
        &lt;span&gt;else&lt;/span&gt;:
            &lt;span&gt;try&lt;/span&gt;:
                addr, port = addrport.&lt;span&gt;split&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;':'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
            &lt;span&gt;except&lt;/span&gt; &lt;span&gt;ValueError&lt;/span&gt;:
                addr, port = &lt;span&gt;''&lt;/span&gt;, addrport
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;not&lt;/span&gt; addr:
            addr = &lt;span&gt;'127.0.0.1'&lt;/span&gt;
&amp;nbsp;
        &lt;span&gt;if&lt;/span&gt; &lt;span&gt;not&lt;/span&gt; port.&lt;span&gt;isdigit&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
            &lt;span&gt;raise&lt;/span&gt; CommandError&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;quot;%r is not a valid port number.&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; port&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        quit_command = &lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;sys&lt;/span&gt;.&lt;span&gt;platform&lt;/span&gt; == &lt;span&gt;'win32'&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt; &lt;span&gt;and&lt;/span&gt; &lt;span&gt;'CTRL-BREAK'&lt;/span&gt; &lt;span&gt;or&lt;/span&gt; &lt;span&gt;'CONTROL-C'&lt;/span&gt;
&amp;nbsp;
        &lt;span&gt;def&lt;/span&gt; inner_run&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;:
            &lt;span&gt;from&lt;/span&gt; django.&lt;span&gt;conf&lt;/span&gt; &lt;span&gt;import&lt;/span&gt; settings
            &lt;span&gt;print&lt;/span&gt; &lt;span&gt;&amp;quot;Validating models...&amp;quot;&lt;/span&gt;
            &lt;span&gt;self&lt;/span&gt;.&lt;span&gt;validate&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;display_num_errors=&lt;span&gt;True&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
            &lt;span&gt;print&lt;/span&gt; &lt;span&gt;&amp;quot;&lt;span&gt;\n&lt;/span&gt;Django version %s, using settings %r&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;django.&lt;span&gt;get_version&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;, settings.&lt;span&gt;SETTINGS_MODULE&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
            &lt;span&gt;print&lt;/span&gt; &lt;span&gt;&amp;quot;Server is running at http://%s:%s/&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; &lt;span&gt;&amp;#40;&lt;/span&gt;addr, port&lt;span&gt;&amp;#41;&lt;/span&gt;
            &lt;span&gt;print&lt;/span&gt; &lt;span&gt;&amp;quot;Quit the server with %s.&amp;quot;&lt;/span&gt; &lt;span&gt;%&lt;/span&gt; quit_command
            application = WSGIHandler&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
            container = wsgi.&lt;span&gt;WSGIContainer&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;application&lt;span&gt;&amp;#41;&lt;/span&gt;
            http_server = httpserver.&lt;span&gt;HTTPServer&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;container&lt;span&gt;&amp;#41;&lt;/span&gt;
            http_server.&lt;span&gt;listen&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;int&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;port&lt;span&gt;&amp;#41;&lt;/span&gt;, address=addr&lt;span&gt;&amp;#41;&lt;/span&gt;
            ioloop.&lt;span&gt;IOLoop&lt;/span&gt;.&lt;span&gt;instance&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;.&lt;span&gt;start&lt;/span&gt;&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        inner_run&lt;span&gt;&amp;#40;&lt;/span&gt;&lt;span&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;To run your tornado webserver, you just need to call your usual management program like manage.py with runtornado command, with the same syntax as runserver. In my case, I just run production server using &lt;a rel=&quot;nofollow&quot; href=&quot;http://supervisord.org/&quot;&gt;supervisord&lt;/a&gt;, with a command like this:&lt;/p&gt;
&lt;pre&gt;$ ./bin/django runtornado --settings=project.settings.production 8000&lt;/pre&gt;
&lt;p&gt;If you found this quick how-to useful, remember to follow me on &lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/geekscrap&quot;&gt;Twitter&lt;/a&gt; or subscribe to my feed for more django tips.&lt;/p&gt;
&lt;!-- Generated by Digg Digg plugin, 
    Author : Yong Mook Kim
    Website : http://www.mkyong.com/blog/digg-digg-wordpress-plugin/ --&gt;

&lt;p&gt;Related posts:&lt;ol&gt;&lt;li&gt;&lt;a href=&quot;http://geekscrap.com/2010/01/gitignore-for-django-buildout/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: .gitignore for Django buildout&quot;&gt;.gitignore for Django buildout&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekscrap.com/2010/01/django-dynamic-template-paths/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: Django dynamic template paths&quot;&gt;Django dynamic template paths&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://geekscrap.com/2010/01/install-wxpython-in-buildout/&quot; rel=&quot;bookmark&quot; title=&quot;Permanent Link: Install wxPython in buildout&quot;&gt;Install wxPython in buildout&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T09:32:00+00:00</dc:date>
</item>
<item rdf:about="http://www.hardcoded.net/articles/embedded-pyobjc.htm">
	<title>Virgil Dupras: Embedded PyObjC</title>
	<link>http://www.hardcoded.net/articles/embedded-pyobjc.htm</link>
	<content:encoded>&lt;p&gt;When people think of a &lt;a href=&quot;http://pyobjc.sourceforge.net/&quot;&gt;PyObjC&lt;/a&gt; application, they usually think of a Python application that uses Objective-C libraries. However, it's also possible to do the opposite: An Objective-C application that embeds Python code through a plugin. Building an application this way has advantages (speed, integration and memory usage) and should be used more often. This article explains why and how to achieve this.
&lt;a href=&quot;http://www.hardcoded.net/articles/embedded-pyobjc.htm&quot;&gt;More&lt;/a&gt;&lt;/p&gt;</content:encoded>
	<dc:date>2010-02-08T08:52:12+00:00</dc:date>
</item>

</rdf:RDF>
