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

<channel>
	<title>yergler.net &#187; development</title>
	<atom:link href="http://yergler.net/blog/category/development/feed/" rel="self" type="application/rss+xml" />
	<link>http://yergler.net</link>
	<description>Because eventually I&#039;ll be right. Theoretically.</description>
	<lastBuildDate>Tue, 31 Jan 2012 05:43:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Updating el-get and getelget.el</title>
		<link>http://yergler.net/blog/2011/09/26/getelget-update/</link>
		<comments>http://yergler.net/blog/2011/09/26/getelget-update/#comments</comments>
		<pubDate>Mon, 26 Sep 2011 16:59:24 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[emacs el-get getelget]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1989</guid>
		<description><![CDATA[Last week one of my Emacs using colleagues asked me how I managed my Emacs packages and configuration. Naturally I pointed him to el-get and my getelget.el bootstrap script. I&#8217;ve been happily managing my Emacs installation over the past five months using el-get and a private git repository for my configuration. However when I tried [...]]]></description>
			<content:encoded><![CDATA[<p>Last week one of my Emacs using colleagues asked me how I managed my Emacs packages and configuration. Naturally I pointed him to <a title="el-get at github.com" href="https://github.com/dimitri/el-get">el-get</a> and my <a title="Managing my Emacs packages with el-get" href="http://yergler.net/blog/2011/04/19/managing-my-emacs-packages-with-el-get/">getelget.el bootstrap script</a>. I&#8217;ve been happily managing my Emacs installation over the past five months using el-get and a private git repository for my configuration. However when I tried to square my <code>.emacs.d/init.el</code> with the current el-get documentation, I got a little confused; el-get is now better at bootstrapping itself from within your Emacs configuration. When my colleague read this and asked why he might want <code>getelget.el</code>, my response was&#8230; well, lackluster; this is an attempt to document that a littler better.)</p>
<p>Last night I decided to do a little clean-up on my Emacs configuration, and see if I could get rid of getelget.el. The <a href="https://github.com/dimitri/el-get/blob/master/README.asciidoc">documentation for el-get</a> is great, so I started there. What I quickly realized is that the included el-get bootstrap mechanism is great if you want to ensure el-get is installed and then use <code>el-get-install</code>, <code>el-get-remove</code>, etc to manage your packages. But if you define your package list in you config file, it&#8217;s not quite enough. Specifically, when you first bootstrap your configuration, you want to defer calling <code>(elget 'sync)</code> until you&#8217;ve bootstrapped el-get. And on future runs, you want to go ahead and install any new packages that have been added to your list.</p>
<p>Luckily el-get has added support for hooks, which makes life a little easier. The new <code>getelget.el</code> (available <a href="http://yergler.net/projects/2011/getelget-201109.el" title="getelget.el source code">here</a>) looks something like this:</p>
<pre><code>
;; getelget - el-get boostrap script
;;
;; Checks to see if el-get has been checked out, and bootstraps it if
;; it has not. After bootstrapping, calls el-get to load specified
;; packages.
;;
;; el-get-packages should be defined before including this file. Any
;; definitions from el-get-sources will be appended to el-get-packages.
;;
;; Written in 2011 by Nathan R. Yergler <nathan@yergler.net>
;;
;; To the extent possible under law, the person who associated CC0 with
;; getelget has waived all copyright and related or neighboring rights
;; to getelget.
;;
;; You should have received a copy of the CC0 legalcode along with this
;; work.  If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.

;; add a hook listener for post-install el-get
(defun post-install-hook (pkg)
  ;; after installing el-get, load the local package list
  (if (string-equal pkg "el-get")
      (el-get 'sync
              (append el-get-packages
                      (mapcar 'el-get-source-name el-get-sources)))))
(add-hook 'el-get-post-install-hooks 'post-install-hook)

;; add the el-get directory to the load path
(add-to-list 'load-path
             (concat (file-name-as-directory user-emacs-directory)
                     (file-name-as-directory "el-get")
                     "el-get"))

;; try to require el-get
(if (eq (require 'el-get nil t) nil)

    ;; urp, need to bootstrap
    (url-retrieve
     "https://raw.github.com/dimitri/el-get/master/el-get-install.el"
     (lambda (s)
         (end-of-buffer)
         (eval-print-last-sexp)))

    ;; successfully required el-get, load the packages!
    (post-install-hook "el-get")
</code></pre>
<p>el-get also <a href="http://tapoueh.org/blog/2011/09/16-el-get-3.1.html">recommends</a> splitting your package definitions from your local source recipes (which can themselves extend an included recipe). So getelget.el now expects you&#8217;ve defined two lists: <code>el-get-packages</code>, a list of packages to install from recipes, and <code>el-get-sources</code>, your local source list. </p>
<p>For example, I define a local recipe for <a href="https://github.com/magit/magit">magit</a> that binds a key to <code>magit-status</code> and enables spell checking and fill mode for commit message editing:</p>
<pre><code>
(setq el-get-sources
      '((:name magit
               :after (lambda ()
                        (global-set-key "\C-x\r\r" 'magit-status)

                        ;; Enable spell checking, fill for log editing
                        (add-hook 'magit-log-edit-mode-hook
                                  (lambda()
                                    (auto-fill-mode 1)
                                    (flyspell-mode 1)))))
        ))
</code></pre>
<p>And my <code>el-get-packages</code> list is just a list of packages I&#8217;m installing from the included el-get recipes.</p>
<pre><code>
(setq el-get-packages
       '(el-get
         google-maps
         color-theme
         python-mode
         virtualenv
         php-mode-improved
         xml-rpc-el
         js2-mode
         org2blog))
</code></pre>
<p>Everything listed in both lists will be installed.</p>
<p>YMMV, FWIW, ZOMG, BBQ, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2011/09/26/getelget-update/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>super(self.__class__, self) # end of the line for subclassing</title>
		<link>http://yergler.net/blog/2011/07/04/super-self/</link>
		<comments>http://yergler.net/blog/2011/07/04/super-self/#comments</comments>
		<pubDate>Tue, 05 Jul 2011 03:44:23 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[super]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1990</guid>
		<description><![CDATA[I&#8217;ve learned (and remembered) a lot in the past two months as I&#8217;ve gotten back to coding as my primary job. One thing that I guess I never quite internalized before is how super works. I have been bitten by code that looks something like the following a few times in the past month: class [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve learned (and remembered) a lot in the past two months as I&#8217;ve gotten back to coding as my primary job. One thing that I guess I never quite internalized before is how <code>super</code> works. I have been bitten by code that looks something like the following a few times in the past month:</p>
<pre><code>
class A(object):
    def __init__(self):
        super(self.__class__, self).__init__()

class B(A):
    def __init__(self):
        super(B, self).__init__()
</code></pre>
<p>The surprise comes when I try to use my sub-class, <code>B</code>. Instantiating <code>B()</code> blows up the stack with: </p>
<p><code>RuntimeError: maximum recursion depth exceeded while calling a Python object</code>.</p>
<p>What? </p>
<p>According to the <a href="http://docs.python.org/library/functions.html#super">Python 2.7.2 standard library documentation</a>, <code>super</code> &#8220;return[s] a proxy object that delegates method calls to a parent or sibling class of type.&#8221; So in the case of single inheritance, it delegates access to the super class, it does not return an instance of the super class. In the example above, this means that when you instantiate B, the follow happens:</p>
<ol>
<li>enter <code>B.__init__()</code></li>
<li>call <code>super</code> on B and call <code>__init__</code> on the proxy object</li>
<li>enter <code>A.__init__()</code></li>
<li>call <code>super</code> on <code>self.__class__</code> and call <code>__init__</code> on the proxy object</li>
</ol>
<p>The problem is that when we get to step four, <code>self</code> still refers to our instance of <code>B</code>, so calling <code>super</code> points back to <code>A</code> again. In technical terms: Ka-bloom.</p>
<p><strong>TL;DR:</strong> <code>super(self.__class__, self)</code> may look like a neat trick, but it&#8217;s the end of the line for sub-classing.</p>
<p><strong>Further reading:</strong> Raymond Hettinger&#8217;s excellent <a href="http://rhettinger.wordpress.com/2011/05/26/super-considered-super/">blog post on super</a> provides a great overview of <code>super</code> and shows off the improved Python 3 syntax, which removes the need to write the class name as part of the <code>super</code> statement. I was really pleased to find the Python standard library documentation links directly to it.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2011/07/04/super-self/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Managing my Emacs packages with el-get</title>
		<link>http://yergler.net/blog/2011/04/19/managing-my-emacs-packages-with-el-get/</link>
		<comments>http://yergler.net/blog/2011/04/19/managing-my-emacs-packages-with-el-get/#comments</comments>
		<pubDate>Wed, 20 Apr 2011 05:17:05 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[tools]]></category>
		<category><![CDATA[el-get]]></category>
		<category><![CDATA[emacs]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1944</guid>
		<description><![CDATA[Update (20 April 2011): I&#8217;ve now tried this on my old MacBook running OS X 10.5. The bootstrap script initially threw an error, which I tracked down to an outdated version of git. Once I upgraded git and installed bzr (used by the python-mode recipe), I started Emacs and was rewarded with a fully functioning [...]]]></description>
			<content:encoded><![CDATA[<p class="update"><strong>Update (20 April 2011):</strong> I&#8217;ve now tried this on my old MacBook running OS X 10.5. The bootstrap script initially threw an error, which I tracked down to an outdated version of <code>git</code>. Once I upgraded <code>git</code> and installed <code>bzr (</code>used by the <code>python-mode</code> recipe), I started Emacs and was rewarded with a fully functioning installation, complete with the extensions I want.</p>
<p>I&#8217;m on vacation for two weeks between jobs, so of course this means it&#8217;s time to sharpen the tools (because writing programs to help you write programs is almost always more fun than actually writing programs). I&#8217;ve been an <a href="http://www.gnu.org/software/emacs/">Emacs</a> user for many years, and of course I&#8217;ve customized my installation with additional modes and extensions. Previously I would check out code that I needed into a <code>vendor</code> directory, and then load it manually in <code>init.el</code>. And this worked fine, but that doesn&#8217;t mean I <del datetime="2011-04-19T23:14:20+00:00">can&#8217;t</del> won&#8217;t spend a chunk of my day making it better.</p>
<p>A <a href="http://dustycloud.org/">friend</a> mentioned <a href="https://github.com/dimitri/el-get">el-get</a> to me, and I decided to give it a try. I like the combination of <a href="https://github.com/dimitri/el-get/tree/master/recipes">recipes</a> for installing common things, and the fact that your list of packages is very explicit in <code>init.el</code> (so if I need to dig into one of them, I know exactly where to begin). Additionally, since I&#8217;ll have a new computer issued for the new job, I also wanted to get things into shape so that I could easily replicate my preferred editing environment. I wound up creating a small bootstrap file to help things along, <strong><code>getelget.el</code></strong>. </p>
<p><strong><code>getelget.el</code></strong> checks to see if el-get has been previously bootstrapped, and if not, performs the lazy installation procedure. After it makes sure el-get is available, it loads and executes el-get. So if you need to get a new machine up and going with Emacs and any extensions, you can drop in your <code>init.el</code> and <strong><code>getelget.el</code></strong>, and Emacs will take care of the rest. </p>
<p>To use <strong>getelget</strong>, define your <code>el-get-sources</code> like you normally would in <code>init.el</code>:</p>
<p><code>
<pre>(setq el-get-sources
      '(el-get
        python-mode
        ;; etc...
      )
 )
</pre>
<p></code> </p>
<p>Then load <strong>getelget</strong> (the following assumes you have getelget.el in your user emacs directory along with <code>init.el</code>):</p>
<p><code>
<pre>
;; getelget -- bootstrap el-get if necessary and load the specified packages
(load-file
 (concat (file-name-as-directory user-emacs-directory) "getelget.el"))
</pre>
<p></code></p>
<p><strong>getelget</strong> will handle bootstrapping, loading, and executing el-get.</p>
<p><strong>getelget</strong> is pretty trivial; you can <a href="http://yergler.net/projects/2011/getelget.el">download it here</a>, and I&#8217;ve waived any rights I may hold on the code using the <a href="http://creativecommons.org/publicdomain/zero/1.0/">CC0 Public Domain Dedication</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2011/04/19/managing-my-emacs-packages-with-el-get/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CI at CC</title>
		<link>http://yergler.net/blog/2010/08/20/ci-at-cc/</link>
		<comments>http://yergler.net/blog/2010/08/20/ci-at-cc/#comments</comments>
		<pubDate>Fri, 20 Aug 2010 17:37:43 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[cc]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[CI]]></category>
		<category><![CDATA[coverage]]></category>
		<category><![CDATA[Hudson]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[sanity]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1734</guid>
		<description><![CDATA[I wrote about our roll-out of Hudson on the CC Labs blog. I wanted to note a few things about deploying that, primarily for my own reference. Hudson has some great documentation, but I found Joe Heck&#8217;s step by step instructions on using Hudson for Python projects particularly helpful. We&#8217;re using nose for most of [...]]]></description>
			<content:encoded><![CDATA[<p>I wrote about <a href="http://labs.creativecommons.org/2010/08/12/welcome-hudson-to-creative-commons/">our roll-out</a> of <a href="http://hudson-ci.org">Hudson</a> on the <a href="http://labs.creativecommons.org/">CC Labs blog</a>.  I wanted to note a few things about deploying that, primarily for my own reference.  Hudson has some great documentation, but I found Joe Heck&#8217;s <a href="http://www.rhonabwy.com/wp/2009/11/04/setting-up-a-python-ci-server-with-hudson/">step by step instructions</a> on using Hudson for Python projects particularly helpful.  We&#8217;re using <a href="http://pypi.python.org/pypi/nose">nose</a> for most of our projects, and <a href="http://pypi.python.org/pypi/zc.buildout">buildout</a> creates a <code>nosetest</code> script wrapper that Hudson runs to generate pass/fail reports.  </p>
<p><a href="http://code.creativecommons.org/issues/issue653">Setting up coverage</a> is on the <a href="http://code.creativecommons.org/issues/">todo list</a>, but it appears that our particular combination of libraries has at least one strange issue: when <a href="http://code.creativecommons.org/viewgit/cc.license.git">cc.license</a> uses <a href="http://jinja.pocoo.org/2/">Jinja2</a> to load a template, coverage thinks it&#8217;s a Python source file (maybe it uses an import hook or something? haven&#8217;t looked) and tries to tokenize it when generating the xml report. <a href="https://groups.google.com/group/coveragepy-dev/browse_thread/thread/62f63eb9a2560b28">Ka-boom</a>. (This has apparently already been <a href="http://bitbucket.org/ned/coveragepy/issue/82/tokenerror-when-generating-html-report">reported</a>.)</p>
<p>Another item in the &#8220;maybe/someday&#8221; file is using <a href="http://codespeak.net/tox">Tox</a> to run the tests using multiple versions of Python (example configuration for <a href="http://codespeak.net/tox/example/hudson.html">Tox + Hudson</a> exists).  I can see that this is a critical part of the process when releasing libraries for others to consume.  We have slightly less surface area &#8212; all the servers run the same version of Python &#8212; but it&#8217;d be great to know exactly what our possible deployment parameters are.</p>
<p>Overall Hudson already feels like it&#8217;s adding to our sanity.  I just received my copy of <a href="http://continuousdelivery.com/">Continuous Delivery</a>, so I think this is the start of something wonderful.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/08/20/ci-at-cc/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Back to the Future: Desktop Applications</title>
		<link>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/</link>
		<comments>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/#comments</comments>
		<pubDate>Tue, 30 Mar 2010 16:04:03 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[cc]]></category>
		<category><![CDATA[ccpublisher]]></category>
		<category><![CDATA[python]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1517</guid>
		<description><![CDATA[One of the best prepared talks I saw at PyCon this year was on Phatch, a cross-platform photo processing application written in Python. Stani Michiels and Nadia Alramli gave a well rehearsed, compelling talk discussing the ins and outs of developing their application for Linux, Mac OS X, and Windows. The video is available from [...]]]></description>
			<content:encoded><![CDATA[<p>One of the best prepared talks I saw at PyCon this year was on <a href="http://photobatch.stani.be/">Phatch</a>, a cross-platform photo processing application written in Python.  Stani Michiels and Nadia Alramli gave a well rehearsed, compelling talk discussing the ins and outs of developing their application for Linux, Mac OS X, and Windows.  The <a href="http://python.mirocommunity.org/video/1595/pycon-2010-cross-platform-appl">video is available</a> from the excellent Python MiroCommunity.</p>
<p>The talk reminded of a blog post I saw late last year and never got around to commenting on, <a href="http://spin.atomicobject.com/2009/01/30/ruby-for-desktop-applications-yes-we-can">Ruby for Desktop Applications? Yes we can.</a>  Now I&#8217;m only a year late in commenting on it.  This post caught my eye for two reasons. First, the software they discuss was commissioned by the <a href="http://www.goldratt.com/">AGI Goldratt Institute</a>.  I had heard about Goldratt from my father, whose employer, <a href="http://trustedmfg.com/">Trusted Manufacturing</a>, was working on implementing constraints-based manufacturing as a way to reduce costs and distinguish themselves from the rest of the market.  More interesting, though, was their discussion of how they built the application, and how it seemed to resonate with some of the work I did in my early days at CC.  </p>
<p>Atomic wrote three blog posts (at least that I saw), and the one with the most text (as determined by my highly unscientific &#8220;page down&#8221; method) was all about how they &#8220;rolled&#8221; the JRuby application: how they laid out the source tree, how they compile Ruby source into Java JARs, and how they distribute a single JAR file with their application and its dependencies.  I thought this was interesting because even though it uses a different language (Python instead of Ruby), GUI framework (wx instead of Swing/Batik), and runtime strategy (bundled interpreter instead of bytecode archive), the thing I spent the most time on when I was developing <a href="http://wiki.creativecommons.org/CC_Publisher">CC Publisher</a> was deployment. </p>
<p>Like Atomic and Phatch, we had a single code base that we wanted to work across the major platforms (Windows, Linux, and Mac OS X in our case).  The presentation about Phatch has some great information about making desktop-specific idioms work in Python, so I&#8217;ll let them cover that.  Packaging and deployment was the biggest challenge, one we never quite got right.</p>
<p>On Windows, we used <a href="http://www.py2exe.org/">py2exe</a> to bundle our Python runtime with the source code and dependencies.  This worked most of the time, unless we forget to specify a sub-package in our manifest, in which case it blew up in amazing and spectacular ways (not really).  Like Atomic, we used <a href="http://nsis.sourceforge.net/">NSIS</a> for the Windows installer portion.  On Mac OS X, we used <a href="http://svn.pythonmac.org/py2app/py2app/trunk/doc/index.html">py2app</a> to do something similar, and distributed a disk image.  On Linux&#8230; well, on Linux, we punted.  We experimented with a <a href="http://cx-freeze.sourceforge.net/">cx-freeze</a> and <a href="http://yergler.net/blog/2005/08/17/packaging-applications-for-linux-with-autopackage/">flirted</a> with <a href="http://autopackage.org/">autopackage</a>.  But nothing ever worked quite right [enough], so we would up shipping tarballs. </p>
<p>The really appealing thing about Atomic&#8217;s approach is that by using a single JAR, you get to leverage a much bigger ecosystem of tools: the Java community has either solved, or has well defined idioms for, launching Java applications from JARs.  You get <a href="http://launch4j.sourceforge.net/">launch4j</a> and <a href="http://izpack.org/">izpack</a>, which look like great additions to a the desktop developer&#8217;s toolbox.</p>
<p>For better or for worse, we [Creative Commons] decided CC Publisher wasn&#8217;t the best place to put our energy and time.  This was probably the right decision, but it was a fun project to work on.  (We do have <a href="http://wiki.creativecommons.org/CC_Publisher_Refresh_and_Update">rebooting CC Publisher</a> listed as a <a href="http://wiki.creativecommons.org/Developer_Challenges">suggested project</a> for <a href="http://socghop.appspot.com/gsoc/org/show/google/gsoc2010/creativecommons">Google Summer of Code</a>, if someone else is interested in helping out.) Given the maturity of Java&#8217;s desktop tool chain, and the vast improvements in <a href="http://jython.org/">Jython</a> over the past year or two, I can imagine considering an approach very much like Atomic&#8217;s were I working on it today.  Even though it seems like the majority of people&#8217;s attention is on web applications these days, I like seeing examples of interesting desktop applications being built with dynamic languages.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/30/back-to-the-future-desktop-applications/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using pip with buildout</title>
		<link>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/</link>
		<comments>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 20:05:22 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[dependencies]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[koucou]]></category>
		<category><![CDATA[pip]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[scm]]></category>
		<category><![CDATA[zc.buildout]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1586</guid>
		<description><![CDATA[I&#8217;ve been asked to add a blog to koucou, and this has turned out to be more of a learning experience than I expected. My first instinct was to use WordPress &#8212; I&#8217;m familiar with it, like the way it works, and I&#8217;m not interested in building my own. The one wrinkle was that we [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been asked to add a blog to <a href="http://koucou.com/">koucou</a>, and this has turned out to be more of a learning experience than I expected.  My first instinct was to use <a href="http://wordpress.org/">WordPress</a> &#8212; I&#8217;m familiar with it, like the way it works, and I&#8217;m not interested in building my own.  The one wrinkle was that we wanted to integrate the blog visually with the rest of the site, which is built on <a href="http://djangoproject.com/">Django</a>.  I decided to give <a href="http://github.com/montylounge/django-mingus">Mingus</a> a try.  This post isn&#8217;t about Mingus &#8212; I&#8217;ll write about that shortly &#8212; but rather about <a href="http://pypi.python.org/pip">pip</a>, which Mingus uses to manage dependencies.  Mingus includes a <a href="http://pip.openplans.org/requirement-format.html">requirements file</a> with the stable dependencies for the application (one of its goals is application re-use, so there are a lot of them).  As I <a href="http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/">mentioned previously</a>, <code>pip</code> is the Python packaging/installation tool I have the least experience with, so I decided to try converting my existing project to pip as a starting point &#8212; to gain experience with pip, and to try and ease integration woes with Mingus.</p>
<p>When I started, the project used the following setup to manage dependencies and the build process:</p>
<ul>
<li>Dependencies which have an <a href="http://peak.telecommunity.com/DevCenter/EggFormats">egg</a> or <a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a>-compatible <a href="http://docs.python.org/distutils/sourcedist.html">sdist</a> available are specified in <a href="http://peak.telecommunity.com/DevCenter/setuptools#declaring-dependencies">install_requires</a> in setup.py
<pre><code>setup(
    name = "soursop",

    # ... details omitted

    install_requires = ['setuptools',
                        'zope.interface',
                        'zope.component',
                        'PILwoTK',
                        'flup',
                        ],

    )
</code></pre>
</li>
<li>A <a href="http://buildout.org/">buildout</a> configuration that uses <code><a href="http://pypi.python.org/pypi/djangorecipe">djangorecipe</a></code> to install Django, and <code><a href="http://pypi.python.org/pypi/zc.recipe.egg">zc.recipe.egg</a></code> to install the application egg and its dependencies<br />
<code>
<pre>[buildout]
develop = .
parts = django scripts
unzip = true
eggs = soursop

[django]
recipe = djangorecipe
version = 1.1.1
settings = settings
eggs = ${buildout:eggs}
project = soursop

[scripts]
recipe = zc.recipe.egg
eggs =
     ${buildout:eggs}
interpreter = python
dependent-scripts = true
extra-paths =
   ${django:location}
initialization =
   import os
   os.environ['DJANGO_SETTINGS_MODULE'] = '${django:project}.${django:settings}'
</pre>
<p></code></li>
<li>Dependencies that didn&#8217;t easily install using setuptools (either they didn&#8217;t have a sane source-tree layout or weren&#8217;t available from PyPI) are either specified as <a href="http://www.kernel.org/pub/software/scm/git/docs/git-submodule.html">git submodules</a> or imported into the repository.</li>
</ul>
<p>All this worked pretty well (although I&#8217;ve never really loved git submodules).</p>
<p><code><a href="http://pypi.python.org/pypi/gp.recipe.pip">gp.recipe.pip</a></code> is a buildout recipe which allows you to install a set of Python packages using pip.  gp.recipe.pip builds on <a href="http://pypi.python.org/pypi/zc.recipe.egg">zc.recipe.egg</a>, so it inherits all the functionality of that recipe (installing dependencies declared in <code>setup.py</code>, generating scripts, etc).  So in that respect, I could simply replace the recipe line in the <code>scripts</code> part and start using pip requirements to install from source control, create editable checkouts, etc.</p>
<p>Previously, I used the <code>${buildout:eggs}</code> setting to share a set of packages to install between the <code>django</code> part (which I used to generate a Django management script) and the <code>scripts</code> part (which I used to resolve the dependency list and install scripts defined as entry points).  I didn&#8217;t spend much time looking into replicating this with gp.recipe.pip; it wasn&#8217;t immediately clear to me how to get a working set out of it that&#8217;s equivalent to an <code>eggs</code> specification (I&#8217;m not even sure it makes sense to expect such a thing).</p>
<p>Ignoring the issue of the management script, I simplified my buildout configuration, removing the <code>django</code> part and using <code>gp.recipe.pip</code>:</p>
<p><code>
<pre>
[buildout]
develop = .
parts = soursop
unzip = true
eggs = soursop
django-settings = settings
django-project = soursop

[soursop]
recipe = gp.recipe.pip
interpreter = python
eggs = ${buildout:eggs}
sources-directory = vendor

initialization =
   import os
   os.environ['DJANGO_SETTINGS_MODULE'] = '${buildout:django-project}.${buildout:django-settings}'
</pre>
<p></code></p>
<p>This allowed me to start specifying the resources I previously included as git submodules as pip requirements:</p>
<p><code>
<pre>
[soursop]
recipe = gp.recipe.pip
interpreter = python
install =
	-r requirements.txt
eggs = ${buildout:eggs}
sources-directory = vendor
</pre>
<p></code></p>
<p>The install parameter specifies a series of pip dependencies that buildout will install when it runs.  These can include version control URLs, recursive requirements (in this case, <a href="http://pip.openplans.org/#requirements-files">a requirements file</a>, <code>requirements.txt</code>), and editable dependencies.  In this case I&#8217;ve also specified a directory, <code>vendor</code>, in which editable dependencies will be installed.</p>
<p>That actually works pretty well: I can define my list of dependencies in a text file on its own, and I can move away from git submodules and vendor imports to specifying [D]VCS urls that pip will pull.  </p>
<p>Unfortunately, I&#8217;m still missing my manage script.  I wound up creating a small function and entry point to cause the script to be generated.  In <code>soursop/scripts.py</code>, I created the following function:</p>
<p><code>
<pre>def manage():
    """Entry point for Django manage command; assumes
    DJANGO_SETTINGS_MODULE has been set in the environment.

    This is a convenience for getting a ./bin/manage console script
    when using buildout."""

    from django.core import management
    from django.utils import importlib
    import os

    settings = importlib.import_module(os.environ.get('DJANGO_SETTINGS_MODULE'))

    management.execute_manager(settings)
</pre>
<p></code></p>
<p>In setup.py, I added an entry point:</p>
<p><code>
<pre>    entry_points = {
        'console_scripts' : [
            'manage = soursop.scripts:manage',
            ]
        },
</pre>
<p></code></p>
<p>Re-run buildout, and a <code>manage</code> script appears in the <code>bin</code> directory.  Note that I&#8217;m still using the environment variable, <code>DJANGO_SETTINGS_MODULE</code>, to specify which settings module we&#8217;re using.  I could specify the settings module directly in my manage script wrapper.  I chose not to do this because I wanted to emulate the behavior of <code>djangorecipe</code>, which lets you change the settings module in buildout.cfg (i.e., from development to production settings).  This is also the reason I have custom initialization code specified in my buildout configuration.</p>
<p>Generally I really like the way this works.  I&#8217;ve been able to eliminate the tracked vendor code in my project, as well as the git submodules.  I can easily move my pip requirements into a requirements file and specify it with -r in the install line, separating dependency information from build information.</p>
<p>There are a couple things that I&#8217;m ambivalent about.  Primarily, I now have two different places where I&#8217;ve declared some of my dependencies, <code>setup.py</code> and a requirements file, and each has advantages (which are correspondingly disadvantages for the other).  Specifying the requirements in the pip requirements file gives me more flexibility &#8212; I can install from subversion, git, or mercurial without even thinking about it.  But if someone installs my package from a source distribution using easy_install or pip, the dependencies won&#8217;t necessarily be satisfied<sup>1, 2</sup>.  And conversely, specifying the requirements in <code>setup.py</code> allows everyone to introspect them at installation time, but sacrifices the flexibility I&#8217;ve gained from pip.</p>
<p>I&#8217;m not sure that we&#8217;ll end up using Mingus for koucou, but I think we&#8217;ll stick with gp.recipe.pip.  The disadvantage is a small one (at least in this situation), and it&#8217;s not really any worse than the previous situation. </p>
<hr />
<p><sup>1</sup> I suppose I could provide a <a href="http://pip.openplans.org/#bundles">bundle</a> for pip that includes the dependencies, but the documentation doesn&#8217;t make that seem very appealing.</p>
<p><sup>2</sup> Inability to install my Django application from an sdist isn&#8217;t really a big deal: the re-use story just isn&#8217;t good enough (in my opinion) to have it make sense.  Generally, however, I like to be able to install a package and pull in the dependencies as well.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/28/using-pip-with-buildout/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>For Some Definition of &#8220;Reusable&#8221;</title>
		<link>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/</link>
		<comments>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/#comments</comments>
		<pubDate>Wed, 10 Mar 2010 02:38:54 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[development]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1539</guid>
		<description><![CDATA[I read &#8220;Why I switched to Pylons after using Django for six months&#8221; yesterday, and it mirrors something I&#8217;ve been thinking about off and on for the past year or so: what is the right level of abstraction for reuse in web applications? I&#8217;ve worked on two Django-based projects over the past 12-18 months: CC [...]]]></description>
			<content:encoded><![CDATA[<p>I read <a href="http://www.mutualinformation.org/2010/03/why-i-switched-to-pylons-after-using-django-for-six-months/">&#8220;Why I switched to Pylons after using Django for six months&#8221;</a> yesterday, and it mirrors something I&#8217;ve been thinking about off and on for the past year or so: what is the right level of abstraction for reuse in web applications?  I&#8217;ve worked on two <a href="http://djangoproject.com/">Django</a>-based projects over the past 12-18 months: <a href="https://creativecommons.net/">CC Network</a> and <a href="http://koucou.com/">koucou</a>.  Neither is what I&#8217;d call &#8220;huge&#8221;, but in both cases I wanted to re-use existing apps, and in both cases it felt&#8230; awkward.</p>
<p>Part of this awkwardness is probably the impedance mismatch of the framework and the toolchain: Django applications are Python packages.  The Python tools for packaging and installing (<a href="http://www.python.org/doc/current/library/distutils.html">distutils</a>, <a href="http://pypi.python.org/pypi/setuptools">setuptools</a>, <a href="http://pypi.python.org/pypi/distribute">distribute</a>, and <a href="http://pip.openplans.org/">pip</a>, I think, although I have the least experience with it) work on &#8220;<a href="http://www.python.org/doc/current/distutils/introduction.html#distutils-specific-terminology">module distributions</a>&#8220;<sup>1</sup>: some chunk of code with a <code>setup.py</code>.  This is as much a &#8220;social&#8221; issue as a technology one: the documentation and tools don&#8217;t encourage the &#8220;right&#8221; kind of behavior, so talk of re-usable applications is often just hand waving or, at best, reinvention<sup>2</sup>. </p>
<p>In both cases we consciously chose Django for what I consider its killer app: the <a href="http://docs.djangoproject.com/en/1.1/ref/contrib/admin/">admin interface</a>. But there have been re-use headaches.  [NB: What follows is based on our experience, which is <a href="http://pypi.python.org/pypi/setuptools">setuptools</a> and <a href="http://buildout.org/">buildout</a> based] The first one you encounter is that not every developer of a reusable app has made it available on <a href="http://pypi.python.org/">PyPI</a>.  If they&#8217;re using Subversion you can still use it with setuptools, but when re-using with git, we have some additional work (a submodule or another buildout recipe).  I understand pip just works with the most commons [D]VCS, but haven&#8217;t used it myself.  Additionally, they aren&#8217;t all structured as projects, and those that are don&#8217;t always declare their dependencies properly<sup>3</sup>.  And finally there&#8217;s the &#8220;real&#8221; issues of templates, URL integration, etc.</p>
<p>I&#8217;m not exactly sure what the answer is, but it&#8217;s probably 80% human (as opposed to technology).  Part of it is practicing good hygiene: writing your apps with <a href="http://www.chipx86.com/blog/2008/04/03/django-development-with-djblets-unrooting-your-urls/">relocatable URLs</a>, using proper <a href="http://docs.djangoproject.com/en/1.1/topics/http/urls/#reverse">URL reversal</a> when generating intra-applications URLs, and making sure your templates are somewhat self-contained.  But even that only gets you so far.  Right now I have to work if I want to make my app easily consumable by others; work, frankly, sucks.</p>
<p>Reuse is one area where I think <a href="http://en.wikipedia.org/wiki/Zope_3">Zope 3</a> (and it&#8217;s derived frameworks, <a href="http://grok.zope.org/">Grok</a> and <a href="http://bfg.repoze.org/">repoze.bfg</a>) have an advantage: if you&#8217;re re-using an application that provides a particular type of model, for example, all you need to do is register a view for it to get a customized template.  The liberal use of interfaces to determine context also helps smooth over some of the URL issues<sup>4</sup>.  Just as, or more, importantly, they have a strong culture of writing code as small &#8220;projects&#8221; and using tools like buildout to assemble the final product.</p>
<p>Code reuse matters, and truth in advertising matters just as much or more.  If we want to encourage people to write reusable applications, the tools need to support that, and we need to be explicit about what the benefits we expect to reap from reuse are.  </p>
<hr />
<p><sup>1</sup> Of course you never actually see these referred to as <em>module distributions</em>; always projects, packages, eggs, or something else. </p>
<p><sup>2</sup> Note that I&#8217;m not saying that <a href="http://pylonshq.com/">Pylons</a> gets the re-use story much better; the author admits choosing Django at least in part because of the perceived &#8220;vibrant community of people writing apps&#8221; but found himself more productive with Pylons.  Perhaps he entered into that with different expectations?  I think it&#8217;s worth noting that we chose Django for a project, in part, for the same reason, but with different expectations: not that the vibrant community writing apps would generate reusable code, but that they would education developers we could hire when the time came.</p>
<p><sup>3</sup> This is partially due to the current state of Python packaging: setuptools and distribute expect the dependency information to be included in setup.py; pip specifies it in a requirements file.</p>
<p><sup>4</sup> At least when dealing with graph-based traversal; it could be true in other circumstances, I just haven&#8217;t thought about it enough.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/09/for-some-definition-of-reusable/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>i18n HTML: Bring the Pain</title>
		<link>http://yergler.net/blog/2010/03/01/i18n-html-bring-the-pain/</link>
		<comments>http://yergler.net/blog/2010/03/01/i18n-html-bring-the-pain/#comments</comments>
		<pubDate>Tue, 02 Mar 2010 07:21:20 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[cc]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[license engine]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1501</guid>
		<description><![CDATA[I have to stay up a little later this evening than I&#8217;d planned, so as a result I&#8217;m finally going through all the tabs and browser windows I&#8217;ve had open on my personal laptop. I think some of these have been &#8220;open&#8221; for months (yes, there have been browser restarts, but they&#8217;re always there when [...]]]></description>
			<content:encoded><![CDATA[<p>I have to stay up a little later this evening than I&#8217;d planned, so as a result I&#8217;m finally going through all the tabs and browser windows I&#8217;ve had open on my personal laptop.  I think some of these have been &#8220;open&#8221; for <em>months</em> (yes, there have been browser restarts, but they&#8217;re always there when the session restores).  One that I&#8217;ve meant to blog is Wil Clouser&#8217;s <a href="http://micropipes.com/blog/2009/09/01/using-substitution-strings-in-po-files/">post on string substitution in .po files</a>.  It&#8217;s actually [at least] his second post on the subject, recanting his <a href="http://micropipes.com/blog/2007/07/26/ten-tips-for-website-localization/">prior advice</a>, coming around to what others told him previously: <strong>don&#8217;t use substitution strings in .po files.  </strong></p>
<p>I wasn&#8217;t aware of Chris&#8217;s previous advice, but had I read it when first published, I would have nodded my head vigorously; after all, that&#8217;s how we <em>did</em> it.  Er, that&#8217;s how we, uh, <em>do</em> it.  And we&#8217;re not really in a position to change that at the moment, although we&#8217;ve certainly looked pretty hard at the issue.</p>
<p>A bit of background: One of the core pieces of technology we&#8217;ve built at Creative Commons is the <a href="http://creativecommons.org/choose/">license chooser</a>.  It&#8217;s a relatively simple application, with a few wrinkles that make it interesting.  It manages a lot of requests, a lot of languages, and has to spit out the right license (type, version, and jurisdiction) based on what the user provides.  The really interesting thing it generates is some XHTML with RDFa that includes the license badge, name, and any additional information the user gives us; it&#8217;s this metadata that we use to generate the copy and paste attribution HTML on the deed.  So what does this have to do with <a href="http://en.wikipedia.org/wiki/Internationalization_and_localization">internationalization</a>?  The HTML is internationalized.  And it contains substitutions.  Yikes.</p>
<p>To follow in the excellent example of AMO and Gnome, we&#8217;d start using English as our <code>msgid</code>s, leaving behind the current symbolic keys of the past.  Unfortunately it&#8217;s not quite so easy.  Every time we look at this issue (and for my first year as CTO we really looked; <a href="http://asheesh.org/">Asheesh</a> can atest we looked at it again and again) and think we&#8217;ve got it figured out, we realize there&#8217;s another corner case that doesn&#8217;t quite work.</p>
<p>The real issue with the HTML <strong>is</strong> the HTML: <a href="http://pypi.python.org/pypi/zope.i18n">zope.i18n</a>, our XSLT selectors<sup>&dagger;</sup>, the ZPT parse tree: none of them really play all that well with HTML <code>msgid</code>s.  The obvious solution would be to get rid of the HTML in translation, and we&#8217;ve tried doing that, although we keep coming back to our current approach.  I guess we&#8217;re always seduced by keeping all the substitution in one place, and traumatized by the time we tried assembling the sentences from smaller pieces<sup>&Dagger;</sup>.</p>
<p>So if we accept that we&#8217;re stuck with the symbolic identifiers, what do we do?  Build tools, of course.  This wasn&#8217;t actually an issue until we started using a &#8220;real&#8221; translation tool &#8212; <a href="http://translate.sourceforge.net/wiki/pootle/index">Pootle</a>, to be specific.  Pootle is pretty powerful, but some of the features depend on having &#8220;English&#8221; <code>msgid</code>s.  Luckily it has no qualms about HTML in those <code>msgid</code>s, it has decent <a href="http://en.wikipedia.org/wiki/Revision_control">VCS</a> support, and we know how to write post-commit hooks.</p>
<p>To support Pootle and provide a better experience for our translators, we maintain two sets of PO files: the &#8220;CC style&#8221; symbolic <code>msgid</code> files, and the &#8220;normal&#8221; English <code>msgid</code> files.  We keep a separate &#8220;master&#8221; PO file where the msgid is the &#8220;CC style&#8221; <code>msgid</code>, and the &#8220;translation&#8221; is the English <code>msgid</code>.  It&#8217;s this file that we update when we need to make changes, and luckily using that format actually makes the extraction work the way it&#8217;s supposed to.  Or close.  And when a user commits their work from Pootle (to the &#8220;normal&#8221; PO file), a post-commit hook keeps the other version in sync.</p>
<p>While we&#8217;ve gotten a lot better at this and have learned to live with this system, it&#8217;s far from perfect.  The biggest imperfection is its custom nature: I&#8217;m still the &#8220;expert&#8221;, so when things go wrong, I get called first.  And when people want to work on the code, it takes some extra indoctrination before they&#8217;re productive.  My goal is still to get to a single set of PO files, but for now, this is what we&#8217;ve got.  Bring the pain.</p>
<hr noshade />
<p><sup>&dagger;</sup> For a while, at least.  We&#8217;re working on a <a href="http://code.creativecomons.org/viewgit/cc.engine.git">new version of the chooser</a> driven by our the license RDF.  This will be better for re-use, but not really an improvement in this area. </p>
<p><sup>&Dagger;</sup> This works great in English, but in languages where gender is more strongly expressed in the word forms, uh, not so much.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/03/01/i18n-html-bring-the-pain/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Thoughts on Deploying and Maintaining SMW Applications</title>
		<link>http://yergler.net/blog/2010/01/25/thoughts-on-deploying-and-maintaining-smw-applications/</link>
		<comments>http://yergler.net/blog/2010/01/25/thoughts-on-deploying-and-maintaining-smw-applications/#comments</comments>
		<pubDate>Tue, 26 Jan 2010 05:24:51 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[cc]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[mediawiki]]></category>
		<category><![CDATA[semantic mediawiki]]></category>
		<category><![CDATA[smw]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1353</guid>
		<description><![CDATA[In September or October of last year, I received an email from someone who had come across CC Teamspace and was wondering if there was a demo site available they could use to evaluate it. I told them, &#8220;No, but I can probably throw one up for you.&#8221; A month later I had to email [...]]]></description>
			<content:encoded><![CDATA[<p>In September or October of last year, I received an email from someone who had come across <a href="http://wiki.creativecommons.org/CcTeamspace">CC Teamspace</a> and was wondering if there was a demo site available they could use to evaluate it.  I told them, &#8220;No, but I can probably throw one up for you.&#8221;  A month later I had to email them and say, &#8220;Sorry, but I haven&#8217;t found the time to do this, and I don&#8217;t see that changing.&#8221;  This is clearly <em>not</em> the message you want to send to possible adopters of your software &#8212; &#8220;Sorry, even I can&#8217;t install it quickly.&#8221;  Now part of the issue was my own <a href="http://yergler.net/blog/2010/01/02/meta/">meta/perfectionism</a>: I wanted to figure out a DVCS driven upgrade and maintenance mechanism at the same time.  But even when I faced the fact that I didn&#8217;t really <em>need</em> to solve both problems at the same time, I quickly became frustrated by the installation process.  The XML file I needed to import seemed to contain extraneous pages, and things seemed to have changed between MediaWiki and/or extension versions since the export was created.  I kept staring at cryptic errors, struggling to figure out if I had all the dependencies installed.  This is not <em>just</em> a documentation problem.</p>
<p>If we think about the application life cycle, there are a three stages a solution to this problem needs to address:<sup>&dagger;</sup></p>
<ol>
<li>Installation</li>
<li>Customization</li>
<li>Upgrade</li>
</ol>
<p>If an extension is created using PHP, users can do all three (and make life considerably easier if they&#8217;re a little VCS savvy).  But if we&#8217;re dealing with an &#8220;application&#8221; built using <a href="http://semantic-mediawiki.org/">Semantic MediaWiki</a> and other <a href="http://semantic-mediawiki.org/wiki/Help:SMW_extensions">SMW Extensions</a>, it&#8217;s possible that there&#8217;s no PHP at all.  If the application lives purely in the wiki, we&#8217;re left with XML export/import<sup>&Dagger;</sup> as the deployment mechanism.  With this we get a frustrating release process, Customization support, and a sub-par Installation experience.</p>
<p class="pullquote">The basic problem is that we currently have two deployment mechanisms: full-fledged PHP extensions, and XML dumps.  If you&#8217;re not writing PHP, you&#8217;re stuck with XML export-import, and that&#8217;s just not good enough.</p>
<p>A bit of history: When Steren created the initial release of CC Teamspace, he did so by exporting the pages and hand tweaking the XML.  This is not a straight-forward, deterministic process that we want to go through every time a bug fix release is needed.</p>
<p>For users of the application, once the import (Installation) is complete (assuming it goes better than my experience), Customization is fairly straight-forward: you edit the pages.  When an Upgrade comes along, though, you&#8217;re in something of a fix: how do you re-import the pages, retaining the changes you may have made?  Until MediaWiki is backed by a DVCS with great merge handling, this is a question we&#8217;ll have to answer.</p>
<p>We brainstormed about these issues at the same time we were thinking about <a href="http://yergler.net/blog/2010/01/07/actions-for-smw-applications-hypothetically/">Actions</a>.  Our initial thoughts were about making the release and installation process easier: how does a developer<sup>&loz;</sup> indicate <em>these pages in my wiki make up my application, and here&#8217;s some metadata about it to make life easier.</em></p>
<p><a href="http://www.flickr.com/photos/nathan_y/2611968330/" title="Semantic Packaging by Nathan Y, on Flickr"><img src="http://farm3.static.flickr.com/2099/2611968330_fc742209cf.jpg" width="500" height="375" alt="Semantic Packaging" /></a></p>
<p>We brainstormed a solution with the following features:</p>
<ol>
<li><strong>An <code>Application</code> namespace:</strong> just as Forms, Filters, and Templates have their own namespace, an Application namespace would be used to define groups of pages that work together.</li>
<li><strong>Individual Application Pages</strong>, each one defining an Application in terms of Components.  In our early thinking, a Component could be a Form, a Template, a Filter, or a Category; in the latter case, only the SMW-related aspects of the Category would be included in the Application (ie, not any pages in the Category, on the assumption that they contain instance-specific data).</li>
<li><strong>Application Metadata</strong>, such as the version<sup>&diams;</sup>, creator, license, etc.</li>
</ol>
<p>A nice side effect of using a wiki page to collect this information is that we now have a URL we can refer to for Installation.  The idea was that a Special page (ie, <code>Special:Install</code>, or <code>Special:Applications</code>) would allow the user to enter the URL of an Application to install.  Magical hand waving would happen, the extension dependencies would be checked, and the necessary pages would be installed.</p>
<p>While we didn&#8217;t get too far with fleshing out the Upgrade scenario, I think that a good first step would be to simply show the edit diff if the page has changed since it was Installed, and let the user sort it out.  It&#8217;s not perfect, but it&#8217;d be a start.</p>
<p>I&#8217;m not sure if this is exactly the right approach to take for packaging these applications.  It does effectively invent a new packaging format, which I&#8217;m somewhat wary of.  At the same time, I like that it seems to utilize the same technologies in use for building these applications; there&#8217;s a certain symmetry that seems reassuring.  Maybe there are other, obvious solutions I haven&#8217;t thought of.  If that&#8217;s the case, I hope to find them before I clear enough time from the schedule to start hacking on this idea.</p>
<hr noshade />
<p><sup>&dagger;</sup> Address or work around, that is; there has to be a clear story for how the user accomplishes each.</p>
<p><sup>&Dagger;</sup> It&#8217;s possible that in the six months since I last worked closely with this, things have changed considerably, but some brief searching didn&#8217;t turn anything up.  I&#8217;d love to be corrected if I&#8217;ve missed something obvious.</p>
<p><sup>&loz;</sup> I think one development model to be encouraged using SMW is that of the user-developer: a user who utilizes SMW to get the job done, and in the process creates something that they&#8217;d like to release to the larger world.  </p>
<p><sup>&diams;</sup> One obvious short-coming of our solution is with respect to versioning: what does it mean to <em>version</em> an application that primarily exists as a bunch of wiki pages?</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/01/25/thoughts-on-deploying-and-maintaining-smw-applications/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>&#8220;Actions&#8221; for SMW Applications (Hypothetically)</title>
		<link>http://yergler.net/blog/2010/01/07/actions-for-smw-applications-hypothetically/</link>
		<comments>http://yergler.net/blog/2010/01/07/actions-for-smw-applications-hypothetically/#comments</comments>
		<pubDate>Fri, 08 Jan 2010 06:13:41 +0000</pubDate>
		<dc:creator>Nathan Yergler</dc:creator>
				<category><![CDATA[cc]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[mediawiki]]></category>
		<category><![CDATA[semantic mediawiki]]></category>
		<category><![CDATA[smw]]></category>
		<category><![CDATA[teamspace]]></category>

		<guid isPermaLink="false">http://yergler.net/?p=1346</guid>
		<description><![CDATA[Talking about AcaWiki has me thinking some more about our experiences over the past couple years with Semantic MediaWiki, particularly about building &#8220;applications&#8221; with it. I suppose that something like AcaWiki could be considered an application of sorts &#8212; I certainly wrote about it as such earlier this week &#8212; but in this case I&#8217;m [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://yergler.net/blog/2010/01/04/acawiki-on-building-emerging-applications/">Talking about AcaWiki</a> has me thinking some more about our experiences over the past couple years with <a href="http://sematic-mediawiki.org/">Semantic MediaWiki</a>, particularly about building &#8220;applications&#8221; with it.  I suppose that something like AcaWiki could be considered an application of sorts &#8212; I certainly wrote about it as such earlier this week &#8212; but in this case I&#8217;m talking about applications as reusable, customizable pieces of software that do a little more than just CRUD data.</p>
<p>In 2008 we were using our internal wiki, Teamspace, for a variety of things: employee handbook, job descriptions, staff contact information, and grants.  We decided we wanted to do a better job at tracking these grants, specifically the concrete tasks associated with each, things we had committed to do (and which potentially required some reporting).  As we iterated on the design of a grant, task, and contact tracking system, we realized that a grant was basically another name for a project, and the <a href="http://wiki.creativecommons.org/CcTeamspace">Teamspace project tracking system</a> was born.</p>
<p><a href="http://www.flickr.com/photos/nathan_y/2438557055/" title="IMG_0552.JPG by Nathan Y, on Flickr"><img src="http://farm3.static.flickr.com/2139/2438557055_1ec9fda7f8.jpg" width="500" height="375" alt="IMG_0552.JPG" /></a></p>
<p>As we began working with the system, it became obvious we needed to improve the user experience; requiring staff members to look at yet another place for information just wasn&#8217;t working.  So <a href="http://creativecommons.org/about/people/alumni#100">Steren Giannini</a>, one of our amazing interns, built <a href="http://www.mediawiki.org/wiki/Extension:SemanticTasks">Semantic Tasks</a>. </p>
<p>Semantic Tasks is a MediaWiki extension, but it&#8217;s driven by semantic annotations on task pages.  Semantic Tasks&#8217; primary function is sending email reminders.  One of the things I really like about Steren&#8217;s design is that it works with existing MediaWiki conventions: we annotate Tasks with the assigned (or cc&#8217;d) User page, and Semantic Tasks gets the email addresses from the User page.</p>
<p>There were two things we brainstormed but never developed in 2008. I think they&#8217;re both still areas of weakness that could be filled to make SMW even more useful as an application platform.  The first is something we called <em>Semantic Actions</em>: actions you could take on a page that would change the information stored there.</p>
<p><a href="http://www.flickr.com/photos/nathan_y/2611966782/" title="Semantic Actions by Nathan Y, on Flickr"><img src="http://farm3.static.flickr.com/2153/2611966782_16926c3938.jpg" width="500" height="375" alt="Semantic Actions" /></a></p>
<p>Consider, for example, marking a task as completed.  There are two things you&#8217;d like to do to &#8220;complete&#8221; a task: set the status to complete and record the date it was completed.  The thought was that it&#8217;d be very convenient to have &#8220;close&#8221; available as a page action, one which would effect both changes at once without requiring the user to manually edit the page.  Our <a href="http://mehfilindian.com/">curry</a>-fueled brainstorm was that you could describe these changes using Semantic Mediawiki annotations<sup>1</sup>.  <a href="http://en.wikipedia.org/wiki/Turtles_all_the_way_down">Turtles all the way down</a>, so to speak.  </p>
<p>The amount of explaining this idea takes, along with some distance, makes me uncertain that it&#8217;s the right approach.  I <strong>do</strong> think that being able to easily write extensions that implement something more than CRUD is important to the story of SMW as a &#8220;real&#8221; application platform.  One thing I that makes me uncertain about this approach is the fear that we are effectively rebuilding Zope 2&#8242;s ZClasses, only crappier.  <a href="http://wiki.zope.org/zope2/ZClasses">ZClasses</a>, for those unfamiliar, were a way to create classes and views through the a web-based interface.  A user with administrative rights could author an &#8220;application&#8221; through the web, getting lots of functionality for &#8220;free&#8221;.  The problem was that once you exhausted ZClasses&#8217; capabilities, you pretty much had to start from scratch when you switched to on disk development.  Hence Zope 2&#8242;s notorious &#8220;Z-shaped learning curve&#8221;.  I think it&#8217;s clear to me now that building actions through the web is going to by necessity expose a limited feature set.  The question is whether it&#8217;s enough, or if we should encourage people to write [Semantic] Mediawiki extensions that implement the features they need.</p>
<p>Maybe the right approach is simply providing really excellent documentation so that developers can easily retrieve the values the SMW annotations on the pages they care about.  You can imagine a skin that exists as a minor patch to Monobook or Vector, which uses a hook to retrieve the installed SMW &#8220;actions&#8221; for a page and displays them in a consistent manner.</p>
<p>Regardless of the approach taken, if SMW is going to be a platform, there has to be an extensibility story.  That story already exists in some form; just look at the <a href="http://semantic-mediawiki.org/wiki/Help:Extensions">extensions already available</a>.  Whether the existing story is sufficient is something I&#8217;m interested in looking at further.</p>
<p>Next time: Thoughts on Installation and Deployment.</p>
<hr noshade />
<p><sup>1</sup> The difference between Semantic Tasks and our hypothetical Semantic Actions is that the latter was concerned solely with making some change to the relevant wiki page.</p>
]]></content:encoded>
			<wfw:commentRss>http://yergler.net/blog/2010/01/07/actions-for-smw-applications-hypothetically/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

