diff --git a/bob/bio/base/annotator/FailSafe.py b/bob/bio/base/annotator/FailSafe.py
index 4ba32ad673d088a7d8bdfffc9a2447dc835d488a..88af4ddce4b4e37bceaea5051601d10bae4315bb 100644
--- a/bob/bio/base/annotator/FailSafe.py
+++ b/bob/bio/base/annotator/FailSafe.py
@@ -38,7 +38,7 @@ class FailSafe(Annotator):
             if not annotations:
                 logger.debug(
                     "Annotator `%s' returned empty annotations.", annotator)
-            kwargs['annotations'].update(annotations)
+            kwargs['annotations'].update(annotations or {})
             # check if we have all the required annotations
             if all(key in kwargs['annotations'] for key in self.required_keys):
                 break
diff --git a/bob/bio/base/database/database.py b/bob/bio/base/database/database.py
index d20f76f67caed469ae13ba33095aa2c2bf8f5535..97d73e4725b884f73845d9195732ee854b7d701f 100644
--- a/bob/bio/base/database/database.py
+++ b/bob/bio/base/database/database.py
@@ -86,7 +86,7 @@ class BioDatabase(six.with_metaclass(abc.ABCMeta, bob.db.base.FileDatabase)):
             **kwargs
     ):
 
-        assert isinstance(name, str)
+        assert isinstance(name, six.string_types)
 
         super(BioDatabase, self).__init__(
             original_directory=original_directory,
@@ -180,7 +180,7 @@ class BioDatabase(six.with_metaclass(abc.ABCMeta, bob.db.base.FileDatabase)):
         """
         if replacements is None:
             return
-        if isinstance(replacements, str):
+        if isinstance(replacements, six.string_types):
             if not os.path.exists(replacements):
                 return
             # Open the database replacement file and reads its content
diff --git a/bob/bio/base/database/filelist/query.py b/bob/bio/base/database/filelist/query.py
index 4bb6487ba9a86e080f6cd5e2ee91b11653a3cf57..1f55662920a6e28a28f699d52b94189096283767 100644
--- a/bob/bio/base/database/filelist/query.py
+++ b/bob/bio/base/database/filelist/query.py
@@ -823,7 +823,7 @@ class FileListBioDatabase(ZTBioDatabase):
           The full path of the original data file.
         """
 
-        if isinstance(self.original_extension, str):
+        if isinstance(self.original_extension, six.string_types):
             # extract file name
             file_name = file.make_path(self.original_directory, self.original_extension)
             if check_existence and os.path.exists(file_name):
diff --git a/bob/bio/base/grid.py b/bob/bio/base/grid.py
index 6390661377eb5fbc73383d8c0df8c8c965bae3ff..60aa0125daebb7903befde653ec53d4e184be123 100644
--- a/bob/bio/base/grid.py
+++ b/bob/bio/base/grid.py
@@ -2,7 +2,7 @@
 # vim: set fileencoding=utf-8 :
 # @author: Manuel Guenther <Manuel.Guenther@idiap.ch>
 # @date: Tue Oct  2 12:12:39 CEST 2012
-
+import six
 
 PREDEFINED_QUEUES = {
   'default'     : {},
@@ -130,7 +130,7 @@ class Grid (object):
     """
     if self.is_local():
       return {}
-    if isinstance(params, str) and params in PREDEFINED_QUEUES:
+    if isinstance(params, six.string_types) and params in PREDEFINED_QUEUES:
       return PREDEFINED_QUEUES[params]
     elif isinstance(params, dict):
       return params
diff --git a/bob/bio/base/script/annotate.py b/bob/bio/base/script/annotate.py
index e9dc135abbd6e42b19ac39e6d9f39fc709ae6965..2918590eec60532410d4fd6af529f44228311027 100644
--- a/bob/bio/base/script/annotate.py
+++ b/bob/bio/base/script/annotate.py
@@ -3,7 +3,7 @@
 import logging
 import json
 import click
-from os.path import dirname, isfile
+from os.path import dirname, isfile, expanduser
 from bob.extension.scripts.click_helper import (
     verbosity_option, ConfigCommand, ResourceOption)
 from bob.io.base import create_directories_safe
@@ -19,9 +19,12 @@ logger = logging.getLogger(__name__)
               entry_point_group='bob.bio.annotator')
 @click.option('--output-dir', '-o', required=True, cls=ResourceOption)
 @click.option('--force', '-f', is_flag=True, cls=ResourceOption)
-@click.option('--array', type=click.INT, default=1,)
+@click.option('--array', type=click.INT, default=1, cls=ResourceOption)
+@click.option('--database-directories-file', cls=ResourceOption,
+              default=expanduser('~/.bob_bio_databases.txt'))
 @verbosity_option(cls=ResourceOption)
-def annotate(database, annotator, output_dir, force, array, **kwargs):
+def annotate(database, annotator, output_dir, force, array,
+             database_directories_file, **kwargs):
     """Annotates a database.
     The annotations are written in text file (json) format which can be read
     back using :any:`bob.db.base.read_annotation_file` (annotation_type='json')
@@ -60,8 +63,12 @@ def annotate(database, annotator, output_dir, force, array, **kwargs):
     logger.debug('force: %s', force)
     logger.debug('output_dir: %s', output_dir)
     logger.debug('array: %s', array)
+    logger.debug('database_directories_file: %s', database_directories_file)
     logger.debug('kwargs: %s', kwargs)
 
+    # Some databases need their original_directory to be replaced
+    database.replace_directories(database_directories_file)
+
     biofiles = database.objects(groups=None, protocol=database.protocol)
     biofiles = sorted(biofiles)
 
diff --git a/bob/bio/base/script/resources.py b/bob/bio/base/script/resources.py
index 15fc021158bd2c40e72f807574e742f31d0a1ad3..c68d6f22202a1f14ece2ecd572ff2dffed071289 100644
--- a/bob/bio/base/script/resources.py
+++ b/bob/bio/base/script/resources.py
@@ -9,8 +9,8 @@ def resources(command_line_parameters = None):
   import argparse
   parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.ArgumentDefaultsHelpFormatter)
   parser.add_argument("--types", '-t', nargs = '+',
-                      choices = ('d', 'database', 'p', 'preprocessor', 'e', 'extractor', 'a', 'algorithm', 'g', 'grid', 'c', 'config'),
-                      default = ('d', 'p', 'e', 'a', 'g', 'c'),
+                      choices = ('d', 'database', 'p', 'preprocessor', 'e', 'extractor', 'a', 'algorithm', 'g', 'grid', 'c', 'config', 'an', 'annotator'),
+                      default = ('d', 'p', 'e', 'a', 'g', 'c', 'an'),
                       help = "Select the resource types that should be listed.")
 
   parser.add_argument("--details", '-d', action='store_true', help = "Prints the complete configuration for all resources")
@@ -51,6 +51,10 @@ def resources(command_line_parameters = None):
     print ("\nList of registered configurations:")
     print (bob.bio.base.list_resources('config', **kwargs))
 
+  if 'an' in args.types or 'annotator' in args.types:
+    print ("\nList of registered annotators:")
+    print (bob.bio.base.list_resources('annotator', **kwargs))
+
   print()
 
 def databases(command_line_parameters = None):
diff --git a/bob/bio/base/tools/command_line.py b/bob/bio/base/tools/command_line.py
index e766070605b3e5b60593e8d9ba3ae22047331f91..d8bb712fa868d0715572771ed2772e7edc94dd2d 100644
--- a/bob/bio/base/tools/command_line.py
+++ b/bob/bio/base/tools/command_line.py
@@ -5,6 +5,7 @@ import argparse
 import os
 import socket
 import sys
+import six
 
 import bob.core
 import bob.extension
@@ -242,7 +243,7 @@ def take_from_config_or_command_line(args, config, keyword, default, required=Tr
 
     elif config is not None and hasattr(config, keyword):
         val = getattr(config, keyword)
-        if isinstance(val, str) and is_resource:
+        if isinstance(val, six.string_types) and is_resource:
             val = utils.load_resource(val, keyword, imports=args.imports, package_prefix=args.package_prefix,
                                       preferred_package=args.preferred_package)
         setattr(args, keyword, val)
@@ -294,10 +295,10 @@ def parse_config_file(parsers, args, args_dictionary, keywords, skips):
 
     take_from_config_or_command_line(args, config, "sub_directory",
                                      parser.get_default("sub_directory"), is_resource=False)
-                                     
+
     take_from_config_or_command_line(args, config, "env",
                                      parser.get_default("env"), is_resource=False)
-                                     
+
     skip_keywords = tuple(['skip_' + k.replace('-', '_') for k in skips])
 
     for keyword in keywords + skip_keywords + ('execute_only',):
diff --git a/bob/bio/base/utils/__init__.py b/bob/bio/base/utils/__init__.py
index 75737bdcead5cabb6aecc3e39e438cb4ab492944..6738ad5ec656126ab9f0e9d6b52ca24d6cbe0843 100644
--- a/bob/bio/base/utils/__init__.py
+++ b/bob/bio/base/utils/__init__.py
@@ -56,7 +56,7 @@ def selected_elements(list_of_elements, desired_number_of_elements = None):
 
 def pretty_print(obj, kwargs):
   """Returns a pretty-print of the parameters to the constructor of a class, which should be able to copy-paste on the command line to create the object (with few exceptions)."""
-  return "%s(%s)" % (str(obj.__class__), ", ".join(["%s='%s'" % (key,value) if isinstance(value, str) else "%s=%s" % (key, value) for key,value in kwargs.items() if value is not None]))
+  return "%s(%s)" % (str(obj.__class__), ", ".join(["%s='%s'" % (key,value) if isinstance(value, six.string_types) else "%s=%s" % (key, value) for key,value in kwargs.items() if value is not None]))
 
 
 def is_argument_available(argument, method):
diff --git a/bob/bio/base/utils/resources.py b/bob/bio/base/utils/resources.py
index 5f6f4c138a11eba79d7defba80aa8b6ced3a21df..fa5e3c42949e026c383fd475406f0471ad2d2770 100644
--- a/bob/bio/base/utils/resources.py
+++ b/bob/bio/base/utils/resources.py
@@ -14,6 +14,7 @@ if sys.version_info[0] == 2:
   from string import letters as ascii_letters
 else:
   from string import ascii_letters
+import six
 
 import logging
 logger = logging.getLogger("bob.bio.base")
@@ -173,7 +174,7 @@ def load_resource(resource, keyword, imports = ['bob.bio.base'], package_prefix=
     for i in imports:
       exec ("import %s"%i)
     # now, evaluate the resource (re-evaluate if the resource is still a string)
-    while isinstance(resource, str):
+    while isinstance(resource, six.string_types):
       resource = eval(resource)
     return resource
 
diff --git a/conda/meta.yaml b/conda/meta.yaml
index 126977b7139886916969a25025f5734e2cbaf5f1..fa9ebaea253d2a12675101a6e0ac1c788761a381 100644
--- a/conda/meta.yaml
+++ b/conda/meta.yaml
@@ -44,10 +44,12 @@ requirements:
     - bob.measure
     - bob.sp
     - scipy {{ scipy }}
+    - six {{ six }}
   run:
     - python
     - setuptools
     - scipy
+    - six
 
 test:
   imports:
diff --git a/doc/annotations.rst b/doc/annotations.rst
index 851a2f2fe48911d18a376f7a7350384962ca8363..7dfe74e6ddf79b850f92d53227d105aad27ed924 100644
--- a/doc/annotations.rst
+++ b/doc/annotations.rst
@@ -27,3 +27,10 @@ The script can also be run in parallel using :ref:`gridtk`:
     $ jman submit --array 64 -- bob bio annotate /path/to/config.py --array 64
 
 The number that is given to the ``--array`` options should match.
+
+You can find the list of readily available annotator configurations using the
+``resources.py`` command:
+
+.. code-block:: sh
+
+    $ resources.py --types annotator
diff --git a/requirements.txt b/requirements.txt
index bc8552c051bfbe99ce18336104afbc26fc222734..774aac2d24b68ddeecc440d62d4a64ae2b2ecab2 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -14,3 +14,4 @@ click-plugins
 numpy
 scipy
 setuptools
+six