diff --git a/README.rst b/README.rst
index c553949d36757a338d4a10febc35185df15a21bd..02b0f6a89e497d67c54bace3e38ffee0fd195562 100644
--- a/README.rst
+++ b/README.rst
@@ -16,8 +16,6 @@ It includes examples with three different complexities:
 To use this example, you will require Bob and the AT&T database.
 If you do not have a Bob version yet, you can get it from http://www.idiap.ch/software/bob.
 
-If you already have installed Bob, please make sure that you have the version 1.0.5, otherwise the example won't work.
-
 The AT&T image database is quite small, but sufficient to show how the face verification methods work.
 Still, the results may not be meaningful.
 One good thing about the AT&T database is that it is freely available.
diff --git a/bootstrap.py b/bootstrap.py
index 7647cbbe10e7638d71079fd8f6ca295e89941a51..ec3757a965c4a28ffd6cd900f4f5260239a30bcc 100644
--- a/bootstrap.py
+++ b/bootstrap.py
@@ -18,75 +18,10 @@ The script accepts buildout command-line options, so you can
 use the -c option to specify an alternate configuration file.
 """
 
-import os, shutil, sys, tempfile, urllib, urllib2, subprocess
+import os, shutil, sys, tempfile
 from optparse import OptionParser
 
-if sys.platform == 'win32':
-    def quote(c):
-        if ' ' in c:
-            return '"%s"' % c  # work around spawn lamosity on windows
-        else:
-            return c
-else:
-    quote = str
-
-# See zc.buildout.easy_install._has_broken_dash_S for motivation and comments.
-stdout, stderr = subprocess.Popen(
-    [sys.executable, '-Sc',
-     'try:\n'
-     '    import ConfigParser\n'
-     'except ImportError:\n'
-     '    print 1\n'
-     'else:\n'
-     '    print 0\n'],
-    stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
-has_broken_dash_S = bool(int(stdout.strip()))
-
-# In order to be more robust in the face of system Pythons, we want to
-# run without site-packages loaded.  This is somewhat tricky, in
-# particular because Python 2.6's distutils imports site, so starting
-# with the -S flag is not sufficient.  However, we'll start with that:
-if not has_broken_dash_S and 'site' in sys.modules:
-    # We will restart with python -S.
-    args = sys.argv[:]
-    args[0:0] = [sys.executable, '-S']
-    args = map(quote, args)
-    os.execv(sys.executable, args)
-# Now we are running with -S.  We'll get the clean sys.path, import site
-# because distutils will do it later, and then reset the path and clean
-# out any namespace packages from site-packages that might have been
-# loaded by .pth files.
-clean_path = sys.path[:]
-import site  # imported because of its side effects
-sys.path[:] = clean_path
-for k, v in sys.modules.items():
-    if k in ('setuptools', 'pkg_resources') or (
-        hasattr(v, '__path__') and
-        len(v.__path__) == 1 and
-        not os.path.exists(os.path.join(v.__path__[0], '__init__.py'))):
-        # This is a namespace package.  Remove it.
-        sys.modules.pop(k)
-
-is_jython = sys.platform.startswith('java')
-
-setuptools_source = 'http://peak.telecommunity.com/dist/ez_setup.py'
-distribute_source = 'http://python-distribute.org/distribute_setup.py'
-
-
-# parsing arguments
-def normalize_to_url(option, opt_str, value, parser):
-    if value:
-        if '://' not in value:  # It doesn't smell like a URL.
-            value = 'file://%s' % (
-                urllib.pathname2url(
-                    os.path.abspath(os.path.expanduser(value))),)
-        if opt_str == '--download-base' and not value.endswith('/'):
-            # Download base needs a trailing slash to make the world happy.
-            value += '/'
-    else:
-        value = None
-    name = opt_str[2:].replace('-', '_')
-    setattr(parser.values, name, value)
+tmpeggs = tempfile.mkdtemp()
 
 usage = '''\
 [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options]
@@ -101,26 +36,8 @@ local resources, you can keep this script from going over the network.
 '''
 
 parser = OptionParser(usage=usage)
-parser.add_option("-v", "--version", dest="version",
-                          help="use a specific zc.buildout version")
-parser.add_option("-d", "--distribute",
-                   action="store_true", dest="use_distribute", default=False,
-                   help="Use Distribute rather than Setuptools.")
-parser.add_option("--setup-source", action="callback", dest="setup_source",
-                  callback=normalize_to_url, nargs=1, type="string",
-                  help=("Specify a URL or file location for the setup file. "
-                        "If you use Setuptools, this will default to " +
-                        setuptools_source + "; if you use Distribute, this "
-                        "will default to " + distribute_source + "."))
-parser.add_option("--download-base", action="callback", dest="download_base",
-                  callback=normalize_to_url, nargs=1, type="string",
-                  help=("Specify a URL or directory for downloading "
-                        "zc.buildout and either Setuptools or Distribute. "
-                        "Defaults to PyPI."))
-parser.add_option("--eggs",
-                  help=("Specify a directory for storing eggs.  Defaults to "
-                        "a temporary directory that is deleted when the "
-                        "bootstrap script completes."))
+parser.add_option("-v", "--version", help="use a specific zc.buildout version")
+
 parser.add_option("-t", "--accept-buildout-test-releases",
                   dest='accept_buildout_test_releases',
                   action="store_true", default=False,
@@ -130,49 +47,38 @@ parser.add_option("-t", "--accept-buildout-test-releases",
                         "extensions for you.  If you use this flag, "
                         "bootstrap and buildout will get the newest releases "
                         "even if they are alphas or betas."))
-parser.add_option("-c", None, action="store", dest="config_file",
+parser.add_option("-c", "--config-file",
                    help=("Specify the path to the buildout configuration "
                          "file to be used."))
+parser.add_option("-f", "--find-links",
+                   help=("Specify a URL to search for buildout releases"))
 
-options, args = parser.parse_args()
-
-# if -c was provided, we push it back into args for buildout's main function
-if options.config_file is not None:
-    args += ['-c', options.config_file]
-
-if options.eggs:
-    eggs_dir = os.path.abspath(os.path.expanduser(options.eggs))
-else:
-    eggs_dir = tempfile.mkdtemp()
 
-if options.setup_source is None:
-    if options.use_distribute:
-        options.setup_source = distribute_source
-    else:
-        options.setup_source = setuptools_source
+options, args = parser.parse_args()
 
-if options.accept_buildout_test_releases:
-    args.append('buildout:accept-buildout-test-releases=true')
-args.append('bootstrap')
+######################################################################
+# load/install distribute
 
+to_reload = False
 try:
-    import pkg_resources
-    import setuptools  # A flag.  Sometimes pkg_resources is installed alone.
+    import pkg_resources, setuptools
     if not hasattr(pkg_resources, '_distribute'):
+        to_reload = True
         raise ImportError
 except ImportError:
-    ez_code = urllib2.urlopen(
-        options.setup_source).read().replace('\r\n', '\n')
     ez = {}
-    exec ez_code in ez
-    setup_args = dict(to_dir=eggs_dir, download_delay=0)
-    if options.download_base:
-        setup_args['download_base'] = options.download_base
-    if options.use_distribute:
-        setup_args['no_fake'] = True
+
+    try:
+        from urllib.request import urlopen
+    except ImportError:
+        from urllib2 import urlopen
+
+    exec(urlopen('http://python-distribute.org/distribute_setup.py').read(), ez)
+    setup_args = dict(to_dir=tmpeggs, download_delay=0, no_fake=True)
     ez['use_setuptools'](**setup_args)
-    if 'pkg_resources' in sys.modules:
-        reload(sys.modules['pkg_resources'])
+
+    if to_reload:
+        reload(pkg_resources)
     import pkg_resources
     # This does not (always?) update the default working set.  We will
     # do it.
@@ -180,31 +86,26 @@ except ImportError:
         if path not in pkg_resources.working_set.entries:
             pkg_resources.working_set.add_entry(path)
 
-cmd = [quote(sys.executable),
-       '-c',
-       quote('from setuptools.command.easy_install import main; main()'),
-       '-mqNxd',
-       quote(eggs_dir)]
+######################################################################
+# Install buildout
+
+ws  = pkg_resources.working_set
 
-if not has_broken_dash_S:
-    cmd.insert(1, '-S')
+cmd = [sys.executable, '-c',
+       'from setuptools.command.easy_install import main; main()',
+       '-mZqNxd', tmpeggs]
 
-find_links = options.download_base
-if not find_links:
-    find_links = os.environ.get('bootstrap-testing-find-links')
+find_links = os.environ.get(
+    'bootstrap-testing-find-links',
+    options.find_links or
+    ('http://downloads.buildout.org/'
+     if options.accept_buildout_test_releases else None)
+    )
 if find_links:
-    cmd.extend(['-f', quote(find_links)])
+    cmd.extend(['-f', find_links])
 
-if options.use_distribute:
-    setup_requirement = 'distribute'
-else:
-    setup_requirement = 'setuptools'
-ws = pkg_resources.working_set
-setup_requirement_path = ws.find(
-    pkg_resources.Requirement.parse(setup_requirement)).location
-env = dict(
-    os.environ,
-    PYTHONPATH=setup_requirement_path)
+distribute_path = ws.find(
+    pkg_resources.Requirement.parse('distribute')).location
 
 requirement = 'zc.buildout'
 version = options.version
@@ -212,14 +113,13 @@ if version is None and not options.accept_buildout_test_releases:
     # Figure out the most recent final version of zc.buildout.
     import setuptools.package_index
     _final_parts = '*final-', '*final'
-
     def _final_version(parsed_version):
         for part in parsed_version:
             if (part[:1] == '*') and (part not in _final_parts):
                 return False
         return True
     index = setuptools.package_index.PackageIndex(
-        search_path=[setup_requirement_path])
+        search_path=[distribute_path])
     if find_links:
         index.add_find_links((find_links,))
     req = pkg_resources.Requirement.parse(requirement)
@@ -241,22 +141,25 @@ if version:
     requirement = '=='.join((requirement, version))
 cmd.append(requirement)
 
-if is_jython:
-    import subprocess
-    exitcode = subprocess.Popen(cmd, env=env).wait()
-else:  # Windows prefers this, apparently; otherwise we would prefer subprocess
-    exitcode = os.spawnle(*([os.P_WAIT, sys.executable] + cmd + [env]))
-if exitcode != 0:
-    sys.stdout.flush()
-    sys.stderr.flush()
-    print ("An error occurred when trying to install zc.buildout. "
-           "Look above this message for any errors that "
-           "were output by easy_install.")
-    sys.exit(exitcode)
+import subprocess
+if subprocess.call(cmd, env=dict(os.environ, PYTHONPATH=distribute_path)) != 0:
+    raise Exception(
+        "Failed to execute command:\n%s",
+        repr(cmd)[1:-1])
 
-ws.add_entry(eggs_dir)
+######################################################################
+# Import and run buildout
+
+ws.add_entry(tmpeggs)
 ws.require(requirement)
 import zc.buildout.buildout
+
+if not [a for a in args if '=' not in a]:
+    args.append('bootstrap')
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args[0:0] = ['-c', options.config_file]
+
 zc.buildout.buildout.main(args)
-if not options.eggs:  # clean up temporary egg directory
-    shutil.rmtree(eggs_dir)
+shutil.rmtree(tmpeggs)
diff --git a/buildout.cfg b/buildout.cfg
index e1ad958be5bd5d680d6cdca9966a384a07e54018..481ab7f5b15a43c13c42013779780c1d23275180 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -5,30 +5,19 @@
 ; This is the configuration file for buildout.
 
 [buildout]
-parts = external python
+parts = scripts
 newest = false
 develop = .
 
 ; required packages: sphinx (to generate the documentation), bob, and our package.
-eggs = sphinx
-       bob
-       bob.example.faceverify
+eggs = bob.example.faceverify
 
 ; This points to the bob databases that are installed locally at Idiap
 ; TODO: remove this as soon as the databases are published at pypi
 find-links = http://www.idiap.ch/software/bob/packages/xbob/nightlies/last
 
-; This defines the installation directory of Bob.
-; The current setup should work fine for use at Idiap.
-; If you are not at Idiap, and bob is not installed in the default location,
-; please modify the egg-directories accordingly.
-; TODO: Change this directory back to the stable version of bob, when appropriate
-[external]
-recipe = xbob.buildout:external
-egg-directories = /idiap/group/torch5spro/nightlies/last/install/linux-x86_64-release/lib
+[bob.example.faceverify]
+recipe = xbob.buildout:develop
 
-
-[python]
-recipe = zc.recipe.egg
-interpreter = python
-eggs = ${buildout:eggs}
+[scripts]
+recipe = xbob.buildout:scripts
diff --git a/faceverify/dct_ubm.py b/faceverify/dct_ubm.py
index 823b9a50b81311f0b5baf17f81e64c96702a2710..48a2ed037dde74e44dac777f857e0ab1dc821b4c 100644
--- a/faceverify/dct_ubm.py
+++ b/faceverify/dct_ubm.py
@@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm"
 def load_images(db, group = None, purpose = None, client_id = None):
   """Reads the images for the given group and the given client id from the given database"""
   # get the file names from the database
-  file_names = db.files(groups = group, purposes = purpose, model_ids = client_id, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION)
+  files = db.objects(groups = group, purposes = purpose)
   # iterate through the list of file names
   images = {}
-  for key, image_name in file_names.iteritems():
+  for k in files:
     # load image and linearize it into a vector
-    images[key] = bob.io.load(image_name).astype(numpy.float64)
+    images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64)
   return images
 
 
diff --git a/faceverify/eigenface.py b/faceverify/eigenface.py
index c42a5d0aa0d15be93bc0211bf224b9428d3e5ffa..61633bf7efe39266784f9ce1f80b2663f2611cf2 100644
--- a/faceverify/eigenface.py
+++ b/faceverify/eigenface.py
@@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm"
 def load_images(db, group = None, purpose = None):
   """Reads the images for the given group and the given purpose from the given database"""
   # get the file names from the database
-  file_names = db.files(groups = group, purposes = purpose, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION)
+  files = db.objects(groups = group, purposes = purpose)
   # iterate through the list of file names
   images = {}
-  for key, image_name in file_names.iteritems():
+  for k in files:
     # load image and linearize it into a vector
-    images[key] = bob.io.load(image_name).astype(numpy.float64)
+    images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64)
   return images
 
 
diff --git a/faceverify/gabor_phase.py b/faceverify/gabor_phase.py
index 3609709fbedb3d41dce20d91edd219922e7c8f80..732d5991ae5ab10e3f46db8981c83a5a55a1fbf2 100644
--- a/faceverify/gabor_phase.py
+++ b/faceverify/gabor_phase.py
@@ -16,12 +16,12 @@ ATNT_IMAGE_EXTENSION = ".pgm"
 def load_images(db, group = None, purpose = None):
   """Reads the images for the given group and the given purpose from the given database"""
   # get the file names from the database
-  file_names = db.files(groups = group, purposes = purpose, directory = ATNT_IMAGE_DIRECTORY, extension = ATNT_IMAGE_EXTENSION)
+  files = db.objects(groups = group, purposes = purpose)
   # iterate through the list of file names
   images = {}
-  for key, image_name in file_names.iteritems():
+  for k in files:
     # load image and linearize it into a vector
-    images[key] = bob.io.load(image_name).astype(numpy.float64)
+    images[k.id] = bob.io.load(k.make_path(ATNT_IMAGE_DIRECTORY, ATNT_IMAGE_EXTENSION)).astype(numpy.float64)
   return images
 
 
diff --git a/setup.py b/setup.py
index f85c72079038ca3ad26ec9c81926eb49dc32ac66..069825452653a1666e0d68de346cafce92e89426 100644
--- a/setup.py
+++ b/setup.py
@@ -28,7 +28,7 @@ setup(
     # This is the basic information about your project. Modify all this
     # information before releasing code publicly.
     name='bob.example.faceverify',
-    version='0.1.3',
+    version='0.1.4',
     description='Example for using Bob to create face verification systems',
     url='http://pypi.python.org/pypi/bob.example.faceverify',
     license='GPLv3',
@@ -49,7 +49,7 @@ setup(
     # TODO: Add a version number requirement to bob, when ready
     install_requires=[
         "sphinx",                     # to generate the documentation
-        "bob >= 1.1.0a0",               # base signal proc./machine learning library
+        "bob >= 1.1.0",               # base signal proc./machine learning library
         "xbob.db.atnt",               # the AT&T (ORL) database of images
     ],