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

<channel>
	<title>Singletoned</title>
	<atom:link href="http://blog.singletoned.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.singletoned.net</link>
	<description>Just another WordPress weblog</description>
	<lastBuildDate>Thu, 21 Jan 2010 20:50:16 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Sociopaths, Clueless and Losers</title>
		<link>http://blog.singletoned.net/2010/01/sociopaths-clueless-and-losers/</link>
		<comments>http://blog.singletoned.net/2010/01/sociopaths-clueless-and-losers/#comments</comments>
		<pubDate>Thu, 21 Jan 2010 20:45:25 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[General]]></category>
		<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[essays]]></category>
		<category><![CDATA[scl thoughts essays]]></category>

		<guid isPermaLink="false">http://blog.singletoned.net/?p=37</guid>
		<description><![CDATA[An overlong response to Venkatesh Rao's Gervais Principle.]]></description>
			<content:encoded><![CDATA[<p>This is the first decent sized non-technical article I have written for around 10 years.  I&#8217;m pleased I did it, and I might try more, but it reads like it was written by someone who hasn&#8217;t written properly in 10 years.</p>

<p>To get any value from this post you really have to go and read the
wonderful article by Venkatesh Rao <a href="http://www.ribbonfarm.com/2009/10/07/the-gervais-principle-or-the-office-according-to-the-office/">The Gervais Principle, Or The
Office According to “The
Office”</a>.</p>

<p>It was possibly one of the best articles written last year, and
certainly one of the two best things I have ever read on the disease
of organisations (not that this article or the other one were actually
about that).</p>

<p>He links his theory to the TV series &#8220;The Office&#8221;, though it doesn&#8217;t
have any direct connection to that; it&#8217;s just that that is where
he saw the clearest examples (another example of satire being truer
than reality).</p>

<p><a href="http://blog.singletoned.net/wp-content/uploads/2010/01/hughMcLeodCompanyHierarchy.jpg"><img src="http://blog.singletoned.net/wp-content/uploads/2010/01/hughMcLeodCompanyHierarchy-300x163.jpg" alt="Hugh McLeod Company Hierarchy" title="hughMcLeodCompanyHierarchy" width="300" height="163" class="alignnone size-medium wp-image-43" /></a></p>

<p>A very basic summary is:</p>

<blockquote>
  <p>Sociopaths, in their own best interests, knowingly promote over-performing losers into middle-management, groom under-performing losers into sociopaths, and leave the average bare-minimum-effort losers to fend for themselves.</p>
</blockquote>

<p>My random notes follow.  This article might be edited in the future as I
think of more things.</p>

<h2>Sociopaths</h2>

<ul>
<li>naturally distrust group thought/morality</li>
<li>emphasis on independent thinking</li>
<li>risk friendly</li>
<li>manage the big picture</li>
</ul>

<h2>Clueless</h2>

<ul>
<li>self-deceitful rationalisers</li>
<li>believe in the group/organisation</li>
<li>value the opinions and beliefs of others</li>
<li>risk averse</li>
<li>manage the people directly below them</li>
</ul>

<h2>Losers</h2>

<ul>
<li>follow the group/organisation without believing in it</li>
<li>have accepted their inability to affect change</li>
<li>are the people who actually produce things</li>
</ul>

<p>The people reading this will be Losers.  Sociopaths have better things to be doing, and the Clueless will react very badly to material such as this.  It breaks their suspension of disbelief, and they will have to either attack it, or ignore the bulk of it’s content.</p>

<p>An example of a Clueless reading the article and having to
deliberately miss the point is highlighted in the first comment under
<a href="http://baitsdeuce.wordpress.com/2009/10/27/are-you-a-loser-clueless-or-a-sociopath/">this
post</a></p>

<h1>Organisational Life-cycle</h1>

<p><a href="http://blog.singletoned.net/wp-content/uploads/2010/01/compLifeCycle.jpg"><img src="http://blog.singletoned.net/wp-content/uploads/2010/01/compLifeCycle-257x300.jpg" alt="Company Life Cycle" title="compLifeCycle" width="257" height="300" class="alignnone size-medium wp-image-44" /></a></p>

<p>Looking at the classic organisation life-cycle:</p>

<ul>
<li>Experimental startup</li>
<li>Growth into productive startup</li>
<li>Growth into small business</li>
<li>Growth into Beaurocracy</li>
<li>Death (merger, acquisition, bankruptcy, etc)</li>
</ul>

<p>Start-ups are started by sociopaths (almost necessarily so).  As they
start to move into a profitable phase they need to hire losers, the only ones who actually produce anything.  By
definition, if you are producing something on the orders of someone
else, that <em>they</em> are being paid for <em>you</em> to make, you are a loser.
You are not getting the best value for your time.  (This is the point
that Marx went all ape-shit over.  He didn&#8217;t notice the fact that the
Losers/Proletariat can&#8217;t make things for themselves because they can&#8217;t
think for themselves what to make.  In this way, they are getting the
best value for <em>their</em> time, because they can&#8217;t do any better.  It
just wouldn&#8217;t be the best value for other people&#8217;s time).</p>

<p>As the company grows, the number of Losers grows.  The Sociopaths
can&#8217;t manage them all.  The projects are bedded in by now so they
hire, or promote, the Clueless to be a safe pair of hands to keep things
ticking over.</p>

<p>In order to be able to live with themselves (they are neither
producing anything of value nor in a position of power) the Clueless
have to deceive themselves that they are important.  They convince themselves that what they do is worth while, and that more people like them are needed.</p>

<p>The levels of Clueless swell as the company grows until they are
pushing out the Sociopaths at the top.  This is when the company
becomes a beaurocratic behemoth that the world at large ridicules.
This is when you start to see the death throes of the company, and
when outsiders start questioning how the company manages to keep going.</p>

<p>Soon after the company hopefully dies.  Either through plain old
bankruptcy or by being bought, merged etc.  Sometimes however, this
doesn&#8217;t happen.  Many public sector institutions can&#8217;t die.  The Civil
Service, the NHS or the BBC can&#8217;t go bankrupt, can&#8217;t be bought, and
can&#8217;t really be got rid of.  Hence they spend a long time in their
death throes.  In this case the Clueless act as a parasite in an
immortal host.</p>

<h1>Hardworking, Lazy, Stupid or Clever</h1>

<p>From <a href="http://en.wikipedia.org/wiki/Kurt_von_Hammerstein-Equord">Wikipedia</a>:</p>

<blockquote>
  <p>As Chief of the Army High Command, Hammerstein-Equord oversaw the composition of the German manual on military unit command (Truppenführung), dated 17 October 1933. He originated a special classification scheme for his officers:</p>
  
  <blockquote>
    <p>I divide my officers into four classes; the clever, the lazy, the industrious, and the stupid. Most often two of these qualities come together. The officers who are clever and industrious are fitted for the highest staff appointments. Those who are stupid and lazy make up around 90% of every army in the world, and they can be used for routine work. The man who is clever and lazy however is for the very highest command; he has the temperament and nerves to deal with all situations. But whoever is stupid and industrious is a menace and must be removed immediately!</p>
  </blockquote>
</blockquote>

<p>I think this breakdown of people works well also.  Instead of the
stupid/clever axis though, I would be tempted to use something more
like self-aware/self-decieving.  What we traditionally think of as
cleverness doesn&#8217;t really come into it.</p>

<p>This lead me to create this diagram:</p>

<p><a href="http://blog.singletoned.net/wp-content/uploads/2010/01/CSHL.png"><img src="http://blog.singletoned.net/wp-content/uploads/2010/01/CSHL-299x300.png" alt="Clever, Stupid, Hardworking, Lazy" title="CSHL" width="299" height="300" class="alignnone size-medium wp-image-41" /></a></p>

<p>There was a clear gap in the bottom right, that I filled in with the idea of the Sociopath Loser.  The Sociopath Loser has the mistrust of organisations of the Sociopath, but without the ability to &#8220;play the game&#8221;, and general settles for a role outside the organisation, or plays a Loser, writing articles on what is wrong with organisations in their spare time.</p>

<p>This then lead to create this version of the hierarchy:</p>

<p><a href="http://blog.singletoned.net/wp-content/uploads/2010/01/SCL.png"><img src="http://blog.singletoned.net/wp-content/uploads/2010/01/SCL-300x209.png" alt="" title="SCL" width="300" height="209" class="alignnone size-medium wp-image-42" /></a></p>

<h1>Thoughts</h1>

<p>The Loser Sociopath, such as a drifter, is distinctly a separate class.  This is separate again from the unpromoted Sociopaths, and unpromoted Clueless, who are temporarily amongst the Losers.</p>

<p>This ‘organisation’ is also society at large, where the Clueless and Losers make up society, and the Sociopaths, the leaders, are separate from it.  They can’t make decisions on behalf of a society that they are part of.  Governments aren’t entirely made up of Sociopaths.  A great deal of Clueless have made it into reasonably high government positions, without being leaders or gaining power.</p>

<p>The Clueless could be there to provide a cushion between the Sociopaths and the Losers, or it could be that Sociopaths promote the Clueless as a human shield, or that Sociopaths put the Clueless there to keep things ticking over.  The Clueless are risk averse and so wont take stupid risks.</p>

<p>I think the rationalising of Clueless is a key thing.  They are in a
difficult situation.  If they were clear minded and honest with
themselves, they would see that they are in a bad situation where they
have no power or freedom, and yet don&#8217;t have the pride of producing
anything.  Necessarily the only way they can continue what  they are
doing is to lie to themselves.  I&#8217;ve seen this myself many times,
where people will go to extraordinary lengths to convince themselves
why what they have been told to do is the Right Thing.  Quite often
they have misunderstood what they have to do, but then go about
rationalising the wrong thing.</p>

<h1>Personal</h1>

<p>I am a Sociopath Loser.  I have toyed at the edges of the Clueless and ran away in horror.  I have also at times done the classic Unpromoted Sociopath thing of putting in less than the minimum effort; preparing myself for the next thing.</p>

<p>I think almost anyone who has commented on any of the articles is a Sociopath Loser, or maybe a Loser.  True Sociopaths have better things to do.  Clueless wouldn&#8217;t be able to do anything but attack or misunderstand.  Losers generally wouldn&#8217;t have it in them to understand the article.</p>

<h1>Further Reading</h1>

<p><a href="http://www.ribbonfarm.com/2009/11/11/the-gervais-principle-ii-posturetalk-powertalk-babytalk-and-gametalk/">A Follow up article that Venkatesh wrote</a></p>

<p><a href="http://fugitive.quadrantcrossing.org/?p=305">A weird, but intelligent, response that someone wrote</a>.  The comments are well worth reading.  I loved the opener &#8220;While I do speak PoMo well enough to understand most of what you wrote&#8230;&#8221;</p>

<p><a href="http://www.jesusmanifesto.com/2009/11/belief-the-gervais-principle/">A good response on how the theory applies in religious organisations, and of how it has already been of genuine use to someone</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2010/01/sociopaths-clueless-and-losers/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Emacs: Wrap lines in html tags</title>
		<link>http://blog.singletoned.net/2009/10/emacs-wrap-lines-in-html-tags/</link>
		<comments>http://blog.singletoned.net/2009/10/emacs-wrap-lines-in-html-tags/#comments</comments>
		<pubDate>Sun, 18 Oct 2009 20:23:51 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[emacs]]></category>
		<category><![CDATA[lisp]]></category>
		<category><![CDATA[yasnippet]]></category>

		<guid isPermaLink="false">http://blog.singletoned.net/?p=30</guid>
		<description><![CDATA[Before I switched to  Emacs, I used TextMate and was mightily
impresed by it.  (I still am).  There are lots of little touches in
there that haven&#8217;t been done better in any other editor, and the
snippet syntax is one of the best balances between ease of use and power I&#8217;ve
seen for a long time.

However [...]]]></description>
			<content:encoded><![CDATA[<p>Before I switched to  Emacs, I used <a href="http://macromates.com/">TextMate</a> and was mightily
impresed by it.  (I still am).  There are lots of little touches in
there that haven&#8217;t been done better in any other editor, and the
snippet syntax is one of the best balances between ease of use and power I&#8217;ve
seen for a long time.</p>

<p>However Emacs is better, cause Steve Yegge says so, and so I switched.
I used yasnippet for while, and loved it.  It&#8217;s a reworking of
TextMate&#8217;s snippet system with added Lisp; more power without a
sacrifice in ease of use.  For some reason I stopped using, but since a <a href="http://stackoverflow.com/questions/1558178/wrap-selection-in-open-close-tag-like-textmate/">StackOverflow
question</a> recently inspired me, I&#8217;m back with a vengence.</p>

<p>A yasnippet to wrap a region or the point in a html tag:</p>

<pre><code>(defun wrap-region-or-point-with-html-tag (start end)
  "Wraps the selected text or the point with a tag"
  (interactive "r")
  (let (string)
    (if mark-active 
        (list (setq string (buffer-substring start end))
          (delete-region start end)))
    (yas/expand-snippet (point)
                        (point)
                        (concat "&lt;${1:p}&gt;" string "$0&lt;/${1:$(replace-regexp-in-string \" .*\" \"\" text)}&gt;"))))

(global-set-key (kbd "C-W") 'wrap-region-or-point-with-html-tag)
</code></pre>

<p>I wrote this a while, and at the time it was one of the most complicated
pieces of Lisp I had written.</p>

<p>I initially misread the StackOverflow question, and submitted the
previous function.  However once I realised that they wanted something
more complex, I felt challenged and dived right in.  I eventually came
up with this, which hasn&#8217;t really been tested:</p>

<pre><code>(defun wrap-lines-in-region-with-html-tag (start end)
  "Wraps the selected text or the point with a tag"
  (interactive "r")
  (let (string)
    (if mark-active 
        (list (setq string (buffer-substring start end))
              (delete-region start end)))
    (yas/expand-snippet
     (replace-regexp-in-string "\\(&lt;$1&gt;\\).*\\'" "&lt;${1:p}&gt;"
      (mapconcat
       (lambda (line) (format "%s" line))
       (mapcar
        (lambda (match) (concat "&lt;$1&gt;" match "&lt;/${1:$(replace-regexp-in-string \" .*\" \"\" text)}&gt;"))
        (split-string string "[\r\n]")) "\n") t nil 1) (point) (point))))
</code></pre>

<p>From the end of the function working back (which seems to be the way
with Functional style), it:</p>

<ul>
<li>splits the region by linebreaks</li>
<li>wraps each line with the yasnippet syntax</li>
<li>formats each entry as a string</li>
<li>concatenates all those strings</li>
<li>replaces the first yasnippet marker with a yasnippet default marker.  </li>
</ul>

<p>I think I should be able to do something better instead of <code>(lambda (line) (format "%s" line))</code> but I don&#8217;t know what.</p>

<p>Definitely the most complex lisp I&#8217;ve written to date and I&#8217;ve learned
quite a lot from writing it.</p>

<p>As always, improvements and suggestions welcome; help yourself to any code.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2009/10/emacs-wrap-lines-in-html-tags/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connecting to MS SQL Server from Python on Linux</title>
		<link>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-linux/</link>
		<comments>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-linux/#comments</comments>
		<pubDate>Thu, 30 Jul 2009 11:28:54 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[freetds]]></category>
		<category><![CDATA[sqlalchemy]]></category>
		<category><![CDATA[unixodbc]]></category>

		<guid isPermaLink="false">http://blog.singletoned.net/?p=24</guid>
		<description><![CDATA[This is the follow up to my post on connecting Python to SQL Server on
Mac.  This describes how I set it up on Linux.

Quite a few bits of it are copied from the Mac instructions, so it
might be a little repetetive if you&#8217;ve already read that.  (No new
jokes, I&#8217;m afraid).

Edit: I&#8217;ve updated this [...]]]></description>
			<content:encoded><![CDATA[<p>This is the follow up to my post on connecting Python to SQL Server on
Mac.  This describes how I set it up on Linux.</p>

<p>Quite a few bits of it are copied from the Mac instructions, so it
might be a little repetetive if you&#8217;ve already read that.  (No new
jokes, I&#8217;m afraid).</p>

<p><em>Edit</em>: I&#8217;ve updated this having tried the installation a few more
times.  I&#8217;m still not 100% sure, but I appear to have got it working
several times in a row.</p>

<h1>Summary</h1>

<ul>
<li>Install unixodbc and unixodbc-dev</li>
<li>Install the patched version of freetds</li>
<li>Install tdsodbc</li>
<li>Install the patched version of freetds again</li>
<li>Configure unixodbc</li>
<li>Install python</li>
<li>Install sqlalchemy and pyodbc</li>
</ul>

<h1>Installing freetds on Linux</h1>

<p>I&#8217;m basing this on a bare bones install of Debian Lenny (ie starting
with the bare minimum you can install).</p>

<p>I initially setup sudo, git, svn, bzr, openssh and emacs22.  I won&#8217;t
go too much into them here.  You might use different tools.  I did
place my <code>/etc</code> and <code>/home</code> under version control with git as soon as
possible, which I highly recommend for experimental setups.  I
regret not putting <code>/usr</code> under version control as well.</p>

<p>At some point you will need the tools to compile source such as
python2.6 and pyodbc.  You might as well install them now.</p>

<pre><code>sudo aptitude install build-essential
</code></pre>

<p>I also recommend installing <code>checkinstall</code> which allows you to install
from source as if it were a proper debian package.  This allows you to
meet dependencies with it and remove it easily at a later date.</p>

<pre><code> sudo aptitude install checkinstall
</code></pre>

<p>Next you&#8217;ll need to install unixodbc.  You&#8217;ll also need
the unixodbc dev headers for later (eg compiling pyodbc).</p>

<pre><code>sudo aptitude install unixodbc, unixodbc-dev
</code></pre>

<p>Then you need to install the patched version of <code>freetds</code>.  I pass two
options to configure which make it work better with SQL Server, but
might stop it working as well with Sybase and others.  I don&#8217;t really
care about that at the moment, but bear it in mind.</p>

<pre><code>mkdir src
cd src/
wget ftp://ftp.ibiblio.org/pub/Linux/ALPHA/freetds/stable/freetds-patched.tgz
tar zxvf freetds-patched.tgz
cd freetds-0.82.1.dev.20090618/
./configure --enable-msdblib  --with-tdsver=8.0
make
sudo checkinstall
# When asked edit the 'provides' (11) value to be 'freetds-common'
# This allows it to be used as a dependency for tdsodbc
</code></pre>

<p>Now install <code>tdsodbc</code>:</p>

<pre><code>sudo aptitude install tdsodbc
</code></pre>

<p>Then install <code>tdsodbc</code> again:</p>

<pre><code>cd src/freetds-0.82.1.dev.20090618/
sudo make clean
./configure --enable-msdblib  --with-tdsver=8.0
make
sudo checkinstall
# When asked edit the 'provides' (11) value to be 'freetds-common'
</code></pre>

<p>I&#8217;m not entirely sure about this, but it appears to work for me.  It
doesn&#8217;t entirely make sense though, so I suspect that there is
something better that can be done here.</p>

<p>Now you&#8217;re ready to setup up your odbc drivers and data sources.</p>

<p>You&#8217;ll need to create two files, <code>tds.driver.template</code> and
<code>tds.dsn.template</code>.  It doesn&#8217;t really matter where you create them,
as they are templates to create your <code>odbcinst.ini</code> and <code>odbc.ini</code>
files, but it&#8217;s worth putting them somewhere safe so that you can
refer back to them later.</p>

<pre><code>touch tds.driver.template
touch tds.dsn.template
</code></pre>

<p>Edit them and add the following, adjusted for your servername, dbname etc.</p>

<pre><code># tds.driver.template
[TDS]
Description     = FreeTDS Driver for Linux &amp; MSSQL on Win32
Driver          = /usr/lib/odbc/libtdsodbc.so
Setup           = /usr/lib/odbc/libtdsS.so

# tds.dsn.template
[my_dsn]
Description     = Connection to windows virtual machine
Driver          = TDS
Trace           = No
Database        = my_database_name
Server          = MY-SERVER
Port            = 1433
TDS_Version     = 8.0
</code></pre>

<p>Note that in the driver template you are naming a driver.  You then
use that name in the dsn template as the value of the driver.  This
can be any name you want instead of <code>TDS</code>, but they must match.
Alternatively, you can specify the path to the driver in the dsn
template.</p>

<p>Now you are ready to install the two templates.  You&#8217;ll need to run
<code>odbcinst</code> for each template.  Running <code>odbcinst</code> without any
arguments will give you some useful info, but I&#8217;ll summarise what you
need to know to get it working.</p>

<pre><code> sudo odbcinst -i -d -f tds.driver.template
 # -i says you want to install
 # -d says you are installing the driver
 # -f says what template you are using

 sudo odbcinst -i -s -l -f tds.dsn.template
 # -i says you want to install
 # -s says you want to install dsn
 # -l says you want to install system dsn
 # -f says what template you are using
</code></pre>

<p>These will copy the contents of the templates to <code>/etc/odbcinst.ini</code>
and <code>/etc/odbc.ini</code> respectively.  They also perform some piece of
magic that I haven&#8217;t worked out yet (eg. if you duplicate the entry it
adds to <code>odbc.ini</code> and change the name slightly, it doesn&#8217;t seem to
work).  However adding a new entry using <code>odbcinst</code> does work.</p>

<p>With the second call to <code>odbcinst</code>, you have a choice between
installing system dsn to <code>/etc/odbc.ini</code> using <code>-l</code> or user
dsn in <code>~/.odbc</code> using <code>-h</code>.  I recommend system dsn for development,
and doing more research for production.</p>

<p>Don&#8217;t forget that you might have to add your db-server to your hosts
file, depending on your network setup.  Just edit <code>/etc/hosts</code> and add
the ip address and name of your server underneath the entry for
localhost.</p>

<p>Now you should be able to run queries on your database, using <code>isql</code>.</p>

<pre><code>isql my_dsn username password
</code></pre>

<p>This should bring up an SQL prompt that allows you to execute queries
on the server.  Try a couple of queries to test it.  If you don&#8217;t have
a legacy database with data already in it, why the hell are you using
SQL Server?</p>

<h1>Connecting Python to SQL Server through pyodbc and freetds on Linux</h1>

<p>You should now be ready to get python sorted out.  If you&#8217;ve had any
problems so far, let me know and I&#8217;ll try to help.</p>

<p>First, you need a python installed.  I&#8217;ve installed 2.6 from source,
which I&#8217;ll briefly cover, but you should also be able to use the
python2.5 package that&#8217;s available.</p>

<p>In order to have all the functionality of python when installing from
source, you will need some extra libraries:</p>

<pre><code>sudo aptitude install libncursesw5-dev libreadline5-dev libssl-dev \
libgdbm-dev libbz2-dev libc6-dev libsqlite3-dev libdb-dev tk-dev
# That's all on one line, not two
</code></pre>

<p>I&#8217;ve used <code>checkinstall</code> to install python as a package.
Alternatively you can install it to your home folder by passing
<code>--prefix=/home/username</code> to configure.</p>

<p>To install it to your home folder, just download the source from the
python website, unzip it, configure it, then use <code>checkinstall</code>.</p>

<pre><code>wget http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tgz
tar zxvf Python-2.6.2.tgz 
cd Python-2.6.2/
./configure
make
sudo checkinstall
</code></pre>

<p>I also strongly recommend using virtualenv and virtualenvwrapper.
Create a virtualenv as soon as you have installed python and always
create your other virtualenvs from that, so that you can easily get
back to a clean python if you need to.  (I&#8217;ll add instructions for
that as a seperate post sometime).  Install <code>pyodbc</code> into your
virtualenv:</p>

<pre><code>    easy_install pyodbc
</code></pre>

<p>If you installed the <code>build-essential</code> and <code>unixodbc-dev</code> earlier you
should have what you need to compile it.</p>

<p>Now checkout the 0.6 branch of SQLAlchemy.  This is currently a branch
but should soon move to trunk.  It&#8217;s fine for development.  If you are
using this as a guide to setting up your production server, you are
insane.</p>

<pre><code>svn checkout http://svn.sqlalchemy.org/sqlalchemy/branches/rel_0_6
# Make sure your virtualenv is activated then:
cd rel_0_6
python setup.py develop
</code></pre>

<p>You should now be able to run some basic tests using SQLAlchemy:</p>

<pre><code>&gt;&gt;&gt; import sqlalchemy as sa
&gt;&gt;&gt; uri = "mssql://username:password@my_dsn"
&gt;&gt;&gt; engine = sa.create_engine(uri)
&gt;&gt;&gt; select_query = sa.text("SELECT * FROM MyTable")
&gt;&gt;&gt; result = engine.execute(select_query)
&gt;&gt;&gt; result.fetchall()
[]
&gt;&gt;&gt; insert_query = sa.text(
    "INSERT INTO MyTable (id, text_field) VALUES (:id, :text_field)")
&gt;&gt;&gt; result = engine.execute(insert_query, 
        id="Brian", text_field="Naughty Boy")
&gt;&gt;&gt; result = engine.execute(select_query)
&gt;&gt;&gt; result.fetchall()
[('Brian', 'Naughty Boy')]
</code></pre>

<p>That should all work.  At this point you should probably try running
some other tests.  Particularly ones involving non-ascii chars.  Then
you can watch it crumble and die.  (Actually if you&#8217;ve installed it
correctly, it should work with non-ascii chars).</p>

<p>The UK Pound Sign (£) is a particularly good symbol to use for testing
as it has a different byte representation between latin-1 and utf-8.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-linux/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connecting to MS SQL Server from Python on Mac OS X Leopard</title>
		<link>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-mac-os-x-leopard/</link>
		<comments>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-mac-os-x-leopard/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 19:00:51 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[freetds]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[sqlalchemy]]></category>
		<category><![CDATA[unixodbc]]></category>

		<guid isPermaLink="false">http://blog.singletoned.net/?p=19</guid>
		<description><![CDATA[This is a draft document, and will be updated as and when I discover
more.  The Mac instructions are very draft as I haven&#8217;t had a chance
to repeat them (I haven&#8217;t worked out how to run OS X Leopard in a virtual
machine yet).

I have unfortunately had to work with a legacy SQL Server database,
and was [...]]]></description>
			<content:encoded><![CDATA[<p>This is a draft document, and will be updated as and when I discover
more.  The Mac instructions are very draft as I haven&#8217;t had a chance
to repeat them (I haven&#8217;t worked out how to run OS X Leopard in a virtual
machine yet).</p>

<p>I have unfortunately had to work with a legacy SQL Server database,
and was reluctant to use Windows to do the development.  As such I
have been trying to get my Mac development machine and a Linux server
to connect to the database.  It has been quite an adventure, and this
is what I think I have worked out so far.</p>

<h1>Installing freetds on Mac</h1>

<p>I used MacPorts for installing packages.  It&#8217;s not perfect
but it&#8217;s a lot easier than installing from source when there is a lot
of dependencies, and quite a bit of complex configuration has often
been done for you.</p>

<p>Install freetds with the +mssql and +odbc variants.</p>

<pre><code>sudo port install freetds+mssql+odbc
</code></pre>

<p>Also install <code>unixODBC</code></p>

<pre><code>sudo port install unixODBC
</code></pre>

<p>You now have a folder <code>/opt/local/etc/freetds/</code> which should contain
two templates <code>tds.driver.template</code> and <code>tds.dsn.template</code> as well as
<code>freetds.conf</code>.  You shouldn&#8217;t need to edit <code>freetds.conf</code>, although
you can choose to specify the global tds version and charset (I have
done neither of those and it works for me, so best leave it alone
unless you have specific problems).</p>

<p>If you don&#8217;t have <code>tds.driver.template</code> or <code>tds.dsn.template</code>, create
them.</p>

<pre><code>sudo touch tds.driver.template
sudo touch tds.dsn.template
</code></pre>

<p>Edit them and add the following, adjusted for your servername, dbname etc.</p>

<pre><code># tds.driver.template
[TDS]
Description     = FreeTDS Driver for Linux &amp; MSSQL on Win32
Driver          = /opt/local/lib/libtdsodbc.so
Setup           = /opt/local/lib/libtdsS.so

# tds.dsn.template
[my_dsn]
Description     = Connection to windows virtual machine
Driver          = TDS
Trace           = No
Database        = my_database_name
Server          = MY-SERVER
Port            = 1433
TDS_Version     = 8.0
</code></pre>

<p>Note that in the driver template you are naming a driver.  You then
use that name in the dsn template as the value of the driver.  This
can be any name you want instead of <code>TDS</code>, but they must match.
Alternatively, you can specify the path to the driver in the dsn
template.</p>

<p>Now you are ready to install the two templates.  You&#8217;ll need to run
<code>odbcinst</code> for each template.  Running <code>odbcinst</code> without any
arguments will give you some useful info, but I&#8217;ll summarise what you
need to know to get it working.</p>

<pre><code> sudo odbcinst -i -d -f tds.driver.template
 # -i says you want to install
 # -d says you are installing the driver
 # -f says what template you are using

 sudo odbcinst -i -s -l -f tds.dsn.template
 # -i says you want to install
 # -s says you want to install dsn
 # -l says you want to install system dsn
 # -f says what template you are using
</code></pre>

<p>These will copy the contents of the templates to
<code>/Library/ODBC/odbcinst.ini</code> and <code>/Library/ODBC/odbc.ini</code>
respectively.  They also perform some piece of magic that I haven&#8217;t
worked out yet (eg. if you duplicate the entry it adds to <code>odbc.ini</code> and
change the name slightly, it won&#8217;t work).  However adding a new entry
using <code>odbcinst</code> does work.</p>

<p>With the second call to <code>odbcinst</code>, you have a choice between
installing system dsn to <code>/Library/ODBC/odbc.ini</code> using <code>-l</code> or user
dsn in <code>~/.odbc</code> using <code>-h</code>.  I recommend system dsn for development,
and doing more research for production.</p>

<p>Now you should be able to run queries on your database, using <code>isql</code>.</p>

<pre><code>isql my_dsn username password
</code></pre>

<p>This should bring up an SQL prompt that allows you to execute queries
on the server.  Try a couple of queries to test it.  If you don&#8217;t have
a legacy database with data already in it, why the hell are you using
SQL Server?</p>

<h1>Connecting Python to SQL Server through freetds on Mac</h1>

<p>You should now be ready to get python sorted out.  If you&#8217;ve had any
problems so far, let me know and I&#8217;ll try to help.</p>

<p>First, you need a python installed.  I&#8217;m using python2.6, but 2.5
should work fine, and maybe 2.4.  I&#8217;m not going to go into installing
python in too much depth, but I recommend not using the Mac system
python, and also not using MacPorts to install python.  I also
strongly recommend using virtualenv and virtualenvwrapper.  Create a
virtualenv as soon as you have installed python and always create your
other virtualenvs from that, so that you can easily get back to a
clean python if you need to.</p>

<p>Install <code>pyodbc</code> into your virtualenv:</p>

<pre><code>    easy_install pyodbc
</code></pre>

<p>Pyodbc needs to be compiled, so you will need a version of GCC.
Either install the latest version through MacPorts (this takes a very
long time) or install XCode which includes Apple&#8217;s own version of
GCC.  You may also need the python-dev headers and/or the unixodbc-dev
headers, depending on how you installed python and unixodbc.</p>

<p>If you have gcc errors and they include the string &#8220;-arch i386 -arch
ppc&#8221; somewhere in them, then python is probably trying to build a universal
build but doesn&#8217;t have the ppc headers.  Edit <your
python>/lib/python2.x/config/MakeFile and delete every instance of
&#8220;-arch ppc&#8221;.  (This is assuming you are running an Intel Mac of
course).</p>

<p>Now checkout the 0.6 branch of SQLAlchemy.  This is currently a branch
but should soon move to trunk.  It&#8217;s fine for development.  If you are
using this as a guide to setting up your production server, you are
insane.</p>

<pre><code>svn checkout http://svn.sqlalchemy.org/sqlalchemy/branches/rel_0_6
# Make sure your virtualenv is activated then:
cd rel_0_6
python setup.py develop
</code></pre>

<p>You should now be able to run some basic tests using SQLAlchemy:</p>

<pre><code>&gt;&gt;&gt; import sqlalchemy as sa
&gt;&gt;&gt; uri = "mssql://username:password@my_dsn"
&gt;&gt;&gt; engine = sa.create_engine(uri)
&gt;&gt;&gt; select_query = sa.text("SELECT * FROM MyTable")
&gt;&gt;&gt; result = engine.execute(select_query)
&gt;&gt;&gt; result.fetchall()
[]
&gt;&gt;&gt; insert_query = sa.text(
    "INSERT INTO MyTable (id, text_field) VALUES (:id, :text_field)")
&gt;&gt;&gt; result = engine.execute(insert_query, 
        id="Brian", text_field="Naughty Boy")
&gt;&gt;&gt; result = engine.execute(select_query)
&gt;&gt;&gt; result.fetchall()
[('Brian', 'Naughty Boy')]
</code></pre>

<p>That should all work.  At this point you should probably try running
some other tests.  Particularly ones involving non-ascii chars.  Then
you can watch it crumble and die.</p>

<p>The UK Pound Sign (£) is a particularly good symbol to use as it has a
different byte representation between latin-1 and utf-8.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2009/07/connecting-to-ms-sql-server-from-python-on-mac-os-x-leopard/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Blogging from an iPhone</title>
		<link>http://blog.singletoned.net/2009/07/blogging-from-an-iphone/</link>
		<comments>http://blog.singletoned.net/2009/07/blogging-from-an-iphone/#comments</comments>
		<pubDate>Thu, 09 Jul 2009 07:15:20 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[mac]]></category>
		<category><![CDATA[iphone]]></category>

		<guid isPermaLink="false">http://blog.singletoned.net/?p=13</guid>
		<description><![CDATA[I&#8217;ve recently bought an iPhone, and have discovered the WordPress app for it.  I thought this might be the encouragement I need to start blogging again, and it could let me blog during those small, previously wasted moments such as meetings, on the toilet, whilst smoking, etc.
]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve recently bought an iPhone, and have discovered the <a href="http://iphone.wordpress.org/">WordPress app</a> for it.  I thought this might be the encouragement I need to start blogging again, and it could let me blog during those small, previously wasted moments such as meetings, on the toilet, whilst smoking, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2009/07/blogging-from-an-iphone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Lock a Mac with a keyboard shortcut</title>
		<link>http://blog.singletoned.net/2008/05/lock-a-mac-with-a-keyboard-shortcut/</link>
		<comments>http://blog.singletoned.net/2008/05/lock-a-mac-with-a-keyboard-shortcut/#comments</comments>
		<pubDate>Tue, 06 May 2008 09:02:48 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[mac]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[macosx]]></category>
		<category><![CDATA[tips]]></category>

		<guid isPermaLink="false">http://singletoned.net/2008/05/06/lock-a-mac-with-a-keyboard-shortcut/</guid>
		<description><![CDATA[At last after a very long time searching, I&#8217;ve found a keyboard shortcut that allows you to lock a Mac in a similar style to (&#x2303;&#x2325;Del, L) on Windows.

In iChat options set Show status in menu bar, and in Keychain also set Show status in menu bar.

Now when you press (&#x2303;F8) the iChat status in [...]]]></description>
			<content:encoded><![CDATA[<p>At last after a very long time searching, I&#8217;ve found a keyboard shortcut that allows you to lock a Mac in a similar style to (&#x2303;&#x2325;Del, L) on Windows.</p>

<p>In iChat options set <code>Show status in menu bar</code>, and in Keychain also set <code>Show status in menu bar</code>.</p>

<p>Now when you press (&#x2303;F8) the iChat status in your menu bar will get the focus.  Then you can just press (&#x2190;) once to highlight the Keychain status, (&#x2193;) to highlight <code>Lock Screen</code> and (&#x21A9;) to select it.</p>

<p>This gives you (&#x2303;F8, &#x2190;, &#x2193;, &#x21A9;) as a rather convoluted and excessively long keyboard shortcut for locking your computer.  It is however very handy when you are working in an office, need to go make coffee and want to <a href="http://www.google.co.uk/search?q=%22every+time+you+touch+the+mouse+god+kills+a+kitten%22">save on kittens</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/05/lock-a-mac-with-a-keyboard-shortcut/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Oh, go on then&#8230;</title>
		<link>http://blog.singletoned.net/2008/04/oh-go-on-then/</link>
		<comments>http://blog.singletoned.net/2008/04/oh-go-on-then/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 09:27:02 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[meme]]></category>
		<category><![CDATA[bash]]></category>

		<guid isPermaLink="false">http://singletoned.net/?p=8</guid>
		<description><![CDATA[As about half the blogs I read are doing it, why can’t I?

history&#124;awk '{a[$2]++} END{for(i in a){printf "%5d\t%s\n",a[i],i}}'&#124;sort -rn&#124;head
71  git
64  cd
45  sudo
41  ls
39  nosetests
35  svn
31  mate
23  couchdb
22  python
22  lla

Which seems about right.  mate is the launcher for Textmate.  lla is my alias for [...]]]></description>
			<content:encoded><![CDATA[<p>As <a title="Labnotes  » Git it is" href="http://blog.labnotes.org/2008/04/11/git-it-is/">about</a> <a title="In Lieu of Content" href="http://adam.gomaa.us/blog/in-lieu-of-content/">half</a> <a title="The B-List: I don't normally do memes" href="http://www.b-list.org/weblog/2008/apr/10/meme/">the</a> <a title="Compound Thinking » Command line meme" href="http://compoundthinking.com/blog/index.php/2008/04/11/command-line-meme/">blogs</a> I read are doing it, why can’t I?</p>

<p><code>history|awk '{a[$2]++} END{for(i in a){printf "%5d\t%s\n",a[i],i}}'|sort -rn|head</code>
<pre><code>71  git
64  cd
45  sudo
41  ls
39  nosetests
35  svn
31  mate
23  couchdb
22  python
22  lla
</code></pre>
Which seems about right.  <code>mate</code> is the launcher for <a title="TextMate — The Missing Editor for Mac OS X" href="http://macromates.com/">Textmate</a>.  <code>lla</code> is my alias for <code>ls -la</code> which I apparently use almost half as much as ls.  <code>sudo</code> was a little surprising, but when I stripped them off, I got this:
<pre><code>71 git
64 cd
41 ls
39 nosetests
35 svn
31 mate
29 port
26 couchdb
22 python
22 lla
</code></pre>
Which explains it.  I recently wiped my Mac and installed Leopard.  I’ve had to reinstall a lot of software using <a title="The MacPorts Project -- Home" href="http://www.macports.org/">MacPorts</a> (and Python modules using <code>easy_install</code> which was at number 11).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/04/oh-go-on-then/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Installing CouchDB on Mac OS 10.5</title>
		<link>http://blog.singletoned.net/2008/04/installing-couchdb-on-mac-os-105/</link>
		<comments>http://blog.singletoned.net/2008/04/installing-couchdb-on-mac-os-105/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 09:29:58 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[couchdb]]></category>
		<category><![CDATA[mac]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[install]]></category>
		<category><![CDATA[leopard]]></category>
		<category><![CDATA[macosx]]></category>

		<guid isPermaLink="false">http://www.singletoned.net/2008/04/10/installing-couchdb-on-mac-os-105/</guid>
		<description><![CDATA[I&#8217;ve been reading about CouchDB on and off for a few months now, and recently decided to properly evaluate it as an option for my new website.  This decision weirdly coincided with the release of Google AppEngine which uses their Bigtable system, which is vaguely similar to CouchDB (non-relational, document based, flexible and scalable).

Anyway, [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been reading about <a href="http://couchdb.org/" title="Apache CouchDB: The CouchDB Project">CouchDB</a> on and off for a few months now, and recently decided to properly evaluate it as an option for my new website.  This decision weirdly coincided with the release of <a href="http://code.google.com/appengine/" title="Google App Engine - Google Code">Google AppEngine</a> which uses their Bigtable system, which is vaguely similar to CouchDB (non-relational, document based, flexible and scalable).</p>

<p>Anyway, I tried to install CouchDB on Leopard, and hit a few minor issues which I thought I&#8217;d document for others trying to install it.</p>

<p>I installed from Macports (always a good first stop).  There appears to be a missing dependency on SeaMonkey, so you need to do:</p>

<p><pre><code>sudo port install seamonkey
sudo port install couchdb
</code></pre></p>

<p>When you first start couchdb it complians that: <code>CouchDB needs write permission on the data directory: /opt/local/var/lib/couchdb</code> or <code>CouchDB needs write permission on the log directory: /opt/local/var/log/couchdb</code>.</p>

<p>I tried doing <code>sudo couchdb</code> to get over that, and couchdb seemed to start happily, and there was a response from <code>http://localhost:5984/</code>.  However, when I inserted my first document using couchdb-python, python hung completely with no repsonse (I left it for 10 minutes while I made a coffee).  In retrospect, <code>sudo couchdb</code> probably wasn&#8217;t the correct way to go (particularly as those directories don&#8217;t even exist), but I was keen to start playing.  The correct thing to do is probably to create a couchdb user that runs the database and do <code>sudo -u couchdb couchdb</code> to start the database.  Unfortunately I&#8217;m quite lazy, so instead I just did:</p>

<p><pre><code>sudo mkdir -p /opt/local/var/lib/couchdb
sudo chown ed /opt/local/var/lib/couchdb
sudo mkdir -p /opt/local/var/log/couchdb
sudo chown ed /opt/local/var/log/couchdb
</code></pre></p>

<p>Where <code>ed</code> should be replaced by your username.  <code>mkdir -p</code> recursively makes directories (incase you don&#8217;t have <code>/opt/local/var/lib/</code> or <code>/opt/local/var/log</code>) yet.</p>

<p>Anyway, hope this helps someone else, if they have problems.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/04/installing-couchdb-on-mac-os-105/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Google AppEngine: YAPWF (Yet Another Python Web Framework)</title>
		<link>http://blog.singletoned.net/2008/04/google-appengine-yapwf-yet-another-python-web-framework/</link>
		<comments>http://blog.singletoned.net/2008/04/google-appengine-yapwf-yet-another-python-web-framework/#comments</comments>
		<pubDate>Tue, 08 Apr 2008 11:52:04 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[yapwf]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[wikiwikiwoo]]></category>

		<guid isPermaLink="false">http://www.singletoned.net/2008/04/08/google-appengine-yapwf-yet-another-python-web-framework/</guid>
		<description><![CDATA[I&#8217;ve been playing around with Google&#8217;s new hosted Python framework.  I created a very basic wiki called WikiWikiWoo! just to get a feel of the system.

It&#8217;s based on Django and Paste and seems to be inspired by bits of web.py and maybe bits of Werkzeug.

The templating is directly Django&#8217;s, which I think is a [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been playing around with <a href="http://code.google.com/appengine/">Google&#8217;s new hosted Python framework</a>.  I created a very basic wiki called <a href="http://wiki-wiki-woo.appspot.com/">WikiWikiWoo!</a> just to get a feel of the system.</p>

<p>It&#8217;s based on <a href="http://www.djangoproject.com/" title="Django | The Web framework for perfectionists with deadlines">Django</a> and <a href="http://pythonpaste.org/" title="Python Paste">Paste</a> and seems to be inspired by bits of <a href="http://webpy.org/" title="(web.py)">web.py</a> and maybe bits of <a href="http://werkzeug.pocoo.org/" title="Welcome // Werkzeug">Werkzeug</a>.</p>

<p>The templating is directly Django&#8217;s, which I think is a shame as <a href="http://jinja.pocoo.org/" title="Index | Jinja Template Engine">Jinja</a> is very similar but better (vaguely useful error messages for a start).</p>

<p>The model is inspired by Django, but using Google&#8217;s Datastore (not an rdb), using GQL, their modified version of SQL.  It wasn&#8217;t easy to get going with, which is partly the fault of the documentation (it took me ages how to work out how to do their version of a primary key).</p>

<p>Once you get the hang, it&#8217;s pretty simple for quick simple data.  It would be tough going to work out how to do complex relationships with it, particularly for anyone from a traditional rdb background (like me).  There&#8217;s no section where they explain how their datastore works and the concepts behind it.  I&#8217;ve been playing with <a href="http://couchdb.org/" title="Apache CouchDB: The CouchDB Project">Couchdb</a> recently and they did a wonderful job of explaining the overall concept before going into how to use it.  That kind of conceptual overview for Datastore would probably make a world of difference.</p>

<p>The controllers seem to be inspired by Web.py.  They are classes with methods for POST, GET, etc.  I like that system from playing around with Web.py.  It allows you to very easily use the same URL for displaying an edit form and saving an item.  It keeps your code nicely grouped, but I think it would make it a little more difficult to create generic CRUD controllers (maybe having to use meta-class magic).</p>

<p>The routing seems based on a corrected version of Web.py&#8217;s.  It fixes the annoying list of tuples into a proper list of lists of tuples.  It uses basic regexs for routing (first one that matches wins), and a direct reference to a class.  This means the routing has to go at the end of the module (which is different to most other frameworks).  I like it and it&#8217;s exactly how I set up the routing when I was messing around with WSGI.</p>

<p>Sessions and deployment are the killer features.  Deployment is just a single command that uploads all your files, and restarts your app.  Session handling uses the Google login system, so sessions are completely abstracted away.  These are often the hardest bits to get right when using a new framework, so they&#8217;ve done impressively well to make them so simple.</p>

<p>Overall, I&#8217;d say it could be outstanding for quickly knocking out an app you&#8217;ve just thought of. A simple app will scale beautifully if it suddenly becomes popular (no more slashdotting) and they&#8217;ve solved the more annoying problems for webapps.  I would have some concerns about trying to create a huge complex app using it, but we&#8217;ll see.  Certainly I&#8217;ll use it again if I ever have a good, simple idea.  For my bad, complex ideas I&#8217;ll continue building my own framework <img src='http://blog.singletoned.net/wp-includes/images/smilies/icon_wink.gif' alt=';-)' class='wp-smiley' /> </p>

<hr />

<p>As an update, it appears you can use almost any Python modules in your code as long as you add them into your project folder (either copy the package or if you use a symlink it will copy them automatically).  That would mean that everything hinges on their storage.  Sessions and deployment are excellent, and everything except for the model you can do yourself.  If their storage is easy to use with potential longterm power, then it could big, and a serious choice for hosting major sites.</p>

<p>The only other issue would be one of branding.  As the login makes it clear that you are using a Google AppEngine, I don&#8217;t see big companies using it.  That&#8217;s a good thing as it gives us open minded charities a leg up on the over-resourced private sector.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/04/google-appengine-yapwf-yet-another-python-web-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>I think I understand WSGI</title>
		<link>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/</link>
		<comments>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/#comments</comments>
		<pubDate>Thu, 20 Mar 2008 16:33:07 +0000</pubDate>
		<dc:creator>Ed Singleton</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[werkzeug]]></category>
		<category><![CDATA[wsgi]]></category>

		<guid isPermaLink="false">http://www.singletoned.net/2008/03/20/i-think-i-understand-wsgi/</guid>
		<description><![CDATA[I&#8217;ve been messing around with Python web frameworks for a quite a while now.  Trying out lots of different ones and seeing which one feels like the best fit.  As I&#8217;ve got closer and closer to the right one, I&#8217;ve also found that i am getting closer and closer to using WSGI.

WSGI seems [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been messing around with Python web frameworks for a quite a while now.  Trying out lots of different ones and seeing which one feels like the best fit.  As I&#8217;ve got closer and closer to the right one, I&#8217;ve also found that i am getting closer and closer to using WSGI.</p>

<p>WSGI seems excellent and could be great for Python.  Frameworks tend to make things seem more difficult and mysterious than they really are.  What has taken me a long time to learn is that WSGI is really very simple.</p>

<p>At it&#8217;s simplest there are three aspects to it:</p>

<ul>
<li>You receive a dictionary with useful information in it (environ)</li>
<li>You receive a function to call that starts the response (start_response)</li>
<li>You return an iterator (ie a list) of strings (this is your page body)</li>
</ul>

<p>Anything on top of that is just helpers.  Helpers are great, but you don&#8217;t need a framework that hides what is really going on, when it&#8217;s as simple as that.</p>

<p>You can create a hello world app as simple as:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return ["Hello World"]
</code></pre></p>

<p>Obviously that just returns <code>Hello World</code> with no html.  Which is bad. So:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    begin_body = "&lt;html&gt;&lt;body&gt;"
    body = "Hello World"
    end_body = "&lt;/body&gt;&lt;/html&gt;"
    return [begin_body, body, end_body]
</code></pre></p>

<p>We don&#8217;t want to write <code>begin_body</code> and <code>end_body</code> every time, so lets write a function to handle this for us:</p>

<p><pre><code>def put_in_body(<em>args):
    begin_body = "&lt;html&gt;&lt;body&gt;"
    end_body = "&lt;/body&gt;&lt;/html&gt;"
    return [begin_body] + list(</em>args) + [end_body]
</code></pre></p>

<p>Then we can just:</p>

<p><pre><code>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body("Hello World")
</code></pre></p>

<p>We&#8217;re going to want to be able to do lots of different things, and we don&#8217;t want to write them all in the body of one function, so let&#8217;s write a dispatcher:</p>

<p><pre><code>def dispatch(environ):
    # We need to get the path from the environ, and work out where to go.
    path_info = environ.get('PATH_INFO', '')
    if path_info == "/goodbye":
        return goodbye(environ)
    else:
        return hello_world(environ)</p>

<p>def hello_world(environ):
    return ["Hello World"]</p>

<p>def goodbye(environ):
    return ["Goodbye World"]</p>

<p>def app(environ, start_response):
    start_response('200 OK', [('content-type', 'text/html')])
    return put_in_body(dispatch(environ))
</code></pre></p>

<p>Now if you go to /goodbye it will say &#8220;Goodbye World&#8221;, otherwise it will say &#8220;Hello World&#8221;.</p>

<p>As you can see it is all very straightforward.  It allows you to do things however you want.  Adding more and more functionality is just a case of adding functions that returns strings, and telling the dispatcher when to call that function.</p>

<p>In a later post I&#8217;ll talk about threading.  It turns out that&#8217;s easy as well.</p>

<p>If you want to run the code above, just <code>easy_install paste</code> and then add this to the bottom of your file (which I called <code>wsgi_sample.py</code>):</p>

<p><pre><code>if <strong>name</strong> == '<strong>main</strong>':
    from paste import httpserver
    httpserver.serve(app, host='127.0.0.1', port='8080')
</code></pre></p>

<p>Then you can do <code>python wsgi_sample.py</code> and visit http://localhost:8080 to see it working (don&#8217;t forget to visit http://localhost:8080/goodbye before you leave).</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.singletoned.net/2008/03/i-think-i-understand-wsgi/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
