diff --git a/bob/io/base/__init__.py b/bob/io/base/__init__.py
index b205ba79fa8acd58c30a009b010f31d66e3c2c2d..340178fa32af8b7b5cbf5408a6692611d3d12b8e 100644
--- a/bob/io/base/__init__.py
+++ b/bob/io/base/__init__.py
@@ -12,7 +12,7 @@ from .version import api as __api_version__
 
 import os
 
-def __is_string__(s):
+def _is_string(s):
   """Returns ``True`` if the given object is a string
 
   This method can be used with Python-2.x or 3.x and returns a string
@@ -30,13 +30,13 @@ def create_directories_safe(directory, dryrun=False):
   If the dryrun option is selected, it does not actually create the directory,
   but just writes the (Linux) command that would have been executed.
 
-  Parameters:
+  **Parameters:**
 
-  directory
+  ``directory`` : str
     The directory that you want to create.
 
-  dryrun
-    Only write the command, but do not execute it.
+  ``dryrun`` : bool
+    Only ``print`` the command to console, but do not execute it.
   """
   try:
     if dryrun:
@@ -51,12 +51,14 @@ def create_directories_safe(directory, dryrun=False):
 
 
 def load(inputs):
-  """Loads the contents of a file, an iterable of files, or an iterable of
+  """load(inputs) -> data
+
+  Loads the contents of a file, an iterable of files, or an iterable of
   :py:class:`bob.io.base.File`'s into a :py:class:`numpy.ndarray`.
 
-  Parameters:
+  **Parameters:**
 
-  inputs
+  ``inputs`` : various types
 
     This might represent several different entities:
 
@@ -66,24 +68,29 @@ def load(inputs):
     2. An iterable of filenames to be loaded in memory. In this case, this
        would assume that each file contains a single 1D sample or a set of 1D
        samples, load them in memory and concatenate them into a single and
-       returned 2D numpy ndarray.
-    3. An iterable of :py:class:`bob.io.base.File`. In this case, this would assume
-       that each :py:class:`bob.io.base.File` contains a single 1D sample or a set
+       returned 2D :py:class:`numpy.ndarray`.
+    3. An iterable of :py:class:`File`. In this case, this would assume
+       that each :py:class:`File` contains a single 1D sample or a set
        of 1D samples, load them in memory if required and concatenate them into
-       a single and returned 2D numpy ndarray.
-    4. An iterable with mixed filenames and :py:class:`bob.io.base.File`. In this
+       a single and returned 2D :py:class:`numpy.ndarray`.
+    4. An iterable with mixed filenames and :py:class:`File`. In this
        case, this would returned a 2D :py:class:`numpy.ndarray`, as described
        by points 2 and 3 above.
+
+  **Returns:**
+
+  ``data`` : :py:class:`numpy.ndarray`
+    The data loaded from the given ``inputs``.
   """
 
   from collections import Iterable
   import numpy
-  if __is_string__(inputs):
+  if _is_string(inputs):
     return File(inputs, 'r').read()
   elif isinstance(inputs, Iterable):
     retval = []
     for obj in inputs:
-      if __is_string__(obj):
+      if _is_string(obj):
         retval.append(load(obj))
       elif isinstance(obj, File):
         retval.append(obj.read())
@@ -94,19 +101,27 @@ def load(inputs):
     raise TypeError("Unexpected input object. This function is expecting a filename, or an iterable of filenames and/or bob.io.base.File's")
 
 def merge(filenames):
-  """Converts an iterable of filenames into an iterable over read-only
-  bob.io.base.File's.
+  """merge(filenames) -> files
 
-  Parameters:
+  Converts an iterable of filenames into an iterable over read-only
+  :py:class`bob.io.base.File`'s.
+
+  **Parameters:**
 
-  filenames
+  ``filenames`` : str or [str]
 
+    A list of file names.
     This might represent:
 
     1. A single filename. In this case, an iterable with a single
-       :py:class:`bob.io.base.File` is returned.
+       :py:class:`File` is returned.
     2. An iterable of filenames to be converted into an iterable of
-       :py:class:`bob.io.base.File`'s.
+       :py:class:`File`'s.
+
+  **Returns:**
+
+  ``files`` : [:py:class:`File`]
+    The list of files.
   """
 
   from collections import Iterable
@@ -121,20 +136,20 @@ def merge(filenames):
 def save(array, filename, create_directories = False):
   """Saves the contents of an array-like object to file.
 
-  Effectively, this is the same as creating a :py:class:`bob.io.base.File` object
-  with the mode flag set to `w` (write with truncation) and calling
-  :py:meth:`bob.io.base.File.write` passing `array` as parameter.
+  Effectively, this is the same as creating a :py:class:`File` object
+  with the mode flag set to ``'w'`` (write with truncation) and calling
+  :py:meth:`File.write` passing ``array`` as parameter.
 
   Parameters:
 
-  array
+  ``array`` : array_like
     The array-like object to be saved on the file
 
-  filename
+  ``filename`` : str
     The name of the file where you need the contents saved to
 
-  create_directories
-    Automatically generate the directories if required
+  ``create_directories`` : bool
+    Automatically generate the directories if required (defaults to ``False`` because of compatibility reasons; might change in future to default to ``True``)
   """
   # create directory if not existent yet
   if create_directories:
@@ -147,47 +162,66 @@ write = save
 read = load
 
 def append(array, filename):
-  """Appends the contents of an array-like object to file.
+  """append(array, filename) -> position
 
-  Effectively, this is the same as creating a :py:class:`bob.io.base.File` object
-  with the mode flag set to `a` (append) and calling
-  :py:meth:`bob.io.base.File.append` passing `array` as parameter.
+  Appends the contents of an array-like object to file.
 
-  Parameters:
+  Effectively, this is the same as creating a :py:class:`File` object
+  with the mode flag set to ``'a'`` (append) and calling
+  :py:meth:`File.append` passing ``array`` as parameter.
 
-  array
+  **Parameters:**
+
+  ``array`` : array_like
     The array-like object to be saved on the file
 
-  filename
+  ``filename`` : str
     The name of the file where you need the contents saved to
+
+  **Returns:**
+
+  ``position`` : int
+    See :py:meth:`File.append`
   """
   return File(filename, 'a').append(array)
 
 def peek(filename):
-  """Returns the type of array (frame or sample) saved in the given file.
+  """peek(filename) -> dtype, shape, stride
 
-  Effectively, this is the same as creating a :py:class:`bob.io.base.File` object
-  with the mode flag set to `r` (read-only) and returning
-  :py:func:`bob.io.base.File.describe`.
+  Returns the type of array (frame or sample) saved in the given file.
 
-  Parameters:
+  Effectively, this is the same as creating a :py:class:`File` object
+  with the mode flag set to `r` (read-only) and calling
+  :py:meth:`File.describe`.
+
+  **Parameters**:
 
-  filename
+  ``filename`` : str
     The name of the file to peek information from
+
+  **Returns:**
+
+  ``dtype, shape, stride`` : see :py:meth:`File.describe`
   """
   return File(filename, 'r').describe()
 
 def peek_all(filename):
-  """Returns the type of array (for full readouts) saved in the given file.
+  """peek_all(filename) -> dtype, shape, stride
 
-  Effectively, this is the same as creating a :py:class:`bob.io.base.File` object
-  with the mode flag set to `r` (read-only) and returning
-  ``bob.io.base.File.describe(all=True)``.
+  Returns the type of array (for full readouts) saved in the given file.
 
-  Parameters:
+  Effectively, this is the same as creating a :py:class:`File` object
+  with the mode flag set to ``'r'`` (read-only) and returning
+  ``File.describe`` with its parameter ``all`` set to ``True``.
+
+  **Parameters:**
 
-  filename
+  ``filename`` : str
     The name of the file to peek information from
+
+  **Returns:**
+
+  ``dtype, shape, stride`` : see :py:meth:`File.describe`
   """
   return File(filename, 'r').describe(all=True)
 
@@ -201,8 +235,18 @@ def get_config():
 
 
 def get_include_directories():
-  """Returns a list of include directories for dependent libraries, such as HDF5."""
-  from bob.extension import pkgconfig
+  """get_include_directories() -> includes
+
+  Returns a list of include directories for dependent libraries, such as HDF5.
+  This function is automatically used by :py:func:`bob.extension.get_bob_libraries` to retrieve the non-standard include directories that are required to use the C bindings of this library in dependent classes.
+  You shouldn't normally need to call this function by hand.
+
+  **Returns:**
+
+  ``includes`` : [str]
+    The list of non-standard include directories required to use the C bindings of this class.
+    For now, only the directory for the HDF5 headers are returned.
+  """
   # try to use pkg_config first
   try:
     from bob.extension.utils import find_header
@@ -214,6 +258,7 @@ def get_include_directories():
 
     return [os.path.dirname(candidates[0])]
   except RuntimeError:
+    from bob.extension import pkgconfig
     pkg = pkgconfig('hdf5')
     return pkg.include_directories()
 
diff --git a/bob/io/base/file.cpp b/bob/io/base/file.cpp
index 164b8644d91ee0e81caeb338ebe1e69777bb1050..585481db3270a023fcea4e7123044572f26bfc5e 100644
--- a/bob/io/base/file.cpp
+++ b/bob/io/base/file.cpp
@@ -396,7 +396,7 @@ static auto s_write = bob::extension::FunctionDoc(
   true
 )
 .add_prototype("data")
-.add_parameter("data", "array_like", "[optional]  The array to be written into the file; it can be a :py:class:`numpy.array`, a :py:class:`bob.blitz.array` or any other object which can be converted to either of them")
+.add_parameter("data", "array_like", "The array to be written into the file; it can be a :py:class:`numpy.array`, a :py:class:`bob.blitz.array` or any other object which can be converted to either of them")
 ;
 static PyObject* PyBobIoFile_write(PyBobIoFileObject* self, PyObject *args, PyObject* kwds) {
 BOB_TRY
@@ -424,7 +424,7 @@ static auto s_append = bob::extension::FunctionDoc(
   true
 )
 .add_prototype("data", "position")
-.add_parameter("data", "array_like", "[optional]  The array to be written into the file; it can be a :py:class:`numpy.array`, a :py:class:`bob.blitz.array` or any other object which can be converted to either of them")
+.add_parameter("data", "array_like", "The array to be written into the file; it can be a :py:class:`numpy.array`, a :py:class:`bob.blitz.array` or any other object which can be converted to either of them")
 .add_return("position", "int", "The current position of the newly written data")
 ;
 static PyObject* PyBobIoFile_append(PyBobIoFileObject* self, PyObject *args, PyObject* kwds) {
diff --git a/bob/io/base/test_utils.py b/bob/io/base/test_utils.py
index 6f1e3072bcd45255dccaabbb3066e6740a349edb..8e83915644dd7821572fea0eb8f1c4b751f9a432 100644
--- a/bob/io/base/test_utils.py
+++ b/bob/io/base/test_utils.py
@@ -11,46 +11,92 @@
 import os
 import functools
 import nose.plugins.skip
-from distutils.version import StrictVersion as SV
 
 def datafile(f, module=None, path='data'):
-  """Returns the test file on the "data" subdirectory of the current module.
+  """datafile(f, [module], [data]) -> filename
 
-  Keyword attributes
+  Returns the test file on the "data" subdirectory of the current module.
 
-  f: str
-    This is the filename of the file you want to retrieve. Something like
-    ``'movie.avi'``.
+  **Parameters:**
 
-  module: string, optional
-    This is the python-style package name of the module you want to retrieve
-    the data from. This should be something like ``bob.io.test``, but you
+  ``f`` : str
+    This is the filename of the file you want to retrieve. Something like ``'movie.avi'``.
+
+  ``module``: str
+    [optional] This is the python-style package name of the module you want to retrieve
+    the data from. This should be something like ``bob.io.base``, but you
     normally refer it using the ``__name__`` property of the module you want to
     find the path relative to.
 
-  path: str, optional
-    This is the subdirectory where the datafile will be taken from inside the
-    module. Normally (the default) ``data``. It can be set to ``None`` if it
-    should be taken from the module path root (where the ``__init__.py`` file
-    sits).
+  ``path``: str
+    [Default: ``'data'``] The subdirectory where the datafile will be taken from inside the module.
+    It can be set to ``None`` if it should be taken from the module path root (where the ``__init__.py`` file sits).
+
+  **Returns:**
 
-  Returns the full path of the file.
+  ``filename`` : str
+    The full path of the file
   """
 
   resource = __name__ if module is None else module
   final_path = f if path is None else os.path.join(path, f)
-  return __import__('pkg_resources').resource_filename(resource, final_path)
+  import pkg_resources
+  return pkg_resources.resource_filename(resource, final_path)
+
 
 def temporary_filename(prefix='bobtest_', suffix='.hdf5'):
-  """Generates a temporary filename to be used in tests"""
+  """temporary_filename([prefix], [suffix]) -> filename
+
+  Generates a temporary filename to be used in tests, using the default ``temp`` directory (on Unix-like systems, usually ``/tmp``).
+  Please note that you are responsible for deleting the file after your test finished.
+  A common way to assure the file to be deleted is:
+
+  .. code-block:: py
+
+     import bob.io.base.test_utils
+     temp = bob.io.base.test_utils.temporary_filename()
+     try:
+       # use the temp file
+       ...
+     finally:
+       if os.path.exist(temp): os.remove(temp)
+
+  **Parameters:**
+
+  ``prefix`` : str
+    [Default: ``'bobtest_'``] The file name prefix to be added in front of the random file name
+
+  ``suffix`` : str
+    [Default: ``'.hdf5'``] The file name extension of the temporary file name
 
-  (fd, name) = __import__('tempfile').mkstemp(suffix, prefix)
+  **Returns:**
+
+  ``filename`` : str
+    The name of a temporary file that you can use in your test.
+    Don't forget to delete!
+
+  """
+  import tempfile
+  fd, name = tempfile.mkstemp(suffix, prefix)
   os.close(fd)
   os.unlink(name)
   return name
 
+
 def extension_available(extension):
-  '''Decorator to check if a extension is available before enabling a test'''
+  '''Decorator to check if a extension is available before enabling a test
+
+  This decorator is mainly used to decorate a test function, in order to skip tests when the extension is not available.
+  The syntax is:
+
+  .. code-block:: py
+
+     import bob.io.base.test_utils
+
+     @bob.io.base.test_utils.extension_available('.ext')
+     def my_test():
+       ...
+  '''
 
   def test_wrapper(test):
 
diff --git a/doc/c_cpp_api.rst b/doc/c_cpp_api.rst
index 35c7a1fd47cddf4d3bb59c3b7faad6289b906792..da4f8fc61673079825426079481f066c78062e18 100644
--- a/doc/c_cpp_api.rst
+++ b/doc/c_cpp_api.rst
@@ -49,7 +49,7 @@ Generic Functions
 
    Converts the input Bob element type into a ``NPY_<TYPE>`` enumeration value.
    Returns ``NPY_NOTYPE`` in case of problems, and sets a
-   :py:class:`RuntimeError`.
+   :py:exc:`RuntimeError`.
 
 .. cpp:function:: PyObject* PyBobIo_TypeInfoAsTuple (const bob::core::array::typeinfo& ti)
 
diff --git a/doc/conf.py b/doc/conf.py
index 34108fbbb9cf0f0c5f5db25d498f2072f3c85806..f5a21b88efeb5b9f322248f1853327a194a7481d 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -251,7 +251,7 @@ autodoc_default_flags = ['members', 'undoc-members', 'inherited-members', 'show-
 
 # For inter-documentation mapping:
 from bob.extension.utils import link_documentation
-intersphinx_mapping = link_documentation()
+intersphinx_mapping = link_documentation(['python', 'numpy', 'scipy', 'bob.io.image', 'bob.io.video', 'bob.io.matlab'])
 
 
 def setup(app):
diff --git a/doc/index.rst b/doc/index.rst
index a95b29006910b7b0b5a3667f0fda09a5fdf81f11..ba226b3964a456e262caf1379cde0d3af295d4bf 100644
--- a/doc/index.rst
+++ b/doc/index.rst
@@ -10,11 +10,15 @@
  Bob's Core I/O Routines
 =========================
 
-.. todolist::
+This module contains a basic interface to read and write files of various types.
+It provides generic functions :py:func:`bob.io.base.save` and :py:func:`bob.io.base.load` to write and read various types of data.
+In this interface, data is mainly written using the :py:class:`bob.io.base.HDF5File` interface.
+To enable further types of IO, please import one of the following packages (the list might not be exhaustive):
+
+* :ref:`bob.io.image <bob.io.image>` to load and save images of various kinds
+* :ref:`bob.io.video <bob.io.video>` to load and save videos of various types
+* :ref:`bob.io.matlab <bob.io.matlab>` to load and save matrices in basic matlab ``.mat`` files
 
-This module contains base functionality from Bob bound to Python, available in
-the C++ counter-part ``bob::io``. It includes input and output operations to
-and from files.
 
 Documentation
 -------------
@@ -26,6 +30,11 @@ Documentation
    py_api
    c_cpp_api
 
+TODO
+----
+
+.. todolist::
+
 Indices and tables
 ------------------