Installing Homebrew & Fabric on OSX 10.9 Mavericks

I’ve just upgraded my Mac at work to 10.9.1 Mavericks. No messing about – completely clean install on a formatted disc. Last year I wrote a quick post about installing Fabric on my Mac, this is an update of that post to reflect a few changes.

If you don’t know…

Fabric is a Python (2.5 or higher) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.

I think Fabric is a good solution to manage the deployment of websites and applications – it is an integral part of my workflow these days.

Homebrew is a package manager for OSX and is an alternative to the commonly used MacPorts. You can find out a bit more about the differences between them in this thread on arstechnica.

Install Command Line Developer Tools

These were previously part of Xcode but now need to be installed separately, open a terminal and type:

xcode-select --install

…and follow the prompts.

Install Homebrew

The address of the download appears to have chnaged slightly since last year…

ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"

…and follow the prompts.

When you see the successful installation message, type:

brew doctor

This will alert you to any problems that you need to resolve.

If everything is good you should see the following message:

Your system is ready to brew.

Install Git, Python and Fabric

brew install git
brew install python

You now need to edit your system paths so that Python can be found:

I edited my .bashrc file: nano ~/.bashrc and added the following line:

export PATH=/usr/local/bin:/usr/local/sbin:~/bin:$PATH

And then /etc/paths sudo nano /etc/paths so that usr/local/bin (the location of packages installed by Homebrew) is first:

/usr/local/bin
 
/usr/local/sbin
 
/usr/bin
 
/bin
 
/usr/sbin
 
/sbin

And finally install Fabric. There isn’t a Homebrew package available by default, so I just installed Fabric using pip – the pip package manager for Python is installed at as part of Python.

pip install fabric

Check if it works…

Let’s check and see if everything has worked…

$ fab
 
Fatal error: Couldn\'t find any fabfiles!
 
Remember that -f can be used to specify fabfile path, and use -h for help.
 
Aborting.

In this case the Fatal error is good. It means that Fabric has installed correctly and you now need to write some fab files.

Installing Homebrew & Fabric on OSX

I recently started using Fabric to simplify my deployment process.

Fabric is a Python (2.5 or higher) library and command-line tool for streamlining the use of SSH for application deployment or systems administration tasks.

I quite like Fabric – I’m not 100% sold, but it’s easy to get started with and it won’t be long until you can write complex scripts.

Being able to deploy a complex app with a single command is great. I do not miss long checklists and having to run through step after step in a hurry.

fab deploy

Pretty easy isn’t it?

Why Fabric? To be honest – why not. I know a little bit of Python, so why not learn a bit more? I like the glueyness, the fact that it (mostly) lets you get on with things and doesn’t force you to work in a particular way.

I had a devil of a time getting it up and running though on my Mac running 10.6.8 (Snow Leopard).

Getting started…

Homebrew http://mxcl.github.io/homebrew/
is a package manager for OSX and alternative to MacPorts. Install Fabric and Python via Homebrew to (hopefully) make your life a bit easier…

Install Homebrew

Open a terminal. Run the commands as your user, not sudo

ruby -e "$(curl -fsSL https://raw.github.com/mxcl/homebrew/go)"

Install Homebrew and then check the install.

brew doctor

Running brew doctor will identify any problems with your install. Any problems are displayed. Work through any issues it flags up one by one. In my case I ended up having to remove MacPorts and had to reinstall Xcode.

Remove MacPorts

MacPorts is another package manager, but apparently it often doesn’t play with Homebrew.

Follow the instructions http://guide.macports.org/chunked/installing.macports.uninstalling.html

sudo port -fp uninstall installed
sudo rm -rf \
    /opt/local \
    /Applications/DarwinPorts \
    /Applications/MacPorts \
    /Library/LaunchDaemons/org.macports.* \
    /Library/Receipts/DarwinPorts*.pkg \
    /Library/Receipts/MacPorts*.pkg \
    /Library/StartupItems/DarwinPortsStartup \
    /Library/Tcl/darwinports1.0 \
    /Library/Tcl/macports1.0 \
    ~/.macports

Remove Xcode

Xcode is Apple’s Integrated Development Environment (IDE) containing tools for developing software for OS X and iOS.

Based on issues listed by brew doctor I removed Xcode and the re-installed it.

sudo /Developer/Library/uninstall-devtools --mode=all

Make sure you have your Apple ID to hand if you don’t have the .dmg and need to download it from Apple.

Install Git

Next I installed Git using Homebrew if you do not already have it (I use Mercurial day to day, so I didn’t)

brew install git
brew upgrade git

Install python

brew install python

Update your paths to use the version of Python that you’ve just installed.

sudo nano /etc/paths
nano ~/.bashrc

Install Fabric

pip install fabric

Edit: To install Fabric you need to use the pip package manager which was installed as part of Python.

Phew! Everything should be working now… time to write a fabfile.py

Setting TinyMCE configs in Django settings.py

Working with the Django Filebrowser and TinyMCE I have just spent quite a while with an utterly frustrating problem.

I want to set all my my inserted image paths to absolute e.g. /media/uploads/someimge.jpg – in TinyMCE the way to do this is to set “convert_urls”: false

The relevant part of my settings.py file looked like this:

TINYMCE_DEFAULT_CONFIG = {
    'plugins': "table,spellchecker,paste,searchreplace",
    'theme': "advanced",
    'theme_advanced_toolbar_location' : "top",
    'theme_advanced_toolbar_align' : "left",
    'theme_advanced_statusbar_location' : "bottom",
    'theme_advanced_resizing' : "true",
    'convert_urls' : "false"
}

But nothing worked and my images were all being inserted as ../../../media/uploads/someimge.jpg

Eventually looking at the generated source of my page I realised that the problem was this was rendering “convert_urls”: “false” it should be rendering “convert_urls”: false

The solution is pretty obvious – but then they usually are:

TINYMCE_DEFAULT_CONFIG = {
    'plugins': "table,spellchecker,paste,searchreplace",
    'theme': "advanced",
    'theme_advanced_toolbar_location' : "top",
    'theme_advanced_toolbar_align' : "left",
    'theme_advanced_statusbar_location' : "bottom",
    'theme_advanced_resizing' : True,
    'convert_urls' : False
}

The reason it took me so long to figure out was that I tried to use ‘convert_urls’ : false – which just resulted in syntax error – coming from PHP I’m used to booleans being case insensitive – in Python they aren’t. It also explains why my ‘theme_advanced_resizing’ didn’t work either.

Flirting with Django – part 3 – setting plural model names in admin

This is probably a bit obvious to any experienced Django user, but it took me a bit of digging to find.

In Django when you create a model to use the automatic admin interface you have to add it to the admin.py file.

Here is an example which only includes a ‘news’ model:

1
2
3
4
5
6
7
8
 
from s2.portfolio.models import News
from django.contrib import admin
 
class NewsAdmin(admin.ModelAdmin):
    pass
 
admin.site.register(News)

The trouble is that it shows up in your Django admin interface as ‘Newss’ which is obviously a bit lame.

The answer is quite simple once you know how, you need to add ‘Meta’ information the model class (I believe this is an example of an ‘internal class’). The ‘Meta’ class contains information about each model such as the ordering with which records should be displayed in the admin etc. This is documented in the Django documentation here.

Example news model including the Meta information

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
class News(models.Model):
    title = models.CharField(max_length=200)
    summary = models.CharField(max_length=200)
    description = tinymce_models.HTMLField()
    slug = models.CharField(max_length=200)
    live = models.BooleanField(default=1)
    date = models.DateField()
 
    def __unicode__(self):
        return self.title
 
    class Meta:
        verbose_name_plural = 'News'

Like most things, easy when you know how!