<?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>The GITS Blog &#187; python</title>
	<atom:link href="http://ginstrom.com/scribbles/category/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://ginstrom.com/scribbles</link>
	<description>Random scribbling about programming, translation, and Japan</description>
	<lastBuildDate>Fri, 11 May 2012 05:10:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Continuous integration in python using watchdog</title>
		<link>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/</link>
		<comments>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/#comments</comments>
		<pubDate>Thu, 10 May 2012 06:00:53 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1752</guid>
		<description><![CDATA[watchdog is a cross-platform python module for watching directories for changes. I use watchdog to run continuous integration on my projects: every time a file changes (e.g. is saved, deleted, or created) in the directory I am watching, a script will automatically run unit tests, compile libraries, build docs, and run other tests, as necessary. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://packages.python.org/watchdog/" title="watchdog package">watchdog</a> is a cross-platform python module for watching directories for changes.</p>
<p>I use watchdog to run continuous integration on my projects: every time a file changes (e.g. is saved, deleted, or created) in the directory I am watching, a script will automatically run unit tests, compile libraries, build docs, and run other tests, as necessary.</p>
<p>Below is a sample script using watchdog that monitors the current directory for changes to .py files and .rst files. When a .py file changes, it runs unit tests; when a .rst file changes, it builds the documentation. Here, I assume that the documentation is built using <a href="http://sphinx.pocoo.org/" title="Sphinx documentation tool overview">Sphinx</a>, and is located in the `docs` subdirectory. `python -m unittest discover -b` is used to run the unit tests.</p>
<p>Of course, you could perform any actions you wanted, using any triggers you choose.</p>
<p>The first thing that you need to do is define an event handler based on <code>watchdog.FileSystemEventHandler</code>:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">from</span> watchdog.<span class="me1">events</span> <span class="kw1">import</span> FileSystemEventHandler</p>
<p>
<span class="kw1">def</span> getext<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the file extension.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">splitext</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>.<span class="me1">lower</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> ChangeHandler<span class="br0">&#40;</span>FileSystemEventHandler<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; React to changes in Python and Rest files by<br />
&nbsp; &nbsp; running unit tests (Python) or building docs (.rst)<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> on_any_event<span class="br0">&#40;</span><span class="kw2">self</span>, event<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;If any file or folder is changed&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> event.<span class="me1">is_directory</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.py'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.rst'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Here, I'm catching all file events, and reacting to changes to .py and .rst (reStructured text) files.</p>
<p>The next thing is to create a <code>watchdog.Observer</code>, and register your event handler.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p><span class="kw1">from</span> watchdog.<span class="me1">observers</span> <span class="kw1">import</span> Observer</p>
<p>BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Called when run as main.<br />
&nbsp; &nbsp; Look for changes to code and doc files.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span> <span class="nu0">1</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; event_handler = ChangeHandler<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer = Observer<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">schedule</span><span class="br0">&#40;</span>event_handler, BASEDIR, recursive=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:<br />
&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Finally, define your actions. Here are mine for running unit tests and building my docs.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">subprocess</span><br />
<span class="kw1">import</span> <span class="kw3">datetime</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p>BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> get_now<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the current date and time as a string&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">datetime</span>.<span class="kw3">datetime</span>.<span class="me1">now</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y/%m/%d %H:%M:%S&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Run the Sphinx build (`make html`) to make sure we have the<br />
&nbsp; &nbsp; latest version of the docs<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Building docs at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>BASEDIR, <span class="st0">&quot;docs&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'make.bat html'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Run unit tests with unittest.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Running unit tests at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span>BASEDIR<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'python -m unittest discover -b'</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>Here is the full code listing:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
Monitors our code &amp; docs for changes<br />
&quot;</span><span class="st0">&quot;&quot;</span></p>
<p><span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> <span class="kw3">sys</span><br />
<span class="kw1">import</span> <span class="kw3">subprocess</span><br />
<span class="kw1">import</span> <span class="kw3">datetime</span><br />
<span class="kw1">import</span> <span class="kw3">time</span></p>
<p><span class="kw1">from</span> watchdog.<span class="me1">observers</span> <span class="kw1">import</span> Observer<br />
<span class="kw1">from</span> watchdog.<span class="me1">events</span> <span class="kw1">import</span> FileSystemEventHandler</p>
<p>
BASEDIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">dirname</span><span class="br0">&#40;</span>__file__<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> get_now<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the current date and time as a string&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">datetime</span>.<span class="kw3">datetime</span>.<span class="me1">now</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">strftime</span><span class="br0">&#40;</span><span class="st0">&quot;%Y/%m/%d %H:%M:%S&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Run the Sphinx build (`make html`) to make sure we have the<br />
&nbsp; &nbsp; latest version of the docs<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Building docs at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>BASEDIR, <span class="st0">&quot;docs&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'make.bat html'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Run unit tests with unittest.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">print</span> &gt;&gt; <span class="kw3">sys</span>.<span class="me1">stderr</span>, <span class="st0">&quot;Running unit tests at %s&quot;</span> % get_now<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">os</span>.<span class="me1">chdir</span><span class="br0">&#40;</span>BASEDIR<span class="br0">&#41;</span><br />
&nbsp; &nbsp; <span class="kw3">subprocess</span>.<span class="me1">call</span><span class="br0">&#40;</span>r<span class="st0">'python -m unittest discover -b'</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> getext<span class="br0">&#40;</span>filename<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;Get the file extension.&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">splitext</span><span class="br0">&#40;</span>filename<span class="br0">&#41;</span><span class="br0">&#91;</span><span class="nu0">-1</span><span class="br0">&#93;</span>.<span class="me1">lower</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> ChangeHandler<span class="br0">&#40;</span>FileSystemEventHandler<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; React to changes in Python and Rest files by<br />
&nbsp; &nbsp; running unit tests (Python) or building docs (.rst)<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> on_any_event<span class="br0">&#40;</span><span class="kw2">self</span>, event<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;If any file or folder is changed&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> event.<span class="me1">is_directory</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.py'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; run_tests<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">elif</span> getext<span class="br0">&#40;</span>event.<span class="me1">src_path</span><span class="br0">&#41;</span> == <span class="st0">'.rst'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; build_docs<span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> main<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Called when run as main.<br />
&nbsp; &nbsp; Look for changes to code and doc files.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">while</span> <span class="nu0">1</span>:<br />
&nbsp; &nbsp; <br />
&nbsp; &nbsp; &nbsp; &nbsp; event_handler = ChangeHandler<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer = Observer<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">schedule</span><span class="br0">&#40;</span>event_handler, BASEDIR, recursive=<span class="kw2">True</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">try</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">True</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw3">time</span>.<span class="me1">sleep</span><span class="br0">&#40;</span><span class="nu0">1</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">except</span> <span class="kw2">KeyboardInterrupt</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">stop</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; observer.<span class="me1">join</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">if</span> __name__ == <span class="st0">'__main__'</span>:<br />
&nbsp; &nbsp; main<span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp;</div>
<p>You can <a href="/code/monitor_changes.zip" title="monitor_changes.py script (zipped)">download the code here</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2012/05/10/continuous-integration-in-python-using-watchdog/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Setting contentEditable in a wxPython IEHtmlWindow</title>
		<link>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/</link>
		<comments>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/#comments</comments>
		<pubDate>Sun, 19 Dec 2010 05:38:09 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1687</guid>
		<description><![CDATA[wxPython's iewin.IEHtmlWindow lets you host the Internet Explorer browser control in a wxPython window. Doing so is quite simple: import wx from wx.lib import iewin class MyFrame&#40;wx.Frame&#41;: &#160; &#160; def __init__&#40;self&#41;: &#160; &#160; &#160; &#160; wx.Frame.__init__&#40;self, None, title=&#34;IEHtmlWindow&#34;&#41; &#160; &#160; &#160; &#160; self.ie = iewin.IEHtmlWindow&#40;self&#41; &#160; &#160; &#160; &#160; self.ie.Navigate&#40;&#34;http://example.com/&#34;&#41; # your URL here app [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.wxpython.org/">wxPython</a>'s iewin.IEHtmlWindow lets you host the Internet Explorer browser control in a wxPython window.</p>
<p>Doing so is quite simple:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> wx<br />
<span class="kw1">from</span> wx.<span class="me1">lib</span> <span class="kw1">import</span> iewin</p>
<p><span class="kw1">class</span> MyFrame<span class="br0">&#40;</span>wx.<span class="me1">Frame</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; wx.<span class="me1">Frame</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw2">None</span>, title=<span class="st0">&quot;IEHtmlWindow&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span> = iewin.<span class="me1">IEHtmlWindow</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">Navigate</span><span class="br0">&#40;</span><span class="st0">&quot;http://example.com/&quot;</span><span class="br0">&#41;</span> <span class="co1"># your URL here</span></p>
<p>app = wx.<span class="me1">App</span><span class="br0">&#40;</span><span class="kw2">False</span><span class="br0">&#41;</span><br />
MyFrame<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">Show</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>app.<span class="me1">MainLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p>IEHtmlWindow has a <code>ctrl</code> member that you can use to manipulate a page's DOM. One of the cool things that this allows you to do is edit a specific element on a page.</p>
<p>To do this, you first need to get the desired element:</p>
<div class="dean_ch" style="white-space: wrap;">element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;some_item_id&quot;</span><span class="br0">&#41;</span></div>
<p>And then set <code>contentEditable</code> to "true".</p>
<p>However, <code>getElementByID</code> returns an <a href="http://msdn.microsoft.com/en-us/library/aa752279%28v=vs.85%29.aspx">IHTMLElement</a> interface, and <code>contentEditable</code> is only supported by the <a href="http://msdn.microsoft.com/en-us/library/aa703950(VS.85).aspx">IHTMLElement3</a> interface and higher (IE has been around for a while, and there are now something like 6 iterations of this interface&#8230;). We therefore need to call <code>QueryInterface</code> on our element in order to get an IHTMLElement3.</p>
<p>The <code>QueryInterface</code> method call takes the class of the interface we want, which lives in the MSHTML module generated by <a href="http://sourceforge.net/projects/comtypes/">comtypes</a> (iewin ensures it's generated), so we need to import that.</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">from</span> comtypes.<span class="me1">gen</span> <span class="kw1">import</span> MSHTML</div>
<p>Then, we get the IHTMLElement3 interface, and set <code>contentEditable</code> to "true" like this:</p>
<div class="dean_ch" style="white-space: wrap;">element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;my_element&quot;</span><span class="br0">&#41;</span><br />
element3 = element.<span class="me1">QueryInterface</span><span class="br0">&#40;</span>MSHTML.<span class="me1">IHTMLElement3</span><span class="br0">&#41;</span><br />
element3.<span class="me1">contentEditable</span> = <span class="st0">&quot;true&quot;</span></div>
<p>Since we can't manipulate the DOM until the document is loaded, it's a good idea to put this code in the <code>DocumentComplete</code> event handler (which we get called by setting ourselves as the event sink).</p>
<p>So putting it all together:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="kw1">import</span> wx<br />
<span class="kw1">from</span> wx.<span class="me1">lib</span> <span class="kw1">import</span> iewin<br />
<span class="kw1">from</span> comtypes.<span class="me1">gen</span> <span class="kw1">import</span> MSHTML</p>
<p><span class="kw1">class</span> MyFrame<span class="br0">&#40;</span>wx.<span class="me1">Frame</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;Init IEHtmlWindow and set ourselves as event sink&quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; wx.<span class="me1">Frame</span>.<span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw2">None</span>, title=<span class="st0">&quot;IEHtmlWindow&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span> = iewin.<span class="me1">IEHtmlWindow</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">AddEventSink</span><span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">Navigate</span><span class="br0">&#40;</span><span class="st0">&quot;http://example.com/&quot;</span><span class="br0">&#41;</span> <span class="co1"># your URL here</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> DocumentComplete<span class="br0">&#40;</span><span class="kw2">self</span>, this, pDisp, URL<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Called when the HTML document finishes loading.<br />
&nbsp; &nbsp; &nbsp; &nbsp; If we were waiting on any actions to perform<br />
&nbsp; &nbsp; &nbsp; &nbsp; when the document was complete, we execute them here.<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element = <span class="kw2">self</span>.<span class="me1">ie</span>.<span class="me1">ctrl</span>.<span class="me1">Document</span>.<span class="me1">getElementById</span><span class="br0">&#40;</span><span class="st0">&quot;my_element&quot;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element3 = element.<span class="me1">QueryInterface</span><span class="br0">&#40;</span>MSHTML.<span class="me1">IHTMLElement3</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; element3.<span class="me1">contentEditable</span> = <span class="st0">&quot;true&quot;</span></p>
<p>app = wx.<span class="me1">App</span><span class="br0">&#40;</span><span class="kw2">False</span><span class="br0">&#41;</span><br />
MyFrame<span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">Show</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>app.<span class="me1">MainLoop</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p>That's it. Not bad for 26 lines of code, including docstrings.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/12/19/setting-contenteditable-in-a-wxpython-iehtmlwindow/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>py2exe gotcha: Building on Windows Vista/7, deploying to XP</title>
		<link>http://ginstrom.com/scribbles/2010/10/23/py2exe-gotcha-building-on-windows-vista7-deploying-to-xp/</link>
		<comments>http://ginstrom.com/scribbles/2010/10/23/py2exe-gotcha-building-on-windows-vista7-deploying-to-xp/#comments</comments>
		<pubDate>Sat, 23 Oct 2010 00:16:28 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1623</guid>
		<description><![CDATA[py2exe is a fantastic module that will package up a Python program into an executable that will run on Windows. py2exe is amazingly good at sussing out your program's dependencies, but it's a complex task, and inevitably there are some gotchas. One of them is the DLL file "POWRPROF.DLL". This happens when building your executable [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.py2exe.org/">py2exe</a> is a fantastic module that will package up a Python program into an executable that will run on Windows.</p>
<p>py2exe is amazingly good at sussing out your program's dependencies, but it's a complex task, and inevitably there are some gotchas.</p>
<p>One of them is the DLL file "POWRPROF.DLL".</p>
<p>This happens when building your executable on Windows Vista/7, and then deploying it on Windows XP. Since this has bitten me twice now, I thought I'd describe it here.</p>
<p>Windows Vista starting shipping a version of POWRPROF.DLL that is incompatible with XP and earlier. Because of the rules that XP uses for DLL lookup, if py2exe includes this DLL, then it won't find the correct one in your system directory.</p>
<p>Typically, the error you'll get when running your compiled program on Windows 2000/XP is "ImportError: DLL load failed: The specified procedure could not be found.", raised by <code>win32api</code>.</p>
<p>The fix is to add "POWRPROF.DLL" to the list of "dll_excludes" passed into py2exe. That will make your executable use whichever version is in the Windows system directory (and will save you a few KB on your bundled app size).</p>
<p>Here's how I do this with the setup script of one of my programs, <a href="http://felix-cat.com/tools/align-assist/">Align Assist</a>:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp; &nbsp; options = <span class="kw2">dict</span><span class="br0">&#40;</span>optimize=<span class="nu0">2</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dist_dir=app_name,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;excludes=excludes,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;packages=packages,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;dll_excludes=<span class="br0">&#91;</span><span class="st0">&quot;POWRPROF.dll&quot;</span><span class="br0">&#93;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; setup_dict<span class="br0">&#91;</span><span class="st0">'options'</span><span class="br0">&#93;</span> = <span class="br0">&#123;</span><span class="st0">&quot;py2exe&quot;</span> : options<span class="br0">&#125;</span></div>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/10/23/py2exe-gotcha-building-on-windows-vista7-deploying-to-xp/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Rapid website development with django and jQuery UI</title>
		<link>http://ginstrom.com/scribbles/2010/06/21/rapid-website-development-with-django-and-jquery-ui/</link>
		<comments>http://ginstrom.com/scribbles/2010/06/21/rapid-website-development-with-django-and-jquery-ui/#comments</comments>
		<pubDate>Mon, 21 Jun 2010 04:30:57 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1555</guid>
		<description><![CDATA[Last week, I launched my latest development project: The official site for the band Murasaki (紫). I was happy to take on this project, partly because Murasaki is something of a legend in the Japanese rock scene (and especially here in their home prefecture of Okinawa), and partly because it would be a good chance [...]]]></description>
			<content:encoded><![CDATA[<p>Last week, I launched my latest development project: The <a href="http://murasaki-band.com/">official site for the band Murasaki (紫)</a>.</p>
<p>I was happy to take on this project, partly because Murasaki is something of a legend in the Japanese rock scene (and especially here in their home prefecture of Okinawa), and partly because it would be a good chance to test out some ideas I've been having about getting simple, clean websites up quickly and efficiently. </p>
<p>There was a firm deadline for getting the site up: a major Japanese heavy-metal magazine (<a href="http://ja.wikipedia.org/wiki/BURRN!">Burrn!</a>) was going to feature Murasaki, and they were going to list the band's website. My strategy was therefore to get something simple and working up by the deadline, and then add to the site gradually.</p>
<h3>The Tools</h3>
<h4><a href="http://www.djangoproject.com/">django</a></h4>
<p>I'm partial to <a href="http://www.cherrypy.org/">cherrypy</a>/<a href="http://jinja.pocoo.org/2/">jinja2</a>/<a href="http://www.sqlalchemy.org/">SQLAlchemy</a> as my web stack, but for this project I chose <a href="http://www.djangoproject.com/">django</a> for the website backend, because django is known for making bog-standard stuff very easy.</p>
<p>The <a href="http://docs.djangoproject.com/en/dev/ref/contrib/admin/">built-in admin interface</a> was a big win for django, because it allowed the band to get in and start adding information right away, as I worked on the site design and structure.</p>
<p>A major annoyance, however, was the inability to smoothly evolve my database. django won't modify database tables for you if you add a field to one of your models, and since I'm growing the site organically, I'm faced with either mucking with the SQL by hand to modify my tables, or violating <a href="http://en.wikipedia.org/wiki/You_ain%27t_gonna_need_it">YAGNI</a> by adding all the fields up front, even if they're not used now (and might never be used). </p>
<p>A good example was lyrics for song tracks. At first, I didn't add a lyrics field, because we weren't sure if we were going to publish them. But then the band's manager decided that it would be OK, so I had to modify the database to add the field. The next issue is samples for tracks; the band thinks that it would be a cool idea, but hasn't worked out if they want them. So that will be another modification to the database if they're added. </p>
<p>I think that django's insistence on making database evolution as hard as possible is wrong-headed and violates the Pythonic principle that we're all consenting adults. Modify the damn table for me, and let me deal with the consequences!</p>
<p>I'll note that although there are a couple of django evolution apps, the ones I checked didn't support sqlite databases (which I'm using because the database is currently around 100 KB, and I don't expect it to ever pass 1 MB).</p>
<h4><a href="http://jqueryui.com/">jQuery UI</a></h4>
<p>I chose <a href="http://jqueryui.com/">jQuery UI</a> for the site layout. The <a href="http://jqueryui.com/themeroller/">Theme Roller</a> application for designing a custom theme was a huge win; I was able to get exactly the look and colors I wanted in minutes.</p>
<p>One small issue I had was that the UI is a bit too coupled to the JavaScript end. For example, I decided to use the <a href="http://jqueryui.com/demos/tabs/">tabs widget</a> for the navigation menu, but out of the box, this widget makes you load all the content into the page, and switch using JavaScript. I had to muck about in the CSS file in order to have the tabs link to actual URLs.</p>
<p>I also benefited from a couple of other jQuery components, such as <a href="http://galleria.aino.se/">jQuery galleria</a> for the <a href="http://murasaki-band.com/en/gallery/">photo gallery</a> (although I'll probably move to something else as more photos are added, and I add a tagging feature).</p>
<h4><a href="http://wordpress.com/">WordPress</a></h4>
<p>I used <a href="http://wordpress.com/">WordPress</a> to create two blogs for the site (one English and one Japanese). Yes, there are blog solutions for django, but WordPress is ready to go out of the box, and in this case (a tight deadline and budget), practicality definitely beat purity.</p>
<p>I created themes integrating the blogs into the site design using <a href="http://www.themespress.com/">Themes Press</a> &#8212; that was $10 very well spent! I doubt that even an experienced wordpress hacker could create an integrated theme for less than $10 of their time.</p>
<h3>Overall Impressions</h3>
<p>I think that the combination of django and jQuery UI can make designing a simple site very quick and painless, although django has some issues with organic site growth, and jQuery UI couples the CSS and JavaScript a bit too tightly for me.</p>
<p>There were a couple of other minor issues (such as when my approach to internationalization differed from django's), but they were probably due more to my lack of familiarity with the frameworks than inherent limitations, and I found workarounds for all of them, so no big deal.</p>
<p>It was also a good experience for me to step away from my more familiar combination of cherrypy/jinja2/SQLAlchemy to use django. I think that in cases like this one, where you have non-programmers contributing a fair amount of the content, the advantages of the free admin interface outweigh the loss of flexibility from using an all-in-one stack like django.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/06/21/rapid-website-development-with-django-and-jquery-ui/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>mailer module uploaded to bitbucket</title>
		<link>http://ginstrom.com/scribbles/2010/05/17/mailer-module-uploaded-to-bitbucket/</link>
		<comments>http://ginstrom.com/scribbles/2010/05/17/mailer-module-uploaded-to-bitbucket/#comments</comments>
		<pubDate>Mon, 17 May 2010 05:26:09 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1550</guid>
		<description><![CDATA[I've created a repository for my mailer module on bitbucket. Here's the project URL: http://bitbucket.org/ginstrom/mailer Apparently you can't open write access to everyone, so if you'd like write privileges, then please let me know your account name. About mailer mailer is a wrapper around the Python email and mimetypes libraries.]]></description>
			<content:encoded><![CDATA[<p>I've created a repository for my <a href="/code/mailer.html">mailer</a> module on bitbucket.</p>
<p>Here's the project URL: <a href="http://bitbucket.org/ginstrom/mailer">http://bitbucket.org/ginstrom/mailer</a></p>
<p>Apparently you can't open write access to everyone, so if you'd like write privileges, then please let me know your account name.</p>
<h3>About mailer</h3>
<p>mailer is a wrapper around the Python <a href="http://docs.python.org/library/email.html">email</a> and <a href="http://docs.python.org/library/mimetypes.html">mimetypes</a> libraries.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/05/17/mailer-module-uploaded-to-bitbucket/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple Ajax with cherrypy and jQuery</title>
		<link>http://ginstrom.com/scribbles/2010/03/07/simple-ajax-with-cherrypy-and-jquery/</link>
		<comments>http://ginstrom.com/scribbles/2010/03/07/simple-ajax-with-cherrypy-and-jquery/#comments</comments>
		<pubDate>Sun, 07 Mar 2010 08:27:04 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1503</guid>
		<description><![CDATA[All the cool kids these days are putting Ajax into their web applications. Ajax is great for when you want to update data on a page without reloading the entire page. Most of the Ajax tutorials use PHP, so I want to show here how easy it is to do Ajax with cherrpy. Ajax stands [...]]]></description>
			<content:encoded><![CDATA[<p>All the cool kids these days are putting Ajax into their web applications. Ajax is great for when you want to update data on a page without reloading the entire page. Most of the Ajax tutorials use PHP, so I want to show here how easy it is to do Ajax with <a href="http://www.cherrypy.org/">cherrpy</a>.</p>
<p>Ajax stands for "asynchronous JavaScript and XML," but these days <a href="http://www.json.org/">json</a> is often used as a lighter-weight alternative to XML. In this tutorial, I'm therefore going to show how to use the python <a href="http://pypi.python.org/pypi/simplejson/">simplejson</a> library to enable communication between python and JavaScript using json.</p>
<p>What you will need for this tutorial:</p>
<ul>
<li><a href="http://www.cherrypy.org/">cherrpy</a></li>
<li><a href="http://pypi.python.org/pypi/simplejson/">simplejson</a></li>
<li><a href="http://jquery.com/">jQuery</a></li>
<li>The <a href="/code/ajax_cherrypy_sample.zip">sample project</a></li>
</ul>
<p>You can get cherrypy and simplejson from pypi via easy_install; there's a copy of jQuery in my <a href="/code/ajax_cherrypy_sample.zip">sample project</a>. The sample project consists of three files, in the following structure:</p>
<pre>
ajax_app.py
media/
  + jquery-1.4.2.min.js
  | index.html
</pre>
<p>First, I'll show the HTML file:</p>
<div class="dean_ch" style="white-space: wrap;">
&lt;html&gt;<br />
&lt;head&gt;<br />
&nbsp; &nbsp; &lt;title&gt;AJAX with jQuery and cherrypy&lt;/title&gt;<br />
&nbsp; &nbsp; &lt;script type=&quot;text/javascript&quot; src=&quot;/media/jquery-1.4.2.min.js&quot;&gt;&lt;/script&gt;<br />
&lt;script type=&quot;text/javascript&quot;&gt;<br />
&nbsp; &nbsp; $(function() {<br />
&nbsp; &nbsp; // When the testform is submitted&#8230;<br />
&nbsp; &nbsp; $(&quot;#testform&quot;).submit(function() {<br />
&nbsp; &nbsp; &nbsp; &nbsp; // post the form values via AJAX&#8230;<br />
&nbsp; &nbsp; &nbsp; &nbsp; var postdata = {name: $(&quot;#name&quot;).val()} ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $.post('/submit', postdata, function(data) {<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // and set the title with the result<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $(&quot;#title&quot;).html(data['title']) ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;});<br />
&nbsp; &nbsp; &nbsp; &nbsp; return false ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; });<br />
&nbsp; &nbsp; });<br />
&lt;/script&gt;<br />
&lt;/head&gt;<br />
&nbsp; &nbsp; &lt;body&gt;<br />
&nbsp; &nbsp; &lt;h1 id=&quot;title&quot;&gt;What's your name?&lt;/h1&gt;</p>
<p>&nbsp; &nbsp; &lt;form id=&quot;testform&quot; action=&quot;#&quot; method=&quot;post&quot;&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;p&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;label for=&quot;name&quot;&gt;Name:&lt;/label&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;input type=&quot;text&quot; id=&quot;name&quot; /&gt; &lt;br /&gt;</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; &lt;input type=&quot;submit&quot; value=&quot;Set&quot; /&gt;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &lt;/p&gt;<br />
&nbsp; &nbsp; &lt;/form&gt;<br />
&nbsp; &nbsp; &lt;/body&gt;<br />
&lt;/html&gt;</div>
<p>Let's see what this is doing. In the body, you've got a title tag, and bog standard HTML form, which asks for a name.</p>
<p>In the head, you've got an include to the jQuery library, and the following JavaScript code:</p>
<div class="dean_ch" style="white-space: wrap;">
&nbsp; &nbsp; $<span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; <span class="co1">// When the testform is submitted&#8230;</span><br />
&nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">&quot;#testform&quot;</span><span class="br0">&#41;</span>.<span class="me1">submit</span><span class="br0">&#40;</span><span class="kw2">function</span><span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// post the form values via AJAX&#8230;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> postdata = <span class="br0">&#123;</span><span class="kw3">name</span>: $<span class="br0">&#40;</span><span class="st0">&quot;#name&quot;</span><span class="br0">&#41;</span>.<span class="me1">val</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#125;</span> ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; $.<span class="me1">post</span><span class="br0">&#40;</span><span class="st0">'/submit'</span>, postdata, <span class="kw2">function</span><span class="br0">&#40;</span>data<span class="br0">&#41;</span> <span class="br0">&#123;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// and set the title with the result</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; $<span class="br0">&#40;</span><span class="st0">&quot;#title&quot;</span><span class="br0">&#41;</span>.<span class="me1">html</span><span class="br0">&#40;</span>data<span class="br0">&#91;</span><span class="st0">'title'</span><span class="br0">&#93;</span><span class="br0">&#41;</span> ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span> ;<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;<br />
&nbsp; &nbsp; <span class="br0">&#125;</span><span class="br0">&#41;</span>;</div>
<p>The initial <code> $(function() </code> statement is a jQuery construct that says, "When the page loads, execute this anonymous function." That function then creates a callback for the submit event of the element with id "testform" (the form). When the form is submitted, the jQuery <code>post</code> function is executed, which is where the magic happens.</p>
<p><a href="http://api.jquery.com/jQuery.post/">jQuery.post</a> is an Ajax method. The first argument is the URL to post to ("/submit"); the second argument is the data to send in the post (the "name" value from the form); and the third argument is the callback to call with the data we receive from the post.</p>
<p>The function then takes this data, and uses its "title" element to update the title of the page.</p>
<p>Next, here's the ajax_app.py file:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> cherrypy<br />
<span class="kw1">import</span> <span class="kw3">webbrowser</span><br />
<span class="kw1">import</span> <span class="kw3">os</span><br />
<span class="kw1">import</span> simplejson<br />
<span class="kw1">import</span> <span class="kw3">sys</span></p>
<p>MEDIA_DIR = <span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">abspath</span><span class="br0">&#40;</span><span class="st0">&quot;.&quot;</span><span class="br0">&#41;</span>, u<span class="st0">&quot;media&quot;</span><span class="br0">&#41;</span></p>
<p><span class="kw1">class</span> AjaxApp<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; @cherrypy.<span class="me1">expose</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> index<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">open</span><span class="br0">&#40;</span><span class="kw3">os</span>.<span class="me1">path</span>.<span class="me1">join</span><span class="br0">&#40;</span>MEDIA_DIR, u<span class="st0">'index.html'</span><span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; @cherrypy.<span class="me1">expose</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> submit<span class="br0">&#40;</span><span class="kw2">self</span>, name<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; cherrypy.<span class="me1">response</span>.<span class="me1">headers</span><span class="br0">&#91;</span><span class="st0">'Content-Type'</span><span class="br0">&#93;</span> = <span class="st0">'application/json'</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> simplejson.<span class="me1">dumps</span><span class="br0">&#40;</span><span class="kw2">dict</span><span class="br0">&#40;</span>title=<span class="st0">&quot;Hello, %s&quot;</span> % name<span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>config = <span class="br0">&#123;</span><span class="st0">'/media'</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span><span class="st0">'tools.staticdir.on'</span>: <span class="kw2">True</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="st0">'tools.staticdir.dir'</span>: MEDIA_DIR,<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></p>
<p><span class="kw1">def</span> open_page<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw3">webbrowser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&quot;http://127.0.0.1:8080/&quot;</span><span class="br0">&#41;</span><br />
cherrypy.<span class="me1">engine</span>.<span class="me1">subscribe</span><span class="br0">&#40;</span><span class="st0">'start'</span>, open_page<span class="br0">&#41;</span><br />
cherrypy.<span class="me1">tree</span>.<span class="me1">mount</span><span class="br0">&#40;</span>AjaxApp<span class="br0">&#40;</span><span class="br0">&#41;</span>, <span class="st0">'/'</span>, config=config<span class="br0">&#41;</span><br />
cherrypy.<span class="me1">engine</span>.<span class="me1">start</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p>First, the <code>AjaxApp</code> class is our application. It's pretty simple, having only two methods: <code>index</code> and <code>submit</code>. </p>
<p>When the index method is called, the app opens the index file and returns it. </p>
<p>The submit method is our Ajax method; when it is called with the form data, we use the information to create a new title, and pass that back as json data using <a href="http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.3/docs/module-simplejson.html#dumps">simplejson.dumps</a>. The JavaScript function that called this method can then use the data to update the page content.</p>
<p>This little piece of code is a convenience for development; when you run the cherrpy app, it loads the index page in your web browser.</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">def</span> open_page<span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="kw3">webbrowser</span>.<span class="kw2">open</span><span class="br0">&#40;</span><span class="st0">&quot;http://127.0.0.1:8080/&quot;</span><span class="br0">&#41;</span><br />
cherrypy.<span class="me1">engine</span>.<span class="me1">subscribe</span><span class="br0">&#40;</span><span class="st0">'start'</span>, open_page<span class="br0">&#41;</span></div>
<p>Finally, the last two lines mount the app, and start up the server. The "config" dict tells cherrpy to serve up static files from the "media" dir in the script's home directory.</p>
<p>If you download the sample project, unzip it, and run ajax_app.py, you should get the following screen (shown here with the name filled in):</p>
<div id="attachment_1506" class="wp-caption alignnone" style="width: 310px"><a href="http://ginstrom.com/scribbles/wp-content/uploads/2010/03/screen1.png"><img src="http://ginstrom.com/scribbles/wp-content/uploads/2010/03/screen1.png" alt="Ajax app -- step1" title="ajax_app1" width="300" height="175" class="size-full wp-image-1506" /></a><p class="wp-caption-text">Ajax app -- step 1</p></div>
<p>Here it is after filling in the name and clicking <strong>Set</strong>:</p>
<div id="attachment_1507" class="wp-caption alignnone" style="width: 310px"><a href="http://ginstrom.com/scribbles/wp-content/uploads/2010/03/screen2.png"><img src="http://ginstrom.com/scribbles/wp-content/uploads/2010/03/screen2.png" alt="Ajax app -- step 2" title="ajax_app2" width="300" height="175" class="alignnone size-full wp-image-1507" /></a><p class="wp-caption-text">Ajax app -- step 2</p></div>
<h3>When to use Ajax</h3>
<p>Ajax is useful when you want to update the page content without reloading the entire page. This is useful for CRUD apps when you want to do things like edit items in place, delete items, or add items.</p>
<h3>When not to use Ajax</h3>
<p>Since Ajax actions don't correspond to URIs, you can't bookmark Ajax actions, send links to friends, or use the back and forward buttons to navigate like in a normal website.</p>
<p>For this reason, avoid Ajax if you want certain application states to be navigable as URIs. For example, if you have a calendar application, and use Ajax to show all the data, the user won't have any way to bookmark an event on December 12th, 2011. Likewise, if you use an Ajax data grid to show tables of data, you won't be able to email your data views to your colleagues.</p>
<p>One middle way is to offer a "permalink" for each Ajax view, which allows for bookmarking, sending links, etc. This still breaks the back-button functionality, but may be worth the trade-off.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2010/03/07/simple-ajax-with-cherrypy-and-jquery/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Easy SFTP uploading with paramiko</title>
		<link>http://ginstrom.com/scribbles/2009/09/14/easy-sftp-uploading-with-paramiko/</link>
		<comments>http://ginstrom.com/scribbles/2009/09/14/easy-sftp-uploading-with-paramiko/#comments</comments>
		<pubDate>Mon, 14 Sep 2009 08:58:33 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1276</guid>
		<description><![CDATA[paramiko makes it so easy to use SFTP that it's hard to believe it's legal in this day and age. Command Line Warriors has a wonderful post showing how to use paramiko to do SFTP uploads/downloads. In this post, I want to share a small helper module called sftp (zip file) (code in post below) [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.lag.net/paramiko/">paramiko</a> makes it so easy to use SFTP that it's hard to believe it's legal in this day and age. <a href="http://commandline.org.uk/">Command Line Warriors</a> has a wonderful post showing <a href="http://commandline.org.uk/python/sftp-python/">how to use paramiko to do SFTP uploads/downloads</a>.</p>
<p>In this post, I want to share a small helper module called <a href="/code/sftp.zip">sftp (zip file)</a> (code in post below) that wraps paramiko.SFTPClient and makes uploading/downloading via SFTP even simpler.</p>
<p>First, some usage</p>
<p><strong>Upload or download a file</strong></p>
<div class="dean_ch" style="white-space: wrap;">
server = sftp.<span class="me1">Server</span><span class="br0">&#40;</span><span class="st0">&quot;user&quot;</span>, <span class="st0">&quot;pass&quot;</span>, <span class="st0">&quot;example.com&quot;</span><span class="br0">&#41;</span><br />
<span class="co1"># upload a file</span><br />
server.<span class="me1">upload</span><span class="br0">&#40;</span><span class="st0">&quot;/local/path&quot;</span>, <span class="st0">&quot;/remote/path&quot;</span><span class="br0">&#41;</span><br />
<span class="co1"># download a file</span><br />
server.<span class="me1">download</span><span class="br0">&#40;</span><span class="st0">&quot;remote/path&quot;</span>, <span class="st0">&quot;/local/path&quot;</span><span class="br0">&#41;</span><br />
server.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
<p><strong>with statement also supported:</strong></p>
<div class="dean_ch" style="white-space: wrap;">
with sftp.<span class="me1">Server</span><span class="br0">&#40;</span><span class="st0">&quot;user&quot;</span>, <span class="st0">&quot;pass&quot;</span>, <span class="st0">&quot;example.com&quot;</span><span class="br0">&#41;</span> as server:<br />
&nbsp; &nbsp; server.<span class="me1">upload</span><span class="br0">&#40;</span><span class="st0">&quot;/local/path&quot;</span>, <span class="st0">&quot;/remote/path&quot;</span><span class="br0">&#41;</span></div>
<p>Finally, a demo recipe for uploading all the png files from a specified local directory to a specified directory on the server:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="co1"># needed for python 2.5</span><br />
<span class="kw1">from</span> <span class="kw3">__future__</span> <span class="kw1">import</span> with_statement</p>
<p><span class="kw1">import</span> sftp<br />
<span class="kw1">import</span> <span class="kw3">glob</span><br />
<span class="kw1">from</span> <span class="kw3">os</span> <span class="kw1">import</span> path</p>
<p>remote_dir = <span class="st0">&quot;/path/on/remote/server/&quot;</span></p>
<p>with sftp.<span class="me1">Server</span><span class="br0">&#40;</span><span class="st0">&quot;user&quot;</span>, <span class="st0">&quot;pass&quot;</span>, <span class="st0">&quot;www.example.com&quot;</span><span class="br0">&#41;</span> as server:<br />
&nbsp; &nbsp; <span class="kw1">for</span> image <span class="kw1">in</span> <span class="kw3">glob</span>.<span class="kw3">glob</span><span class="br0">&#40;</span><span class="st0">&quot;/local/path/to/*.png&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; base = path.<span class="me1">basename</span><span class="br0">&#40;</span>image<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; server.<span class="me1">upload</span><span class="br0">&#40;</span>image, path.<span class="me1">join</span><span class="br0">&#40;</span>remote_dir, base<span class="br0">&#41;</span><span class="br0">&#41;</span></div>
<p>Now, here's the code for my sftp module:</p>
<div class="dean_ch" style="white-space: wrap;">
<span class="kw1">import</span> paramiko</p>
<p><span class="kw1">class</span> Server<span class="br0">&#40;</span><span class="kw2">object</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Wraps paramiko for super-simple SFTP uploading and downloading.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> <span class="kw4">__init__</span><span class="br0">&#40;</span><span class="kw2">self</span>, username, password, host, port=<span class="nu0">22</span><span class="br0">&#41;</span>:</p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">transport</span> = paramiko.<span class="me1">Transport</span><span class="br0">&#40;</span><span class="br0">&#40;</span>host, port<span class="br0">&#41;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">transport</span>.<span class="me1">connect</span><span class="br0">&#40;</span>username=username, password=password<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">sftp</span> = paramiko.<span class="me1">SFTPClient</span>.<span class="me1">from_transport</span><span class="br0">&#40;</span><span class="kw2">self</span>.<span class="me1">transport</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> upload<span class="br0">&#40;</span><span class="kw2">self</span>, local, remote<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">sftp</span>.<span class="me1">put</span><span class="br0">&#40;</span>local, remote<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> download<span class="br0">&#40;</span><span class="kw2">self</span>, remote, local<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">sftp</span>.<span class="me1">get</span><span class="br0">&#40;</span>remote, local<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> close<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; &nbsp; &nbsp; Close the connection if it's active<br />
&nbsp; &nbsp; &nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span></p>
<p>&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="kw2">self</span>.<span class="me1">transport</span>.<span class="me1">is_active</span><span class="br0">&#40;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">sftp</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">transport</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># with-statement support</span><br />
&nbsp; &nbsp; <span class="kw1">def</span> __enter__<span class="br0">&#40;</span><span class="kw2">self</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">self</span></p>
<p>&nbsp; &nbsp; <span class="kw1">def</span> __exit__<span class="br0">&#40;</span><span class="kw2">self</span>, <span class="kw2">type</span>, value, tb<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">self</span>.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span></div>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2009/09/14/easy-sftp-uploading-with-paramiko/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>On rapid iteration</title>
		<link>http://ginstrom.com/scribbles/2009/06/07/on-rapid-iteration/</link>
		<comments>http://ginstrom.com/scribbles/2009/06/07/on-rapid-iteration/#comments</comments>
		<pubDate>Sun, 07 Jun 2009 08:39:00 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1130</guid>
		<description><![CDATA[I think that one of the great strengths of interpreted languages like Python is the ability to iterate rapidly, due to the lack of a compilation step. I've been reading Richard Feynmann's fascinating reminiscences in Surely You're Joking, Mr. Feynmann. The entire text is available online. One passage that really struck me was where he [...]]]></description>
			<content:encoded><![CDATA[<p>I think that one of the great strengths of interpreted languages like Python is the ability to iterate rapidly, due to the lack of a compilation step.</p>
<p>I've been reading Richard Feynmann's fascinating reminiscences in <a href="http://en.wikipedia.org/wiki/Surely_You%27re_Joking,_Mr._Feynman!">Surely You're Joking, Mr. Feynmann</a>. The entire text is <a href="http://www.gorgorat.com/">available online</a>.</p>
<p>One passage that really struck me was where he described the cyclotrons at Princeton, MIT, and Cornell:</p>
<blockquote><p>
It reminded me of my lab at  home. Nothing at MIT had ever reminded  me of  my  lab at home.  I suddenly realized why Princeton was getting results. They were working with the instrument. They built  the instrument; they knew where everything was, they knew how everything worked, there was no engineer involved, except maybe  he was working  there too. It  was much smaller than the cyclotron at MIT, and "gold-plated"? &#8212; it was  the exact opposite. When they wanted to fix a vacuum, they'd drip glyptal on it,  so there were drops of glyptal on the floor. It was wonderful! Because they worked with it. They didn't have to sit in another room and push buttons! (Incidentally, they had a fire in  that  room, because of all the chaotic mess that they had  &#8212; too many  wires &#8212; and it destroyed the cyclotron. But I'd better not tell about that!)</p>
<p>(When I  got  to Cornell I  went to look  at the cyclotron there.  This<br />
cyclotron hardly required a room: It was about a yard across &#8212; the diameter of the whole thing.  It was the world's smallest cyclotron, but they had got fantastic  results. They had all kinds of  special techniques and tricks. If they wanted to  change something  in the "D's" &#8212;  the D-shaped half circles that  the particles go around &#8212; they'd take a screwdriver, and remove the D's by hand, fix  them, and put them back. At Princeton it was a lot harder, and at MIT you had  to take  a crane  that came rolling  across the ceiling, lower the hooks, and it was a hellllll of a job.)</p></blockquote>
<p>Princeton and Cornell had inferior equipment, but they got superior results partly because of the quick iteration loop, eliminating the step of waiting on the engineers to make changes. Scientists at these schools could very quickly try something, make adjustments, and try again, where at MIT the same adjustments took a lot of time.</p>
<p><a href="http://en.wikipedia.org/wiki/Shuji_Nakamura">Shuji Nakamura</a>, inventor of the blue LED, <a href="http://archive.sciencewatch.com/jan-feb2000/sw_jan-feb2000_page3.htm">said something similar about his work</a>:</p>
<blockquote><p>I had a very, very small budget and had to make everything I needed myself. I even made my own reactors—the furnaces needed to do the crystal work. </p></blockquote>
<p>Nakamura succeeded in creating a blue LED, working by himself, when huge multinationals were pouring hundreds of millions of dollars into R&amp;D without results. Elsewhere, he commented that the ability to make adjustments to his equipment quickly, without getting engineers involved, was one of the secrets to his success.</p>
<p>It struck me that this is one of the reasons why I get better results with Python than with compiled languages like C and C++. With Python, there's no compiler in the loop, so the iteration cycle is very fast &#8212; rarely more than 10 seconds to run all the unit tests.</p>
<p>This affects every part of the development cycle. Development itself is a lot faster, so you get more done. With a faster cycle, refactoring code in small steps is also quick and painless, so it's easier to evolve code. The cost of trying out new ideas is low, so you're encouraged to prototype lots of designs to get the best ones.</p>
<p>I think that in just about any kind of creative endeavor, the ability to rapidly iterate between creation and feedback gives a tremendous boost to productivity. This is one of the reasons why I'm so much more productive with Python.</p>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2009/06/07/on-rapid-iteration/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>mailer version 0.5 released</title>
		<link>http://ginstrom.com/scribbles/2009/05/28/mailer-version-05-released/</link>
		<comments>http://ginstrom.com/scribbles/2009/05/28/mailer-version-05-released/#comments</comments>
		<pubDate>Thu, 28 May 2009 01:02:05 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[email]]></category>
		<category><![CDATA[mailer]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1094</guid>
		<description><![CDATA[I've released version 0.5 of my mailer python module for sending emails. Thanks to a patch from Douglas Mayle, this version makes it possible to send HTML emails with attachments (previous versions only let you do one or the other). Project homepage pypi page]]></description>
			<content:encoded><![CDATA[<p>I've released version 0.5 of my <a href="http://pypi.python.org/pypi/mailer/">mailer python module</a> for sending emails. Thanks to a patch from Douglas Mayle, this version makes it possible to send HTML emails with attachments (previous versions only let you do one or the other).</p>
<ul>
<li><a href="/code/mailer.html">Project homepage</a></li>
<li><a href="http://pypi.python.org/pypi/mailer/">pypi page</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2009/05/28/mailer-version-05-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Converting kanji numbers to integers with Python</title>
		<link>http://ginstrom.com/scribbles/2009/04/28/converting-kanji-numbers-to-integers-with-python/</link>
		<comments>http://ginstrom.com/scribbles/2009/04/28/converting-kanji-numbers-to-integers-with-python/#comments</comments>
		<pubDate>Tue, 28 Apr 2009 05:19:25 +0000</pubDate>
		<dc:creator>Ryan Ginstrom</dc:creator>
				<category><![CDATA[programming]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[conversion]]></category>
		<category><![CDATA[kanji]]></category>

		<guid isPermaLink="false">http://ginstrom.com/scribbles/?p=1008</guid>
		<description><![CDATA[A question on StackOverflow about converting kanji numbers (e.g. "五十五") into integers in C++ got me interested in solving this using Python. The result is my kanjinums module, with a function kanji2num that will convert a string containing a kanji num to a Python integer. Download the source distribution (kanjinums-0.1.zip) Download the Windows installer (kanjinums-0.1.win32.exe) [...]]]></description>
			<content:encoded><![CDATA[<p>A <a href="http://stackoverflow.com/questions/795868/how-to-parse-kanji-numeric-characters-using-icu" rel="nofollow">question on StackOverflow</a> about converting kanji numbers (e.g. "五十五") into integers in C++ got me interested in solving this using Python.</p>
<p>The result is my kanjinums module, with a function kanji2num that will convert a string containing a kanji num to a Python integer.</p>
<p><a href="/code/kanjinums-0.1.zip">Download the source distribution (kanjinums-0.1.zip)</a><br />
<a href="/code/kanjinums-0.1.win32.exe">Download the Windows installer (kanjinums-0.1.win32.exe)</a><br />
<a href="/code/test_kanjinums.zip">Download the unit tests (test_kanjinums.zip)</a></p>
<p>Examples:</p>
<div class="dean_ch" style="white-space: wrap;">
&gt;&gt;&gt; <span class="kw1">import</span> kanjinums<br />
&gt;&gt;&gt; kanjinums.<span class="me1">kanji2num</span><span class="br0">&#40;</span><span class="st0">&quot;五百十一&quot;</span>, <span class="st0">&quot;sjis&quot;</span><span class="br0">&#41;</span><br />
<span class="nu0">511</span><br />
&gt;&gt;&gt; kanjinums.<span class="me1">kanji2num</span><span class="br0">&#40;</span><span class="st0">&quot;三万十五&quot;</span>, <span class="st0">&quot;sjis&quot;</span><span class="br0">&#41;</span><br />
<span class="nu0">30015</span></div>
<p>Here's the full code:</p>
<div class="dean_ch" style="white-space: wrap;"><span class="co1">#coding: UTF8</span><br />
<span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
Converts kanji numbers into integers</p>
<p>Can covert numbers up to 9,999,999,999,999,999<br />
(九千九百九十九兆九千九百九十九億九千九百九十九万九千九百九十九)</p>
<p>Released under MIT license.<br />
&quot;</span><span class="st0">&quot;&quot;</span><br />
__version__ = <span class="st0">&quot;0.1&quot;</span><br />
__author__ &nbsp;= <span class="st0">&quot;Ryan Ginstrom&quot;</span><br />
__license__ = <span class="st0">&quot;MIT&quot;</span><br />
__description__ = <span class="st0">&quot;A module to convert kanji numbers into Python integers&quot;</span></p>
<p>NUMS = <span class="br0">&#40;</span><span class="br0">&#40;</span><span class="nu0">1</span>, u<span class="st0">&quot;一&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">2</span>, u<span class="st0">&quot;二&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">3</span>, u<span class="st0">&quot;三&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">4</span>, u<span class="st0">&quot;四&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">5</span>, u<span class="st0">&quot;五&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">6</span>, u<span class="st0">&quot;六&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">7</span>, u<span class="st0">&quot;七&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">8</span>, u<span class="st0">&quot;八&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">9</span>, u<span class="st0">&quot;九&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">10</span>, u<span class="st0">&quot;十&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">100</span>, u<span class="st0">&quot;百&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">1000</span>, u<span class="st0">&quot;千&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">10000</span>, u<span class="st0">&quot;万&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">100000000</span>, u<span class="st0">&quot;億&quot;</span><span class="br0">&#41;</span>,<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#40;</span><span class="nu0">1000000000000</span>, u<span class="st0">&quot;兆&quot;</span><span class="br0">&#41;</span><span class="br0">&#41;</span></p>
<p>KANJIS = <span class="kw2">dict</span><span class="br0">&#40;</span><span class="br0">&#40;</span>kanji, num<span class="br0">&#41;</span> <span class="kw1">for</span> <span class="br0">&#40;</span>num, kanji<span class="br0">&#41;</span> <span class="kw1">in</span> NUMS<span class="br0">&#41;</span></p>
<p><span class="kw1">def</span> _break_down_nums<span class="br0">&#40;</span>nums<span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; first, second, third, rest = nums<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, nums<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, nums<span class="br0">&#91;</span><span class="nu0">2</span><span class="br0">&#93;</span>, nums<span class="br0">&#91;</span><span class="nu0">3</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> first &lt; third <span class="kw1">or</span> third &lt; second:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#91;</span>first+second, third<span class="br0">&#93;</span> + rest<br />
&nbsp; &nbsp; <span class="kw1">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#91;</span>first, second*third<span class="br0">&#93;</span> + rest</p>
<p><span class="kw1">def</span> kanji2num<span class="br0">&#40;</span>kanji, enc=<span class="st0">&quot;utf-8&quot;</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; <span class="st0">&quot;&quot;</span><span class="st0">&quot;<br />
&nbsp; &nbsp; Convert the kanji number to a Python integer.<br />
&nbsp; &nbsp; Supply `kanji` as a unicode string, or a byte string<br />
&nbsp; &nbsp; with the encoding specified in `enc`.<br />
&nbsp; &nbsp; &quot;</span><span class="st0">&quot;&quot;</span><br />
&nbsp; &nbsp; <span class="kw1">if</span> <span class="kw1">not</span> <span class="kw2">isinstance</span><span class="br0">&#40;</span>kanji, <span class="kw2">unicode</span><span class="br0">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; kanji = <span class="kw2">unicode</span><span class="br0">&#40;</span>kanji, enc<span class="br0">&#41;</span></p>
<p>&nbsp; &nbsp; <span class="co1"># get the string as list of numbers</span><br />
&nbsp; &nbsp; nums = <span class="br0">&#91;</span>KANJIS<span class="br0">&#91;</span>x<span class="br0">&#93;</span> <span class="kw1">for</span> x <span class="kw1">in</span> kanji<span class="br0">&#93;</span></p>
<p>&nbsp; &nbsp; num = <span class="nu0">0</span><br />
&nbsp; &nbsp; <span class="kw1">while</span> <span class="kw2">len</span><span class="br0">&#40;</span>nums<span class="br0">&#41;</span> &gt; <span class="nu0">1</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; first, second, rest = nums<span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span>, nums<span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>, nums<span class="br0">&#91;</span><span class="nu0">2</span>:<span class="br0">&#93;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> second &lt; first: <span class="co1"># e.g. [10, 3, ...]</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> any<span class="br0">&#40;</span>x &gt; first <span class="kw1">for</span> x <span class="kw1">in</span> rest<span class="br0">&#41;</span>: <span class="co1"># e.g. [500, 3, 10000, ...]</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nums = _break_down_nums<span class="br0">&#40;</span>nums<span class="br0">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>: <span class="co1"># e.g. [500, 3, 10, ...]</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; num += first<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nums = <span class="br0">&#91;</span>second<span class="br0">&#93;</span> + rest<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span>: <span class="co1"># e.g. [3, 10, ...]</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; nums = <span class="br0">&#91;</span>first*second<span class="br0">&#93;</span> + rest</p>
<p>&nbsp; &nbsp; <span class="kw1">return</span> num + <span class="kw2">sum</span><span class="br0">&#40;</span>nums<span class="br0">&#41;</span></div>
]]></content:encoded>
			<wfw:commentRss>http://ginstrom.com/scribbles/2009/04/28/converting-kanji-numbers-to-integers-with-python/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

