2011 In Review

Since it seems that everyone and their mother is doing a "year in review" post, I find it fitting that I be no different and write one as well - except it's three weeks later than everyone else. 2011 was an exciting year for me for a variety of reasons, as I went through some big work and life changes, met some great new friends, and reunited with a few long lost ones.

Work

In February of 2011, I left my job at exhibit-E where I was a web developer making web sites for the art world. Over the past few years, I've always done freelance work on the side whether it be small contract jobs or building full social networking websites as a solo developer. My decision to leave exhibit-E seemed to make sense now - I wanted to see if I had what it took to survive as a full-time freelancer while working under my own company name before I got too old and perhaps couldn't take on so much risk. I wasn't too concerned with finding work, but more so about being able to GROW my own company; the latter obviously being the hardest part. Within a week or two, I managed to land myself a great gig as the lead developer for the RachaelRayShow.com...and now it was off to the races!

Conferences

In March, I went to PyCon 2011 in Atlanta, GA. This was my first programming conference and I met some fantastically smart people there - some of which I'm fortunate to actually work with right now on some of 3atmosphere's current projects, and some that I still keep in contact with via email. The talks were great and the "networking" at night (aka exploring ATL's nightlife) was the best part of the trip. I'm really looking forward to returning to PyCon again this year.

Nick's new laptop
Nick holding up his new laptop that we bought at a mall in Atlanta during PyCon...during iPad 2 (insanity) launch day!

More Work!

Over the next few months into the early summer, the project load at 3atmospheres really started to pick up. I take pride in the fact that I never made one cold call or solicited ads for work - all the requests we got in were from word-of-mouth and I couldn't be more proud of our humble beginning. It picked up so much that the once lonely one-man show (me!) turned into (at the peak) six people working on several different projects. I found myself quickly transitioning from coding to project management, which I would say still is evenly split for me today. Out of necessity for a meeting spot, we bought some seats at General Assembly where we currently work.

On a personal note, I got engaged at the end of the summer to my lovely girlfriend of over four years, Patricia, which easily made 2011 the best year of my life thus far.

More Conferences!

In September, I was fortunate enough to get to go to three conferences:

And for the rest of the fall season into winter, it was just work, work, and more work - literally every free hour I had was devoted to meeting the deadlines that were set at the end of the year.

Let's Wrap It Up...

2011 was a great year and I've never worked harder, been more tired, and, at the same time, had as much fun as I've ever had in my professional career. I am so lucky to have gotten to meet and work with such smart people, clients and coworkers alike, and I'm extremely proud at how far we've come today. Admittedly, it wasn't always rainbows and butterflies with work, but for all the negative moments I've had this year, I've used it as a learning experience and I wouldn't trade it for a second. I get to program in languages and frameworks of my choosing (Python and Django!) and get to work with people that are smarter than me. Here's to a great 2011 and an even better 2012!


Virtualenv and pip Basics

When doing any kind of Python development, one tool I find indispensable is virtualenv. Virtualenv, along with virtualenvwrapper and pip, make for a great way to completely isolate your development environment.

When I first started out developing Django sites, I used to use easy_install to install all packages I needed to the system-wide site-packages directory. Even as a newbie to Django, I knew this wasn't good practice, but it ensured that commonly used libraries such as MySQL-python was available without any extra configuration with new projects. Regardless, completely isolating your environment with virtualenv ensures that a) you don't install conflicting packages and b) any bugs introduced in your project can be traced back directly to the packages you installed. Also, a huge benefit is that it makes installing multiple versions of Python super easy without having to create any symlinks.

Getting started with Virtualenv and pip

The first thing you will need to do is install pip. If you have setuptools installed, which you most likely will with most modern platforms, you can install pip through easy_install:

easy_install pip

Next, you'll need to install virtualenv with pip:

pip install virtualenv

Finally, I would highly recommend installing virtualenvwrapper as it makes it much easier to create and start virtual environments:

pip install virtualenvwrapper

As part of the install instructions for virtualenvwrapper, you need to add this to your .bash_profile

# virtualenv
export WORKON_HOME=$HOME/.virtualenvs
source /Library/Frameworks/Python.framework/Versions/2.7/bin/virtualenvwrapper.sh

*Please note that this path may differ depending on what version of Python you have. Also, I like to keep all my virtualenvs in a directory called .virtualenvs in my home directory, but this may differ for you if you choose to keep your virtual environments in a different directory.

Make sure you source your new .bash_profile

source ~/.bash_profile

...and that's it! Now you're all set to start using virtual environments!

Creating a Virtual Environment

A few handy aliases I have in my .bash_profile are found on Doug Hellmann's blog and listed below:

# virtualenv aliases
# http://blog.doughellmann.com/2010/01/virtualenvwrapper-tips-and-tricks.html
alias v='workon'
alias v.deactivate='deactivate'
alias v.mk='mkvirtualenv --no-site-packages'
alias v.mk_withsitepackages='mkvirtualenv'
alias v.rm='rmvirtualenv'
alias v.switch='workon'
alias v.add2virtualenv='add2virtualenv'
alias v.cdsitepackages='cdsitepackages'
alias v.cd='cdvirtualenv'
alias v.lssitepackages='lssitepackages'

This saves some keystrokes, especially since I always create new virtual environments with the --no-site-packages switch to ensure a completely clean environment.

To create and start a new virtual environment with --no-site-packages, enter:

$ v.mk myvirtualenv
New python executable in myvirtualenv/bin/python
Installing setuptools............done.
(myvirtualenv) $

This creates and virtual environment and makes it active. To deactivate it, you can simply type:

(myvirtualenv) $ deactivate
$

So let's go ahead and start our virtual environment once again and install some packages to it.

$ v myvirtualenv
(myvirtualenv) $

We're going to install Python package Yolk as it is a useful command line utility that lists the packages installed for the environment.

$ v myvirtualenv
(myvirtualenv) $
(myvirtualenv) $ pip install yolk
Downloading/unpacking yolk
  Downloading yolk-0.4.1.tar.gz (80Kb): 80Kb downloaded
  Running setup.py egg_info for package yolk

Requirement already satisfied (use --upgrade to upgrade): setuptools in /Users/jonathan/.virtualenvs/myvirtualenv/lib/python2.7/site-packages/setuptools-0.6c11-py2.7.egg (from yolk)
Installing collected packages: yolk
  Running setup.py install for yolk

    Installing yolk script to /Users/jonathan/.virtualenvs/myvirtualenv/bin
Successfully installed yolk
Cleaning up...

Now you can use yolk -l to list the packages installed for this virtual environment:

(myvirtualenv) $ yolk -l
Python          - 2.7.1        - active development (/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-dynload)
pip             - 0.8.1        - active
setuptools      - 0.6c11       - active
wsgiref         - 0.1.2        - active development (/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7)
yolk            - 0.4.1        - active

Here is a brief one-line example showing how to create a virtualenv and install Django, MySQL Python, South, Python Imaging Library (PIL), and ImageKit using pip:

$ v.mk newdjangoenv
(newdjangoenv) $ pip install django MySQL-python south pil django-imagekit

When you have your requirements installed, it's always good to take a snapshot of the requirements and the current versions. You can do this by typing freeze and specifying an output file:

(newdjangoenv) $ pip freeze > requirements.txt

And finally, you can use the requirements.txt file so that your environment is completely and easily replicable:

$ pip install -r requirements.txt

And there you have it -- you can now create and test your Python applications in completely isolated environments!

For more on pip and virtualenv, check out this great post by Salty Crane which got me started on all this.


New Blog Platform

After a long blogging hiatus, I recently decided to switch over my custom Django blog to a static site generator, following the trend that many others have started. What made the switch so appealing, going from a full-featured blogging engine to a simple static site generator, was that I could write my blog entries in a text editor of my choice and keep everything under version control with Git. A simple push to the production server would serve my static pages up via Nginx, which in the end would take up far less resources and memory than a Django-powered blog application or even Wordpress. So with that, I decided to search for a static site generator that would suit me. I did some research and narrowed my choices down to three static site generators:

Jekyll is the creation of @mojombo, in which he refers to it as "Blogging Like a Hacker" as he so eloquently put it in his article. He pretty much hit the nail on the head; blogging becomes a bit of a hassle when you use a complicated blogging engine like Wordpress and the likes. Many are using Jekyll and seem to be very happy with it.

In the end, I decided to go with Growl. I chose Growl because it was pure Python, had support for Jinja2, and was extremely lightweight with few dependencies. I decided not to go with Jekyll, arguably the most popular static site generator currently out there, because I wasn't too fond of the templating language. Also, I decided not to go with Hyde simply because I prefer Jinja2 over Django templates, which is utilized in Hyde.

Growl is written by Rico Schiekel and "shamelessly stole some really cool ideas from Jekyll", which is absolutely awesome in my opinion. I think it's great that software can be created from borrowing the best parts of other pieces of software, regardless of language.

This blog is written and compiled with a slightly modified version of Growl. So far, I'm loving the writing process:

You can find out more about Growl by reading its documentation. Here are some of the main features of Growl:

The basic structure of my blog looks something like this:

Jontourage Directory Structure

All files that end with an underscore, such as index.html_ for example, get processed by Growl as a page. All processed pages and media assets get dumped in the deploy directory, which serves up your static site.

Posts need to be named in the following structure:

2011-01-18-new-blog-platform.md2

When the posts are processed by Growl, the date 2011-01-18 gets parsed and the directory structure is created - http://jontourage.com/2011/01/18/new-blog-platform/

As for the post content itself, it simply is a mix of YAML and Markdown. Here's an example of what a post header looks like:

---
layout: post
title: New Blog Platform
publish: false
---

And the rest of the post is just Markdown! When I'm done writing the article, I simply push to GitHub and sync up the production server using a rsync hook:

$ growl.py --deploy jontourage

And that's it! You can checkout my blog and the structure in more detail here.


Review: MacBook Air 13"

I recently decided to purchase a MacBook Air to use as my primary computer, saying goodbye to my previous laptop - a 15" MacBook Pro with a HiRes AntiGlare display, 2.66GHz i7, 8GB RAM, and 500GB HD @ 7200RPM, NVIDIA GeForce GT 330M with 512MB memory. I went with the 13", 2.13GHz Core 2 Duo, 4GB RAM, 256GB flash storage configuration and could not be happier with its performance. Portability was a very important factor to me in making this decision, as I carry my laptop with me everyday. It's been serving as my primary computer for the past three weeks and the transition has been absolutely seamless.

MBA 1

Hardware

The Air weighs in at about 3 lbs and is surprisingly sturdy in terms of build. Being a MacBook Pro user for most of my developer life, I was a little wary that the build quality was going to be less sturdy from what I'm used to, which was not the case at all. The glossy screen on the Air was a concern of mine before purchasing, especially since I just came from a matte display. The glossy screen on the stock MacBook Pro's is just too glossy for me to not be annoying. The Air is a good middle ground - albeit not matte, it offers good enough contrast and isn't as glossy as the MacBook Pro line. One thing I am missing on the Air is a backlit keyboard. The lack of ethernet port has never bothered me as I have a wireless-N network at home which offer better speeds than your average B/G network.

MBA 2

One thing that does annoy me is that the Air does not fit well on my Rain Design mStand. As you can see in the picture below, aluminum does not rest on the pads because of the thinness.

MBA 3

Performance

Despite the fact that the Air has a far inferior processor and only half the amount of RAM as my previous laptop, I can honestly say that the Air just feels faster. Most applications launch within one second, such as the Microsoft Office apps, while the Adobe CS5 Suite launches within a respectable two to three seconds. The flash storage is the obvious difference maker here. As for configuration, I decided to start with a new install and not restore from a Time Machine backup. The first thing I did was install Xcode and Homebrew, along with a bunch of apps that I use daily for development. At the end of the whole config and install process, the Applications folder takes up about 15GB and my iTunes library takes up about 47GB of disk space, leave roughly 135GB remaining - which is more than enough space left. Considering what's on the flash storage, it takes ~15 seconds to boot up and ~25 seconds to shut down.

The resolution on the Air is 1440x900, which is the same as the 15" MacBook Pro, but greater than the 13" MacBook Pro's 1280x800. When I'm at home, the Air is connected to my Apple LED Cinema Display 24" model (discontinued) and supports 1920x1200. The connectors make for a perfect fit being that the MiniDisplay Port is on the right side of the laptop, while the power and USB are on the left.

MBA 4

MBA 5

As far as graphic intensive applications and games, I haven't tried playing any games or doing any video editing, but I can imagine there will be some limitations. I've read in several places that games such as World of Warcraft and StarCraft II run perfectly fine on the MacBook Airs and may even start up faster, but the framerate is lower. This is a limitation I can deal with given the hardware.

Likes

Dislikes

Conclusion

I feel like the MBA is changing the way I work and I absoutely love that. Now that I have a more portable laptop, I find myself working in places that I normally wouldn't (and didn't with my 15" MacBook Pro, i.e. - on the couch in front of the TV). If not having a DVD drive is a dealbreaker, I would say this isn't the laptop for you. All in all, I could not be happier with the Air. It's an excellent laptop and has been able to handle all my tasks with ease.