<?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>Edward Andrew Robinson &#187; Python</title>
	<atom:link href="http://www.earobinson.org/category/programing/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.earobinson.org</link>
	<description>“Brilliant people simplify things, and mediocre people complicate things.” — Unknown</description>
	<lastBuildDate>Mon, 04 Oct 2010 02:12:05 +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>Alive and Well (Just Busy)!</title>
		<link>http://www.earobinson.org/2010/02/24/alive-and-well-just-busy/</link>
		<comments>http://www.earobinson.org/2010/02/24/alive-and-well-just-busy/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 02:52:06 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Personal]]></category>
		<category><![CDATA[Programing]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[1and1]]></category>
		<category><![CDATA[blogging]]></category>
		<category><![CDATA[Brazilian Jiu-Jitsu]]></category>
		<category><![CDATA[cae]]></category>
		<category><![CDATA[flickr]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[job]]></category>
		<category><![CDATA[lazyweb]]></category>
		<category><![CDATA[mma]]></category>
		<category><![CDATA[photography]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[toronto bjj]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://www.earobinson.org/?p=364</guid>
		<description><![CDATA[It has been ages since I last posted, and for that I am sorry, but I have kept up with my twitter and identica accounts. Things have been moving really fast for me of late and as a result my blogging has slipped. So whats new in the world of earobinson? I am now working [...]]]></description>
			<content:encoded><![CDATA[<p>It has been ages since I <a href="/2009/11/09/ubuntu-shirts/">last posted</a>, and for that I am sorry, but I have kept up with my <a href="http://twitter.com/earobinson">twitter</a> and <a href="http://identi.ca/earobinson">identica</a> accounts. Things have been moving really fast for me of late and as a result <a href="/">my blogging</a> has slipped. So whats new in the world of <a href="/">earobinson</a>?</p>
<ol>
<li>I am now working for <a href="http://www.cae.com/">CAE</a>, more precisely <a href="http://www.cae.com/ps/">CAE PS</a> out of <a href="http://en.wikipedia.org/wiki/Toronto">Toronto</a>, and I am loving every moment of it. They have a very open culture and encourage the use of open source tools when appropriate. I have been able to use <a href="http://www.ubuntu.com/">Ubuntu</a> to host some of the websites I have developed in <a href="http://www.djangoproject.com/">Django</a>. This has kept me very happy. I can honestly say that I think that my <a href="http://www.ubuntu.com/">Ubuntu</a>, and Open Source knowledge set me apart.</li>
<li><a href="http://www.flickr.com/photos/earobinson/">I have been getting more and more into photography</a> with my new <a href="http://www.usa.canon.com/consumer/controller?act=ModelInfoAct&amp;fcategoryid=139&amp;modelid=18385">Canon EOS Rebel T1i</a>, you can follow me on <a href="http://www.flickr.com/photos/earobinson/">flickr</a>.</li>
<li>I have been ramping up my fitness (and <a href="http://en.wikipedia.org/wiki/Brazilian_Jiu-Jitsu">Brazilian Jiu-Jitsu</a> skills) at <a href="http://torontobjj.com/">Toronto BJJ</a>.</li>
</ol>
<p>This brings me to my goals for the future, I am falling in love with <a href="http://www.djangoproject.com/">Django</a> and as a result I want to play with it more and more, now my current hosting provider <a href="http://www.1and1.com/?k_id=16239276">1and1 </a>has served me very well up to now. But now that I want to start playing with <a href="http://www.djangoproject.com/">Django</a> more I need to get a hosting provider that can support <a href="http://www.djangoproject.com/">Django</a> (because I want to show off my work of course). I would hope that any new hosting provider I use could support both <a href="http://www.djangoproject.com/">Django</a>, and <a href="http://rubyonrails.org/">ruby on rails</a> (as I may want to play with it in the future). So dear lazy web what do you recommend? And I know I could use <a href="http://code.google.com/appengine/articles/django.html">Google app engein</a> but I like the idea of pure <a href="http://www.djangoproject.com/">Django</a>, not some hack, I have also looked at <a href="http://djangohosting.org/">djangohosting.org </a>but would love some recommendations from actual users of hosting plans.</p>
<p>Any advise <a href="http://www.urbandictionary.com/define.php?term=lazyweb">lazyweb</a>?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2010/02/24/alive-and-well-just-busy/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>DeadlineExceededError on Google App Engine</title>
		<link>http://www.earobinson.org/2008/07/20/deadlineexceedederror-on-google-app-engine/</link>
		<comments>http://www.earobinson.org/2008/07/20/deadlineexceedederror-on-google-app-engine/#comments</comments>
		<pubDate>Sun, 20 Jul 2008 22:02:42 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Open Source]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.earobinson.org/?p=138</guid>
		<description><![CDATA[A while back I wrote a post about using Google docs as an expense tracker. The post received a lot of great feedback and so when I wanted to learn about Google App Engine I decided the best way was to create a Google app that connects to my Google docs to let the user [...]]]></description>
			<content:encoded><![CDATA[<p>A while back I wrote a post about using <a href="http://www.earobinson.org/2008/05/08/google-docs-as-an-expense-tracker/#content">Google docs as an expense tracker</a>. The post received a lot of great feedback and so when I wanted to learn about <a href="http://code.google.com/appengine/">Google App Engine</a> I decided the best way was to create a Google app that connects to my <a href="https://docs.google.com/">Google docs</a> to let the user easily add expenses. This would solve the problem I had with the <a href="http://www.earobinson.org/2008/05/08/google-docs-as-an-expense-tracker/#content">original Google expense tracker</a> that anyone could add an expense to my spreadsheet. The result of this is <a href="http://eyecost.appspot.com">eyecost</a> released under the <a href="http://www.gnu.org/licenses/gpl.txt">gpl</a> (I had wanted to use the <a href="http://www.gnu.org/licenses/agpl.txt">agpl</a> but I don&#8217;t think that that is an option since it connects to Google servers) you can <a href="http://www.earobinson.org/wp-content/uploads/2008/07/eyecosttar.gz">download eyecost here</a>. The problem I am having is that if I do a lot of spreadsheet editing the <a href="http://code.google.com/appengine/">Google App Engine</a> times out.</p>
<p>Anyone know how I can get around this?</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2008/07/20/deadlineexceedederror-on-google-app-engine/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Mapping Wikipedia</title>
		<link>http://www.earobinson.org/2008/04/27/mapping-wikipedia/</link>
		<comments>http://www.earobinson.org/2008/04/27/mapping-wikipedia/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 22:04:23 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[graphviz]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[Programing]]></category>
		<category><![CDATA[sandbox]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[wikipedia]]></category>
		<category><![CDATA[wikis]]></category>

		<guid isPermaLink="false">http://www.earobinson.org/?p=106</guid>
		<description><![CDATA[I was reading reddit the other day and stumbled upon the fact that wikipedia has an API. Neat I thought, and having some free time since my exams are now over I figured I would play around a bit with it. When I browse wikipedia I often click from link to link, and have come [...]]]></description>
			<content:encoded><![CDATA[<p>I was reading <a href="http://reddit.com/">reddit</a> the other day and <a href="http://reddit.com/info/6h7rn/comments/">stumbled upon the fact</a> that <a href="http://en.wikipedia.org/w/api.php">wikipedia has an API</a>. Neat I thought, and having some free time since my <a href="http://twitter.com/earobinson/statuses/797057597">exams are now over</a> I figured I would play around a bit with it. When I browse <a href="http://en.wikipedia.org">wikipedia</a> I often click from <a href="http://en.wikipedia.org/wiki/Hyperlink">link</a> to <a href="http://en.wikipedia.org/wiki/Hyperlink">link</a>, and have come to the conclusion that all articles are <a href="http://en.wikipedia.org/wiki/Six_degrees_of_separation">6 degrees of separation</a>. For example I can go from <a href="http://en.wikipedia.org/wiki/Ubuntu_(operating_system)">Ubuntu</a> to <a href="http://en.wikipedia.org/wiki/Tesco">Tesco</a> to <a href="http://en.wikipedia.org/wiki/Japan">Japan</a> to <a href="http://en.wikipedia.org/wiki/G8">G8</a> to <a href="http://en.wikipedia.org/wiki/United_States">United States</a> to <a href="http://en.wikipedia.org/wiki/George_W._Bush">George W. Bush</a> bet you never knew <a href="http://en.wikipedia.org/wiki/Ubuntu_(operating_system)">Ubuntu</a> was connected to <a href="http://en.wikipedia.org/wiki/George_W._Bush">George W. Bush</a>. I once wrote a <a href="http://www.earobinson.org/2007/10/15/map-of-the-internet/">map of the internet program</a> that people seemed to like to download and modify so in that spirit I wrote <a href="http://www.files.earobinson.org/wiki/wikimap.py.txt">wikimap.py</a> to map <a href="http://en.wikipedia.org">wikipedia</a>. <a href="http://www.files.earobinson.org/wiki/wikimap.py.txt">wikimap.py</a> Requires <a href="https://networkx.lanl.gov/wiki/pygraphviz">pygraphviz</a> (Install using sudo aptitude install <a href="apt://python-pygraphviz">python-pygraphviz</a>). To use the program simply run the program and give it the wiki page name for example &#8220;python <a href="http://www.files.earobinson.org/wiki/wikimap.py.txt">wikimap.py</a> <a href="http://en.wikipedia.org/wiki/Norman_Graham">Norman_Graham</a>&#8221; Note that <a href="http://en.wikipedia.org/wiki/Ubuntu_(operating_system)">Ubuntu</a> is <a href="http://en.wikipedia.org/wiki/Ubuntu_(Linux_distribution)">Ubuntu_(Linux_distribution)</a> and you can find the full name in the address bar of your browser. For more complicated maps use <a href="http://www.files.earobinson.org/wiki/wikimap.py.txt">wikimap.py</a> &#8211;help for full usage info.</p>
<p>Here are a few examples that I created with <a href="http://www.files.earobinson.org/wiki/wikimap.py.txt">wikimap.py<br />
<img class="alignnone" src="http://www.files.earobinson.org/wiki/Fulacunda-1-neato.png" alt="" /><br />
<img class="alignnone" src="http://www.files.earobinson.org/wiki/Norman_Graham-1-neato.png" alt="" width="465" height="262" /></a><br />
And a really large one being viewed in <a href="http://www.inkscape.org/">inkscape</a>.<br />
<img class="alignnone" src="http://www.files.earobinson.org/wiki/Screenshot-Fulacunda-2-neato.svg%20-%20Inkscape.png" alt="" /></p>
<p>More examples including the dot files can be found at <a href="http://www.files.earobinson.org/wiki/">http://www.files.earobinson.org/wiki/</a>. But there are a few features I would like to add:</p>
<ol>
<li>Generating the graph using <a href="apt://python-pygraphviz">python-pygraphviz</a> currently takes a really long time and I would like to be able to do it faster</li>
<li>Page links currently include templates, I would like to only use links in the body of the text</li>
<li>It would be nice if the software cached previously seen connections. (But then I need to detect updates to that page)</li>
</ol>
<p>If anyone has a nice simple soultion to any of those problems leave a comment. Also if you are able to generate any neat images I would love to see them.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2008/04/27/mapping-wikipedia/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Map of The Internet</title>
		<link>http://www.earobinson.org/2007/10/15/map-of-the-internet/</link>
		<comments>http://www.earobinson.org/2007/10/15/map-of-the-internet/#comments</comments>
		<pubDate>Mon, 15 Oct 2007 03:41:41 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Internet Map]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[image]]></category>
		<category><![CDATA[internet]]></category>
		<category><![CDATA[map]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[source code]]></category>

		<guid isPermaLink="false">http://earobinson.org/?p=23</guid>
		<description><![CDATA[The other day I stumbled upon Chris Harrison&#8217;s internet map, the only problem I found with his map is that I wanted to know exactly which country each network connection was in. So using the DIMES public data repository, and 1site1moment&#8217;s country boarders I have mapped the internet for myself. From Public Feel free to [...]]]></description>
			<content:encoded><![CDATA[<p>The other day I stumbled upon <a href="http://chrisharrison.net">Chris Harrison&#8217;s</a> <a href="http://chrisharrison.net/projects/InternetMap/index.html">internet map</a>, the only problem I found with his map is that I wanted to know exactly which country each  network connection was in. So using the <a href="http://www.netdimes.org/DIMESControlCenter/MonthlyData.jsp">DIMES public data repository</a>, and <a href="http://www.1site1moment.com">1site1moment&#8217;s</a> <a href="http://www.1site1moment.com/toby/countryborders.asp">country boarders</a> I have mapped the internet for myself.</p>
<table style="width: auto">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Public/photo#5121539486098262978"><img src="http://lh5.google.com/earobinson/RxNdBwwGC8I/AAAAAAAAAZ0/ViebU3sbKBs/s288/CityEdges2_2007.csv.jpg" height="201" width="442" /></a></td>
</tr>
<tr>
<td style="font-family: arial,sans-serif; font-size: 11px; text-align: right">From <a href="http://picasaweb.google.com/earobinson/Public">Public</a></td>
</tr>
</table>
<p>Feel free to download the <a href="http://www.edwardandrewrobinson.com-a.googlepages.com/internetImage.tar.gz">source code</a> and come up with your own internet map, I would love to see what other people can come up with.</p>
<p><strong>UPDATE 01: </strong>Image is back up, If the source code link wont work for you email me and I will send you a copy. Feel free to host this anywhere you like just post a link back to this site.</p>
<p><strong>UPDATE 02:</strong> <a href="http://earobinson.googlepages.com/internetImage.tar.gz">Source code can now also be found here</a>.</p>
<p><strong>UPDATE 03:</strong> Would love to see what other people can do with this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2007/10/15/map-of-the-internet/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Propensity v0.1.2.1906 — Now With an Icon! (shameless repost)</title>
		<link>http://www.earobinson.org/2007/09/17/propensity-v0121906-%e2%80%94-now-with-an-icon-shameless-repost/</link>
		<comments>http://www.earobinson.org/2007/09/17/propensity-v0121906-%e2%80%94-now-with-an-icon-shameless-repost/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 13:24:10 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Propensity]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://earobinson.org/?p=47</guid>
		<description><![CDATA[Due to an issue with wordpress I have been forced to repost this. It has been about a week since I released Propensity into the wild for your feedback, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 [...]]]></description>
			<content:encoded><![CDATA[<p>Due to an <a href="http://earobinson.wordpress.com/2007/09/17/feeds-seem-to-be-broken/">issue with wordpress</a> I have been forced to <a href="http://earobinson.wordpress.com/2007/09/17/propensity-v0121906-now-with-an-icon/">repost this</a>.</p>
<p>It has been about a week since I <a href="http://earobinson.wordpress.com/2007/09/02/propensity-feedback-wanted/">released Propensity into the wild</a> for your <a href="http://earobinson.wordpress.com/2007/09/02/propensity-feedback-wanted/#respond">feedback</a>, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 well version 0.1.1.xxxx was released as a limited demo but I have pushed forward to release version 0.1.2.190.</p>
<p>New to this version we have:</p>
<ul>
<li>The ability to add your own programs to propensity (you can import them or manually add them)</li>
<li>A Propensity Icon</li>
<li>Cleaned up and much prettier terminal</li>
<li>And many other little features.</li>
</ul>
<p>As always feedback is wanted and bugs can be emailed to earobinson+propensity@gmail.com.</p>
<p><a href="http://www.edwardandrewrobinson.com-a.googlepages.com/propensity-0.1.2.1906.deb">Download Propensity Here</a><br />
<a href="http://www.edwardandrewrobinson.com-a.googlepages.com/propensity.tar.gz">Download Propensity Source Here</a></p>
<p><a href="http://ubuntuforums.org/showthread.php?t=540787&amp;highlight=propensity">Ubuntu forums propensity post can be found here</a></p>
<p><a href="http://picasaweb.google.com/earobinson/Propensity">Screenshots</a> below</p>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494613514139234"><img src="http://lh4.google.com/earobinson/RuiSR5xINmI/AAAAAAAAAVE/Mxh3StbyV9g/s400/PropensityIcon.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494519024858578"><img src="http://lh6.google.com/earobinson/RuiSMZxINdI/AAAAAAAAATY/bcPpEcFQCh0/s400/Screenshot-Changes%20Applied-1.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494540499695090"><img src="http://lh3.google.com/earobinson/RuiSNpxINfI/AAAAAAAAATw/8fgQoACqtGg/s400/Screenshot-Propensity-1.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2007/09/17/propensity-v0121906-%e2%80%94-now-with-an-icon-shameless-repost/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Propensity v0.1.2.1906 &#8212; Now With an Icon!</title>
		<link>http://www.earobinson.org/2007/09/17/propensity-v0121906-now-with-an-icon/</link>
		<comments>http://www.earobinson.org/2007/09/17/propensity-v0121906-now-with-an-icon/#comments</comments>
		<pubDate>Mon, 17 Sep 2007 02:57:24 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Propensity]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://earobinson.org/?p=45</guid>
		<description><![CDATA[It has been about a week since I released Propensity into the wild for your feedback, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 well version 0.1.1.xxxx was released as a limited demo but I have pushed [...]]]></description>
			<content:encoded><![CDATA[<p>It has been about a week since I <a href="http://earobinson.wordpress.com/2007/09/02/propensity-feedback-wanted/">released Propensity into the wild</a> for your <a href="http://earobinson.wordpress.com/2007/09/02/propensity-feedback-wanted/#respond">feedback</a>, I have gotten a fair bit of feedback and received a lot of help. You will also notice that I jumped from version 0.1.0.1772 to 0.1.2.1906 well version 0.1.1.xxxx was released as a limited demo but I have pushed forward to release version 0.1.2.190.</p>
<p>New to this version we have:</p>
<ul>
<li>The ability to add your own programs to propensity (you can import them or manually add them)</li>
<li>A Propensity Icon</li>
<li>Cleaned up and much prettier terminal</li>
<li>And many other little features.</li>
</ul>
<p>As always feedback is wanted and bugs can be emailed to earobinson+propensity@gmail.com.</p>
<p><a href="http://www.edwardandrewrobinson.com-a.googlepages.com/propensity-0.1.2.1906.deb">Download Propensity Here</a><br />
<a href="http://www.edwardandrewrobinson.com-a.googlepages.com/propensity.tar.gz">Download Propensity Source Here</a></p>
<p><a href="http://ubuntuforums.org/showthread.php?t=540787&amp;highlight=propensity">Ubuntu forums propensity post can be found here</a></p>
<p><a href="http://picasaweb.google.com/earobinson/Propensity">Screenshots</a> below</p>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494613514139234"><img src="http://lh4.google.com/earobinson/RuiSR5xINmI/AAAAAAAAAVE/Mxh3StbyV9g/s400/PropensityIcon.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494519024858578"><img src="http://lh6.google.com/earobinson/RuiSMZxINdI/AAAAAAAAATY/bcPpEcFQCh0/s400/Screenshot-Changes%20Applied-1.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
<table style="width:auto;">
<tr>
<td><a href="http://picasaweb.google.com/earobinson/Propensity/photo#5109494540499695090"><img src="http://lh3.google.com/earobinson/RuiSNpxINfI/AAAAAAAAATw/8fgQoACqtGg/s400/Screenshot-Propensity-1.jpg" /></a></td>
</tr>
<tr>
<td style="font-family:arial,sans-serif;font-size:11px;text-align:right;">From <a href="http://picasaweb.google.com/earobinson/Propensity">Propensity</a></td>
</tr>
</table>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2007/09/17/propensity-v0121906-now-with-an-icon/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Python vte.Terminal example</title>
		<link>http://www.earobinson.org/2007/09/10/python-vteterminal-example/</link>
		<comments>http://www.earobinson.org/2007/09/10/python-vteterminal-example/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 19:09:35 +0000</pubDate>
		<dc:creator>Edward Andrew Robinson</dc:creator>
				<category><![CDATA[Gnome]]></category>
		<category><![CDATA[Propensity]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>

		<guid isPermaLink="false">http://earobinson.org/?p=43</guid>
		<description><![CDATA[About a week ago while working on propensity, I was trying to add an impeded terminal into the program instead of just sending commands to an xterm. I quickly found out about the VTE Terminal Widget, this is the same widget used by the gnome-terminal. Now while I was able to find a great API, [...]]]></description>
			<content:encoded><![CDATA[<p>About a week ago while working on <a href="http://earobinson.wordpress.com/2007/09/02/propensity-feedback-wanted/">propensity</a>, I was trying to add an impeded terminal into the program instead of just sending commands to an <a href="http://invisible-island.net/xterm/">xterm</a>. I quickly found out about the <a href="http://developer.gnome.org/arch/gnome/widgets/vte.html">VTE Terminal Widget</a>, this is the same widget used by the <a href="http://en.wikipedia.org/wiki/Gnome_Terminal">gnome-terminal</a>. Now while I was able to find a <a href="http://library.gnome.org/devel/vte/unstable/VteTerminal.html"></a><a href="http://library.gnome.org/devel/vte/unstable/VteTerminal.html">great API</a>, I was working in <a href="http://www.python.org/">python</a> not <a href="http://en.wikipedia.org/wiki/C_(programming_language)">C</a> and while I love API&#8217;s when I&#8217;m using a new feature I also find examples to be one of the best ways for me to learn, but even with all my google searching I found it really hard to find a simple python example of the <a href="http://developer.gnome.org/arch/gnome/widgets/vte.html">VTE Terminal Widget</a>. The good news is I now have a simple working example, its a basic gui that lets you enter a command and then that command will be run in a separate terminal window (I&#8217;m not exactly sure why I used two windows now that I think of it.)</p>
<p><a href="http://picasaweb.google.com/earobinson/Public/photo#5108649835635639618"><img src="http://lh6.google.com/earobinson/RuWR9W7rhUI/AAAAAAAAASk/roFjQjT8z9c/s400/Screenshot-TestVirtualTerminal.py-1.jpg" alt="" /></a><br />
<a href="http://picasaweb.google.com/earobinson/Public/photo#5108649839930606930"><img src="http://lh3.google.com/earobinson/RuWR9m7rhVI/AAAAAAAAASs/jmh0wgczHNk/s400/Screenshot-TestVirtualTerminal.py.jpg" alt="" /></a></p>
<p>An so without further ado here is the code (all <a href="http://www.gnu.org/copyleft/gpl.html">GPL</a>). Hope this helps someone in the future.  You can <a href="http://files.earobinson.org/programs/terminal.0.1.0.1844.tar.gz">download the code here</a>, or view it below.</p>
<p><strong>VirtualTerminal.py</strong> (This code could be used in your program)<br />
[sourcecode language="python"]#!/usr/bin/env python<br />
#<br />
#      VirtualTerminal.py<br />
#<br />
#      Copyright 2007 Edward Andrew Robinson &amp;lt;earobinson@gmail&amp;gt;<br />
#<br />
#      This program is free software; you can redistribute it and/or modify<br />
#      it under the terms of the GNU General Public License as published by<br />
#      the Free Software Foundation; either version 2 of the License, or<br />
#      (at your option) any later version.<br />
#<br />
#      This program is distributed in the hope that it will be useful,<br />
#      but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br />
#      GNU General Public License for more details.<br />
#<br />
#      You should have received a copy of the GNU General Public License<br />
#      along with this program; if not, write to the Free Software<br />
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#</p>
<p># Imports<br />
import os<br />
import vte<br />
import gtk<br />
import time</p>
<p>class VirtualTerminal(vte.Terminal):<br />
def __init__(self, log_file = None, history_length = 5, prompt_watch = {}, prompt_auto_reply = True, icon = None):<br />
# Set up terminal<br />
vte.Terminal.__init__(self)</p>
<p>self.history = []<br />
self.history_length = history_length<br />
self.icon = icon<br />
self.last_row_logged = 0<br />
self.log_file = log_file<br />
self.prompt_auto_reply = prompt_auto_reply<br />
self.prompt_watch = prompt_watch</p>
<p>self.connect(&#8216;eof&#8217;, self.run_command_done_callback)<br />
self.connect(&#8216;child-exited&#8217;, self.run_command_done_callback)<br />
self.connect(&#8216;cursor-moved&#8217;, self.contents_changed_callback)</p>
<p>if False:<br />
self.connect(&#8216;char-size-changed&#8217;, self.activate_action, &#8216;char-size-changed&#8217;)<br />
#self.connect(&#8216;child-exited&#8217;, self.activate_action, &#8216;child-exited&#8217;)<br />
self.connect(&#8216;commit&#8217;, self.activate_action, &#8216;commit&#8217;)<br />
self.connect(&#8216;contents-changed&#8217;, self.activate_action, &#8216;contents-changed&#8217;)<br />
#self.connect(&#8216;cursor-moved&#8217;, self.activate_action, &#8216;cursor-moved&#8217;)<br />
self.connect(&#8216;decrease-font-size&#8217;, self.activate_action, &#8216;decrease-font-size&#8217;)<br />
self.connect(&#8216;deiconify-window&#8217;, self.activate_action, &#8216;deiconify-window&#8217;)<br />
self.connect(&#8216;emulation-changed&#8217;, self.activate_action, &#8216;emulation-changed&#8217;)<br />
self.connect(&#8216;encoding-changed&#8217;, self.activate_action, &#8216;encoding-changed&#8217;)<br />
#self.connect(&#8216;eof&#8217;, self.activate_action, &#8216;eof&#8217;)<br />
self.connect(&#8216;icon-title-changed&#8217;, self.activate_action, &#8216;icon-title-changed&#8217;)<br />
self.connect(&#8216;iconify-window&#8217;, self.activate_action, &#8216;iconify-window&#8217;)<br />
self.connect(&#8216;increase-font-size&#8217;, self.activate_action, &#8216;increase-font-size&#8217;)<br />
self.connect(&#8216;lower-window&#8217;, self.activate_action, &#8216;lower-window&#8217;)<br />
self.connect(&#8216;maximize-window&#8217;, self.activate_action, &#8216;maximize-window&#8217;)<br />
self.connect(&#8216;move-window&#8217;, self.activate_action, &#8216;move-window&#8217;)<br />
self.connect(&#8216;raise-window&#8217;, self.activate_action, &#8216;raise-window&#8217;)<br />
self.connect(&#8216;refresh-window&#8217;, self.activate_action, &#8216;refresh-window&#8217;)<br />
self.connect(&#8216;resize-window&#8217;, self.activate_action, &#8216;resize-window&#8217;)<br />
self.connect(&#8216;restore-window&#8217;, self.activate_action, &#8216;restore-window&#8217;)<br />
self.connect(&#8216;selection-changed&#8217;, self.activate_action, &#8216;selection-changed&#8217;)<br />
self.connect(&#8216;status-line-changed&#8217;, self.activate_action, &#8216;status-line-changed&#8217;)<br />
self.connect(&#8216;text-deleted&#8217;, self.activate_action, &#8216;text-deleted&#8217;)<br />
self.connect(&#8216;text-inserted&#8217;, self.activate_action, &#8216;text-inserted&#8217;)<br />
self.connect(&#8216;text-modified&#8217;, self.activate_action, &#8216;text-modified&#8217;)<br />
self.connect(&#8216;text-scrolled&#8217;, self.activate_action, &#8216;text-scrolled&#8217;)<br />
self.connect(&#8216;window-title-changed&#8217;, self.activate_action, &#8216;window-title-changed&#8217;)</p>
<p>def activate_action(self, action, string):<br />
print &#8216;Action &#8216; + action.get_name() + &#8216; activated &#8216; + str(string)</p>
<p>def capture_text(self,text,text2,text3,text4):<br />
return True</p>
<p>def contents_changed_callback(self, terminal):<br />
&#8221;&#8217;Gets the last line printed to the terminal, it will log<br />
this line using self.log() (if the logger is on, and it will<br />
also prompt this line using self.prompt() if the line needs<br />
prompting&#8221;&#8217;<br />
column,row = self.get_cursor_position()<br />
if self.last_row_logged != row:<br />
off = row-self.last_row_logged<br />
text = self.get_text_range(row-off,0,row-1,-1,self.capture_text)<br />
self.last_row_logged=row<br />
text = text.strip()</p>
<p># Log<br />
self.log(text)</p>
<p># Prompter<br />
self.prompter()</p>
<p>def get_last_line(self):<br />
terminal_text = self.get_text(self.capture_text)<br />
terminal_text = terminal_text.split(&#8216;\\\\n&#8217;)<br />
ii = len(terminal_text) &#8211; 1<br />
while terminal_text[ii] == &#8221;:<br />
ii = ii &#8211; 1<br />
terminal_text = terminal_text[ii]</p>
<p>return terminal_text</p>
<p>def log(self, text):<br />
&#8221;&#8217;if self.log_file is not None the the line will be logged to<br />
self.log_file. This function also stors the info in self.histoy<br />
if self.history_lenght &amp;gt; 0&#8221;&#8217;<br />
if self.log_file != None:<br />
date_string = time.strftime(&#8216;[%d %b %Y %H:%M:%S] &#8216;, time.localtime())<br />
file = open(self.log_file, &#8216;a&#8217;)<br />
file.write(date_string + text + &#8216;\\\\n&#8217;)<br />
file.close</p>
<p># Append to internal history<br />
if self.history_length != 0:<br />
if len(self.history) &amp;gt;= self.history_length:<br />
self.history.pop(0)<br />
self.history.append(text)</p>
<p>def prompter(self):<br />
last_line = self.get_last_line()<br />
if last_line in self.prompt_watch:<br />
if self.prompt_auto_reply == False:<br />
message = &#8221;<br />
for ii in self.prompt_watch[last_line]:<br />
message = message + self.history[self.history_length - 1 - ii]<br />
if self.yes_no_question(message):<br />
self.feed_child(&#8216;Yes\\\\n&#8217;)<br />
# TODO not sure why this is needed twice<br />
self.feed_child(&#8216;Yes\\\\n&#8217;)<br />
else:<br />
self.feed_child(&#8216;No\\\\n&#8217;)<br />
else:<br />
self.feed_child(&#8216;Yes\\\\n&#8217;)</p>
<p>def run_command(self, command_string):<br />
&#8221;&#8217;run_command runs the command_string in the terminal. This<br />
function will only return when self.thred_running is set to<br />
True, this is done by run_command_done_callback&#8221;&#8217;<br />
self.thread_running = True<br />
spaces = &#8221;<br />
for ii in range(80 &#8211; len(command_string) &#8211; 2):<br />
spaces = spaces + &#8216; &#8216;<br />
self.feed(&#8216;$ &#8216; + str(command_string) + spaces)<br />
self.log(&#8216;$ &#8216; + str(command_string) + spaces)</p>
<p>command = command_string.split(&#8216; &#8216;)<br />
pid =  self.fork_command(command=command[0], argv=command, directory=os.getcwd())</p>
<p>while self.thread_running:<br />
#time.sleep(.01)<br />
gtk.main_iteration()</p>
<p>def run_command_done_callback(self, terminal):<br />
&#8221;&#8217;When called this function sets the thread as done allowing<br />
the run_command function to exit&#8221;&#8217;<br />
#print &#8216;child done&#8217;<br />
self.thread_running = False</p>
<p>def yes_no_question(self, message):<br />
message = message.replace(&#8216;\\\\n\\\\n&#8217;, &#8216;[NEWLINE][NEWLINE]&#8216;).replace(&#8216;\\\\n&#8217;, &#8221;).replace(&#8216;[NEWLINE]&#8216;, &#8216;\\\\n&#8217;)</p>
<p>if message.find(&#8216;?&#8217;) == -1:<br />
message = message + &#8216;\\\\n\\\\nDo you want to continue?&#8217;</p>
<p>type=gtk.MESSAGE_QUESTION<br />
if message.lower().find(&#8216;warning&#8217;) != -1:<br />
type=gtk.MESSAGE_WARNING</p>
<p>dialog = gtk.MessageDialog(parent=None, flags=0, type=type, buttons=gtk.BUTTONS_YES_NO, message_format=message)<br />
dialog.set_icon(self.icon)<br />
dialog.show_all()<br />
responce = dialog.run()<br />
dialog.destroy()</p>
<p># Responce == yes<br />
return responce == -8<br />
[/sourcecode]</p>
<p><strong>TestVirtualTerminal.py</strong> Used to actually make the GUIs, this is the program you should run.<br />
[sourcecode language="python"]#!/usr/bin/env python<br />
#<br />
#      TestVirtualTerminal.py<br />
#<br />
#      Copyright 2007 Edward Andrew Robinson &amp;lt;earobinson@gmail&amp;gt;<br />
#<br />
#      This program is free software; you can redistribute it and/or modify<br />
#      it under the terms of the GNU General Public License as published by<br />
#      the Free Software Foundation; either version 2 of the License, or<br />
#      (at your option) any later version.<br />
#<br />
#      This program is distributed in the hope that it will be useful,<br />
#      but WITHOUT ANY WARRANTY; without even the implied warranty of<br />
#      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the<br />
#      GNU General Public License for more details.<br />
#<br />
#      You should have received a copy of the GNU General Public License<br />
#      along with this program; if not, write to the Free Software<br />
#      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.<br />
#</p>
<p>import gtk</p>
<p>from VirtualTerminal import VirtualTerminal</p>
<p>class mainWindow(gtk.Window):<br />
def __init__(self):<br />
gtk.Window.__init__(self)<br />
self.connect(&#8216;destroy&#8217;, lambda w: gtk.main_quit())<br />
self.set_default_size(400, 400)</p>
<p>self.button = gtk.Button(&#8216;press me&#8217;)<br />
self.button.connect(&#8220;clicked&#8221;, self.pressed_callback)</p>
<p>self.command_entry = gtk.Entry()<br />
self.command_entry.set_text(&#8216;python count.py&#8217;)<br />
#self.command_entry.set_text(&#8216;sudo aptitude install gaim-encryption&#8217;)</p>
<p>vbox = gtk.VBox()</p>
<p>self.r = 0</p>
<p>self.add(vbox)</p>
<p>vbox.pack_start(self.command_entry, False)<br />
vbox.pack_start(self.button, True)</p>
<p>self.myTerminal = terminal()</p>
<p>self.show_all()</p>
<p>gtk.main()</p>
<p>def pressed_callback(self, button):<br />
print &#8216;presed&#8217;<br />
column,row = self.myTerminal.terminal.get_cursor_position()<br />
if self.r != row:<br />
off = row-self.r<br />
text = self.myTerminal.terminal.get_text_range(row-off,0,row-1,-1,self.capture_text)<br />
self.r=row<br />
text = text.strip()<br />
print text<br />
self.button.set_sensitive(False)<br />
self.myTerminal.terminal.run_command(self.command_entry.get_text())<br />
self.button.set_sensitive(True)<br />
print &#8216;done&#8217;</p>
<p>def capture_text(self,text,text2,text3,text4):<br />
return True</p>
<p>class terminal(gtk.Window):<br />
def __init__(self):<br />
gtk.Window.__init__(self)<br />
#self.set_title(self.settings.application_name)<br />
self.connect(&#8216;destroy&#8217;, lambda w: gtk.main_quit())</p>
<p>self.terminal = VirtualTerminal()</p>
<p>#self.child_pid = self.terminal.fork_command()</p>
<p>self.add(self.terminal)<br />
self.show_all()</p>
<p>mainWindow()[/sourcecode]</p>
<p><strong>count.py</strong> A little test program but you can run any command you want<br />
[sourcecode language="python"]#!/usr/bin/python</p>
<p>import time</p>
<p>print &#8217;0&#8242;</p>
<p>for ii in range (10):<br />
time.sleep(1)<br />
print ii + 1[/sourcecode]</p>
<p>A special thanks to <a href="http://albertomilone.com/wordpress/">Alberto Milone</a> for all the <a href="http://ubuntuforums.org/showthread.php?t=366720&amp;highlight=python+vte">help he provided me with</a> for this.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.earobinson.org/2007/09/10/python-vteterminal-example/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
	</channel>
</rss>

