Thursday, August 30, 2012

Dell Sputnik Ultrabook: Initial Impressions

I got word a couple of days ago that I got into the Dell "Sputnik" beta program, which is Dell's incubation project to bring a GNU/Linux-based (specifically Ubuntu-based) XPS 13 Ultrabook to market as a product, specifically as a machine aimed at developers. (We developers, lone wolves though we tend to be, do like a little attention now and then!)

As a huge free software and Linux proponent I have been watching this project closely so I was really excited to get an invite to the beta, and I received the machine today. General Disclaimer: The machine was not free. Dell did offer a discount for beta program participants but is heavily encouraging everyone to be very transparent and honest with their impressions of the machine.

In another blog post I'll cover how I went about installing Ubuntu and the Sputnik-specific PPAs, but in this post I'll share my initial impressions of the machine. (tl;dr version: With one minor exception, this is an absolutely beautiful, exceedingly well-built ultrabook that's an absolute pleasure to use.)

This is a DELL?

As I said above I'll cover Ubuntu installation in another post, but as a very quick aside -- the machine does ship with Windows 7, the explanation being they didn't want to delay shipping the beta machines to get the logistics of pre-installing Ubuntu worked out. On first boot I booted to an Ubuntu USB stick so I never let Windows see the light of day.

As the heading above indicates, to be perfectly honest I was shocked that this is a Dell. Admittedly I haven't owned a Dell in many years though I've had several Dell laptops and desktops in the past, but everything about this machine screams high-end quality. (You can see my quick, too dark unboxing photos on Google+) From the packaging to the machine itself, they clearly put a lot of thought into the design from top to bottom.

The first thing I noticed is how unbelievably solid it feels for such a small, light machine. The machined aluminum lid opens smoothly and firmly to an extremely nice backlit keyboard with a really nice, solid feel. The 13.3" HD screen is extremely sharp, running at a native 1366x768 pixels. Note that some 13" ultrabooks have a slightly higher screen resolution, but for me this resolution is perfect for this size screen, striking a good balance between screen real estate and readability.

The bottom of the machine is carbon fiber which is quite cool to the touch for the most part (particularly given that there's an Intel i7 chip inside), save for one warm spot towards the back of the machine (presumably right where the processor is). There is a bit of faint fan noise as the machine is running but it's very, very quiet compared to a couple other ultrabooks I've had so they've put some nice thought into cooling such a small little package without copping out and constantly running a loud fan full speed.

I feel like I should say a bit more about the keyboard since I'm typing this blog post on it -- it's incredibly nice to type on. The keys have a really great, firm action and as you depress the keys the machine body doesn't "give" as with some ultrabooks, so it doesn't feel flimsy in any way or like you'll break it if you get to typing incredibly quickly (which I have a tendency to do).

Even just picking up the machine and carrying it around everything feels amazingly tight and solid. This is a far cry from the Dells I've had in the past, and I would think even the most ardent Mac proponent would have to admit the quality of the hardware rivals, if not exceeds, that of Apple.

Tech Specs

You can see and read more about the XPS 13 in general on Dell's web site, but the Sputnik developer machine is the high-end model, specifically with the following specs:
  • 13.3" HD (720p) Corning Gorilla Glass WLED screen, 1366x768 resolution
  • Intel i7 processor running at 1.7GHz (with TurboBoost up to 2.8GHz)
  • Intel HD Graphics 3000
  • 256GB SSD
  • 4GB of dual-channel DDR3 RAM (1333MHz)
  • Backlit keyboard
  • Two USB ports, 1 USB 2, 1 USB 3
  • Mini display port
  • Headphone jack
  • Marketing claim on battery life: 8 - 9 hours (I'll test this to see what real-world battery life is)
In my estimation they did a good job of keeping things very minimalistic while focusing on what's important. Adding things like more USB ports, multiple (and potentially large in size) display output options, and even wired ethernet would have cause the machine to lose its singular focus which is a small, light, high quality ultrabook.

What this machine doesn't have, that you should be aware of if these things matter to you, are an optical drive and the aforementioned wired ethernet, and if you want to output to VGA or HDMI you need to pick up a dongle. None of these things matter to me personally; in fact on my other new, larger laptop I got a couple of weeks ago I opted for a second hard drive in place of an optical drive because I can't even remember the last time I used an optical drive.

The lack of wired ethernet also doesn't bother me because I personally never used a wired connection, and since this machine is so incredibly thin (and I mean incredibly thin) there isn't space for an ethernet jack anyway. If you absolutely have to have wired ethernet in an office setting or somewhere without wi-fi you can always get a USB ethernet adapter.

Overall, this is an impressively equipped little powerhouse.

One Minor Potential Downside: Memory

On balance Dell made very smart decisions about what to put into the machine, with the one question mark in my mind being why they chose not to put more than 4GB of RAM in the machine. (It's worth noting at this point that the machine is not user-upgradeable.) I can't imagine it was for cost or size reasons, so I have to guess that it was a necessary design/engineering decision for some other reason.

Granted, for many users 4GB of RAM is plenty, and if nothing else putting Ubuntu on the machine will make it run a lot more efficiently than Windows 7. That said, for a machine targeted at developers 4GB seems a tad on the low side these days, so although I'd certainly stop well short of calling it a show-stopper for me at least, it's something to be aware of and given your situation that may or may not work for you. (Note that Dell makes a slightly larger XPS 14 in which you can get 8GB of RAM.)

Sputnik as a Developer Machine

I'll find out a lot more about what the Sputnik can and can't handle next week when I take it to DjangoCon, but the i7 chip is extremely zippy, and my guess is that I'll find 4GB to be adequate for most of my needs. Ubuntu, Chrome with my usual 12-15 tabs open, and Emacs or Sublime Text are running quite happily and responsively. (Note that I have not yet installed and tried a heavier IDE like PyCharm or Eclipse.)

If you're a big user of VMs, given my experience on another ultrabook with 4GB of RAM I can say Windows 7 runs decently in 2GB of RAM in VirtualBox on Ubuntu. I wouldn't want to spend a lot of time in it with only 2GB, but if you need to test something in IE or jump into Windows to run a specific application (e.g. I have to get into Windows on rare occasions to run the VMWare console app to manage our VMs since their web-based console tool is abysmal), it should be a decent experience. Not as nice as on my laptop with 16GB of RAM certainly, and you won't be able to get away with running multiple VMs at once, but running a VM is certainly possible.

If you're a Java or CFML developer, I fired up some Java-based applications on Tomcat on this machine, giving Tomcat 1GB and then 2GB of heap space. Things ran fine, though if like me you abuse the heck out of memory if you have it available, I suspect you're not going to be able to get away running dozens of webapps simultaneously under Tomcat on this machine.

That said I'm moving away from the Java/CFML world into the Python/Django world which is much more memory-friendly, so for Python development this machine should be really excellent. Most of the time when I'm doing Python development I don't see my memory or CPU monitors even act like much is going on, which is quite a different experience than I was used to with Java and CFML.

The CPU is certainly up to practically any development task, just be aware that depending on the type of development you're doing and your development style, you might need to think a little bit about the RAM limitation.

Bottom line on Sputnik as a developer machine is I see this as being an absolutely fantastic developer machine, with a minor caveat about the RAM.


The Dell XPS 13 is a huge winner in my book. It's exceedingly well built, light, quiet, and has all the bells and whistles you need in an ultrabook -- particularly one aimed at developers -- and Dell made intelligent omissions across the board with the possible exception of the amount of RAM pre-installed.

If like me you've had Dells in the past and hadn't thought about Dell in a while, this machine may well change your mind about Dell. After only a few hours of using it it's certainly starting to change mine, and I can already see myself gravitating to the Sputnik as my go-to machine.

Sunday, August 26, 2012

Installing MySQL Python Module on Ubuntu

After tearing through several other Django books and tutorials using sqlite3 as the database, I'm starting to go through the book Beginning Django E-Commerce and it uses MySQL as the database. I use MySQL quite a lot so that side of things isn't an issue, but I did run into a couple of wrinkles getting MySQL and Django playing nice so I thought I'd share.

Basically if after configuring your database in and running python dbshell you get a bunch of errors, you have a minor amount of installation work to do to get things rolling.

First thing I did was install pip, which is a better version of/replacement for easy_install:
sudo easy_install pip

Next I ran pip upgrade for good measure (probably not necessary but can't hurt, and worth running if you already had pip installed):
sudo pip install pip --upgrade

On my machine (Ubuntu 12.04 64-bit) I also had to build the dependencies for the python-mysqldb libraries:
sudo apt-get build-dep python-mysqldb

And finally with that in place you can use pip to install the Python MySQL libraries:
sudo pip install MySQL-python

If everything worked you should now be able to run python dbshell from your Django project and have it load up the MySQL console.

Tuesday, August 21, 2012

Manually Installing the Django Plugin for Eric

If you install Eric (specifically Eric 4) from the Ubuntu software repos, the Eric plugin repository points to a location that's unavailable:

I'm sure there's a way to change it but I don't see how to do it in the app itself (haven't started poking around to see if there are config files somewhere yet), but luckily Eric plugins are just zip files so you can download them from a repository URL that works, and then add them to Eric.

The working plugin repository is here:

From there just do a ctrl-F to find the plugin you're looking for, then copy/paste the URL for the plugin's zip file into your browser (or use wget or whatever floats your boat) to download the plugin.

With the zip file downloaded, in Eric go to Plugins -> Install Plugins, click Add, and then point to the zip file you downloaded.

If someone knows how to change the plugin repository URL in Eric I'd love to learn.

Sunday, August 19, 2012

Connecting to SQL Server with pyodbc

At long last after my previous posts on this topic we get to the easy part: using pyodbc to run queries against SQL Server.

If you need to get caught up, the posts you'll want to go through before proceeding with this one are:

With a datasource created in unixODBC this last part is rather anti-climactic, but this is of course also where you can get some real work done in Python.

First, in a Python console ('python' from a terminal or whatever your favorite Python console tool is), import pyodbc:
>>> import pyodbc

Next, create a connection to the datasource using the datasource name, which in this case we'll assume is foo:
>>> conn = pyodbc.connect('DSN=foo;UID=username;PWD=password')

If you don't get any errors, the connection was successful. Next, create a cursor on that connection:
>>> cursor = conn.cursor()

Now we can execute a query against SQL Server using that cursor:
>>> cursor.execute("SELECT * FROM bar")

If the query ran successfully, you'll see that a pyodbc.Cursor object is returned:
<pyodbc.Cursor object at 0x15a5a50>

Next, and this is is not the most efficient way to do things (see below) but is good for demonstration purposes, let's call fetachall() on the cursor and set that to a variable called rows:
>>> rows = cursor.fetchall()

This returns a list of pyodbc Row objects, which are basically tuples.

Finally, we can iterate on the Cursor and output the results of the query:
for row in rows:
    print row

This will output each row so you can see the results of your handiwork.

That's all there is to it!

Of course there are a lot of ways to get at the individual column values returned from the query, so be sure and check out the pyodbc Getting Started wiki for details.

Note that there are numerous considerations depending on the volume and nature of data with which you're dealing. For example if you have a large amount of data, using fetchall() isn't advisable since that will load all the results into memory, so you'll probably much more commonly want to use fetchone() in a loop instead since that's much more memory efficient.

You can learn all about the objects, methods, etc. involved with pyodbc in the pyodbc wiki.

Next up is pymssql!

Creating a Datasource with FreeTDS and unixODBC

In a couple of previous posts I've been working up to using Python to talk to SQL Server from Linux. There are a few moving parts involved so I'm documenting as I go.

Thus far I've done the following:
  1. Installed unixODBC
  2. Installed FreeTDS
  3. Installed pyodbc
  4. Installed pymssql
Note that pyodbc and pymssql accomplish the same thing in slightly different ways, and I'll document both as I get those set up.

To put the first two items above in perspective, unixODBC provides the underpinnings for the ODBC API on Unix/Linux platforms. unixODBC does not, however, provide what you need to talk to specific databases. For that you need ODBC drivers for each database with which you wish to communicate, which is where FreeTDS comes in.

FreeTDS is an implementation of the Tabular Data Stream protocol, which is the protocol used by SQL Server (and Sybase), and FreeTDS includes ODBC libraries that you can install in unixODBC. So when you put these two pieces together, you can talk to SQL Server from Linux over ODBC.

If you were following along with the previous couple of posts at this point you'd have unixODBC and FreeTDS installed, but FreeTDS hasn't yet been installed as a driver in unixODBC, which is what this post will cover. I found a lot of dated information out in the interwebs so hopefully this will bring things more up to date. Specifically I'm doing this on Ubuntu 12.04, so beware that the specifics of where things get installed on other distros might differ slightly (find | grep is your friend!).


Installation basically involves creating a template file for FreeTDS that we can read into unixODBC to install FreeTDS as an available ODBC driver, and then running odbcinst to install the FreeTDS driver in unixODBC.

  1. Open up a terminal and navigate to /etc/ODBCDatasources
  2. Using vim or whatever editor you prefer, create a new file. It can be called anything; I called mine tds.driver.template since that's the name I saw someone use in another post about getting this set up.
  3. Type the following into the newly created file and save it:
    Description = FreeTDS v0.91
    Driver = /usr/local/lib/
  4. Install the driver into unixODBC by running the following command:
    sudo odbcinst -i -d -f tds.driver.template
After running that final command you should see something like this:
odbcinst: Driver installed. Usage count increased to 1.
    Target directory is /etc

If you get an error -- the one I ran into was "odbcinst: SQLInstallDriverEx failed with Invalid install path" -- double-check everything and make sure to run the odbcinst command as root. I originally wasn't doing sudo which is why I got the error I saw, but when I ran the command with sudo it went away and the driver was installed.

For an extra warm fuzzy you can have unixODBC list the installed drivers:
odbcinst -q -d

Creating a Datasource

As you might be familiar with from the ODBC of the Windows world, you can pre-define ODBC datasources to easily access the datasource via an alias instead of providing all the connection details when you wish to connect.

Let's go ahead and create a datasource pointing to a SQL Server database so we have that in place for future use from Python.

Again in the /etc/ODBCDatasources directory, create a new file for your datasource. You can call the file whatever you want; I called mine dsn_foo

In that new file enter the following, adjusting according to the server and database to which you want to connect:
Driver = FreeTDS
TDS_Version = 7.2
Description = My foo datasource
Server = my.sql.server
Port = 1433
Database = foo

Couple of points about the datasource configuration file:
  • [foo] at the top is the alias/datasource name by which you'll refer to the datasource when you want to connect to it
  • Driver = FreeTDS is obviously referring to the FreeTDS driver alias that was created in unixODBC in the steps above
  • TDS_Version is dependent upon the version of SQL Server to which you're connecting. 7 is for SQL 7, 7.1 is for SQL 2000, and 7.2 is for SQL 2005 and 2008.
  • Concerning the Server setting -- I read some references to using Servername instead and providing the alias created in freetds.conf file, but other sources explicitly said NOT to use that. I stuck with Server and provided a host name since that works.
  • The rest of the settings are self-explanatory, but there's a list of all the configuration options available in the FreeTDS User Guide. Note that some settings I'm using in my examples work even though they differ from what's listed in the guide.
  • From my testing you cannot include the username and password in the datasource configuration file. Obviously that's a balance of handy vs. security concerns anyway. Some examples show including it but according to my testing as well as the FreeTDS documentation you have to provide the username and password as part of the connection string as opposed to storing it in the configuration file.

Save that file, and then install the datasource in unixODBC:
sudo odbcinst -i -s -l -f dsn_foo

If it installs successfully in true *nix philosophy you'll see nothing as a response to this action. If like me you like verifying things worked, you can list the datasources installed in unixODBC:
odbcinst -q -s

If you see your datasource listed, it's installed.

You can also check out what unixODBC puts in its configuration file based on your installation by looking at /etc/odbc.ini

Testing the Datasource

The final step in this process is to run a query against the datasource to make sure everything's working, and we'll do that using the isql tool that's included with unixODBC.

In a terminal run the following:
isql foo username password

In the command above foo is the datasource alias, and then as outlined above you do have to provide the username and password since they aren't included in the datasource configuration itself.

If everything's in order you'll get a SQL> prompt and can run SQL statements against your database.

We're getting closer to our final goal, running SQL statements against SQL Server from Python! I'll cover that in my next post.

Saturday, August 18, 2012

FreeTDS Quick Start

This is the first of a couple of follow-ups to my last post which covered how to install pyodbc on Ubuntu. The ultimate goal here is to be able to use Python (my new development weapon of choice) to communicate with SQL Server from GNU/Linux (specifically Ubuntu).

Part of this equation is to install FreeTDS, which is a set of C libraries that facilitate talking to SQL Server from Linux. I'm still wading through both pyodbc and pymssql but from what I can tell thus far both these solutions use (or can use) FreeTDS. (Random aside: if you're familiar with jTDS that's a Java implementation of FreeTDS. And another fun fact, TDS stands for "Tabular Data Stream," which is the protocol used by the native SQL Server client from Microsoft.)

Installing and using FreeTDS is simple enough but I figured I'd take notes for my own reference and share in case they help anyone else wanting to set this up.


If you're familiar with compiling and installing things from source on Linux there's nothing new here, and if you're not, this will show you just how easy this is.

First, download FreeTDS by clicking on the "stable release" link on the right-hand side of, extract the tar file, and in a terminal, navigate to the directory to which the files were extracted.

Next, type the following three commands, hitting enter after each one:
sudo make install

You'll see a ton of stuff being spit out to your terminal as you do this, but unless you see actual error messages that cause the execution of any of this to abort, that's all there is to it.

You can test the installation and get some information about the compile settings, etc. by typing this in a terminal:
tsql -C

With FreeTDS installed, now you just need to add some information to a configuration file to provide details about the servers and databases to which you wish to connect.


In your terminal, navigate to /usr/local/etc/ and in that directory you'll see the file freetds.conf Open that file in vim or your favorite text editor (note that you need to open the file using sudo).

The file contains some global settings and a couple of sample server entries, and you'll just be adding a new section to this config file.

At the bottom of the file add the following information, adjusting as appropriate with the connection information for your server and database.

    host =
    port = 1433
    tds version = 7.2

A few notes about these settings:

  • The [foo] in brackets at the top can be anything you want. That's simply an alias for these configuration settings, and we'll see how this is used in the "testing" section below.
  • The host is the host name or IP address of the server
  • The port is (obviously) the port number. By default SQL Server uses port 1433 but of course change accordingly if you're running on a non-standard port or using a named instance (which under the covers is just a port).
  • The tds version setting is specific to the version of SQL Server (or Sybase) to which you're connecting. Use 7.0 for SQL Server 7, 7.1 for SQL 2000, and 7.2 for SQL 2005 or 2008 (full details about TDS versions).

The FreeTDS docs have more details about the configuration file, including some additional settings you can include in the configuration file.


With your configuration file updated and saved, you can test your settings using the tsql utility that is installed as part of FreeTDS.

In a terminal enter the following:
tsql -S foo -U username -P password -D databasename

Notes about these flags and values:

  • The -S flag for the "server" is referring to the alias you created in the configuration file above.
  • -U is the user name and -P is the password for the database to which you wish to connect.
  • -D is the database name you wish to use after connecting to the server. If you don't provide a database name, it will connect to the default database for the user.

After you connect successfully you should see this prompt:

At that prompt you can enter and execute SQL statements against the database to which you connected.

More information about the tsql utility can be found on the "Confirm the install" page of the FreeTDS web site.

Errors and Troubleshooting

I personally didn't run into any issues in setting up FreeTDS that couldn't be chalked up to user error due to a lack of willingness to RTFM on my part.

That said, I just installed everything on a new machine this weekend and I do get an innocuous error after connecting to SQL Server:
Error 100 (severity 11):
    unrecognized msgno

At least I'm assuming it's innocuous since everything seems to be working, and unfortunately I couldn't find any additional information about this error (though admittedly I didn't hit up the mailing list yet).

Getting More Information

FreeTDS is an extremely well-documented project, so be sure and take advantage of the User Guide, which has a wealth of information about using FreeTDS in various programming languages, troubleshooting, advanced configuration, and more.

That's pretty much it for FreeTDS. Next time we'll bring pyodbc and pymssql back into the picture and start running some queries against SQL Server using Python.

Friday, August 17, 2012

Installing pyodbc on Ubuntu

If like me you have to begrudgingly talk to SQL Server on occasion, but you want to do so from Python on Ubuntu, you're in luck. As I'm finding is true with most things in the Python world there's a module to suit your needs.

Where SQL Server is concerned there are actually two modules available, pyodbc and pymssql, and I'm going to try both of these out to compare and contrast. In theory pymssql should be faster since it doesn't use ODBC, but pyodbc seemed as good a place as any to start.

Installation is simple enough in theory -- download the source zip and run:
python build install

On Ubuntu, however, you may run into an error or two due to missing libraries. Thankfully this is also quite easy to fix.

The specific error I ran into was:
cc1plus: warning: command line option ‘-Wstrict-prototypes’ is valid for Ada/C/ObjC but not for C++ [enabled by default]

The fix is to install the unixodbc libraries as well as the python-dev libraries:
sudo apt-get install unixodbc-dev unixodbc-bin unixodbc python-dev python2.7-dev

With those installed the build and install for pyodbc works.

Next up is actually using pyodbc to talk to SQL Server, so expect a follow-up post relatively soon.

Saturday, August 4, 2012

Pidgin, SIPE, and Read Error on Ubutnu 12.04

I think I may have posted about this before but I couldn't find it, so since I was doing a clean install of Ubuntu 12.04 on one of my laptops this weekend I figured I'd write it up again.

If you're on Ubuntu 12.04, you use Pidgin (which you should -- Empathy sucks), and you need to connect to MS Lync (formerly known as Office Communicator), thankfully you can simply install the SIPE plugin for Pidgin:
sudo apt-get install pidgin-sipe

In my case I also had to specify this as the User Agent to get it to connect:
UCCAPI/4.0.7577.314 OC/4.0.7577.314 (Microsoft Lync 2010)

There's one additional wrinkle on Ubuntu 12.04, because even after installing the SIPE plugin and setting the user agent, you may see "Read error" when you try to connect.

You're never alone on the Internet -- other people have run into this too, and the solution is simple enough, but since I didn't want to have to do that every time I launched Pidgin I put that in a bash script and changed the Pidgin launcher to point to this script.

You can put this anywhere so long as it's executable, but here's the script:

I feel like a bad nerd by admitting that I have no idea what that does and didn't take the time to look into it since it solved my problem, but there's the solution that works for me.

Notes on Practical Django Projects (Part 1)

I'm currently making my way through Practical Django Projects by James Bennett and thought I'd share some notes and errata as I go along. (Side note: If you want a paper copy of this book, it's dirt cheap at; just make sure to get the second edition which was published in 2008).

I've done a small amount with Python here and there in the past (writing some scripts to handle very specific tasks or that used libraries available in Python that were better than what's available in Java) and always really liked the language, but I haven't ever looked into building webapps with Python until now.

So far I'm quite impressed. Having worked with Grails a little in the not-too-distant past I'm finding Django to be similar conceptually but a little simpler, and it seems to be extremely well thought-out and strike an excellent balance between forcing a convention on the developer and requiring just enough to configuration to maintain a lot of flexibility.

I'll save a more thorough review of Django for a future date when I have it under my belt better, but for now I wanted to point out a stumbling block I hit due to a minor lack of specificity in the book.

For those of you even less familiar with Django than I am, Django operates on the concept of a high-level project and within that project are one or more applications. Conceptually this is similar to what other frameworks might call a module, or kinda-sorta-but-not-completely like a Grails plugin. The point is that Django projects are built of multiple modular building blocks, which is a really great way of organizing things.

On my machine I'm building all this stuff in a ~/djangoprojects directory, so inside there I have a cms directory for the simple CMS that you build as one of the projects in the book. So ~/djangoprojects/cms is the project directory, and inside that directory is a cms directory (so ~/djangoprojects/cms/cms) for the CMS application that is part of this project.

This is the way it should be, I believe, since you first run a script to create the project, then navigate into the project directory and run another script to create the first application that will make up the project. (If anyone with Django experience reads this and what I'm saying here isn't accurate, I'd love to be corrected so I can learn.)

Beginning on page 43 you add a search system to the CMS, and following the modular convention you start things off by running the startapp script from the project directory.

On page 43 it reads:
So let's make this into its own application. Go to your project [emphasis mine] directory and type the following command: 
python startapp search

The problem is the book gets the terminology a bit wrong (based on my understanding of the terminology thus far at any rate) and this leads to an error which took me a little time to track down, probably largely due to my newbness with Django.

As directed I went into my project directory and created the search application, which means I wound up with a cms directory and a search directory at the same level in the project (which again, I believe is how it's supposed to be), so specificially I have these directories:

Later you add a URL pattern to the project's file to tell Django what URL route you want to use to hit the search application:
(r'^search/$', '')

When I ran the code, I was getting the error "ImportError at /search/ No module named search"

Note the path to the search application in the URL pattern above:

I probably should have noticed that right away since that indicates the search application would be inside the cms application, but since I created search in the project directory instead of the cms application directory, a simple change to the URL pattern to ommit the cms. at the beginning fixed the problem:
(r'^search/$', '')

As I said above all of this could be my own misunderstanding, and maybe the cms and search applications aren't supposed to be siblings, so if someone comments with a simple "you're wrong" that's a great way for me to learn. I did notice that Phil Gyford who was nice enough to put his completed source for the book online got it "right" so might just be me.

I'll share more notes/thoughts as I make my way through the rest of this (so far) excellent book, and if you have questions about any of this or thoughts you'd like to share about Python and Django I'd love to hear them.