Now, this as well might be a feature, but doctest strings are not being executed for decorated functions (at least in version 2.7). However, there is a workaround.

You need to decorate your functions with functools.wraps within a decorator to import docstrings into a decorator scope.

#!/usr/bin/env python

from functools import wraps

def decorator(func):
    def wrapper():
        return func()
    return wrapper

def foo():
    >>> foo()
    return True

import doctest

Now you can see this test failing, where otherwise it would have been ignored:

File "", line 12, in
Failed example:
1 items had failures:
   1 of   1 in
***Test Failed*** 1 failures.

When it comes to tests, doctest is a great simple module to write tests for your application. However it is pretty basic and does not have any extended features like, for example, centralized unit tests. If you have multiple modules with doctests (and you probably do) you most likely want to be able to run all doctests recursively from one place. That’s where unittest comes in.

Let’s assume we store modules in the lib/ directory:

$ ls lib/

Here are the contents of and respectfully:

def foo():
    >>> foo()
    return False

def bar():
    >>> bar()
    return True

def baz():
    >>> baz()
    return False

Now, to run all tests we need a wrapper script. Let’s call it:

#!/usr/bin/env python

import unittest
import doctest
import os

files = []
root_dir = 'lib/'

for root, _, filenames in os.walk(root_dir):
    for filename in filenames:
        if filename == '' or filename[-3:] != '.py':
        f = os.path.join(root, filename)
        f = f.replace('/', '.')
        f = f[:-3]

suite = unittest.TestSuite()
for module in files:

This approach invokes the doctest.DocTestSuite method, which converts doctests strings into unittest suites. Time to run our tests:

$ chmod +x
$ ./
Ran 3 tests in 0.008s


And just to be sure that approach actually works, let’s make one of the tests fail:

$ ./
FAIL: baz (
Traceback (most recent call last):
  File "/usr/lib/python2.7/", line 2201, in runTest
    raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for
  File "/home/rosipov/unitdoc/lib/", line 8, in baz

File "/home/rosipov/unitdoc/lib/", line 10, in
Failed example:

Ran 3 tests in 0.009s

FAILED (failures=1)

I had an issue with pygame not being able to find a dependency for the font module. After quite a time-consuming search the missing package name was libsdl-ttf2.0-dev.

Hope this helps someone.

Using vimdiff as a git mergetool can be pretty confusing - multiple windows and little explanation. This is a short tutorial which explains basic usage, and what the LOCAL, BASE, and REMOTE keywords mean. This implies that you have at least a little bit of basic vim knowledge (how to move, save, and switch between split windows). If you don’t, there’s a short article for you: Using vim for writing code. Some basic understanding of git and branching is required as well, obviously.

Git config

Prior to doing anything, you need to know how to set vimdiff as a git mergetool. That being said:

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

This will set git as the default merge tool, will display a common ancestor while merging, and will disable the prompt to open the vimdiff.

Creating merge conflict

Let’s create a test situation. You are free to skip this part or you can work along with the tutorial.

mkdir zoo
cd zoo
git init
vi animals.txt

Let’s add some animals:


Save the file.

git add animals.txt
git commit -m "Initial commit"
git branch octodog
git checkout octodog
vi animals.txt  # let's change octopus to octodog
git add animals.txt
git commit -m "Replace octopus with an octodog"
git checkout master
vi animals.txt  # let's change octopus to octoman
git add animals.txt
git commit -m "Replace octopus with an octoman"
git merge octodog  # merge octodog into master

That’s where we get a merge error:

Auto-merging animals.txt
CONFLICT (content): Merge conflict in animals.txt
Automatic merge failed; fix conflicts and then commit the result.

Resolving merge conflict with vimdiff

Let’s resolve the conflict:

git mergetool

This looks terrifying at first, but let me explain what is going on.

From left to right, top to the bottom:

LOCAL – this is file from the current branch BASE – common ancestor, how file looked before both changes REMOTE – file you are merging into your branch MERGED – merge result, this is what gets saved in the repo

Let’s assume that we want to keep the “octodog” change (from REMOTE). For that, move to the MERGED file (Ctrl + w, j), move your cursor to a merge conflict area and then:

:diffget RE

This gets the corresponding change from REMOTE and puts it in MERGED file. You can also:

:diffg RE  " get from REMOTE
:diffg BA  " get from BASE
:diffg LO  " get from LOCAL

Save the file and quit (a fast way to write and quit multiple files is :wqa).

Run git commit and you are all set!

This alias has been around the web for quite some time, but it does look fantastic indeed.

To add the alias git pretty-log, execute the following command (join string prior to executing):

git config alias.pretty-log 'log --graph --pretty=format:"%Cred%h%Creset
-%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset"'