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

<channel>
	<title>Mischiefblog &#187; Python</title>
	<atom:link href="http://www.mischiefblog.com/?feed=rss2&#038;cat=9" rel="self" type="application/rss+xml" />
	<link>http://www.mischiefblog.com</link>
	<description>I WATN 2 MAEK GAEM!</description>
	<lastBuildDate>Fri, 03 Sep 2010 19:17:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Configuring Apache 2 in Ubuntu for WSGI Python</title>
		<link>http://www.mischiefblog.com/?p=908</link>
		<comments>http://www.mischiefblog.com/?p=908#comments</comments>
		<pubDate>Fri, 03 Sep 2010 19:17:56 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=908</guid>
		<description><![CDATA[There&#8217;s a great thread on the Ubuntu forums regarding this topic. For the purpose of keeping a record of what I needed to do: Install Apache 2 Install libapache2-mod-wsgi # apt-get install libapache2-mod-wsgi Link the project directory to /var/www # cd /var/www # ln -s /some/path/DevTools Update /etc/apache2/sites-available/default &#160;&#160;&#160;&#160;&#60;Directory /var/www/&#62; &#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;Options Indexes FollowSymLinks MultiViews ExecCGI [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s <a href="http://ubuntuforums.org/showthread.php?t=833766" target="_blank">a great thread on the Ubuntu forums</a> regarding this topic.  For the purpose of keeping a record of what I needed to do:</p>
<ol>
<li>Install Apache 2</li>
<li>Install libapache2-mod-wsgi<br />
<code><br />
# apt-get install libapache2-mod-wsgi<br />
</code></li>
<li>Link the project directory to <b>/var/www</b><br />
<code><br />
# cd /var/www<br />
# ln -s /some/path/DevTools<br />
</code></li>
<li>Update <b>/etc/apache2/sites-available/default</b><br />
<code><br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;Directory /var/www/&gt;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Options Indexes FollowSymLinks MultiViews ExecCGI<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AllowOverride None<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Order allow,deny<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;allow from all<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddHandler cgi-script .cgi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AddHandler wsgi-script .wsgi<br />
&nbsp;&nbsp;&nbsp;&nbsp;&lt;/Directory&gt;<br />
</code></li>
<li>Restart Apache<br />
<code><br />
# apache2ctl restart<br />
</code></li>
<li>Create the tester script, <b>/var/www/DevTools/tester.wsgi</b><br />
<code><br />
def application(environ, start_response):<br />
&nbsp;&nbsp;&nbsp;&nbsp;status = "200 OK"<br />
&nbsp;&nbsp;&nbsp;&nbsp;output = "Hello World!"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;response_headers = [('Content-type', 'text/plain'),<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;('Content-Length', str(len(output)))]<br />
&nbsp;&nbsp;&nbsp;&nbsp;start_response(status, response_headers)<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;return [output]<br />
</code></li>
<li>Verify your tester by going to <a href="http://localhost/DevTools/tester.wsgi" target="_blank">http://localhost/DevTools/tester.wsgi</a>.  The output should be:<br />
<code><br />
Hello World!<br />
</code></li>
</ol>
<p>If you get any <b>500 Server Error</b> responses, check <b>/var/log/apache2/error.log</b> first.  mod_python does a better job with error reporting than WSGI but is, in my experience, a more fragile framework for configuring and developing web apps.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=908</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Radar Revisited</title>
		<link>http://www.mischiefblog.com/?p=857</link>
		<comments>http://www.mischiefblog.com/?p=857#comments</comments>
		<pubDate>Wed, 14 Oct 2009 07:08:20 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=857</guid>
		<description><![CDATA[I&#8217;ve been snatching 30 and 60 minute blocks of time in the evenings and on the weekends to get back to work on my Radar test in Python with PyGame from nearly four years ago. PyGame 1.9.1 installed easily on my Windows box and OS X laptop and integrated well with Python 3.1 (on Windows) [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been snatching 30 and 60 minute blocks of time in the evenings and on the weekends to get back to work on my <a href="http://www.mischiefblog.com/?p=230" target="_blank">Radar</a> test in Python with PyGame from nearly four years ago.  <a href="http://pygame.org/download.shtml" target="_blank">PyGame 1.9.1</a> installed easily on my Windows box and OS X laptop and integrated well with Python 3.1 (on Windows) and <a href="http://www.stackless.com/" target="_blank">Stackless Python</a> 2.6 (on OS X).  The only significant changes to be made in the code between Python 2 and Python 3 had to do with <a href="http://docs.python.org/dev/3.0/whatsnew/2.6.html#pep-3110" target="_blank">exception handling</a>.<br />
<span id="more-857"></span><br />
So, what&#8217;s new and different in this version?
<ul>
<li>I lost my version of Radar that supported chat, so I had to rewrite it from scratch.  This version only supports standard layout US keyboards (the shift-modifiers are hard-coded) and I haven&#8217;t tweaked the fonts, set up an input box, or limited the input string to make things look nicer.</li>
<li>I likewise lost the code to add names and chat messages above the arrow sprites, so I rewrote that.  This version should be more correct than the one from 2005.</li>
<li>I&#8217;m using the standard Python logger (based on log4j) instead of a custom logging class.</li>
<li>I&#8217;m using a Singleton logger instance for all the arrow sprites.</li>
</ul>
<p>The arrow sprite logic has gotten complicated enough that I need to develop good unit tests for it.  I&#8217;ve been developing with rapid integration tests, but I believe I&#8217;ve hit the point with the sprite where significant changes could break the correct behavior it&#8217;s exhibiting now.  A good suite of unit tests against the sprite will help with later refactoring and will also provide a base for testing sprites in other projects.  Unit tests should be written before I approach anything as complicated as, say, collision detection (which PyGame handles nicely now) or basic AI or pathfinding.</p>
<p><a href="http://www.moviepartners.com/blog/2009/03/20/making-py2exe-play-nice-with-pygame/" target="_blank">I&#8217;ve looked into</a> using <a href="http://www.py2exe.org/" target="_blank">py2exe</a> to package the application as a Windows executable.  It looks like, with a few hours of testing and pruning, it&#8217;ll work well and still produce a relatively small executable.</p>
<p>I&#8217;m considering using <a href="http://incubator.apache.org/thrift/" target="_blank">Thrift</a> to automate generation and interpretation of the client-server messages.  I&#8217;m willing to pay a little more in bandwidth and processing time rather than spending time writing custom binary packing and unpacking code for messages.  Thrift should let me abstract the process a little more, and I&#8217;m very curious to see how well it works for me in practice.</p>
<p>Finally, I&#8217;ll implement the server.  With the minimal prediction in place on the arrow sprites, I&#8217;m very curious to see how well the client runs and how much rubberbanding will take place.</p>
<p>Komodo Edit is still working well for me, although I wonder if the Komodo IDE would help to speed up my develop-test iteration cycle.</p>
<p>Grab the <a href="uploads/Radar2.zip">Radar2.zip</a> file here.  Install Python 3.1 and Pygame 1.9.1 for 3.1, add Python to your path, and test the program with <code>python Main.py</code>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=857</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Windows setup for my project</title>
		<link>http://www.mischiefblog.com/?p=810</link>
		<comments>http://www.mischiefblog.com/?p=810#comments</comments>
		<pubDate>Wed, 29 Jul 2009 06:31:39 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=810</guid>
		<description><![CDATA[Here are the steps required to set up a development environment on Windows for my Python project: Download the required programs and libraries Komodo Edit for best-of-breed Python editing Oracle Berekely DB 4.7.25 for the storage engine Stackless Python 2.6 (I&#8217;ll eventually convert to 3.x) setuptools-0.6c9.tar.gz to install Python eggs]]></description>
			<content:encoded><![CDATA[<p>Here are the steps required to set up a development environment on Windows for my Python project:</p>
<ol>
<li>Download the required programs and libraries
<ul>
<li><a href="http://www.activestate.com/komodo_edit/" target="_blank">Komodo Edit</a> for best-of-breed Python editing</li>
<li><a href="http://www.oracle.com/technology/software/products/berkeley-db/index.html" target="_blank">Oracle Berekely DB 4.7.25</a> for the storage engine</li>
<li><a href="http://www.stackless.com/download" target="_blank">Stackless Python 2.6</a> (I&#8217;ll eventually convert to 3.x)</li>
<li><a href="http://pypi.python.org/pypi/setuptools" target="_blank">setuptools-0.6c9.tar.gz</a> to install Python eggs</li>
<li><a href=http://pypi.python.org/packages/source/b/bsddb3/bsddb3-4.7.6.zip">bsddb3-4.7.6.zip</a></li>
<li>If you don&#8217;t have a tar.gz expander, <a href="http://www.7-zip.org/download.html" target="_blank">7-Zip</a></li>
<li>If you don&#8217;t have a C++ compiler, or yours is out of date, get <a href="http://www.microsoft.com/express/vc/#webInstall" target="_blank">Visual C++ Express 2009</a></li>
</ul>
</li>
<li>Install Visual C++ Express</li>
<li>Install Komodo Edit</li>
<li>Install Stackless Python 2.6</li>
<li>Install Berkeley DB 4.7</li>
<li>Expand bsddb3-4.7.6.zip to a known directory</li>
<li>Install setuptools and PyBSDDB
<ol>
<li>Expand setuptools into a temporary directory</li>
<li>Open a command line (on Vista, <b>Windows-R</b> and enter <i>cmd</i>)</li>
<li>Add Python to the command line environment with:<br />
<code>set PATH=%PATH%;C:\Python26</code></li>
<li>Change directory to the temporary directory where you expanded setuptools</li>
<li>Install setuptools with:<br />
<code>python setup.py install</code></li>
<li>Install PyBSDDB with:<br />
<code><br />
cd \Users\Chris\Temp\bsddb3-4.7.6 <i>(where I expanded bsdb4)</i><br /> <br />
mkdir db<br />
cd db<br />
xcopy /e /v "C:\Program Files\Oracle\Berkeley DB 4.7.25\include" include\<br />
xcopy /e /v "C:\Program Files\Oracle\Berkeley DB 4.7.25\lib" lib\<br />
cd ..<br />
"C:\Program Files\Microsoft Visual Studio 9\VC\vcvarsall.bat"<br />
python setup.py install</code></li>
</ol>
</li>
</ol>
<p>. . . time for bed, but I&#8217;m having a little trouble with MSVC:<br />
<code><br />
<i>snip</i><br />
Modules/_bsddb.c(8358) : warning C4996: 'strncpy': This function or variable may be unsafe. Consider using strncpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.<br />
        F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\string.h(157) :<br />
see declaration of 'strncpy'<br />
warning: I don't know what to do with 'runtime_library_dirs': ['db/lib']<br />
error: don't know how to set runtime library search path for MSVC++<br />
</code></p>
<p>Yeah, I&#8217;m probably nuts for trying to compile this myself.  On OS X or Linux, there are still plenty of steps but no major hurdles.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=810</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Got transactions working in BDB 4.7 and Python</title>
		<link>http://www.mischiefblog.com/?p=751</link>
		<comments>http://www.mischiefblog.com/?p=751#comments</comments>
		<pubDate>Fri, 26 Sep 2008 14:44:54 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=751</guid>
		<description><![CDATA[I&#8217;ve been working on a personal, side-project for about a week. This morning, I finally got transactions working. I need to learn a little more about BDB tuning and I&#8217;m not planning on releasing my code until I&#8217;m happier with it and it&#8217;s been tested more thoroughly. Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26) [GCC [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a personal, side-project for about a week.  This morning, I finally got transactions working.  I need to learn a little more about BDB tuning and I&#8217;m not planning on releasing my code until I&#8217;m happier with it and it&#8217;s been tested more thoroughly.<br />
<code><br />
Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26)<br />
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin<br />
Type "help", "copyright", "credits" or "license" for more information.<br />
>>> import Configure<br />
>>> cfg = Configure.Configure()<br />
>>> class Alpha:<br />
...     def __init__(self):<br />
...             self.field = 'alpha'<br />
...<br />
>>> cfg.databases['objects'][1].get('a')<br />
Traceback (most recent call last):<br />
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;<br />
  File "RefCache.py", line 110, in get<br />
    value = self.repository.get(key)<br />
  File "Repository.py", line 104, in get<br />
    raise KeyError, key<br />
KeyError: 'a'<br />
>>> txn = cfg.databases['objects'][1].beginTransaction()<br />
>>> a = Alpha()<br />
>>> cfg.databases['objects'][1].put('a', a, txn)<br />
>>> cfg.databases['objects'][1].commitTransaction(txn)<br />
>>> a.field<br />
'alpha'<br />
>>> a = None<br />
>>> a<br />
>>> a = cfg.databases['objects'][1].get('a')<br />
>>> a.field<br />
'alpha'<br />
>>> b = Alpha()<br />
>>> b.field = 'beta'<br />
>>> txn = cfg.databases['objects'][1].beginTransaction()<br />
>>> cfg.databases['objects'][1].put('b', b, txn)<br />
>>> cfg.databases['objects'][1].rollbackTransaction(txn)<br />
>>> cfg.shutdown()<br />
>>> ^D<br />
&nbsp;<br />
$ python<br />
Python 2.5.1 (r251:54863, Apr 15 2008, 22:57:26)<br />
[GCC 4.0.1 (Apple Inc. build 5465)] on darwin<br />
Type "help", "copyright", "credits" or "license" for more information.<br />
>>> import Configure<br />
>>> cfg = Configure.Configure()<br />
>>> class Alpha:<br />
...     def __init__(self):<br />
...             self.field = 'alpha'<br />
...<br />
>>> b = cfg.databases['objects'][1].get('b')<br />
Traceback (most recent call last):<br />
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;<br />
  File "RefCache.py", line 110, in get<br />
    value = self.repository.get(key)<br />
  File "Repository.py", line 104, in get<br />
    raise KeyError, key<br />
KeyError: 'b'<br />
>>> a<br />
Traceback (most recent call last):<br />
  File "&lt;stdin&gt;", line 1, in &lt;module&gt;<br />
NameError: name 'a' is not defined<br />
>>> a = cfg.databases['objects'][1].get('a')<br />
>>> a.field<br />
'alpha'<br />
>>> a = None<br />
>>> a<br />
>>> cfg.shutdown()<br />
>>> ^D<br />
&nbsp;<br />
$ db_stat -e -h db<br />
Fri Sep 26 07:35:53 2008	Local time<br />
0x120897	Magic number<br />
0	Panic value<br />
4.7.25	Environment version<br />
<b>...trimmed...</b><br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=751</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Working XML HTTP Update framework in Python</title>
		<link>http://www.mischiefblog.com/?p=715</link>
		<comments>http://www.mischiefblog.com/?p=715#comments</comments>
		<pubDate>Mon, 14 Jan 2008 00:55:13 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=715</guid>
		<description><![CDATA[I have a working, end-to-end XMLHTTPUpdate handling framework written in Python running as a CGI application. Ewww. Download the framework here. It&#8217;s simple and probably has some bugs in it. You can test it as well, but don&#8217;t expect it to work under Internet Explorer. I didn&#8217;t bother writing Javascript for IE, only Firefox (which [...]]]></description>
			<content:encoded><![CDATA[<p>I have a working, end-to-end <code>XMLHTTPUpdate</code> handling framework written in Python running as a CGI application.  Ewww.</p>
<p><a href="http://www.mischiefbox.com/xmlhttp/xmlhttp.zip">Download the framework here.</a>  It&#8217;s simple and probably has some bugs in it.</p>
<p>You can <a href="http://www.mischiefbox.com/xmlhttp/xmlupdate.html">test it as well</a>, but don&#8217;t expect it to work under Internet Explorer.  I didn&#8217;t bother writing Javascript for IE, only Firefox (which means it will also run under Safari and on an iPhone).  If you try it out, give it a couple seconds to fetch the time from the server.</p>
<p>There are obvious points of extension, starting from the <code>Handlers.py</code> file.  I chose to explicitly check handler names rather than use them to dynamically call into code from a string passed through the update.  It just seems safer. <img src='http://www.mischiefblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=715</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>. . . just 90% stupid.</title>
		<link>http://www.mischiefblog.com/?p=708</link>
		<comments>http://www.mischiefblog.com/?p=708#comments</comments>
		<pubDate>Tue, 08 Jan 2008 20:27:15 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=708</guid>
		<description><![CDATA[I figured out what I was doing wrong. Nothing except for how I chose to echo or display the XML. Since it&#8217;s a dynamic call, I can&#8217;t view the page source to see the XML that gets returned. And I never verified that I was getting a String: I assumed that because it was inside [...]]]></description>
			<content:encoded><![CDATA[<p>I figured out what I was doing wrong.  <i>Nothing</i> except for how I chose to echo or display the XML.</p>
<p>Since it&#8217;s a dynamic call, I can&#8217;t view the page source to see the XML that gets returned.  And I never verified that I was getting a String:  I assumed that because it was inside a <code>CDATA</code> block that the tags would be visible, but what I actually got was the tags being evaluated, and since <code>^&lt;get>&lt;time />&lt;/get></code> isn&#8217;t part of XHTML 1.1 . . . my XML never appeared.</p>
<p>So in the interest of saving some future developer a few minutes or hours or days of trouble, if you&#8217;re trying to parse POST-ed XMLHttpRequest XML DOM objects in a Python CGI web application and it looks like STDIN is empty or you&#8217;re not getting the POST contents, verify that you&#8217;re reading something by checking the length and extracting a part of the string.  And convert your tags.<br />
<span id="more-708"></span><br />
<code><br />
#!/Python24/python<br />
&nbsp;<br />
import os<br />
import sys<br />
&nbsp;<br />
def main():<br />
&nbsp;&nbsp;&nbsp;&nbsp;print "Content-Type: application/xml\n\n"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;print "<test>< ![CDATA[<br/>\n";<br />
&nbsp;&nbsp;&nbsp;&nbsp;for key in os.environ:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print key + "=" + os.environ[key] + "<br />\n"<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;if os.environ.has_key("CONTENT_LENGTH"):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;length = int(os.environ["CONTENT_LENGTH"])<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = str(sys.stdin.read(length))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = s.replace('< ', '&lt;')<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;print "
<pre>" + s + "";<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;print "<br />\n]]&gt;</test>\n";<br />
&nbsp;<br />
if __name__ == '__main__':<br />
&nbsp;&nbsp;&nbsp;&nbsp;main()<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=708</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>I&#8217;m not entirely stupid . . .</title>
		<link>http://www.mischiefblog.com/?p=707</link>
		<comments>http://www.mischiefblog.com/?p=707#comments</comments>
		<pubDate>Tue, 08 Jan 2008 00:11:59 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=707</guid>
		<description><![CDATA[Now, I&#8217;m not entirely stupid. Lacking common sense? Yes. Forgetful of dates, appointments, anniversaries, bills? Yes. Easily confused? Absolutely. But I&#8217;ve also been programming in Python for years and wrote my first CGI scripts in 1993 or 1994 or thereabouts. I&#8217;m kind of familiar with both environments, even if this is the first time I&#8217;ve [...]]]></description>
			<content:encoded><![CDATA[<p>Now, I&#8217;m not entirely stupid.  Lacking common sense?  Yes.  Forgetful of dates, appointments, anniversaries, bills?  Yes.  Easily confused?  Absolutely.</p>
<p>But I&#8217;ve also been programming in Python for years and wrote my first CGI scripts in 1993 or 1994 or thereabouts.  I&#8217;m kind of familiar with both environments, even if this is the <a href="http://www.mischiefblog.com/?p=706">first time I&#8217;ve actually put them together</a>.  Everything seemed to be meshing really, really well until I tried to get XML content from the web client through a DOM document passed into the XMLHttpRequest.  (And yes, I am new to XMLHttpRequest dynamic app development.  I&#8217;d always had the pleasure of using someone else&#8217;s library.)</p>
<p><code><br />
function createDocGetTime() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;docGetTime = document.implementation.createDocument("", "", null);<br />
&nbsp;&nbsp;&nbsp;&nbsp;var getNode = docGetTime.createElement("get");<br />
&nbsp;&nbsp;&nbsp;&nbsp;var getTime = docGetTime.createElement("time");<br />
&nbsp;&nbsp;&nbsp;&nbsp;getNode.appendChild(getTime);<br />
&nbsp;&nbsp;&nbsp;&nbsp;docGetTime.appendChild(getNode);<br />
}<br />
&nbsp;<br />
function updateTime() {<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerClient = new XMLHttpRequest();<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerClient.onreadystatechange = timerHandler;<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerClient.open("POST", "xmltimer.py");<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerClient.setRequestHeader("Content-Type", "text/xml;charset=UTF-8");<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerClient.send(docGetTime);<br />
&nbsp;&nbsp;&nbsp;&nbsp;timerId = setTimeout("updateTime()", 1500);<br />
}<br />
</code></p>
<p>Evil code (there&#8217;s no way to stop calling <code>updateTime()</code> <img src='http://www.mischiefblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> ), tutorial-simple, and pretty obvious, or at least it should be.  The problem looks to be Python.<br />
<span id="more-707"></span><br />
From the old days of CGI, if you wanted to read the contents of a <code>POST</code>ed form, you&#8217;d need to split and parse the contents of the body of the HTTP request which should come in through STDIN.  (The <code>QUERY_STRING</code> is only useful for <code>GET</code> requests.)  This is old, ancient stuff, and should be possible with something like:</p>
<p><code><br />
import os<br />
import sys<br />
&nbsp;<br />
print "Content-Type: text/html\n\n&lt;b>Body Content:&lt;/b>&lt;pre>&lt;![CDATA["<br />
if os.environ.has_key("CONTENT_LENGTH"):<br />
&nbsp;&nbsp;&nbsp;&nbsp;print sys.stdin.read(os.environ["CONTENT_LENGTH"])<br />
print "]]&gt;&lt;/pre>"<br />
</code></p>
<p>Except that the body never gets read.</p>
<p>In these paranoid times, you can&#8217;t call a different server, port, or host than the one that served up the webpages, or you&#8217;d become vulnerable to <abbr title="Cross-Site Scripting">XSS</abbr>, so the browser forbids that kind of request.  I had to shut down Apache and start netcat to verify that wasn&#8217;t not a problem with how I was using XMLHttpRequest.<br />
<code><br />
$ ./netcat -l -p 80<br />
POST /demo/simple.py HTTP/1.1<br />
Host: localhost<br />
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11<br />
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5<br />
Accept-Language: en-us,en;q=0.5<br />
Accept-Encoding: gzip,deflate<br />
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7<br />
Keep-Alive: 300<br />
Connection: keep-alive<br />
Content-Type: text/xml;charset=UTF-8<br />
Referer: http://localhost/demo/xmlupdate.html<br />
Content-Length: 18<br />
Pragma: no-cache<br />
Cache-Control: no-cache<br />
&nbsp;<br />
&lt;get>&lt;time />&lt;/get><br />
</code></p>
<p>So I&#8217;m stuck wondering what I screwed up with my Python CGI configuration or with how I invoke the XMLHttpRequest.</p>
<p>I&#8217;ve been bugged by this since Saturday and haven&#8217;t figured it out yet.  Does anyone have any idea why STDIN is empty?
<ul>
<li>Is it something to do with how Python is invoked (however unlikely)?  This error should also cause the standard <code>cgi</code> library to fail&#8211;but it doesn&#8217;t.</li>
<li>Is it something to do with the content type?  Changing to plain <code>text/html</code> doesn&#8217;t help, and neither does the incorrect <code>application/x-www-form-urlencoded</code>.</li>
</ul>
<p>My code which dumps the POST content works fine with an HTML FORM submission:<br />
<code><br />
$ ./netcat -l -p 80<br />
POST /demo/simple.py HTTP/1.1<br />
Host: localhost<br />
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.11) Gecko/2<br />
0071127 Firefox/2.0.0.11<br />
Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plai<br />
n;q=0.8,image/png,*/*;q=0.5<br />
Accept-Language: en-us,en;q=0.5<br />
Accept-Encoding: gzip,deflate<br />
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7<br />
Keep-Alive: 300<br />
Connection: keep-alive<br />
Referer: http://localhost/demo/xmlupdate.html<br />
Content-Type: application/x-www-form-urlencoded<br />
Content-Length: 45<br />
&nbsp;<br />
yourname=xxx&#038;yourmood=yyy&#038;Submit=Submit+Query<br />
</code></p>
<p><b>Output</b><br />
<code><br />
&lt;test><br />
&lt;![CDATA[<br />
&lt;br/><br />
HTTP_REFERER=http://localhost/demo/xmlupdate.html&lt;br/><br />
SERVER_SOFTWARE=Apache/2.0.54 (Win32)&lt;br/><br />
SCRIPT_NAME=/demo/simple.py&lt;br/><br />
&nbsp;<br />
. . . <i>skipped</i> . . .<br />
&nbsp;<br />
CONTENT_LENGTH=45&lt;br/><br />
HTTP_ACCEPT_CHARSET=ISO-8859-1,utf-8;q=0.7,*;q=0.7&lt;br/><br />
&nbsp;<br />
. . . <i>skipped</i> . . .<br />
&nbsp;<br />
CONTENT_TYPE=application/x-www-form-urlencoded&lt;br/><br />
HTTP_ACCEPT_ENCODING=gzip,deflate&lt;br/><br />
&nbsp;<br />
&lt;pre>yourname=xxx&#038;yourmood=yyy&#038;Submit=Submit+Query&lt;/pre><br />
&lt;br/><br />
&lt;/test><br />
]]&gt;<br />
</code></p>
<p>So Python with CGI doesn&#8217;t appear to be entirely at fault.</p>
<p>The easy solution would appear to be to shove the XML content as a String in Javascript into a form field value and submit the form.  I hate to take that approach when I should be able to do native and correct XML through the DOM object.  Another point of view may say, &#8220;If you wanted to save bandwidth, don&#8217;t use XML:  use tokens and plain text instead.&#8221;  I tend to regard that as premature optimization.</p>
<p>I have learned that <code>sys.stdin.seek(0)</code> is useless, so if you plan on using the <code>cgi</code> library with your own routine to read the body, pass the body to <code>cgi.FieldStorage()</code> after you&#8217;ve read and parsed it, or patch <code>cgi</code> (subclass or override) with a version that stores the unaltered body in a field.</p>
<p>I might find time to test if I can get the XML update request working with PHP.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=707</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Laying the groundwork</title>
		<link>http://www.mischiefblog.com/?p=706</link>
		<comments>http://www.mischiefblog.com/?p=706#comments</comments>
		<pubDate>Fri, 04 Jan 2008 22:37:41 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.mischiefblog.com/?p=706</guid>
		<description><![CDATA[I&#8217;ve previously identified a few elements that are needed to make a successful web based application. Since then, I&#8217;ve been prototyping, designing, coding on the bus and while making dinner, and have a pared down, minimal proof of concept for a few of those. XMLHttpRequest: I&#8217;ve verified XMLHttpRequest works with my wife&#8217;s iPhone. I expected [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve <a href="http://www.mischiefblog.com/?p=681">previously identified a few elements</a> that are needed to make a successful web based application.  Since then, I&#8217;ve been prototyping, designing, coding on the bus and while making dinner, and have a pared down, minimal proof of concept for a few of those.</p>
<ul>
<li>XMLHttpRequest:  I&#8217;ve verified XMLHttpRequest works with my wife&#8217;s iPhone.  I expected it to, but had to make sure.  This is the core Javascript call for dynamic web pages that retrieve content from servers.</li>
<li>Timer:  I still need to verify this works as expected on the iPhone, but I have a demo page to verify it ready.</li>
</ul>
<p>In addition to the front end work (of which there will be much, much more), I needed a back-end that I could develop actively.  My platform choices were limited in that it needs to work on a Dreamhost shared server, work on my desktop at home, and also on my laptop for the bus or coding around the house.  Tomcat had to be discarded:  I&#8217;d need to set up a separate Tomcat server and Java environment at Dreamhost.  Perl was discarded as I really don&#8217;t appreciate the language.  <img src='http://www.mischiefblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />   I strongly considered PHP but decided against it in the end.  Ruby was also considered but I didn&#8217;t want to learn a new language while coding a new app.  I toyed with using Lua.  In the end, I decided on Python 2.4 so I don&#8217;t have to do any gymnastics at Dreamhost.  As far as my scripts are concerned, it&#8217;s a one-line change between platforms:</p>
<p><code>#!/Python24/pythonw</code> <i>for Win32</i><br />
<code>#!/usr/bin/python</code> <i>for Linux</i></p>
<p>I have a working Python back-end that gives me a minimum of helper objects for working with HTTP requests in a CGI environment.  (No WSGI here, at least not yet.)  I have room to plug in different request interpreters and a complete world engine or whatever might strike my fancy as long as I keep this minimal interface in place.</p>
<p>Now, nobody said I had to produce anything <i>pretty</i> when proving this works&#8230;</p>
<p><a href="http://www.mischiefbox.com/demo2/xmlupdate.html" target="_blank">Try out my first proof of concept</a></p>
<p>I&#8217;d like my next proof of concept to be an interactive &#8220;game&#8221; or other social, multi-user activity.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=706</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Unpacking sequences in Python when used as function arguments</title>
		<link>http://www.mischiefblog.com/?p=541</link>
		<comments>http://www.mischiefblog.com/?p=541#comments</comments>
		<pubDate>Wed, 22 Nov 2006 16:57:21 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.mischiefbox.com/blog/?p=541</guid>
		<description><![CDATA[D&#8217;oh. Next time, I&#8217;ll just search the docs instead of thrusting blindly forward in an inefficient direction. See 4.7.4 Unpacking Argument Lists in the Python Tutorial. It just goes to show that even when you think you know a language pretty well, there&#8217;s always something new to learn, especially if it&#8217;s a language feature you [...]]]></description>
			<content:encoded><![CDATA[<p>D&#8217;oh.  Next time, I&#8217;ll just search the docs instead of thrusting blindly forward in an inefficient direction.</p>
<p>See <a href="http://docs.python.org/tut/node6.html#SECTION006740000000000000000" target="_blank">4.7.4 Unpacking Argument Lists</a> in the <a href="http://docs.python.org/tut/tut.html" target="_blank">Python Tutorial</a>.  It just goes to show that even when you <i>think</i> you know a language pretty well, there&#8217;s always something new to learn, especially if it&#8217;s a language feature you haven&#8217;t used before.</p>
<p>Instead of doing this:<br />
<code><br />
values = self.get_field_values()<br />
&nbsp;<br />
# build the value string<br />
value_str = ''<br />
&nbsp;<br />
for value in values:<br />
&nbsp;&nbsp;&nbsp;&nbsp;if len(value_str) > 0:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value_str += ','<br />
&nbsp;&nbsp;&nbsp;&nbsp;if isinstance(value, str):<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value = replace("'", "''")<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value_str += "'" + value + "'"<br />
&nbsp;&nbsp;&nbsp;&nbsp;else:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;value_str += str(value)<br />
&nbsp;<br />
result = eval("somefunc(" + value_str + ")")<br />
</code></p>
<p>you can simply do this:<br />
<code><br />
somefunc(*values)<br />
</code><br />
and Python will unpack the sequence into an argument list.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=541</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Thank goodness OS X is becoming popular</title>
		<link>http://www.mischiefblog.com/?p=540</link>
		<comments>http://www.mischiefblog.com/?p=540#comments</comments>
		<pubDate>Wed, 22 Nov 2006 05:13:47 +0000</pubDate>
		<dc:creator>Chris</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Tech]]></category>

		<guid isPermaLink="false">http://www.mischiefbox.com/blog/?p=540</guid>
		<description><![CDATA[For the first time, I&#8217;ve had no problem finding a good binary distribution of Stackless Python for OS X. It should be everything you need to run it on either PPC or i386 Macs. It might not have all the synchronization controls I&#8217;m used to, but I&#8217;m willing to learn how to use it to [...]]]></description>
			<content:encoded><![CDATA[<p>For the first time, I&#8217;ve had <i>no</i> problem finding a good binary distribution of <a href="http://www.stackless.com/download" target="_blank">Stackless Python</a> for OS X.  It should be everything you need to run it on either PPC or i386 Macs.  It might not have all the synchronization controls I&#8217;m used to, but I&#8217;m willing to learn how to use it to write (slightly) higher performance Python apps.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.mischiefblog.com/?feed=rss2&amp;p=540</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
