Installing Older Versions of Python with Brew

Published on

I created a brew tap for installing older versions of python on my own machine. The source code is located at


The formula openssl needs to be installed and linked, otherwise the python installed will be without ssl support.

$ brew install openssl
$ brew link --force openssl


Start by adding the brew tap derekkwok/python

$ brew tap derekkwok/python

Adding this brew tap will make all the formulas in the Github repository derekkwok/python available to be brew installed. The following formulas are available in this tap:

  • python26 - version 2.6.9
  • python31 - version 3.1.5
  • python32 - version 3.2.6
  • python33 - version 3.3.6
  • python34 - version 3.4.4

Example 1: installing python 3.4

$ brew install python34
$ python3.4 --version
Python 3.4.4

Example 2: installing python 2.6

$ brew install python26
$ python2.6 --version
Python 2.6.9

These formulas will not overwrite any existing symlinks to python and python3. As an example, if the python3 formula is installed from the official brew repository, the python3 symlink will still point to the original brew installation of python.

The older versions of python will work with virtualenv

$ mkvirtualenv venv --python=/usr/local/bin/python3.4
(venv) $ python --version
Python 3.4.4
(venv) $ pip --version
pip 7.1.2 from ... (python 3.4)


To uninstall, use the commands brew uninstall and brew untap E.g.

$ brew uninstall python26 python34
$ brew untap derekkwok/python
  • python
  • homebrew

Implementing a Compressed TextField in Django

Published on

I recently answered an interesting question on Stack Overflow - how can text be stored compressed in the database?

Django itself doesn't offer anyway to store data compressed, but this is actually quite easily implemented using zlib (also used by gzip for compression)

class CompressedTextField(models.TextField):

    def __init__(self, compress_level=6, *args, **kwargs):
        self.compress_level = compress_level
        super(CompressedTextField, self).__init__(*args, **kwargs)

    def to_python(self, value):
        value = super(CompressedTextField, self).to_python(value)
        return zlib.compress(value.encode(), self.compress_level)

    def get_prep_value(self, value):
        value = super(CompressedTextField, self).get_prep_value(value)
        return zlib.decompress(value).decode()

Here is an example using CompresssedTextField

class MyModel(models.Model):

    # zlib offers compression levels 0-9
    #    0 is no compression
    #    9 is maximum compression
    big_text = CompressedTextField(compress_level=9)

As an example, I generated 1000 words of lorem ipsum that used 7,411 bytes. After compression it was reduced down to 2,360 bytes - a savings of 5,051 bytes or 68% reduction in size!

As a side note, most databases already have some built-in form of compression for stored data, which means this solution may not yield actual storage benefits. Another down side of using such a field is django filters such as contains and icontains no longer work.

  • django
  • python

Generate Multi-Domain CSR with openssl

Published on

Start by copying your system's openssl.cnf and opening it in your favorite editor. The copied file will be used as the config for our certificate signing request (CSR).

$ cp /etc/ssl/openssl.cnf
$ vi openssl.cnf

In the section marked as [ req ], uncomment the following line by removing #.

req_extensions = v3_req

In the section marked as [ v3_req ], add the following line

subjectAltName = @alt_names

At the bottom of the file, add a new section with a list of domains for your CSR:

[ alt_names ]

DNS.1 =
DNS.2 =
DNS.3 =

Now we're ready to generate a CSR. Start by creating a new private key

$ openssl genrsa -out 4096

Then generate a CSR

$ openssl req -new -key -out -config openssl.cnf

A new file called should have been created. This file is your certificate signing request! Verify the contents of the generated CSR and make sure it contains the correct information

$ openssl -req -in -noout -text

The text should contain a section with Alternative Name

X509v3 Subject Alternative Name:,,
  • ssl
  • openssl
  • https

ffmpeg -map option examples

Published on

The ffmpeg -map option is used to map input streams to output streams. In short, it's used to specify the input streams you want in the output file.

Here is a video file with 7 streams:

$ ffmpeg -i input.mkv
Stream #0:0: Video: h264 (High), yuv420p, 640x480, SAR 1:1 DAR 4:3, 29.97 fps, 29.97 tbr, 1k tbn, 59.94 tbc (default)
Stream #0:1(eng): Audio: ac3, 48000 Hz, stereo, fltp, 256 kb/s (default)
Stream #0:2(jpn): Audio: ac3, 48000 Hz, stereo, fltp, 256 kb/s
Stream #0:3(eng): Subtitle: subrip (default)
Stream #0:4(jpn): Subtitle: subrip
Stream #0:5(eng): Subtitle: dvd_subtitle, 720x480
Stream #0:6(jpn): Subtitle: dvd_subtitle, 720x480
  • stream #0:0 is the video stream
  • stream #0:1 and #0:2 are the audio streams for English and Japanese respectively
  • stream #0:3 and #0:5 are different version of subtitles for the English audio
  • stream #0:4 and #0:6 are different version of subtitles for the Japanese audio

Example 1

An output file that contains the video and Japanese audio

$ ffmpeg -i input.mkv -map 0:0 -map 0:2 output.mkv

Example 2

Extracting the subtitles for Japanese audio (non-dvd version)

$ ffmpeg -i input.mkv -map 0:4 subtitles.ass

Example 3

Extracting the English audio track as an mp3 file

$ ffmpeg -i input.mkv -map 0:1 output.mp3
  • ffmpeg