<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:blogChannel="http://backend.userland.com/blogChannelModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" version="2.0">
  <channel>
    <title>#.think.in</title>
    <description>learn.create.enjoy</description>
    <link>http://blog.sharpthinking.com.au/</link>
    <docs>http://www.rssboard.org/rss-specification</docs>
    <generator>BlogEngine.NET 1.4.5.0</generator>
    <language>en-Au</language>
    <blogChannel:blogRoll>http://blog.sharpthinking.com.au/opml.axd</blogChannel:blogRoll>
    <blogChannel:blink>http://www.dotnetblogengine.net/syndication.axd</blogChannel:blink>
    <dc:title>#.think.in</dc:title>
    <atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/sharpthinking" /><feedburner:info xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" uri="sharpthinking" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><creativeCommons:license>http://creativecommons.org/licenses/by/2.0/</creativeCommons:license><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">sharpthinking</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><item>
      <title>A new home</title>
      <description>&lt;p&gt;
&lt;font size="0"&gt;I will no longer be posting to #think.in and will now be posting to my personal blog I&amp;#39;ve started building at &lt;a href="http://tarnbarford.net" title="tarnbarford.net"&gt;tarnbarford.net&lt;/a&gt;. I&amp;#39;ve been hinting at doing this for a while and I&amp;#39;m looking forward to being able to post richer content to a much simpler blog. &lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="0"&gt;Much thanks goes to Andrew Brodie who did most of the work getting this site up and running and getting me started blogging. It has been fun. Thanks also to everyone who has stopped by to read my posts and an extra special thanks to those who took the time to leave a comment. I encourage you to come &lt;a href="http://blog.sharpthinking.com.au/admin/Pages/tarnbarford.net" title="check it out"&gt;check out my new site &lt;/a&gt;and let me know what you think.&lt;/font&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;font size="0"&gt;Peace out.&lt;/font&gt;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/bwtfUIWi1VM" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2011/01/14/A-new-home.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2011/01/14/A-new-home.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=f8b2949d-4195-4791-8ff3-ffd74fe358f4</guid>
      <pubDate>Fri, 14 Jan 2011 18:22:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=f8b2949d-4195-4791-8ff3-ffd74fe358f4</pingback:target>
      <slash:comments>13</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=f8b2949d-4195-4791-8ff3-ffd74fe358f4</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2011/01/14/A-new-home.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=f8b2949d-4195-4791-8ff3-ffd74fe358f4</wfw:commentRss>
    </item>
    <item>
      <title>How do you test your applications?</title>
      <description>&lt;p&gt;I've wanted to post about using Selenium and TeamCity to build and test .NET websites on Windows for a while. 
Unfortunatley it hasn't been forthcoming as I only really use Windows/.NET at work these days.&lt;/p&gt;
&lt;p&gt;I decided I would get my shit together today and write, what may be my last post on .NET for a while, 
in response to &lt;a href="http://twitter.com/DavidBurela"&gt;@DavidBurela&lt;/a&gt;'s &lt;a href="http://davidburela.wordpress.com/developer-blog-banter/"&gt;Developer Blog Banter&lt;/a&gt; topic 
&lt;a href="http://davidburela.wordpress.com/2010/10/13/developer-blog-banter-2-how-do-you-test-your-applications/"&gt;"How do you test your applications?"&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I'm going skip unit-testing (which we do and try to get better at), BDD and JavaScript testing (which I would like to do and get better at) and focus on automated browser testing.&lt;/p&gt;
&lt;h2&gt;The Build Process&lt;/h2&gt;
&lt;p&gt;Watching automated test may be fun the first few runs, &lt;a href="http://xkcd.com/303/"&gt;but it won't last long&lt;/a&gt;.
Anyway if you want automated browsers tests, surely you want to automate the automated tests, right? &lt;/p&gt;
&lt;p&gt;The build process is going to need to automate the browser and run the site the browser is browsing.
For this we use IIS which is scriptable with the PowerShell &lt;a href="webadministration"&gt;WebAdministration&lt;/a&gt; module (maybe I will write another post on .NET).&lt;/p&gt;
&lt;p&gt;&lt;img alt="Standard Build Process" src="http://static.sharpthinking.com.au/2010/ui-testing/BuildProcess.png" /&gt;&lt;/p&gt;
&lt;p&gt;The problem with having the UI Test step in this sequential process is it very quickly starts taking ages. 
This sucks; I want feedback as soon as possible.
TeamCity provides feedback after each stage, but we don't get our green light.&lt;/p&gt;
&lt;p&gt;This could be resolved by putting the UI tests in a nightly build, but I think a staged build or build pipeline is usually better.&lt;/p&gt;
&lt;p&gt;The first stage compiles, runs unit tests and produces a deployable website as an artifact, this process is hopefully quite fast. 
If the first stage is successful the next stage in the pipeline is triggered which runs the less timely integration and UI tests.
With a build file that has appropriate build targets setup, this build pipeline can be setup in the TeamCity administration web interface.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Pipeline Build Process" src="http://static.sharpthinking.com.au/2010/ui-testing/BuildProcessPipeline.png" /&gt;&lt;/p&gt;
&lt;p&gt;If you want to get awesome you can also start using &lt;a href="http://seleniumhq.org/download/"&gt;Selenium Grid&lt;/a&gt; to distribute test agents or use a cloud based solution like &lt;a href="http://saucelabs.com/"&gt;SauceLabs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;p&gt;Our automated build process consists of a few tools.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.jetbrains.com/teamcity/"&gt;TeamCity&lt;/a&gt; for our build management and CI server. 
After years of using CC.Net and a very brief and painful exposure to TFS, I love TeamCity. 
I also hear great thing about Hudson.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.nunit.org/"&gt;NUnit&lt;/a&gt; and included &lt;a href="http://www.nunit.org/index.php?p=nunit-console&amp;amp;r=2.4"&gt;NUnit-Console&lt;/a&gt;. It does what I expect a unit-test framework and runner should do.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/0k6kkbsd.aspx"&gt;MSBuild&lt;/a&gt; with the &lt;a href="http://msbuildtasks.tigris.org/"&gt;MSBuild Community Tasks&lt;/a&gt; for our build scripts. 
I have to have some sort of build script to do continuous integration in .NET when not using TFS.
I would like to be using a modern scripting language or DSL instead, but MsBuild is doing the job for now. &lt;/p&gt;
&lt;p&gt;&lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; for our browsers automation tests. It has a recorder, a server which does the brower automation and can be controlled from by
 .NET client library.&lt;/p&gt;
&lt;h2&gt;Creating Tests&lt;/h2&gt;
&lt;p&gt;Selenium IDE is a Firefox plug-in for recording and running tests.&lt;/p&gt;
&lt;p&gt;&lt;img alt="SeleniumIDE" src="http://static.sharpthinking.com.au/2010/ui-testing/SeleniumIDE.png" /&gt;&lt;/p&gt;
&lt;p&gt;Selenium IDE is pretty slick and importantly it's a tool non-developer-testers-types can quickly get their head round and start producing some tests.&lt;/p&gt;
&lt;p&gt;What we really want though, is to have our tests in code so we can run on them on build machine and version them in a repository.&lt;/p&gt;
&lt;h2&gt;Test Scripts&lt;/h2&gt;
&lt;p&gt;&lt;img alt="SeleniumID Export" src="http://static.sharpthinking.com.au/2010/ui-testing/SeleniumIDE_Export.png" /&gt;&lt;/p&gt;
&lt;p&gt;That should generate something like this.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Generated code" src="http://static.sharpthinking.com.au/2010/ui-testing/generatedtest.png" /&gt;&lt;/p&gt;
&lt;p&gt;This generates test files you can pretty much just add to your project as NUnit tests. 
This also means automation tests can be run by the nunit-console just like unit tests.
The .NET client drivers are in the &lt;a href="http://seleniumhq.org/download/"&gt;Selenium Core download&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It may be worth considering if exporting these tests to C# ideal.
Keeping them in the standard html table based form means they can be reloaded into the IDE, 
and there are also alternate languages that you can export to. &lt;/p&gt;
&lt;h2&gt;Selenium Server&lt;/h2&gt;
&lt;p&gt;Selenium server runs on the JVM - Yep, suck it up. TeamCity does too :)&lt;/p&gt;
&lt;p&gt;Any standard version of &lt;a href="http://www.java.com/en/download/inc/windows_upgrade_xpi.jsp"&gt;Java&lt;/a&gt; should be fine.
If you've installed Java correctly it should be in your path and you should be able to type this in a console.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;c:\&amp;gt;java -version

java version "1.6.0_18"
Java(TM) SE Runtime Environment (build 1.6.0_18-b07)
Java HotSpot(TM) Client VM (build 16.0-b13, mixed mode, sharing)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This should output the Java version and build information. If so you have successfully installed a java runtime. Yay!&lt;/p&gt;
&lt;p&gt;You need to download the &lt;a href="http://seleniumhq.org/download/"&gt;Selenium RC&lt;/a&gt; and extract the selenium-server.jar file. &lt;/p&gt;
&lt;p&gt;Once you have Java and Selenium Server you should be able to start the server from the command-line.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;java -jar selenium-server.jar
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Selenium Server as a Service&lt;/h2&gt;
&lt;p&gt;I wanted to run SeleniumRC (the same Jar) as a service. Console windows on servers are not so cool. 
Another, probably better, option is to have the build script itself start and take down the server. 
I went with the service option.&lt;/p&gt;
&lt;p&gt;I found a &lt;a href="http://unintelligible.org/blog/2009/07/28/installing-selenium-rc-as-a-windows-service"&gt;solution&lt;/a&gt; for running a .jar as a service, but it &lt;a href="http://serverfault.com/questions/58025/install-service-in-windows-server-2008"&gt;didn't work on 2k8&lt;/a&gt;. 
Luckily that lead me to the &lt;a href="http://iain.cx/src/nssm/"&gt;Non Sucking Service Manager&lt;/a&gt; which has a great name and worked fine.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Non sucking service manager" src="http://static.sharpthinking.com.au/2010/ui-testing/nssm.png" /&gt;&lt;/p&gt;
&lt;p&gt;The parameters I used were "-Xrs -jar [path/to/selenium-server.jar]"&lt;/p&gt;
&lt;h2&gt;Discussion&lt;/h2&gt;
&lt;p&gt;I went down the path of browsers automation because I was finding none of our other testing efforts, while valuable, 
were not actually testing the website would work.&lt;/p&gt;
&lt;p&gt;Despite our best efforts we were still have problems where a page or an entire site would return a HTTP 500 Server Error for many reasons.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code problems a unit-test would ensure the fix. &lt;/li&gt;
&lt;li&gt;IOC or ORM/Database configuration.&lt;/li&gt;
&lt;li&gt;Compilation error at runtime on a JIT compiled view page.&lt;/li&gt;
&lt;li&gt;JavaScript Ajax. &lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Anyway it happened for all types of reasons. What we needed was an end-to-end integration test. Browser automation provides these tests, and it has helped.&lt;/p&gt;
&lt;p&gt;I actually don't see the tests themselves as being particularly fragile. 
No doubt they can be, but I think it also encourages clean markup.
If the hierarchy or attributes change then UI tests are not the only thing that will break. 
Stylesheets, scripts and some server logic also depend on it. &lt;/p&gt;
&lt;p&gt;While I have seen good value from browser automation testing, 
I feel that mocking out the entire web framework (like &lt;a href="http://farmdev.com/projects/nosegae/"&gt;NoseGAE&lt;/a&gt; for AppEngine) 
or testing at HTTP level (which I think is what &lt;a href="http://github.com/brynary/webrat"&gt;WebRat&lt;/a&gt; does for Rails) can test almost the same thing without involving browser autmation at all.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/LAmaHqiVIng" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/10/15/How-do-you-test-your-applications.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/10/15/How-do-you-test-your-applications.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=7644a3d1-94de-406f-a3a7-50c320385ca3</guid>
      <pubDate>Fri, 15 Oct 2010 13:09:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=7644a3d1-94de-406f-a3a7-50c320385ca3</pingback:target>
      <slash:comments>47</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=7644a3d1-94de-406f-a3a7-50c320385ca3</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/10/15/How-do-you-test-your-applications.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=7644a3d1-94de-406f-a3a7-50c320385ca3</wfw:commentRss>
    </item>
    <item>
      <title>The Mouse is Dead, Long Live the Keyboard</title>
      <description>&lt;p&gt;&lt;em&gt;First up a disclaimer, this is how I like to role. I enjoy it. I'm not saying you shouldn't use a mouse or I'll never use one again.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I spend a lot of time programming on my netbook development environment because I enjoy it. 
Without all the visual tooling I feel can focus on working with the machine, learning its many tongues and tricks.
I've run ubuntu on it for about a year and have learned heaps about linux.
There have been many languages, tools and skills I would not have otherwise been able to learn.&lt;/p&gt;
&lt;p&gt;One thing I don't like about it is using the crappy mouse pad. It has long been a pain point, even doing trivial things.
Recently I saw a tweet by &lt;a href="http://twitter.com/TheColonial"&gt;@TheColonial&lt;/a&gt; listing some mostly unfamiliar names and
adding #themouseisdead. 
This was exciting, I had recently adopted vim and was loving it.&lt;/p&gt;
&lt;p&gt;Last weekend I was a bit under the weather and not thinking clearly enough to write code.
So I used to time to set-up and learn a few new tools.
I put together a powerful, mouse-less development environment on my tiny netbook, 
which I think is pretty fun to use.&lt;/p&gt;
&lt;h2&gt;xmonad&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://xmonad.org"&gt;xmonad&lt;/a&gt; is a great window manager (~1000 lines of haskell) which seems to plug into most X systems. 
There are other ways of managing a windowed environment, I never new existed!
It is all keyboard driven, it works out non-overlapping window layouts, you can move between multiple desktops and move windows between them.&lt;/p&gt;

&lt;p&gt;Here are some typical tasks in a desktop with a few windows using xmonad:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Switch between window layouts, generated by haskell algorithms (mod-space). &lt;/li&gt;
&lt;li&gt;Select between windows on screen (mod-tab). &lt;/li&gt;
&lt;li&gt;Throw the selected window to another desktop (shift-mod-2).&lt;/li&gt;
&lt;li&gt;Change to the desktop (mod-2).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On Ubuntu it installed with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install xmonad
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Which installed its haskell dependencies and configured itself. 
It also added an xmonad session option on the login screen,
I wanted to use this and keep the normal session intact.&lt;/p&gt;

&lt;p&gt;When you start an xmonad session you are presented with a completely empty screen except for a background picture.
You can start terminal session with some keys (mod-shift-enter), but a menu would be nice.&lt;/p&gt;
&lt;h2&gt;dmenu&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://tools.suckless.org/dmenu/"&gt;dmenu&lt;/a&gt; is a generic dynamic menu for X systems, it allows menu items to be selected efficiently with a keyboard.&lt;/p&gt;
&lt;p&gt;It installed with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install dwm-tools
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This adds another session to the login screen, now anything can be opened from the xmonad session by bringing up dmenu (mod-p) and typing the first few letters of the desired application.&lt;/p&gt;
&lt;h2&gt;Vim&lt;/h2&gt;
&lt;p&gt;I'm surprised and a little annoyed I didn't start using it sooner really, it is a very powerful text editor.
I still fumble through it but feel I'm learning to increase my productivity and reduced my frustration working with code.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;sudo apt-get install vim
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now vim is available from the terminal. The vim-tutor is the best place to start, then there is a large ecosystem of plugins.&lt;/p&gt;
&lt;h2&gt;Vimperator&lt;/h2&gt;
&lt;p&gt;Vimperator is a Firefox extension that provides command from the keyboard, with vim idioms.
It provides deep control of firefox, a basic browsing scenario might work like:&lt;/p&gt;
&lt;p&gt;You can open a page in a new tab&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;:tabopen theage.com.au
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then to open a link to a story in a new tab&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;shift-f
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This adds unique two digit numbers to all links. 
Now any link can be opened by typing the digits or the link text.&lt;/p&gt;

&lt;p&gt;To go to the new tab:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;gt
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once read the tab can be deleted&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;d
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;TTYtter&lt;/h2&gt;
&lt;p&gt;Anything typed that doesn't start with "/" is a tweet (the -verify and -slowpost options can help with potential problems that might cause)
The forward slash is used to invoke commands like "whois", "replies", "reply", "dm", "follow", "thread" etc.
It's built on curl, so we need that first.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;apt-get install curl
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then download the &lt;a href="http://www.floodgap.com/software/ttytter/dist1/1.0.04.txt"&gt;perl script&lt;/a&gt; from the website, make it executable and move it to the /usr/bin folder.&lt;/p&gt;

&lt;p&gt;I like everything about this app down to the ascii art in the menus. The dude has some pretty cool stuff including a network of &lt;a href="gopher://gopher.floodgap.com/"&gt;gopher servers&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Vimium&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://vimium.github.com/"&gt;Vimium&lt;/a&gt; is not as powerful as Vimperator, but provides some vim-like keyboard controls for Chrome. Easily installed as a chrome add-in.&lt;/p&gt;
&lt;h2&gt;Rock'n'roll time?&lt;/h2&gt;
&lt;p&gt;I can now manage windows over multiple virtual desktops. 
Use a fast, effective menu to opening applications.
Have extensive control of firefox and most importantly, 
can tweet about it with TTYtter. 
I am excited and looking forward to working with some code.&lt;/p&gt;
&lt;p&gt;My set-up still isn't right yet though; I need a status bar and decent start script (the plain xmonad session just a blank canvas, an internet connection, battery power monitor and a clock would be useful). 
I'm going to try &lt;a href="http://sites.google.com/site/gotmor/dzen"&gt;dzen&lt;/a&gt; for this.&lt;/p&gt;

&lt;p&gt;And my keyboard skills on the special keys is way worse than than I'd like it to be. 
The best way to fix that is to keep my hands on the keyboard, right?&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Finally thanks to all the people responsible for the OSS platform, languages and many tools. They are a pleasure to use.&lt;/em&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/AuwzIGF7zzc" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/06/16/The-Mouse-is-Dead-Long-Live-the-Keyboard.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/06/16/The-Mouse-is-Dead-Long-Live-the-Keyboard.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=8703a18a-fe58-41fe-b061-6dea7609f57e</guid>
      <pubDate>Wed, 16 Jun 2010 23:40:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=8703a18a-fe58-41fe-b061-6dea7609f57e</pingback:target>
      <slash:comments>175</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=8703a18a-fe58-41fe-b061-6dea7609f57e</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/06/16/The-Mouse-is-Dead-Long-Live-the-Keyboard.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=8703a18a-fe58-41fe-b061-6dea7609f57e</wfw:commentRss>
    </item>
    <item>
      <title>Revisiting dragging and inertia with RxJs</title>
      <description>&lt;p&gt;
I&amp;#39;ve been enjoying spending some time playing with the Reactive Extensions for Javascript and wanted to write about it before I lost my netbook in bar. Sadly this blog makes it difficult present the content and examples together, so before fixing that, I put it &lt;a href="http://static.sharpthinking.com.au/2010/rx/revisiting-dragging-and-inertia-with-rxjs.htm"&gt;here&lt;/a&gt;.&amp;nbsp; 
&lt;/p&gt;
&lt;p&gt;
&amp;nbsp;
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/1kXQmYZM6ds" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/06/07/Revisiting-dragging-and-inertia-with-RxJs.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/06/07/Revisiting-dragging-and-inertia-with-RxJs.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=f8202e9d-2a70-4061-bf64-3721e9b27547</guid>
      <pubDate>Mon, 07 Jun 2010 19:54:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=f8202e9d-2a70-4061-bf64-3721e9b27547</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=f8202e9d-2a70-4061-bf64-3721e9b27547</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/06/07/Revisiting-dragging-and-inertia-with-RxJs.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=f8202e9d-2a70-4061-bf64-3721e9b27547</wfw:commentRss>
    </item>
    <item>
      <title>Map-Reduce on Mongo</title>
      <description>&lt;p&gt;I'm doing a presentation on non-relational databases at &lt;a href="http://www.dddmelbourne.com/"&gt;DDD Melbourne&lt;/a&gt; this weekend where I am going to demonstrate a map-reduce example with MongoDB and server side Javascript. I've been interested in both independently recently and it's been fun getting them to working together with some Javascript TDD to boot.&lt;/p&gt;
&lt;p&gt;I needed a good example to demonstrate map-reduce and decided finding word occurrences across a series of documented seemed a simple enough scenario that is suited to being solved by a map-reduce query.&lt;/p&gt;
&lt;p&gt;Below is an example of how we might solve this in plain C# &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System&lt;/span&gt;;
&lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Collections.Generic&lt;/span&gt;;

&lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Linq&lt;/span&gt;;
&lt;span style="color: #008000; font-weight: bold"&gt;using&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Text&lt;/span&gt;;

&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;wordCounts&lt;/span&gt; {

    &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;Main&lt;/span&gt;(&lt;span style="color: #B00040"&gt;string&lt;/span&gt;[] args) {

        &lt;span style="color: #408080; font-style: italic"&gt;// Setup some data&lt;/span&gt;

        List&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;&amp;gt; lines = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; List&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;&amp;gt;() 
            { 
              &lt;span style="color: #BA2121"&gt;&amp;quot;Peter Piper picked a peck of pickled peppers&amp;quot;&lt;/span&gt;, 
              &lt;span style="color: #BA2121"&gt;&amp;quot;A peck of pickled peppers Peter Piper picked&amp;quot;&lt;/span&gt;,
              &lt;span style="color: #BA2121"&gt;&amp;quot;If Peter Piper picked a peck of pickled peppers&amp;quot;&lt;/span&gt;,
              &lt;span style="color: #BA2121"&gt;&amp;quot;Where&amp;#39;s the peck of pickled peppers Peter Piper picked?&amp;quot;&lt;/span&gt;

            };

        &lt;span style="color: #408080; font-style: italic"&gt;// select all words, group, count&lt;/span&gt;
        var wordCounts = lines.SelectMany(m =&amp;gt; m.Split())
                              .GroupBy(m =&amp;gt; m.ToLower())
                              .Select(m =&amp;gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; KeyValuePair&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;int&lt;/span&gt;&amp;gt;(m.Key, m.Count()));

        &lt;span style="color: #408080; font-style: italic"&gt;// Print out the results&lt;/span&gt;

        &lt;span style="color: #008000; font-weight: bold"&gt;foreach&lt;/span&gt; (var wordCount &lt;span style="color: #008000; font-weight: bold"&gt;in&lt;/span&gt; wordCounts) 
        {
            Console.WriteLine(&lt;span style="color: #B00040"&gt;string&lt;/span&gt;.Format(&lt;span style="color: #BA2121"&gt;&amp;quot;{0} {1}&amp;quot;&lt;/span&gt;, wordCount.Value, wordCount.Key));     
        }
    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;This prints each different word in all the lines and the number of the times it occurs. The collection of strings is isomorphic to a collection of documents in the MongoDB for this example.&lt;/p&gt;

&lt;p&gt;The SelectMany flattens lists of words from each line to a single list of words and the Group provides keys for each word, this is very similar to what the map function in the map-reduce query does.&lt;/p&gt;
&lt;p&gt;The Select function is similar to the reduce function, but as we will see some additional considerations need to be made to allow it to be distributed. &lt;/p&gt;
&lt;p&gt;I saw a &lt;a href="http://ayende.com/Blog/archive/2010/03/14/map-reduce-ndash-a-visual-explanation.aspx"&gt;good diagram&lt;/a&gt; ayande published on his blog but I didn't understand why he had multiple instance of the same document being mapped. &lt;/p&gt;
&lt;p&gt;I created my own low key diagram to help demonstrate how a functional map-reduce could be distributed. The diagram shows the initial items can be split in half and reduced completely independently. This is interesting as it means our query can be distributed, but it also means we have to handle reducing a little differently.&lt;/p&gt;
&lt;p&gt;It's also worth noting that this example shows a balanced tree, but it could be unbalanced and even introduce some redundancy.&lt;/p&gt;
&lt;div&gt;
&lt;img src="http://static.sharpthinking.com.au/2010/map-reduce-example.png" width="500px"/&gt;
&lt;/div&gt;

&lt;p&gt;MongoDB allows clients to send JavaScript map and reduce functions that will get eval'd and run on the server. Here is the map function.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; wordMap() {

    &lt;span style="color: #408080; font-style: italic"&gt;// try find words in document text&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; words &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;this&lt;/span&gt;.text.match(&lt;span style="color: #BB6688"&gt;/\w+/g&lt;/span&gt;);

    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (words &lt;span style="color: #666666"&gt;===&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;null&lt;/span&gt;) { 
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt;;
    }

    &lt;span style="color: #408080; font-style: italic"&gt;// loop every word in the document &lt;/span&gt;

    &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; (&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; i &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;0&lt;/span&gt;; i &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt; words.length; i&lt;span style="color: #666666"&gt;++&lt;/span&gt;) {
        &lt;span style="color: #408080; font-style: italic"&gt;// emit every word, with count of one&lt;/span&gt;

        emit(words[i], { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; });
    }

}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;The misunderstood Javascript "this" will be the context from which the function is called. Mongo will call function each document in the collection we are querying, and we can call it from a test context. Unlike the SelectMany the map function doesn't return a list, instead it calls an emit function which it expects to be defined.&lt;/p&gt;
&lt;p&gt;We can write unit tests for this function by calling the function from a test mock context, calling a mock emit function (using Javascript as our mocking framework, wow).&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;eval&lt;/span&gt;(loadFile(&lt;span style="color: #BA2121"&gt;&amp;quot;src/js/wordMap.js&amp;quot;&lt;/span&gt;));


&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; emit;
&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; results;
&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; context;

testCases(test,

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; setUp() {
        emit &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; (key, value) { 
            results.push({ key &lt;span style="color: #666666"&gt;:&lt;/span&gt; key, value &lt;span style="color: #666666"&gt;:&lt;/span&gt; value });
        };
        context &lt;span style="color: #666666"&gt;=&lt;/span&gt; { text &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;&amp;quot;&lt;/span&gt;, map &lt;span style="color: #666666"&gt;:&lt;/span&gt; wordMap };
        results &lt;span style="color: #666666"&gt;=&lt;/span&gt; []; 
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; empty_string_emits_nothing() {
        context.text &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        context.map();
        assert.that(results.length, eq(&lt;span style="color: #666666"&gt;0&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; single_word_emits_single_word() {
        context.text &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;findme&amp;quot;&lt;/span&gt;;
        context.map();
        assert.that(results.length, eq(&lt;span style="color: #666666"&gt;1&lt;/span&gt;));
        assert.that(results[&lt;span style="color: #666666"&gt;0&lt;/span&gt;].key, eq(&lt;span style="color: #BA2121"&gt;&amp;quot;findme&amp;quot;&lt;/span&gt;));
        assert.that(results[&lt;span style="color: #666666"&gt;0&lt;/span&gt;].value.count, eq(&lt;span style="color: #666666"&gt;1&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; two_different_words_emits_twice() {
        context.text &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;for bar&amp;quot;&lt;/span&gt;;
        context.map();
        assert.that(results.length, eq(&lt;span style="color: #666666"&gt;2&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; two_same_words_emits_twice() {
        context.text &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;test test&amp;quot;&lt;/span&gt;;
        context.map();
        assert.that(results.length, eq(&lt;span style="color: #666666"&gt;2&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; tearDown() {
    }
);

&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;The reduce function must reduce a list of a chosen type to a single value of that same type; it must be transitive so it doesn't matter how the mapped items are grouped.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; wordReduce(key, values) {
        &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; total &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;0&lt;/span&gt;;
        &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; (&lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; i &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #666666"&gt;0&lt;/span&gt;; i &lt;span style="color: #666666"&gt;&amp;lt;&lt;/span&gt; values.length; i&lt;span style="color: #666666"&gt;++&lt;/span&gt;) {
            total &lt;span style="color: #666666"&gt;+=&lt;/span&gt; values[i].count;
        }
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; total };
    }

&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;Similarly we can test this method does exactly what we expect it to. &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000"&gt;eval&lt;/span&gt;(loadFile(&lt;span style="color: #BA2121"&gt;&amp;quot;src/js/wordReduce.js&amp;quot;&lt;/span&gt;));

testCases(test,

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; reduce_one_items_returns_count_of_one() {
        &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; result &lt;span style="color: #666666"&gt;=&lt;/span&gt; wordReduce(&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, [{ count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }]);
        assert.that(result.count, eq(&lt;span style="color: #666666"&gt;1&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; reduce_multiple_items_returns_item_count() {
        &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; result &lt;span style="color: #666666"&gt;=&lt;/span&gt; wordReduce(&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, [{ count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }, { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }, { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }]);
        assert.that(result.count, eq(&lt;span style="color: #666666"&gt;3&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; reduce_sums_counts() {
        &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; result &lt;span style="color: #666666"&gt;=&lt;/span&gt; wordReduce(&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, [{ count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;2&lt;/span&gt; }, { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;3&lt;/span&gt; }]);
        assert.that(result.count, eq(&lt;span style="color: #666666"&gt;5&lt;/span&gt;));
    },

    &lt;span style="color: #008000; font-weight: bold"&gt;function&lt;/span&gt; reduce_is_transitive() {
        &lt;span style="color: #008000; font-weight: bold"&gt;var&lt;/span&gt; result &lt;span style="color: #666666"&gt;=&lt;/span&gt; wordReduce(&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, [{ count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }].concat(
                        wordReduce(&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;, [{ count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }, { count &lt;span style="color: #666666"&gt;:&lt;/span&gt; &lt;span style="color: #666666"&gt;1&lt;/span&gt; }]
                     ));
        assert.that(result.count, eq(&lt;span style="color: #666666"&gt;3&lt;/span&gt;));
    }
);

&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;I'm using &lt;a href="http://www.mozilla.org/rhino/"&gt;Rhino&lt;/a&gt; to run the Javascript so I used &lt;a href="http://code.google.com/p/rhinounit/"&gt;RhinoUnit&lt;/a&gt; as a test runner as it also uses the JVM and runs as an ANT scriptdef task, the setup was pretty painless. Here are the relevant ANT script sections&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;scriptdef&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;rhinounit&amp;quot;&lt;/span&gt;

           &lt;span style="color: #7D9029"&gt;src=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;lib/rhinoUnitAnt.js&amp;quot;&lt;/span&gt;
           &lt;span style="color: #7D9029"&gt;language=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;javascript&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;attribute&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;options&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;attribute&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;ignoredglobalvars&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;

    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;attribute&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;haltOnFirstFailure&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;attribute&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;rhinoUnitUtilPath&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;element&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;fileset&amp;quot;&lt;/span&gt; &lt;span style="color: #7D9029"&gt;type=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;fileset&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/scriptdef&amp;gt;&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;target&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;javascript-tests&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;rhinounit&lt;/span&gt; &lt;span style="color: #7D9029"&gt;options=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;{verbose:true, stackTrace:true}&amp;quot;&lt;/span&gt; 
               &lt;span style="color: #7D9029"&gt;haltOnFirstFailure=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;false&amp;quot;&lt;/span&gt; 
               &lt;span style="color: #7D9029"&gt;rhinoUnitUtilPath=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;lib/rhinoUnitUtil.js&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;

        &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;fileset&lt;/span&gt; &lt;span style="color: #7D9029"&gt;dir=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;&amp;gt;&lt;/span&gt;
            &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;include&lt;/span&gt; &lt;span style="color: #7D9029"&gt;name=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;*.js&amp;quot;&lt;/span&gt;&lt;span style="color: #008000; font-weight: bold"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/fileset&amp;gt;&lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/rhinounit&amp;gt;&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;&amp;lt;/target&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
The word count example recreated in Mongo using a Python client and passing the map/reduce functions to the server.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pymongo&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Connection;
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pymongo.code&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Code;


&lt;span style="color: #408080; font-style: italic"&gt;# open connection and connect to &amp;#39;ddd&amp;#39; database&lt;/span&gt;
connection &lt;span style="color: #666666"&gt;=&lt;/span&gt; Connection()
db &lt;span style="color: #666666"&gt;=&lt;/span&gt; connection&lt;span style="color: #666666"&gt;.&lt;/span&gt;ddd

&lt;span style="color: #408080; font-style: italic"&gt;# remove any existing data&lt;/span&gt;
db&lt;span style="color: #666666"&gt;.&lt;/span&gt;drop_collection(&lt;span style="color: #BA2121"&gt;&amp;quot;messages&amp;quot;&lt;/span&gt;)


&lt;span style="color: #408080; font-style: italic"&gt;# insert some data&lt;/span&gt;
lines &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;open&lt;/span&gt;(&lt;span style="color: #BA2121"&gt;&amp;quot;data/peter_piper.txt&amp;quot;&lt;/span&gt;)&lt;span style="color: #666666"&gt;.&lt;/span&gt;readlines();

&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; line &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; lines:
    db&lt;span style="color: #666666"&gt;.&lt;/span&gt;messages&lt;span style="color: #666666"&gt;.&lt;/span&gt;insert( { &lt;span style="color: #BA2121"&gt;&amp;quot;text&amp;quot;&lt;/span&gt; : line } )


&lt;span style="color: #408080; font-style: italic"&gt;# load map and reduce functions&lt;/span&gt;
&lt;span style="color: #008000"&gt;map&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; Code(&lt;span style="color: #008000"&gt;open&lt;/span&gt;(&lt;span style="color: #BA2121"&gt;&amp;quot;src/js/wordMap.js&amp;quot;&lt;/span&gt;,&lt;span style="color: #BA2121"&gt;&amp;quot;r&amp;quot;&lt;/span&gt;)&lt;span style="color: #666666"&gt;.&lt;/span&gt;read())
&lt;span style="color: #008000"&gt;reduce&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; Code(&lt;span style="color: #008000"&gt;open&lt;/span&gt;(&lt;span style="color: #BA2121"&gt;&amp;quot;src/js/wordReduce.js&amp;quot;&lt;/span&gt;,&lt;span style="color: #BA2121"&gt;&amp;quot;r&amp;quot;&lt;/span&gt;)&lt;span style="color: #666666"&gt;.&lt;/span&gt;read())


&lt;span style="color: #408080; font-style: italic"&gt;# run the map-reduce query&lt;/span&gt;
result &lt;span style="color: #666666"&gt;=&lt;/span&gt; db&lt;span style="color: #666666"&gt;.&lt;/span&gt;messages&lt;span style="color: #666666"&gt;.&lt;/span&gt;map_reduce(&lt;span style="color: #008000"&gt;map&lt;/span&gt;, &lt;span style="color: #008000"&gt;reduce&lt;/span&gt;)

&lt;span style="color: #408080; font-style: italic"&gt;# print the results    &lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; doc &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; result&lt;span style="color: #666666"&gt;.&lt;/span&gt;find():
    &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; doc[&lt;span style="color: #BA2121"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;][&lt;span style="color: #BA2121"&gt;&amp;quot;count&amp;quot;&lt;/span&gt;],doc[&lt;span style="color: #BA2121"&gt;&amp;quot;_id&amp;quot;&lt;/span&gt;]

&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;And it worked! I'd like to run the query on a larger result-set, but there isn't much point on this tiny low-spec'd netbook.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/2j0txZ4uMoc" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/05/12/Map-Reduce-on-Mongo.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/05/12/Map-Reduce-on-Mongo.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=f5a7b4d1-5cd4-4f12-b8cd-c91cc5e2b4b4</guid>
      <pubDate>Wed, 12 May 2010 19:00:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=f5a7b4d1-5cd4-4f12-b8cd-c91cc5e2b4b4</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=f5a7b4d1-5cd4-4f12-b8cd-c91cc5e2b4b4</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/05/12/Map-Reduce-on-Mongo.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=f5a7b4d1-5cd4-4f12-b8cd-c91cc5e2b4b4</wfw:commentRss>
    </item>
    <item>
      <title>DevEvening NoSql/MongoDB Presentation</title>
      <description>&lt;p&gt;The slides and demo I'll show in my NoSql presentation for tomorrows DevEvenings Melbourne ORM Smackdown. I hope to take the time and write a more considered post of my findings and opinions as I've found it very interesting. &lt;/p&gt;
&lt;p&gt;Here is a link to &lt;a href="http://blog.sharpthinking.com.au/file.axd?file=2010%2f4%2fno_sql.odp"&gt;the slides&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First I'll use some Python and the PyMongo module to connect to MongoDB, list databases, insert documents and get them out again. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Python 2.6.4 (r264:75706, Dec  7 2009, 18:45:15) 
[GCC 4.4.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
&amp;gt;&amp;gt;&amp;gt; from pymongo import Connection
&amp;gt;&amp;gt;&amp;gt; connection = Connection()
&amp;gt;&amp;gt;&amp;gt; connection.database_names()
[u'files', u'working', u'demo', u'downloads', u'posts', u'local', u'admin']
&amp;gt;&amp;gt;&amp;gt; db = connection.demo
&amp;gt;&amp;gt;&amp;gt; import datetime
&amp;gt;&amp;gt;&amp;gt; db.messages.insert( { 'author' : 'tarn', 'date': datetime.now(), 'message' : 'Hello Mongo' } )
ObjectId('4bbc4beec73d721445000003')
&amp;gt;&amp;gt;&amp;gt; db.messages.find_one()
{u'date': datetime.datetime(2010, 4, 7, 19, 10, 6, 355000), u'message': u'Hello Mongo', 
u'_id': ObjectId('4bbc4beec73d721445000003'), u'author': u'tarn'}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then have a look at some content I have in the database&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; db = connection.working
&amp;gt;&amp;gt;&amp;gt; db.posts.count()
106
&amp;gt;&amp;gt;&amp;gt; for post in db.posts.find()[:5]:
...     print post["date"],post["title"],"by",post["author"]
... 
2010-01-25 18:06:00 Python Silverlight/Moonlight 2 Xapping by tarn
2010-03-12 13:53:00 Devevenings Presentation - IOC/Unit Testing/Mocking in ASP.NET MVC by tarn
2010-02-17 19:25:00 Revisiting Modal Binding an Interface, now with DictionaryAdapterFactory by tarn
2009-12-02 18:35:00 Creating Silverlight apps in the browser by tarn
2009-10-02 23:08:00 #.think.in infoDose #43 (11th September - 22nd September) by brodie
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;File storage using the GridFS class from the gridfs module. Show some files and then write a file out to the file system.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; from gridfs import GridFS
&amp;gt;&amp;gt;&amp;gt; fs = GridFS(connection.files)
&amp;gt;&amp;gt;&amp;gt; len(fs.list())
116
&amp;gt;&amp;gt;&amp;gt; for file in fs.list()[:5]:
...     print file
... 
post/debugging-ironpython-with-my-excalibur/image.png
post/debugging-ironpython-with-my-excalibur/image_thumb.png
post/devevenings-presentation---iocunit-testingmocking-in-asp.net-mvc/20102f32fdevevening_presentation.pptx
post/devevenings-presentation---iocunit-testingmocking-in-asp.net-mvc/20102f32fguestbook.zip
post/think.in-infodose-40-5th-august---16th-august/image.png
&amp;gt;&amp;gt;&amp;gt;
&amp;gt;&amp;gt;&amp;gt; with open('image.png','w') as out_file:
...     with fs.open('post/debugging-ironpython-with-my-excalibur/image.png') as in_file:
...             out_file.write(in_file.read())
...
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now to some C# (mono) and a controller class for a basic web application to view the data. It serves files found in the database, but only sends bach the correct MIME type for "image/png". Lazy.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class HomeController : Controller
{
    BlogRepository _blogRepository;

    public HomeController()
    {
        _blogRepository = new BlogRepository(); 
    }

    public ActionResult Index ()
    {
        ViewData["posts"] = _blogRepository.GetPosts();
        return View ();
    }

    public ActionResult Entry(string id)
    {
        ViewData["post"] = _blogRepository.GetById(id);
        return View ();
    }

    public ActionResult Resource(string slug, string fileName)
    {
        return new FileStreamResult(_blogRepository.GetFile( "post/" + slug + "/" + fileName ), "image/png");
    }

}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a very basic repository that provides the data for the demo application. I did only enough with the C# provider to get it working and try to disconnect my connections. &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;public class BlogRepository
{
    Mongo _mongo;

    public BlogRepository()
    {
        string connstr = ConfigurationManager.AppSettings["connectionString"];
        _mongo = new Mongo(connstr);
    }

    public Stream GetFile(string name)
    {
        try
        {
            _mongo.Connect();
            var db = _mongo["files"];
            var fs = new GridFile(db);
            Stream data = fs.Open(name, FileMode.Open, FileAccess.Read);
            Stream output = new MemoryStream();
            CopyStream(data,output);
            output.Seek(0,SeekOrigin.Begin);
            return output;
        }
        finally
        {
            _mongo.Disconnect();    
        }
    }

    public List&amp;lt;Document&amp;gt; GetPosts()
    {
        try
        {
            _mongo.Connect(); 
            var db = _mongo["working"];
            var posts = db["posts"];
            using(ICursor all = posts.Find(new Document())){
                return all.Documents.ToList();
            }
        }
        finally
        {
            _mongo.Disconnect();
        }
    }

    public Document GetById(string id)
    {   
        try
        {
            _mongo.Connect();
            var db = _mongo["working"];
            var posts = db["posts"];
            Document doc = posts.FindOne( new Document() {{ "_id" , new Oid(id) }} );
            return doc;
        }
        finally
        {
            _mongo.Disconnect();    
        }
    }

    public static void CopyStream(Stream input, Stream output)
    {
        byte[] buffer = new byte[32768];
        while (true)
        {
            int read = input.Read (buffer, 0, buffer.Length);
            if (read &amp;lt;= 0)
                return;
            output.Write (buffer, 0, read);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;So that's where I got for my demo for the DevEvenings ORM Smackdown. No doubt I will continue looking into MongoDB and other object/document databases.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/CiI-7tK6Bvc" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/04/07/DevEvening-NoSqlMongoDB-Presentation.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/04/07/DevEvening-NoSqlMongoDB-Presentation.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=9a71ca56-2cf1-4cc1-bbd7-8de8b3775689</guid>
      <pubDate>Wed, 07 Apr 2010 21:12:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=9a71ca56-2cf1-4cc1-bbd7-8de8b3775689</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=9a71ca56-2cf1-4cc1-bbd7-8de8b3775689</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/04/07/DevEvening-NoSqlMongoDB-Presentation.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=9a71ca56-2cf1-4cc1-bbd7-8de8b3775689</wfw:commentRss>
    </item>
    <item>
      <title>Scraping this blog</title>
      <description>&lt;p&gt;I have created a monster and this post is about killing it off by scraping the contents of this blog into structured Python objects. Sometime later I will convert the HTML content to markdown and download the images and other resources locally. &lt;/p&gt;
&lt;p&gt;I want to put the contents into a ZODB object database to get a feel for working with object database. A greated goal is to migrate the content a new blog engine. I don't want to go into why I felt I need to scrape it or why I want to migrate to another blog engine as it's depressing. &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Moving on, I wanted to put the content into these classes  &lt;br /&gt;
&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Post&lt;/span&gt;():
    title &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;

    content &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    date &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    tags &lt;span style="color: #666666"&gt;=&lt;/span&gt; []
    comments &lt;span style="color: #666666"&gt;=&lt;/span&gt; []


&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Comment&lt;/span&gt;():
    content &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    author &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
    date &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;

    website &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;#39;&amp;#39;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;The scraping code is not elegant but was quite fun to write as I could write it all from an interactive console session. I found BeautifulSoup was fantastic in making HTML into something that was easy to work with, although I would have liked to have used jQuery/CSS style selectors.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;BeautifulSoup&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; BeautifulSoup

&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;datetime&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; datetime
&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;urllib2&lt;/span&gt; 
&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;re&lt;/span&gt;

&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;ParseComment&lt;/span&gt;(soup):
    comment &lt;span style="color: #666666"&gt;=&lt;/span&gt; Comment()
    comment&lt;span style="color: #666666"&gt;.&lt;/span&gt;author &lt;span style="color: #666666"&gt;=&lt;/span&gt; soup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;first()&lt;span style="color: #666666"&gt;.&lt;/span&gt;string&lt;span style="color: #666666"&gt;.&lt;/span&gt;strip
    content &lt;span style="color: #666666"&gt;=&lt;/span&gt; soup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;content&amp;quot;&lt;/span&gt;})
    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; content:
        comment&lt;span style="color: #666666"&gt;.&lt;/span&gt;content &lt;span style="color: #666666"&gt;=&lt;/span&gt; content&lt;span style="color: #666666"&gt;.&lt;/span&gt;prettify()
    website &lt;span style="color: #666666"&gt;=&lt;/span&gt; soup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;first()    
    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; website&lt;span style="color: #666666"&gt;.&lt;/span&gt;has_key(&lt;span style="color: #BA2121"&gt;&amp;#39;href&amp;#39;&lt;/span&gt;):
        comment&lt;span style="color: #666666"&gt;.&lt;/span&gt;website &lt;span style="color: #666666"&gt;=&lt;/span&gt; soup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;author&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;first()[&lt;span style="color: #BA2121"&gt;&amp;#39;href&amp;#39;&lt;/span&gt;]
    r &lt;span style="color: #666666"&gt;=&lt;/span&gt; re&lt;span style="color: #666666"&gt;.&lt;/span&gt;compile(&lt;span style="color: #BA2121"&gt;&amp;#39;\d*/\d*/\d* \d*.\d*&amp;#39;&lt;/span&gt;)    
    date &lt;span style="color: #666666"&gt;=&lt;/span&gt; r&lt;span style="color: #666666"&gt;.&lt;/span&gt;findall(soup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;p&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;date&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;renderContents())[&lt;span style="color: #666666"&gt;0&lt;/span&gt;]
    comment&lt;span style="color: #666666"&gt;.&lt;/span&gt;date &lt;span style="color: #666666"&gt;=&lt;/span&gt; datetime&lt;span style="color: #666666"&gt;.&lt;/span&gt;strptime(date,&lt;span style="color: #BA2121"&gt;&amp;#39;&lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%d&lt;/span&gt;&lt;span style="color: #BA2121"&gt;/%m/%Y %H:%M&amp;#39;&lt;/span&gt;)
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; comment


&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;ParsePost&lt;/span&gt;(postSoup):
    post &lt;span style="color: #666666"&gt;=&lt;/span&gt; Post()    
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;title &lt;span style="color: #666666"&gt;=&lt;/span&gt;  postSoup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:re&lt;span style="color: #666666"&gt;.&lt;/span&gt;compile(&lt;span style="color: #BA2121"&gt;&amp;#39;posthead.*&amp;#39;&lt;/span&gt;)})&lt;span style="color: #666666"&gt;.&lt;/span&gt;string
    &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;title
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;content &lt;span style="color: #666666"&gt;=&lt;/span&gt; postSoup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;, {&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;entry&amp;quot;&lt;/span&gt;})
    date &lt;span style="color: #666666"&gt;=&lt;/span&gt; postSoup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;descr&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;contents[&lt;span style="color: #666666"&gt;0&lt;/span&gt;][:&lt;span style="color: #666666"&gt;-4&lt;/span&gt;]
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;date &lt;span style="color: #666666"&gt;=&lt;/span&gt; datetime&lt;span style="color: #666666"&gt;.&lt;/span&gt;strptime(date,&lt;span style="color: #BA2121"&gt;&amp;#39;%B &lt;/span&gt;&lt;span style="color: #BB6688; font-weight: bold"&gt;%d&lt;/span&gt;&lt;span style="color: #BA2121"&gt;, %Y %H:%M&amp;#39;&lt;/span&gt;)
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;author &lt;span style="color: #666666"&gt;=&lt;/span&gt; postSoup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;class&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;descr&amp;quot;&lt;/span&gt;})&lt;span style="color: #666666"&gt;.&lt;/span&gt;first()&lt;span style="color: #666666"&gt;.&lt;/span&gt;string
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;tags &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;map&lt;/span&gt;(&lt;span style="color: #008000; font-weight: bold"&gt;lambda&lt;/span&gt; x: x&lt;span style="color: #666666"&gt;.&lt;/span&gt;string, postSoup(&lt;span style="color: #BA2121"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;rel&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;tag&amp;quot;&lt;/span&gt;}))
    comments &lt;span style="color: #666666"&gt;=&lt;/span&gt; postSoup&lt;span style="color: #666666"&gt;.&lt;/span&gt;find(&lt;span style="color: #BA2121"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;,{&lt;span style="color: #BA2121"&gt;&amp;quot;id&amp;quot;&lt;/span&gt;:&lt;span style="color: #BA2121"&gt;&amp;quot;commentlist&amp;quot;&lt;/span&gt;})(&lt;span style="color: #BA2121"&gt;&amp;#39;div&amp;#39;&lt;/span&gt;)
    post&lt;span style="color: #666666"&gt;.&lt;/span&gt;comments &lt;span style="color: #666666"&gt;=&lt;/span&gt; [ParseComment(commentSoup) &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; commentSoup &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; comments]
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; post


&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;DownloadPost&lt;/span&gt;(url):
    postHtml &lt;span style="color: #666666"&gt;=&lt;/span&gt; urllib2&lt;span style="color: #666666"&gt;.&lt;/span&gt;urlopen(&lt;span style="color: #BA2121"&gt;&amp;#39;http://blog.sharpthinking.com.au/&amp;#39;&lt;/span&gt; &lt;span style="color: #666666"&gt;+&lt;/span&gt; url)&lt;span style="color: #666666"&gt;.&lt;/span&gt;read()
    postSoup &lt;span style="color: #666666"&gt;=&lt;/span&gt; BeautifulSoup(postHtml)
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; ParsePost(postSoup);


&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;GetPosts&lt;/span&gt;():
    page &lt;span style="color: #666666"&gt;=&lt;/span&gt; urllib2&lt;span style="color: #666666"&gt;.&lt;/span&gt;urlopen(&lt;span style="color: #BA2121"&gt;&amp;quot;http://blog.sharpthinking.com.au/archive.aspx&amp;quot;&lt;/span&gt;)
    soup &lt;span style="color: #666666"&gt;=&lt;/span&gt; BeautifulSoup(page)
    postUrls &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;map&lt;/span&gt;(&lt;span style="color: #008000; font-weight: bold"&gt;lambda&lt;/span&gt; x: x[&lt;span style="color: #BA2121"&gt;&amp;#39;href&amp;#39;&lt;/span&gt;], soup(&lt;span style="color: #BA2121"&gt;&amp;#39;a&amp;#39;&lt;/span&gt;, href&lt;span style="color: #666666"&gt;=&lt;/span&gt;re&lt;span style="color: #666666"&gt;.&lt;/span&gt;compile(&lt;span style="color: #BA2121"&gt;&amp;#39;/post/.*&amp;#39;&lt;/span&gt;)))
    &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; [DownloadPost(url) &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; url &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; postUrls[:&lt;span style="color: #666666"&gt;-10&lt;/span&gt;]]

&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;  &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I'm sure there is better way, but this was better than any way I've used previously. Anyway I've done a lot of work untangling the mess I created.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; posts &lt;span style="color: #666666"&gt;=&lt;/span&gt; GetPost()    
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; post &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; posts[:&lt;span style="color: #666666"&gt;5&lt;/span&gt;]:

&lt;span style="color: #666666"&gt;...&lt;/span&gt;     &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;date, post&lt;span style="color: #666666"&gt;.&lt;/span&gt;title
&lt;span style="color: #666666"&gt;...&lt;/span&gt;
&lt;span style="color: #666666"&gt;2010-03-17&lt;/span&gt; &lt;span style="color: #666666"&gt;22&lt;/span&gt;:&lt;span style="color: #666666"&gt;16&lt;/span&gt;:&lt;span style="color: #666666"&gt;00&lt;/span&gt; OMG&lt;span style="color: #666666"&gt;.&lt;/span&gt; It&lt;span style="color: #BA2121"&gt;&amp;#39;s a JavaScript Rhino&lt;/span&gt;

&lt;span style="color: #666666"&gt;2010-03-12&lt;/span&gt; &lt;span style="color: #666666"&gt;13&lt;/span&gt;:&lt;span style="color: #666666"&gt;53&lt;/span&gt;:&lt;span style="color: #666666"&gt;00&lt;/span&gt; Devevenings Presentation &lt;span style="color: #666666"&gt;-&lt;/span&gt; IOC&lt;span style="color: #666666"&gt;/&lt;/span&gt;Unit Testing&lt;span style="color: #666666"&gt;/&lt;/span&gt;Mocking &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; ASP&lt;span style="color: #666666"&gt;.&lt;/span&gt;NET MVC

&lt;span style="color: #666666"&gt;2010-02-20&lt;/span&gt; &lt;span style="color: #666666"&gt;17&lt;/span&gt;:&lt;span style="color: #666666"&gt;18&lt;/span&gt;:&lt;span style="color: #666666"&gt;00&lt;/span&gt; Revisiting Pygments &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; the browser &lt;span style="color: #008000; font-weight: bold"&gt;with&lt;/span&gt; Silverlight, now &lt;span style="color: #008000; font-weight: bold"&gt;with&lt;/span&gt; BackgroundWorker

&lt;span style="color: #666666"&gt;2010-02-17&lt;/span&gt; &lt;span style="color: #666666"&gt;19&lt;/span&gt;:&lt;span style="color: #666666"&gt;25&lt;/span&gt;:&lt;span style="color: #666666"&gt;00&lt;/span&gt; Revisiting Modal Binding an Interface, now &lt;span style="color: #008000; font-weight: bold"&gt;with&lt;/span&gt; DictionaryAdapterFactory
&lt;span style="color: #666666"&gt;2010-02-16&lt;/span&gt; &lt;span style="color: #666666"&gt;20&lt;/span&gt;:&lt;span style="color: #666666"&gt;34&lt;/span&gt;:&lt;span style="color: #666666"&gt;00&lt;/span&gt; Modal Binding an Interface &lt;span style="color: #008000; font-weight: bold"&gt;with&lt;/span&gt; DynamicProxy

&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;I wanted to put the contents into the object database tonight, but I have pickled it to be revisited later.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/KPG-f3gDVKQ" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/03/18/Scraping-this-blog.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/03/18/Scraping-this-blog.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=ba935f61-e498-41a7-984a-53530f3cd258</guid>
      <pubDate>Thu, 18 Mar 2010 23:31:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=ba935f61-e498-41a7-984a-53530f3cd258</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=ba935f61-e498-41a7-984a-53530f3cd258</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/03/18/Scraping-this-blog.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=ba935f61-e498-41a7-984a-53530f3cd258</wfw:commentRss>
    </item>
    <item>
      <title>OMG. It's a JavaScript Rhino</title>
      <description>&lt;p&gt;JavaScript is a slightly flawed language but it's got elegant parts too. All languages do to some degree, it's just JavaScript seems to have both in extremes. Whatever you think of it, history has made it the language for scripting the client-side web. It has become a mainstream language that shows no sign of falling off.&lt;/p&gt;
&lt;p&gt;The excelent book &lt;a href="http://oreilly.com/catalog/9780596517748"&gt;JavaScript: The Good Parts&lt;/a&gt; by Douglas Crockford, working with the jQuery library and learning a little Lisp has lead me to really embrace JavaScript. &lt;/p&gt;
&lt;p&gt;It's no secret that I like programming with interactive consoles and decided I wanted find out if there was an interactive console for JavaScript. A language that only lives inside web browser environment didn't seem right to me. &lt;/p&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en/Rhino"&gt;Rhino&lt;/a&gt; is a JavaScript implementation on the JVM. It has a compiler, a debugger and interactive console.&lt;/p&gt;
&lt;p&gt;To get started you obviously need a version of the JVM. That's not to difficult. On Windows I just downloaded a &lt;a href="http://java.sun.com/javase/downloads/index.jsp"&gt;Sun Java 6 installer&lt;/a&gt;. On my Ubuntu install I installed openjdk but found Rhino didn't work. So I installed sun-java6, which worked.&lt;br /&gt;

&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt-get install sun-java6-bin sun-java6-jre sun-java6-jdk
&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;You can find what version you've installed by running &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ java -version
java version "1.6.0_15"
Java(TM) SE Runtime Environment (build 1.6.0_15-b03)
Java HotSpot(TM) Client VM (build 14.1-b02, mixed mode, sharing)
&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;Excellent. The &lt;a href="https://developer.mozilla.org/en/Rhino"&gt;Rhino&lt;/a&gt; binaries includes js.jar which is needed for the console. Now should be able to run the jar&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ java -jar js.jar

&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;When all goes well this will take you into the Rhino shell &lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Rhino 1.7 release 2 2009 03 22
js&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;We can start playing with the language.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;js&amp;gt; get_counter = function() { var counter = 0; return function() { print(counter); counter++; } };
..
js&amp;gt; counter1 = get_counter();
.. 
js&amp;gt; counter1();
0
js&amp;gt; counter1();
1
js&amp;gt; counter2 = get_counter();
..
js&amp;gt; counter2()
0
js&amp;gt; counter1()
2

&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;Which is cool and there is some of the weirdness&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;js&amp;gt; '5' + 3
53
js&amp;gt; '5' - 2
3
&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;And some interesting features&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;js&amp;gt; parseInt('06')
6
js&amp;gt; parseInt('08')
NaN
js&amp;gt; parseInt('10')
10
js&amp;gt; parseInt('010')
8

&lt;/code&gt;&lt;/pre&gt;
&lt;br/&gt;

&lt;p&gt;I'm looking forward to learning more about writing code in JavaScript.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/paWqE--lHmo" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/03/17/OMG-Its-a-JavaScript-Rhino.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/03/17/OMG-Its-a-JavaScript-Rhino.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=1a854dca-c0bf-496e-8841-29d31eb5e31c</guid>
      <pubDate>Wed, 17 Mar 2010 22:16:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=1a854dca-c0bf-496e-8841-29d31eb5e31c</pingback:target>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=1a854dca-c0bf-496e-8841-29d31eb5e31c</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/03/17/OMG-Its-a-JavaScript-Rhino.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=1a854dca-c0bf-496e-8841-29d31eb5e31c</wfw:commentRss>
    </item>
    <item>
      <title>Devevenings Presentation - IOC/Unit Testing/Mocking in ASP.NET MVC</title>
      <description>&lt;p&gt;
Here are the slides and the mysterious code that was never shown from my &lt;a href="http://www.deveve.net/"&gt;DevEvening&lt;/a&gt; presentation. 
&lt;/p&gt;
&lt;p&gt;
Appologies it&amp;#39;s taken a while to get them up, I was hoping to write a bit of a post about what I covered and some of the discussion that came up. That never happened.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.sharpthinking.com.au/file.axd?file=2010%2f3%2fDevevening_Presentation.pptx"&gt;Devevening_Presentation.pptx
(565.68 kb)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://blog.sharpthinking.com.au/file.axd?file=2010%2f3%2fGuestbook.zip"&gt;Guestbook.zip (3.42 
mb)&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
I think the presentation went well, the group was really good and we got some good discussions happening before being interrupted by delicious paramas of the world.
&lt;/p&gt;
&lt;p&gt;
I&amp;#39;m looking forward to the next meeting, except it appears I&amp;#39;ve signed up to represent NoSql (of which I currently know very little about) in an ORM smackdown. 
&lt;/p&gt;
&lt;p&gt;
That&amp;#39;s what happens when you have meetings at a pub. Anyway it should fun and I&amp;#39;m looking forward to learning enough about NoSql to adequatly represent it in the smackdown.
&lt;/p&gt;
&lt;p&gt;
See ya there. 
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/w7T-EujCfJo" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/03/12/Devevenings-Presentation-IOCUnit-TestingMocking-in-ASPNET-MVC.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/03/12/Devevenings-Presentation-IOCUnit-TestingMocking-in-ASPNET-MVC.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=5dd96b08-4e15-4f1a-baab-d8279dd3c8e3</guid>
      <pubDate>Fri, 12 Mar 2010 13:53:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=5dd96b08-4e15-4f1a-baab-d8279dd3c8e3</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=5dd96b08-4e15-4f1a-baab-d8279dd3c8e3</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/03/12/Devevenings-Presentation-IOCUnit-TestingMocking-in-ASPNET-MVC.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=5dd96b08-4e15-4f1a-baab-d8279dd3c8e3</wfw:commentRss>
    </item>
    <item>
      <title>Revisiting Pygments in the browser with Silverlight, now with BackgroundWorker</title>
      <description>&lt;p&gt;A couple of week ago I &lt;a href="http://blog.sharpthinking.com.au/post/2010/01/31/Pygments-in-the-browser-with-Silverlight.aspx"&gt;blogged&lt;/a&gt; about using &lt;a href="http://www.google.com.au/url?sa=t&amp;amp;source=web&amp;amp;ct=res&amp;amp;cd=1&amp;amp;ved=0CAgQFjAA&amp;amp;url=http%3A%2F%2Fpygments.org%2F&amp;amp;ei=8IV_S8e6CIHUsgPtofz1Aw&amp;amp;usg=AFQjCNGVIxeCqQ14mGgLNznFat5nyACb5Q"&gt;Pygments&lt;/a&gt; to do live syntax highlighting in the browser using Silverlight. &lt;/p&gt;
&lt;p&gt;A major problem with the sample was that it did the pygmentizing on the UI thread which caused most
browsers to become unresponsive. Today I wanted to fix that by using the &lt;a href="http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker%28VS.95%29.aspx"&gt;BackgroundWorker&lt;/a&gt; to do the 
pygmentizing in a background thread.&lt;/p&gt;
&lt;p&gt;Firstly I refactored the pygmentizing into a method that didn't interact with the UI. &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;pygmentize_text&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, text, language):
    &lt;span style="color: #408080; font-style: italic"&gt;# attempt to pygmentize input with current language &lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:

        &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; highlight
        &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments.lexers&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; get_lexer_by_name
        &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments.formatters&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; HtmlFormatter

        lexer &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_lexer_by_name( language, stripall&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #008000"&gt;True&lt;/span&gt;)
        formatter &lt;span style="color: #666666"&gt;=&lt;/span&gt; HtmlFormatter(linenos&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #008000"&gt;False&lt;/span&gt;, cssclass&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;)
        markup &lt;span style="color: #666666"&gt;=&lt;/span&gt; highlight(text, lexer, formatter)

        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; markup

    &lt;span style="color: #008000; font-weight: bold"&gt;except&lt;/span&gt;:

        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Error Generating Markup&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;          &lt;br /&gt;
I then added a method that could be passed into a DoWorkEventHandler. It gets it arguments as a tuple from 
the event arguments and then sets the event argument result with the marked up HTML. The lack of explicit 
typing and use of tuples is good example of how some python idioms can be used when working with the .NET framework.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;worker&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, sender, e):

    &lt;span style="color: #408080; font-style: italic"&gt;# do work off UI thread. &lt;/span&gt;
    e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Result &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pygmentize_text(e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Argument[&lt;span style="color: #666666"&gt;0&lt;/span&gt;],e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Argument[&lt;span style="color: #666666"&gt;1&lt;/span&gt;])
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
The required BackgroundWorker and DoWorkEventHandler can be simply imported from the System.ComponentModel
namespace. &lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.ComponentModel&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; BackgroundWorker, DoWorkEventHandler
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
The BackgroundWorker can then be setup and started. Again it's syntactically nice how the tuple can be created
 and passed as a RunWorkerAsync parameter. &lt;br /&gt;
&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;start_pygmentize&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):

    &lt;span style="color: #408080; font-style: italic"&gt;# update application state&lt;/span&gt;
    &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input_changed &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;False&lt;/span&gt;        
    &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pygmentizing &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;True&lt;/span&gt;
    &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;show_message(&lt;span style="color: #BA2121"&gt;&amp;quot;pygmentizing..&amp;quot;&lt;/span&gt;)

    &lt;span style="color: #408080; font-style: italic"&gt;# get paremters&lt;/span&gt;
    &lt;span style="color: #008000"&gt;input&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;)
    language &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;language&lt;span style="color: #666666"&gt;.&lt;/span&gt;value

    &lt;span style="color: #408080; font-style: italic"&gt;# setup background worker&lt;/span&gt;
    worker &lt;span style="color: #666666"&gt;=&lt;/span&gt; BackgroundWorker()
    worker&lt;span style="color: #666666"&gt;.&lt;/span&gt;DoWork &lt;span style="color: #666666"&gt;+=&lt;/span&gt; DoWorkEventHandler(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;worker)
    worker&lt;span style="color: #666666"&gt;.&lt;/span&gt;RunWorkerCompleted &lt;span style="color: #666666"&gt;+=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;complete

    &lt;span style="color: #408080; font-style: italic"&gt;# start the worker&lt;/span&gt;
    worker&lt;span style="color: #666666"&gt;.&lt;/span&gt;RunWorkerAsync( (&lt;span style="color: #008000"&gt;input&lt;/span&gt;,language) )
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
The completed event handler is the responsible for taking the markup generated by the BackgroundWorker and 
updating the DOM. It also fires off another worker if the source has changed since the 
last worker started.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;complete&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, sender, e):

    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Error:

        &lt;span style="color: #408080; font-style: italic"&gt;# handle errors/exceptions in worker&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;source&lt;span style="color: #666666"&gt;.&lt;/span&gt;SetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;innerHTML&amp;quot;&lt;/span&gt;,e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Error&lt;span style="color: #666666"&gt;.&lt;/span&gt;Message)

    &lt;span style="color: #008000; font-weight: bold"&gt;else&lt;/span&gt;:

        &lt;span style="color: #408080; font-style: italic"&gt;# show the result&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;source&lt;span style="color: #666666"&gt;.&lt;/span&gt;SetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;innerHTML&amp;quot;&lt;/span&gt;,e&lt;span style="color: #666666"&gt;.&lt;/span&gt;Result)

    &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input_changed:

        &lt;span style="color: #408080; font-style: italic"&gt;# input has changed, starty pygmentize again&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;start_pygmentize()

    &lt;span style="color: #008000; font-weight: bold"&gt;else&lt;/span&gt;:

        &lt;span style="color: #408080; font-style: italic"&gt;# no work queued&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pygmentizing &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;False&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;hide_message()
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;      &lt;br /&gt;
The update has made the sample much more responsive, however it appears downloading the Silverlight application is still causing some browers to become a little unresponsive 
which is annoying. I will be interested to find out if this effect can be mitigated.&lt;/p&gt;
&lt;p&gt;The actually pygmentizing processing could possibly be made a little faster by reusing the BackgroundWorker and 
only doing the Pygment imports once but the responsiveness of the browser has improved the 
sample enormously. &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;Check out the updated demo &lt;a href="http://markdown-madness.appspot.com/silverlight-pygments"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/FwxRcfZewao" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/02/20/Revisiting-Pygments-in-the-browser-with-Silverlight-now-with-BackgroundWorker.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/02/20/Revisiting-Pygments-in-the-browser-with-Silverlight-now-with-BackgroundWorker.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=2e3f214f-4930-40d9-953a-ec99be91e110</guid>
      <pubDate>Sat, 20 Feb 2010 17:18:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=2e3f214f-4930-40d9-953a-ec99be91e110</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=2e3f214f-4930-40d9-953a-ec99be91e110</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/02/20/Revisiting-Pygments-in-the-browser-with-Silverlight-now-with-BackgroundWorker.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=2e3f214f-4930-40d9-953a-ec99be91e110</wfw:commentRss>
    </item>
    <item>
      <title>Revisiting Modal Binding an Interface, now with DictionaryAdapterFactory</title>
      <description>&lt;p&gt;After &lt;a href="http://www.sharpthinking.com.au/post/2010/02/16/ModalBinding-an-Interface-with-DynamicProxy.aspx"&gt;my post&lt;/a&gt; yesterday &lt;a href="http://kozmic.pl/"&gt;Krzysztof Kozmic&lt;/a&gt; (&lt;a href="http://twitter.com/kkozmic"&gt;@kkozmic&lt;/a&gt;) &lt;a href="http://twitter.com/kkozmic/statuses/9191658727"&gt;messaged me&lt;/a&gt; saying I should use the &lt;a href="http://www.castleproject.org/components/dictionaryadapter/basics.html"&gt;Castle DictionaryAdapterFactory&lt;/a&gt; instead.&lt;/p&gt;
&lt;p&gt;For the record Krzysztof has a &lt;a href="http://kozmic.pl/archive/2008/12/16/castle-dynamicproxy-tutorial-part-i-introduction.aspx"&gt;great series of posts on DynamicProxy&lt;/a&gt;
and was also very helpful &lt;a href="http://twitter.com/kkozmic/statuses/9134188880"&gt;answering&lt;/a&gt; a specific &lt;a href="http://twitter.com/tarnacious/status/9134151576"&gt;question of mine&lt;/a&gt; yesterday.&lt;/p&gt;
&lt;p&gt;Anyway this is great news! I can do the same thing only referencing &lt;a href="https://sourceforge.net/projects/castleproject/files/DictionaryAdapter%20Component/1.1/CastleDictionaryAdapter-1.1.0.zip/download"&gt;one assembly&lt;/a&gt;.
The DictionaryAdapterFactory returns an object that passes all my tests from yesterday and slides staight into the model binder.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;FakeInterfaceModelBinder&lt;/span&gt; : DefaultModelBinder
{
    &lt;span style="color: #008000; font-weight: bold"&gt;protected&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;override&lt;/span&gt; &lt;span style="color: #B00040"&gt;object&lt;/span&gt; &lt;span style="color: #0000FF"&gt;CreateModel&lt;/span&gt;(ControllerContext controllerContext,
                                          ModelBindingContext bindingContext,
                                          Type modelType)
    {
        Dictionary&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;object&lt;/span&gt;&amp;gt; dictionary = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;object&lt;/span&gt;&amp;gt;();
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; &lt;span style="color: #0000FF"&gt;DictionaryAdapterFactory&lt;/span&gt;().GetAdapter(modelType, dictionary);
    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;It was fun playing with DynamicProxy yesterday, but I did &lt;a href="http://twitter.com/tarnacious/status/9180071375"&gt;think&lt;/a&gt; it might not have been a good idea for a model binder. I'm glad I was pointed in the right direction. &lt;/p&gt;
&lt;p&gt;Cheers Krzysztof!&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/awVSLg_gBHk" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/02/17/Revisiting-Modal-Binding-an-Interface-now-with-DictionaryAdapterFactory.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/02/17/Revisiting-Modal-Binding-an-Interface-now-with-DictionaryAdapterFactory.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=cd2580ae-ba9b-42d3-83cb-32e106756b09</guid>
      <pubDate>Wed, 17 Feb 2010 19:25:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=cd2580ae-ba9b-42d3-83cb-32e106756b09</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=cd2580ae-ba9b-42d3-83cb-32e106756b09</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/02/17/Revisiting-Modal-Binding-an-Interface-now-with-DictionaryAdapterFactory.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=cd2580ae-ba9b-42d3-83cb-32e106756b09</wfw:commentRss>
    </item>
    <item>
      <title>Modal Binding an Interface with DynamicProxy</title>
      <description>&lt;p&gt;&lt;br/&gt;&lt;strong&gt;Update: I posted an &lt;a href="http://www.sharpthinking.com.au/post/2010/02/17/Revisting-Modal-Binding-an-Interface-now-with-DictionaryAdapterFactorye2808f.aspx"&gt;update to this post&lt;/a&gt; which uses the Castle DictionaryAdapterFactory after getting some feedback from this post.&lt;/strong&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;This started while I was playing with some ASP.NET MVC architectural ideas in simple application.&lt;/p&gt;
&lt;p&gt;I wanted to less code than other projects I'd worked on but still have it decoupled and testable.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;At some point I started ranting on twitter (&lt;a href="http://twitter.com/tarnacious/status/9090317966"&gt;1&lt;/a&gt;, &lt;a href="http://twitter.com/tarnacious/status/9090453396"&gt;2&lt;/a&gt;, &lt;a href="http://twitter.com/tarnacious/status/9090509896"&gt;3&lt;/a&gt;)
about wanting a Model Binder that could bind to an interface without needing a concrete type.&lt;/p&gt;
&lt;p&gt;It was quickly &lt;a href="http://twitter.com/craigtech/statuses/9091802953"&gt;pointed out&lt;/a&gt; that what I &lt;em&gt;probably&lt;/em&gt; wanted was a Model Binder that resolves an implementation at runtime with IOC.&lt;/p&gt;
&lt;p&gt;While this was &lt;em&gt;probably&lt;/em&gt; true as I was using already using StuctureMap and it did seemed like a much better idea I still some &lt;a href="http://twitter.com/tarnacious/status/9092355362"&gt;my reservations&lt;/a&gt;.
But mainly &lt;a href="http://twitter.com/tarnacious/status/9133991635"&gt;I wanted to try&lt;/a&gt; using the &lt;a href="http://www.castleproject.org/dynamicproxy/index.html"&gt;Castle DynamicProxy&lt;/a&gt; in an application.&lt;/p&gt;
&lt;p&gt;Clearly the reason the default model binder can't bind to an interface is because it can't create an instance of it.
Thanks to some nice extensibility hooks in the default model binder, all I had to do was override the CreateModel method and return my DynamicProxy instance.
The default model binder then could do the rest of binding work as normal.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;FakeInterfaceModelBinder&lt;/span&gt; : DefaultModelBinder
{
    &lt;span style="color: #008000; font-weight: bold"&gt;protected&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;override&lt;/span&gt; &lt;span style="color: #B00040"&gt;object&lt;/span&gt; &lt;span style="color: #0000FF"&gt;CreateModel&lt;/span&gt;(ControllerContext controllerContext,
                                          ModelBindingContext bindingContext,
                                          Type modelType)
    {
        var generator = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; ProxyGenerator();
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; generator.CreateInterfaceProxyWithoutTarget(modelType,
                &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; &lt;span style="color: #0000FF"&gt;FakePropertiesInterceptor&lt;/span&gt;());
    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;What I needed then was a DynamicProxy object that had properties the behaved like you'd &lt;em&gt;expect&lt;/em&gt; properties to on a normal class.
I came up with some test scenarios I'd expect the proxy to pass using a test interface.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;interface&lt;/span&gt; IDynamicProxyTest
{
    &lt;span style="color: #B00040"&gt;int&lt;/span&gt; Integer { &lt;span style="color: #008000; font-weight: bold"&gt;get&lt;/span&gt;; &lt;span style="color: #008000; font-weight: bold"&gt;set&lt;/span&gt;; }
    &lt;span style="color: #B00040"&gt;string&lt;/span&gt; String { &lt;span style="color: #008000; font-weight: bold"&gt;get&lt;/span&gt;; &lt;span style="color: #008000; font-weight: bold"&gt;set&lt;/span&gt;; }
    DateTime Date { &lt;span style="color: #008000; font-weight: bold"&gt;get&lt;/span&gt;; &lt;span style="color: #008000; font-weight: bold"&gt;set&lt;/span&gt;; }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;I figured the Model Binder would set values on the Dynamic Proxy object and the controller would get the properties back to validate and pass them to the data layer or something like that.
I came up with these tests.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;If_date_has_been_set_then_return_it&lt;/span&gt;()
{
    var date = DateTime.Now;
    var proxy = CreateProxy();
    proxy.Date = date;
    Assert.AreEqual(date, proxy.Date);
}

&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;If_string_has_been_set_then_return_it&lt;/span&gt;()
{
    var proxy = CreateProxy();
    proxy.String = &lt;span style="color: #BA2121"&gt;&amp;quot;Hello Proxy&amp;quot;&lt;/span&gt;;
    Assert.AreEqual(&lt;span style="color: #BA2121"&gt;&amp;quot;Hello Proxy&amp;quot;&lt;/span&gt;, proxy.String);
}

&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;If_int_has_been_set_then_return_it&lt;/span&gt;()
{
    var proxy = CreateProxy();
    proxy.Integer = &lt;span style="color: #666666"&gt;42&lt;/span&gt;;
    Assert.AreEqual(&lt;span style="color: #666666"&gt;42&lt;/span&gt;, proxy.Integer);
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;After implementing these I was &lt;a href="http://twitter.com/tarnacious/status/9133692420"&gt;surprised&lt;/a&gt; to find the default model binder did some gets on the properties before sets.
So I added some more tests.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;For_date_instance_if_value_not_set&lt;/span&gt;()
{
    var proxy = CreateProxy();
    var b = proxy.Date;
}

&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;For_int_instance_if_value_not_set&lt;/span&gt;()
{
    var post = CreateProxy();
    var b = post.Integer;
}

&lt;span style="color: #7D9029"&gt;[Test]&lt;/span&gt;
&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;For_string_instance_if_value_not_set&lt;/span&gt;()
{
    var post = CreateProxy();
    var b = post.String;
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;My property interceptor isn't as clean as I'd like it but did the job passing tests.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;ProperyInterceptor&lt;/span&gt; : IInterceptor
{
    Type _type;

    Dictionary&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;object&lt;/span&gt;&amp;gt; properties;

    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #0000FF"&gt;ProperyInterceptor&lt;/span&gt;(Type type)
    {
        properties = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;object&lt;/span&gt;&amp;gt;();
        _type = type;
        var fields = _type.GetProperties();
    }

    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;Intercept&lt;/span&gt;(IInvocation invocation)
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (IsSetter(invocation))
        {
            properties[Name(invocation)] = invocation.Arguments[&lt;span style="color: #666666"&gt;0&lt;/span&gt;];
        }

        &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (IsGetter(invocation))
        {
            &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (properties.ContainsKey(Name(invocation)))
            {
                invocation.ReturnValue = properties[Name(invocation)];
            }
            &lt;span style="color: #008000; font-weight: bold"&gt;else&lt;/span&gt;
            {
                GetDefaultValue(invocation);
            }
        }
    }

    &lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;GetDefaultValue&lt;/span&gt;(IInvocation invocation)
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;if&lt;/span&gt; (invocation.Method.ReturnType == &lt;span style="color: #008000; font-weight: bold"&gt;typeof&lt;/span&gt;(&lt;span style="color: #B00040"&gt;string&lt;/span&gt;))
        {
            invocation.ReturnValue = &lt;span style="color: #BA2121"&gt;&amp;quot;&amp;quot;&lt;/span&gt;;
        }
        &lt;span style="color: #008000; font-weight: bold"&gt;else&lt;/span&gt;
        {
            invocation.ReturnValue = Activator.CreateInstance(invocation.Method.ReturnType);
        }
    }

    &lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #B00040"&gt;string&lt;/span&gt; &lt;span style="color: #0000FF"&gt;Name&lt;/span&gt;(IInvocation method)
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; method.Method.Name.Substring(&lt;span style="color: #666666"&gt;4&lt;/span&gt;);
    }

    &lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #B00040"&gt;bool&lt;/span&gt; &lt;span style="color: #0000FF"&gt;IsSetter&lt;/span&gt;(IInvocation method)
    {

        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; method.Method.IsSpecialName &amp;amp;&amp;amp;
               method.Method.Name.StartsWith(&lt;span style="color: #BA2121"&gt;&amp;quot;set_&amp;quot;&lt;/span&gt;, StringComparison.Ordinal);

    }
    &lt;span style="color: #008000; font-weight: bold"&gt;private&lt;/span&gt; &lt;span style="color: #B00040"&gt;bool&lt;/span&gt; &lt;span style="color: #0000FF"&gt;IsGetter&lt;/span&gt;(IInvocation method)
    {

        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; method.Method.IsSpecialName &amp;amp;&amp;amp;
               method.Method.Name.StartsWith(&lt;span style="color: #BA2121"&gt;&amp;quot;get_&amp;quot;&lt;/span&gt;, StringComparison.Ordinal);

    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;I used the &lt;a href="http://mokhan.lostechies.com/blogs/jimmy_bogard/archive/2009/03/17/a-better-model-binder.aspx"&gt;better model binder&lt;/a&gt; Jimmy Bogard discusses as it makes
writing binders for derived types and specific "types of type" more straight forward.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;InterfaceBinder&lt;/span&gt; : FakeInterfaceModelBinder, IFilteredModelBinder
{
    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #B00040"&gt;bool&lt;/span&gt; &lt;span style="color: #0000FF"&gt;IsMatch&lt;/span&gt;(Type modelType)
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;return&lt;/span&gt; modelType.IsInterface;
    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;br/&gt;

&lt;p&gt;I did try writing a test which ran my model binder, but found it too much trouble. When I tried it out in a sample web project it worked exactly as I expected.&lt;/p&gt;
&lt;p&gt;While this was fun I don't actually think it's a very good idea.
I was thinking about the interface as DTO's and it breaks down if you want any additional methods on the interface, as they just won't work.
Anyway it's been fun as always and maybe I'll find a good place to use these dynamic proxies in the future.&lt;/p&gt;
&lt;p&gt;Source code with the sample website is all &lt;a href="http://static.sharpthinking.com.au/2010/DynamicProxyModelBinder.zip"&gt;here&lt;/a&gt;.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/05ZAxfeeE4k" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/02/16/ModalBinding-an-Interface-with-DynamicProxy.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/02/16/ModalBinding-an-Interface-with-DynamicProxy.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=3df274ef-7c55-46e1-94d6-81adfdb05eeb</guid>
      <pubDate>Tue, 16 Feb 2010 20:34:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=3df274ef-7c55-46e1-94d6-81adfdb05eeb</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=3df274ef-7c55-46e1-94d6-81adfdb05eeb</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/02/16/ModalBinding-an-Interface-with-DynamicProxy.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=3df274ef-7c55-46e1-94d6-81adfdb05eeb</wfw:commentRss>
    </item>
    <item>
      <title>Scripting your Data Model</title>
      <description>&lt;p&gt;I really like the way you can script your data model from a python REPL console on the Django and the Google App Engine web frameworks.&lt;/p&gt;
&lt;p&gt;For me it is a hands down &lt;a href="http://twitter.com/tarnacious/status/8841617430"&gt;better way&lt;/a&gt; of working with data in your domain model than writing SQL.&lt;/p&gt;
&lt;p&gt;I've since wanted to &lt;a href="http://twitter.com/tarnacious/status/8841455390"&gt;do it in .NET projects&lt;/a&gt; I work on, but it wasn't till I was playing with Castle ActiveRecord yesterday that I decided I'd try it out.&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://martinfowler.com/eaaCatalog/activeRecord.html"&gt;ActiveRecord pattern&lt;/a&gt; is an intuitive way of programming with data persistence, so it's also nice to script with.&lt;/p&gt;
&lt;p&gt;It turned out to be really easy in the project I was playing with. I didn't need to write a single additional line of C# as I already had the configuration decoupled for integration testing with an in-memory SQLite database.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;namespace&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;SimpleBlog.Data&lt;/span&gt;
{
    &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;Configuration&lt;/span&gt; : IBootstrapperTask
    {
        &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;Execute&lt;/span&gt;()
        {
            Configure(GetDefaultSettings());
        }

        &lt;span style="color: #008000; font-weight: bold"&gt;public&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;static&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;void&lt;/span&gt; &lt;span style="color: #0000FF"&gt;Configure&lt;/span&gt;(IDictionary&amp;lt;&lt;span style="color: #B00040"&gt;string&lt;/span&gt;, &lt;span style="color: #B00040"&gt;string&lt;/span&gt;&amp;gt; properties)
        {
            InPlaceConfigurationSource source = &lt;span style="color: #008000; font-weight: bold"&gt;new&lt;/span&gt; InPlaceConfigurationSource();
            source.Add(&lt;span style="color: #008000; font-weight: bold"&gt;typeof&lt;/span&gt;(ActiveRecordBase), properties);
            ActiveRecordStarter.Initialize(source);
            ActiveRecordStarter.RegisterAssemblies(Assembly.GetExecutingAssembly());
        }

        ...
    }
}
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
I then just wrote this little script to help with the configuration, it uses the static method above and passes in the properties for working with a development database.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;clr&lt;/span&gt;
clr&lt;span style="color: #666666"&gt;.&lt;/span&gt;AddReferenceToFile(&lt;span style="color: #BA2121"&gt;&amp;quot;SimpleBlog.Data.dll&amp;quot;&lt;/span&gt;)

&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Collections.Generic&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Dictionary
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;SimpleBlog.Data&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Configuration

&lt;span style="color: #408080; font-style: italic"&gt;# NHibinate Setting&lt;/span&gt;

properties &lt;span style="color: #666666"&gt;=&lt;/span&gt; Dictionary[&lt;span style="color: #008000"&gt;str&lt;/span&gt;,&lt;span style="color: #008000"&gt;str&lt;/span&gt;]()

properties&lt;span style="color: #666666"&gt;.&lt;/span&gt;Add(&lt;span style="color: #BA2121"&gt;&amp;quot;connection.driver_class&amp;quot;&lt;/span&gt;,
               &lt;span style="color: #BA2121"&gt;&amp;quot;NHibernate.Driver.SqlClientDriver&amp;quot;&lt;/span&gt;);

properties&lt;span style="color: #666666"&gt;.&lt;/span&gt;Add(&lt;span style="color: #BA2121"&gt;&amp;quot;dialect&amp;quot;&lt;/span&gt;,
           &lt;span style="color: #BA2121"&gt;&amp;quot;NHibernate.Dialect.MsSql2005Dialect&amp;quot;&lt;/span&gt;);

properties&lt;span style="color: #666666"&gt;.&lt;/span&gt;Add(&lt;span style="color: #BA2121"&gt;&amp;quot;connection.provider&amp;quot;&lt;/span&gt;,
           &lt;span style="color: #BA2121"&gt;&amp;quot;NHibernate.Connection.DriverConnectionProvider&amp;quot;&lt;/span&gt;);

properties&lt;span style="color: #666666"&gt;.&lt;/span&gt;Add(&lt;span style="color: #BA2121"&gt;&amp;quot;connection.connection_string&amp;quot;&lt;/span&gt;,
           &lt;span style="color: #BA2121"&gt;&amp;quot;Data Source=[CONNECTION_STRING]&amp;quot;&lt;/span&gt;); &lt;span style="color: #408080; font-style: italic"&gt;# Add&lt;/span&gt;

properties&lt;span style="color: #666666"&gt;.&lt;/span&gt;Add(&lt;span style="color: #BA2121"&gt;&amp;quot;proxyfactory.factory_class&amp;quot;&lt;/span&gt;,
           &lt;span style="color: #BA2121"&gt;&amp;quot;NHibernate.ByteCode.Castle.ProxyFactoryFactory, NHibernate.ByteCode.Castle&amp;quot;&lt;/span&gt;);

Configuration&lt;span style="color: #666666"&gt;.&lt;/span&gt;Configure(properties)
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
Using the helper script it's pretty easy to get in and start working with the data in the data model.  &lt;br /&gt;
&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;IronPython &lt;span style="color: #666666"&gt;2.6&lt;/span&gt; (&lt;span style="color: #666666"&gt;2.6.10920.0&lt;/span&gt;) on &lt;span style="color: #666666"&gt;.&lt;/span&gt;NET &lt;span style="color: #666666"&gt;2.0.50727.4927&lt;/span&gt;
Type &lt;span style="color: #BA2121"&gt;&amp;quot;help&amp;quot;&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;quot;copyright&amp;quot;&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;quot;credits&amp;quot;&lt;/span&gt; &lt;span style="color: #AA22FF; font-weight: bold"&gt;or&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;license&amp;quot;&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; more information&lt;span style="color: #666666"&gt;.&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;ActiveRecord&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;SimpleBlog.Data.Models&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; &lt;span style="color: #666666"&gt;*&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post &lt;span style="color: #666666"&gt;=&lt;/span&gt; Post()
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;Title &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Working with SQL sucks!&amp;quot;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;Content &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;Try using a scripting langauge instead. It rocks!&amp;quot;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;Author &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #BA2121"&gt;&amp;quot;tarn&amp;quot;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;Save()
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; post&lt;span style="color: #666666"&gt;.&lt;/span&gt;Id
&lt;span style="color: #666666"&gt;2&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; posts &lt;span style="color: #666666"&gt;=&lt;/span&gt; Post()&lt;span style="color: #666666"&gt;.&lt;/span&gt;FindAll()
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;    
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;for&lt;/span&gt; p &lt;span style="color: #AA22FF; font-weight: bold"&gt;in&lt;/span&gt; posts:
&lt;span style="color: #666666"&gt;...&lt;/span&gt;     &lt;span style="color: #008000; font-weight: bold"&gt;print&lt;/span&gt; p&lt;span style="color: #666666"&gt;.&lt;/span&gt;Title, &lt;span style="color: #BA2121"&gt;&amp;quot;by&amp;quot;&lt;/span&gt;, p&lt;span style="color: #666666"&gt;.&lt;/span&gt;Author
&lt;span style="color: #666666"&gt;...&lt;/span&gt;
&lt;span style="color: #BA2121"&gt;Hey, It&amp;#39;s alive by tarn&lt;/span&gt;
&lt;span style="color: #BA2121"&gt;Working with SQL sucks! by tarn&lt;/span&gt;
&lt;span style="color: #666666"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
This is a simple example of a database agnostic data script using your domain model and a powerful scripting language. I think scripting data models like this could add a lot of value in many .NET development scenarios.&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/jGpR1x2VNi0" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/02/14/Scripting-your-Data-Model.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/02/14/Scripting-your-Data-Model.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=45de8ad3-5792-489d-aa09-a9ca4f9dd1e5</guid>
      <pubDate>Sun, 14 Feb 2010 14:13:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=45de8ad3-5792-489d-aa09-a9ca4f9dd1e5</pingback:target>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=45de8ad3-5792-489d-aa09-a9ca4f9dd1e5</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/02/14/Scripting-your-Data-Model.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=45de8ad3-5792-489d-aa09-a9ca4f9dd1e5</wfw:commentRss>
    </item>
    <item>
      <title>Pygments in the browser with Silverlight</title>
      <description>&lt;p&gt;&lt;strong&gt; 17-02-2010 I've updated the demo to use the BackgroundWorker and &lt;a href="http://blog.sharpthinking.com.au/post/2010/02/20/Revisiting-Pygments-in-the-browser-with-Silverlight-now-with-BackgroundWorker.aspx"&gt;posted about the update&lt;/a&gt; &lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I decided it might be fun to try get &lt;a href="http://www.freewisdom.org/projects/python-markdown/"&gt;Python Markdown&lt;/a&gt; and &lt;a href="http://pygments.org/"&gt;Pygments&lt;/a&gt; running in the browser to enhance a markdown preview experience by eliminating the server-side round trips and provide a more responsive preview.&lt;/p&gt;
&lt;p&gt;I managed to get it working entirely in Python but I found the application size excessively large (almost 3mb) and, more annoyingly, it seems to block the entire browser when it initially loads the pygments module. I think there is some sort of silverlight background thread I should be using.&lt;/p&gt;
&lt;p&gt;I think it would work better with &lt;a href="http://code.google.com/p/markdownsharp/"&gt;MarkdownSharp&lt;/a&gt; as pure C# silverlight applications are a fair bit leaner in size and probably run a little quicker than dynamic language applications. But this was for fun and I prefer coding in Python when not working.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt; 17-02-2010 I've since found the MarkdownSharp doesn't do syntax hightlighting &lt;/strong&gt;&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;I ended up having to write so little Python code to get this working that I can include it all here, syntax highlighted with Pygments of course.&lt;/p&gt;
&lt;div class="codehilite"&gt;&lt;pre&gt;&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Windows&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; Application
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Windows.Controls&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; UserControl
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System.Windows.Browser&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; HtmlPage
&lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;System&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; EventHandler

&lt;span style="color: #008000; font-weight: bold"&gt;class&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;App&lt;/span&gt;:

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;__init__&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):

        &lt;span style="color: #408080; font-style: italic"&gt;# load relevent HTML DOM elements&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input &lt;span style="color: #666666"&gt;=&lt;/span&gt; HtmlPage&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetElementById(&lt;span style="color: #BA2121"&gt;&amp;quot;input&amp;quot;&lt;/span&gt;)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;source &lt;span style="color: #666666"&gt;=&lt;/span&gt; HtmlPage&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetElementById(&lt;span style="color: #BA2121"&gt;&amp;quot;output&amp;quot;&lt;/span&gt;)
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;language &lt;span style="color: #666666"&gt;=&lt;/span&gt; HtmlPage&lt;span style="color: #666666"&gt;.&lt;/span&gt;Document&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetElementById(&lt;span style="color: #BA2121"&gt;&amp;quot;lang&amp;quot;&lt;/span&gt;)

        &lt;span style="color: #408080; font-style: italic"&gt;# fire javascript functions to indicate the application has been load&lt;/span&gt;
        HtmlPage&lt;span style="color: #666666"&gt;.&lt;/span&gt;Window&lt;span style="color: #666666"&gt;.&lt;/span&gt;CreateInstance(&lt;span style="color: #BA2121"&gt;&amp;quot;silverlight_loaded&amp;quot;&lt;/span&gt;);

        &lt;span style="color: #408080; font-style: italic"&gt;# pygmentize initial &lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pygmentize()

        &lt;span style="color: #408080; font-style: italic"&gt;# register events&lt;/span&gt;
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input&lt;span style="color: #666666"&gt;.&lt;/span&gt;AttachEvent(&lt;span style="color: #BA2121"&gt;&amp;#39;onkeyup&amp;#39;&lt;/span&gt;, EventHandler( &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;update_handler )) 
        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;language&lt;span style="color: #666666"&gt;.&lt;/span&gt;AttachEvent(&lt;span style="color: #BA2121"&gt;&amp;#39;onchange&amp;#39;&lt;/span&gt;, EventHandler( &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;update_handler ))

        &lt;span style="color: #408080; font-style: italic"&gt;# fire javascript function to indicated the pygments has been loaded&lt;/span&gt;
        HtmlPage&lt;span style="color: #666666"&gt;.&lt;/span&gt;Window&lt;span style="color: #666666"&gt;.&lt;/span&gt;CreateInstance(&lt;span style="color: #BA2121"&gt;&amp;quot;pygments_loaded&amp;quot;&lt;/span&gt;);

   &lt;span style="color: #408080; font-style: italic"&gt;# handle language or input changes by pygmentizing &lt;/span&gt;
    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;update_handler&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;, sender, e):

        &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;pygmentize()

    &lt;span style="color: #008000; font-weight: bold"&gt;def&lt;/span&gt; &lt;span style="color: #0000FF"&gt;pygmentize&lt;/span&gt;(&lt;span style="color: #008000"&gt;self&lt;/span&gt;):
        &lt;span style="color: #008000"&gt;input&lt;/span&gt; &lt;span style="color: #666666"&gt;=&lt;/span&gt; &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;input&lt;span style="color: #666666"&gt;.&lt;/span&gt;GetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;value&amp;quot;&lt;/span&gt;)

        &lt;span style="color: #408080; font-style: italic"&gt;# attempt to pygmentize input with current language &lt;/span&gt;
        &lt;span style="color: #008000; font-weight: bold"&gt;try&lt;/span&gt;:

            &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; highlight
            &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments.lexers&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; get_lexer_by_name
            &lt;span style="color: #008000; font-weight: bold"&gt;from&lt;/span&gt; &lt;span style="color: #0000FF; font-weight: bold"&gt;pygments.formatters&lt;/span&gt; &lt;span style="color: #008000; font-weight: bold"&gt;import&lt;/span&gt; HtmlFormatter

            lexer &lt;span style="color: #666666"&gt;=&lt;/span&gt; get_lexer_by_name(&lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;language&lt;span style="color: #666666"&gt;.&lt;/span&gt;value, stripall&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #008000"&gt;True&lt;/span&gt;)
            formatter &lt;span style="color: #666666"&gt;=&lt;/span&gt; HtmlFormatter(linenos&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #008000"&gt;False&lt;/span&gt;, cssclass&lt;span style="color: #666666"&gt;=&lt;/span&gt;&lt;span style="color: #BA2121"&gt;&amp;quot;source&amp;quot;&lt;/span&gt;)
            markup &lt;span style="color: #666666"&gt;=&lt;/span&gt; highlight(&lt;span style="color: #008000"&gt;input&lt;/span&gt;, lexer, formatter)

            &lt;span style="color: #408080; font-style: italic"&gt;# update the preview&lt;/span&gt;
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;source&lt;span style="color: #666666"&gt;.&lt;/span&gt;SetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;innerHTML&amp;quot;&lt;/span&gt;,markup)

        &lt;span style="color: #008000; font-weight: bold"&gt;except&lt;/span&gt;:

            &lt;span style="color: #408080; font-style: italic"&gt;# indicate there was an error in pygmentize&lt;/span&gt;
            &lt;span style="color: #008000"&gt;self&lt;/span&gt;&lt;span style="color: #666666"&gt;.&lt;/span&gt;source&lt;span style="color: #666666"&gt;.&lt;/span&gt;SetProperty(&lt;span style="color: #BA2121"&gt;&amp;quot;innerHTML&amp;quot;&lt;/span&gt;, &lt;span style="color: #BA2121"&gt;&amp;quot;Error Generating Markup&amp;quot;&lt;/span&gt; )

&lt;span style="color: #408080; font-style: italic"&gt;# Do it!    &lt;/span&gt;
App()
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;br/&gt;
Despite the fact that there isn't much code, the development experience writing silverlight application in python is a bit of a pain in the arse. Granted it's much better with the python console in the browser and better error reporting in most recent SDK, but it still sucks; debugging and logging support is very limited and on some errors the application dies without reporting anything.&lt;/p&gt;
&lt;p&gt;Another difficulty is having to manually copy all the python standard library modules required by the module from the library folders into the application (which explains something about the bloated application size). And even though the code in the demo works, some very similar code from the pygments quick start doesn't.&lt;/p&gt;
&lt;p&gt;Check out the &lt;a href="http://markdown-madness.appspot.com/silverlight-pygments"&gt;live demo&lt;/a&gt;. &lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/DV7UB3yW4aw" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/01/31/Pygments-in-the-browser-with-Silverlight.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/01/31/Pygments-in-the-browser-with-Silverlight.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=007a39a4-c93c-47cb-aa0b-45f29149a554</guid>
      <pubDate>Sun, 31 Jan 2010 23:40:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=007a39a4-c93c-47cb-aa0b-45f29149a554</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=007a39a4-c93c-47cb-aa0b-45f29149a554</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/01/31/Pygments-in-the-browser-with-Silverlight.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=007a39a4-c93c-47cb-aa0b-45f29149a554</wfw:commentRss>
    </item>
    <item>
      <title>Python Silverlight/Moonlight 2 Xapping</title>
      <description>&lt;h2&gt;Context&lt;/h2&gt;
&lt;p&gt;
I was asked do a presentation about developing Silverlight applications to the &lt;a href="http://wiki.python.org/moin/MelbournePUG"&gt;Melbourne Python User-group&lt;/a&gt;. Hell yeah, I love participating in user groups but I obviously needed some content. Unfortunately I didn&amp;#39;t know this local user-group existed, so I&amp;#39;ve haven&amp;#39;t been and have little idea of number of people or the type of stuff they do. This has made preparing relevant content a little challenging, but hopefully I can find the right mix.
&lt;/p&gt;
&lt;p&gt;
Given it&amp;#39;s a Python user-group I felt I might look like a bit of dick rolling with Windows and doing a demo with an environment and .NET tools that some part of the group couldn&amp;#39;t/don&amp;#39;t use. Besides I&amp;#39;ve always felt the Python language support and being able to build on any platform is a very compelling reason for non-.NET developers get into building Silverlight applications. &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
I don&amp;#39;t yet have a Mac (I&amp;#39;m really starting to want one) so my other option was to do the demo on Linux. This presented some difficulties and some opportunities. Firstly I&amp;#39;m still a bit of Linux noob and, although I&amp;#39;m wrapped to have learned a lot in the last couple of weeks there has been some pain and some compromise.
&lt;/p&gt;
&lt;p&gt;
Also Microsoft don&amp;#39;t have a Silverlight browser plug-in for Linux, that support is provided by &lt;a href="http://www.mono-project.com/Moonlight"&gt;Moonlight&lt;/a&gt;. Moonlight is currently at version 2 and although it supports some of the features of Silverlight 3 it doesn&amp;#39;t have the key version 3 features which have really improved the Python development environment (namely IronPython 2.6 support) and application deployment (namely allowing static assemblies that add dynamic languages support to be downloaded independently of the application and therefore cached in the browser).
&lt;/p&gt;
&lt;p&gt;
Plugin and development support on both Mac and Windows is much better, but I&amp;#39;m happy here  sacrificing some of the newer features for inclusivity (and apparently inventing words). We&amp;#39;re targeting Silverlight 2/Moonlight 2 and effectively using no development tools besides a couple of Python scripts which I&amp;#39;ll get onto.
&lt;/p&gt;
&lt;h2&gt;Dynamic Language Silverlight Applications&lt;/h2&gt;
&lt;p&gt;
Silverlight applications are packaged into binary files with an &amp;quot;xap&amp;quot; extension. It turns out these packages are just standard zip files containing all the &amp;quot;stuff&amp;quot; needed by the application. The minimum &amp;quot;stuff&amp;quot; needed in dynamic language application is;
&lt;/p&gt;
&lt;ul&gt;
	&lt;li&gt;
	&lt;p&gt;
	An XML based application manifest file (app.manifest) that describes the target runtime, language type, entry point and some other information needed to run the application  &lt;br /&gt;
	&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
	&lt;p&gt;
	A collection of assemblies that add dynamic language and Python support to the Silverlight runtime.
	&lt;/p&gt;
	&lt;/li&gt;
	&lt;li&gt;
	&lt;p&gt;
	A plain text file containing the your Python script to make the application dance.
	&lt;/p&gt;
	&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;
The package can contain more Python scripts, binary assemblies (which can be imported as modules) and XAML files (which are declarative xml type format typically used for describing user interfaces). Resources such as images and video can also be included in the package but it usually make more sense for the application to download them independently when they are required. 
&lt;/p&gt;
&lt;p&gt;
Serving the application on a webpage is also quite straight forward. An object tag in the html has attributes to tell the browser the URL to download the application and that the Silverlight/Moonlight plugin should be used to run the application.
&lt;/p&gt;
&lt;h2&gt;Helper Scripts and Templates&lt;/h2&gt;
&lt;p&gt;
With a couple of templates and Python scripts we can get started developing Silverlight applications in any environment with that has Python and a browser with a Silverlight/Moonlight plug-in. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;xap.py&lt;/strong&gt;  builds xaps by adding all the files from a source code directory and an assemblies directory into xap file and writing it to disk. 
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;http_server.py&lt;/strong&gt; is the simplest python server which just serves all the files in the current directory on a specified port.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;index.html&lt;/strong&gt; contains the object tag referencing sample.xap and a tiny bit of Javascript to catch, format and display critical error messages that may be caused by the application.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;app.manifest&lt;/strong&gt; is a template with everything needed to describe a typical Python Silverlight application. The template should be fine as-is unless additional assemblies are required or you want to change the script entry point. The template is surprisingly small and undaunting.
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;app.py&lt;/strong&gt; is the script entry point of the application.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;strong&gt;assemblies&lt;/strong&gt; a folder with all the additional assemblies need by the Silverlight runtime to run Python scripts.
&lt;/p&gt;
&lt;h2&gt;Packaging and Running an Application&lt;/h2&gt;
&lt;p&gt;
So you&amp;#39;ve skipped the previous three sections and jumped straight here. I don&amp;#39;t blame you. Here&amp;#39;s how to get going with the script and templates described above.
&lt;/p&gt;
&lt;p&gt;
Download &lt;a href="http://sharpthinking.com.au/file.axd?file=2010%2f1%2fsample_silverlight.zip"&gt;this zip&lt;/a&gt;  containing the assemblies, scripts and templates and unzip it someone, anywhere.
&lt;/p&gt;
&lt;p&gt;
From the terminal/console/command-line go the the place you unzipped it to and run the following command to build an xap.
&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;python xap.py samples.xap assemblies source
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;
A sample.xap should be generated in the same directory.
&lt;/p&gt;
&lt;p&gt;
To fire-up the basic web server just run
&lt;/p&gt;
&lt;pre&gt;
&lt;code&gt;python http_server.py
&lt;/code&gt;
&lt;/pre&gt;
&lt;p&gt;
Then just fire up a browsers and go to http://localhost:8000/ and you should see the sample Silverlight application running.&lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
That&amp;#39;s it. Now you can edit app.py to add functionality and repeat.
&lt;/p&gt;
&lt;h2&gt;Going further&lt;/h2&gt;
&lt;p&gt;
Clearly this a very bare bones approach to development which has very limited development and debugging tools (and a server that can only serve files). There is more tooling out there, but surprisingly litte for Python developers.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://monodevelop.com/Download/What%27s_new_in_MonoDevelop_2.2"&gt;MonoDevelop 2.2&lt;/a&gt;, the Moonlight SKD and Python bindings may provide some sort of IDE support but it&amp;#39;s only just been released, it is not easy to get up and running and I not sure if it even supports packaging or debugging of dynamic language Silverlight applications. 
&lt;/p&gt;
&lt;p&gt;
You might think Visual Studio 2008/2010 would provide significant additional support, but as far as I&amp;#39;m aware only the Windows Debugger which is free in the Windows SDK is much help.
&lt;/p&gt;
&lt;p&gt;
Chiron is a .NET tool provided in the &lt;a href="http://silverlight.net/learn/dynamic-languages/"&gt;Microsoft Dynamic Language SDK&lt;/a&gt; which can package and server XAP&amp;#39;s much like I&amp;#39;ve described above. I found I could compile it on Mono, but couldn&amp;#39;t get it serving files. I don&amp;#39;t think your missing much here.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.kaxaml.com/"&gt;XamlPad&lt;/a&gt; is my favourite free XAML editor, but it doesn&amp;#39;t work on Linux. Blend and Expression Studio are pay to play Microsoft tools for designing and developing XAML. Maybe someone should write a good one in Silverlight.
&lt;/p&gt;
&lt;p&gt;
&lt;a href="http://www.ironpython.com/"&gt;IronPython&lt;/a&gt; can be downloaded and run on Mono.
&lt;/p&gt;
&lt;h2&gt;Some Thoughts&lt;/h2&gt;
&lt;p&gt;
It&amp;#39;s easy to get started writing and deploying Silverlight applications in Python on any platform but I think it&amp;#39;s fair to say the tooling and support is just not there yet. On any platform.
&lt;/p&gt;
&lt;p&gt;
The Silverlight 2/Moonlight implementations of Python are still missing large parts of the Python standard library, which will come as a bit of a shock to Python developers and makes it difficult to import modules that depend on it. Almost the entire Silverlight 2 Base Class Library is accessible through Python but although the Python/.NET integratation is very impressive, working with the BCL does seem to limit the expressivness of the code.    &lt;br /&gt;
&lt;/p&gt;
&lt;p&gt;
Silverlight 3 appears to have some additional built-in support for interacting with the application at runtime through a Python REPL console, it supports IronPython 2.6 (which implements a lot more of the Python standard library) and has additional deployment improvements discussed above. 
&lt;/p&gt;
&lt;h2&gt;Finally&lt;/h2&gt;
&lt;p&gt;
I hope to do another post before the meeting with some examples I&amp;#39;ll be showing, but as always I won&amp;#39;t promise anything (in case I get distracted writing a Socket Server in Erlang I&amp;#39;ve been thinking about). In the mean time I do have some examples on PythonSilverScripting that can be run from the browser.
&lt;/p&gt;
&lt;p&gt;
I&amp;#39;d love to know the tools other people are using to develop Python/Silverlight and thoughts people have of it. If your in Melbourne and your at all interested you should come down to the &lt;a href="http://wiki.python.org/moin/MelbournePUG"&gt;meeting&lt;/a&gt;.
&lt;/p&gt;
&lt;p&gt;
&lt;em&gt;Update 26/01/10: Updated scripts and templates to work in Windows&lt;/em&gt;
&lt;/p&gt;
&lt;p&gt;
Here is a &lt;a href="http://sharpthinking.com.au/file.axd?file=2010%2f1%2fsample_silverlight.zip"&gt;zip&lt;/a&gt; with the bits and pieces.
&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/sharpthinking/~4/63iGVYScRhc" height="1" width="1"/&gt;</description>
      <link>http://blog.sharpthinking.com.au/post/2010/01/25/Python-SilverlightMoonlight-2-Xapping.aspx</link>
      <author>tarn</author>
      <comments>http://blog.sharpthinking.com.au/post/2010/01/25/Python-SilverlightMoonlight-2-Xapping.aspx#comment</comments>
      <guid>http://blog.sharpthinking.com.au/post.aspx?id=dba50bd3-38e3-45f2-9475-415556d775f1</guid>
      <pubDate>Mon, 25 Jan 2010 18:06:00 +0900</pubDate>
      <dc:publisher>tarn</dc:publisher>
      <pingback:server>http://blog.sharpthinking.com.au/pingback.axd</pingback:server>
      <pingback:target>http://blog.sharpthinking.com.au/post.aspx?id=dba50bd3-38e3-45f2-9475-415556d775f1</pingback:target>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://blog.sharpthinking.com.au/trackback.axd?id=dba50bd3-38e3-45f2-9475-415556d775f1</trackback:ping>
      <wfw:comment>http://blog.sharpthinking.com.au/post/2010/01/25/Python-SilverlightMoonlight-2-Xapping.aspx#comment</wfw:comment>
      <wfw:commentRss>http://blog.sharpthinking.com.au/syndication.axd?post=dba50bd3-38e3-45f2-9475-415556d775f1</wfw:commentRss>
    </item>
  </channel>
</rss>
