diff --git a/bob/devtools/bootstrap.py b/bob/devtools/bootstrap.py
index 64ecb6d787c5d00e6aa90b40142d8ce891828855..135d72eefc11d9481c8da22bf389f1fd003e0a09 100644
--- a/bob/devtools/bootstrap.py
+++ b/bob/devtools/bootstrap.py
@@ -2,7 +2,7 @@
 # -*- coding: utf-8 -*-
 
 
-"""Bootstraps a new miniconda installation and prepares it for development"""
+"""Bootstraps a new miniconda installation and prepares it for development."""
 
 
 _BASE_CONDARC = """\
@@ -48,7 +48,7 @@ logger = logging.getLogger(__name__)
 
 
 def set_environment(name, value, env=os.environ):
-    """Function to setup the environment variable and print debug message
+    """Function to setup the environment variable and print debug message.
 
     Args:
 
@@ -63,7 +63,7 @@ def set_environment(name, value, env=os.environ):
 
 
 def human_time(seconds, granularity=2):
-    '''Returns a human readable time string like "1 day, 2 hours"'''
+    """Returns a human readable time string like "1 day, 2 hours"."""
 
     result = []
 
@@ -92,17 +92,15 @@ def human_time(seconds, granularity=2):
 
 
 def run_cmdline(cmd, env=None):
-    """Runs a command on a environment, logs output and reports status
+    """Runs a command on a environment, logs output and reports status.
 
+    Parameters:
 
-  Parameters:
+      cmd (list): The command to run, with parameters separated on a list
 
-    cmd (list): The command to run, with parameters separated on a list
-
-    env (dict, Optional): Environment to use for running the program on. If not
-      set, use :py:obj:`os.environ`.
-
-  """
+      env (dict, Optional): Environment to use for running the program on. If not
+        set, use :py:obj:`os.environ`.
+    """
 
     if env is None:
         env = os.environ
@@ -136,21 +134,21 @@ def run_cmdline(cmd, env=None):
 
 
 def touch(path):
-    """Python-implementation of the "touch" command-line application"""
+    """Python-implementation of the "touch" command-line application."""
 
     with open(path, "a"):
         os.utime(path, None)
 
 
 def merge_conda_cache(cache, prefix, name):
-    """Merges conda pkg caches and conda-bld folders
+    """Merges conda pkg caches and conda-bld folders.
 
-  Args:
+    Args:
 
-    cache: The cached directory (from previous builds)
-    prefix: The current prefix (root of conda installation)
-    name: The name of the current package
-  """
+      cache: The cached directory (from previous builds)
+      prefix: The current prefix (root of conda installation)
+      name: The name of the current package
+    """
 
     pkgs_dir = os.path.join(prefix, "pkgs")
     pkgs_urls_txt = os.path.join(pkgs_dir, "urls.txt")
@@ -204,7 +202,7 @@ def merge_conda_cache(cache, prefix, name):
 
 
 def get_miniconda_sh():
-    """Retrieves the miniconda3 installer for the current system"""
+    """Retrieves the miniconda3 installer for the current system."""
 
     import http.client
 
@@ -232,14 +230,13 @@ def get_miniconda_sh():
 
 
 def install_miniconda(prefix, name):
-    """Creates a new miniconda installation
-
-  Args:
+    """Creates a new miniconda installation.
 
-    prefix: The path leading to the (new) root of the miniconda installation
-    name: The name of this package
+    Args:
 
-  """
+      prefix: The path leading to the (new) root of the miniconda installation
+      name: The name of this package
+    """
 
     logger.info("Installing miniconda in %s...", prefix)
 
@@ -264,37 +261,36 @@ def install_miniconda(prefix, name):
 
 
 def get_channels(public, stable, server, intranet, group):
-    """Returns the relevant conda channels to consider if building project
-
-  The subset of channels to be returned depends on the visibility and stability
-  of the package being built.  Here are the rules:
+    """Returns the relevant conda channels to consider if building project.
 
-  * public and stable: only returns the public stable channel(s)
-  * public and not stable: returns both public stable and beta channels
-  * not public and stable: returns both public and private stable channels
-  * not public and not stable: returns all channels
+    The subset of channels to be returned depends on the visibility and stability
+    of the package being built.  Here are the rules:
 
-  Beta channels have priority over stable channels, if returned.  Private
-  channels have priority over public channles, if turned.
+    * public and stable: only returns the public stable channel(s)
+    * public and not stable: returns both public stable and beta channels
+    * not public and stable: returns both public and private stable channels
+    * not public and not stable: returns all channels
 
+    Beta channels have priority over stable channels, if returned.  Private
+    channels have priority over public channles, if turned.
 
-  Args:
 
-    public: Boolean indicating if we're supposed to include only public
-      channels
-    stable: Boolean indicating if we're supposed to include only stable
-      channels
-    server: The base address of the server containing our conda channels
-    intranet: Boolean indicating if we should add "private"/"public" prefixes
-      on the conda paths
-    group: The group of packages (gitlab namespace) the package we're compiling
-      is part of.  Values should match URL namespaces currently available on
-      our internal webserver.  Currently, only "bob" or "beat" will work.
+    Args:
 
+      public: Boolean indicating if we're supposed to include only public
+        channels
+      stable: Boolean indicating if we're supposed to include only stable
+        channels
+      server: The base address of the server containing our conda channels
+      intranet: Boolean indicating if we should add "private"/"public" prefixes
+        on the conda paths
+      group: The group of packages (gitlab namespace) the package we're compiling
+        is part of.  Values should match URL namespaces currently available on
+        our internal webserver.  Currently, only "bob" or "beat" will work.
 
-  Returns: a list of channels that need to be considered.
 
-  """
+    Returns: a list of channels that need to be considered.
+    """
 
     if (not public) and (not intranet):
         raise RuntimeError(
diff --git a/bob/devtools/build.py b/bob/devtools/build.py
index 41bb20755fa572b8e35b17c1f179708f6b156875..1ad84e52868c1259681b57adf68d3a5163a7a412 100644
--- a/bob/devtools/build.py
+++ b/bob/devtools/build.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Tools for self-building and other utilities"""
+"""Tools for self-building and other utilities."""
 
 
 import os
@@ -23,21 +23,21 @@ import conda_build.api
 
 
 def comment_cleanup(lines):
-    """Cleans-up comments and empty lines from textual data read from files"""
+    """Cleans-up comments and empty lines from textual data read from files."""
 
     no_comments = [k.partition("#")[0].strip() for k in lines]
     return [k for k in no_comments if k]
 
 
 def load_order_file(path):
-    """Loads an order.txt style file, removes empty lines and comments"""
+    """Loads an order.txt style file, removes empty lines and comments."""
 
     with open(path, "rt") as f:
         return comment_cleanup(f.readlines())
 
 
 def conda_arch():
-    """Returns the current OS name and architecture as recognized by conda"""
+    """Returns the current OS name and architecture as recognized by conda."""
 
     r = "unknown"
     if platform.system().lower() == "linux":
@@ -57,32 +57,30 @@ def conda_arch():
 
 def should_skip_build(metadata_tuples):
     """Takes the output of render_recipe as input and evaluates if this
-  recipe's build should be skipped.
-  """
+    recipe's build should be skipped."""
 
     return all(m[0].skip() for m in metadata_tuples)
 
 
 def next_build_number(channel_url, basename):
-    """Calculates the next build number of a package given the channel
+    """Calculates the next build number of a package given the channel.
 
-  This function returns the next build number (integer) for a package given its
-  resulting tarball base filename (can be obtained with
-  :py:func:`get_output_path`).
+    This function returns the next build number (integer) for a package given its
+    resulting tarball base filename (can be obtained with
+    :py:func:`get_output_path`).
 
 
-  Args:
+    Args:
 
-    channel_url: The URL where to look for packages clashes (normally a beta
-      channel)
-    basename: The tarball basename to check on the channel
+      channel_url: The URL where to look for packages clashes (normally a beta
+        channel)
+      basename: The tarball basename to check on the channel
 
-  Returns: The next build number with the current configuration.  Zero (0) is
-  returned if no match is found.  Also returns the URLs of the packages it
-  finds with matches on the name, version and python-version, ordered by
-  (reversed) build-number.
-
-  """
+    Returns: The next build number with the current configuration.  Zero (0) is
+    returned if no match is found.  Also returns the URLs of the packages it
+    finds with matches on the name, version and python-version, ordered by
+    (reversed) build-number.
+    """
 
     from conda.exports import get_index
 
@@ -141,23 +139,23 @@ def next_build_number(channel_url, basename):
 
 
 def make_conda_config(config, python, append_file, condarc_options):
-    """Creates a conda configuration for a build merging various sources
+    """Creates a conda configuration for a build merging various sources.
 
-  This function will use the conda-build API to construct a configuration by
-  merging different sources of information.
+    This function will use the conda-build API to construct a configuration by
+    merging different sources of information.
 
-  Args:
+    Args:
 
-    config: Path leading to the ``conda_build_config.yaml`` to use
-    python: The version of python to use for the build as ``x.y`` (e.g.
-      ``3.6``)
-    append_file: Path leading to the ``recipe_append.yaml`` file to use
-    condarc_options: A dictionary (typically read from a condarc YAML file)
-      that contains build and channel options
+      config: Path leading to the ``conda_build_config.yaml`` to use
+      python: The version of python to use for the build as ``x.y`` (e.g.
+        ``3.6``)
+      append_file: Path leading to the ``recipe_append.yaml`` file to use
+      condarc_options: A dictionary (typically read from a condarc YAML file)
+        that contains build and channel options
 
-  Returns: A dictionary containing the merged configuration, as produced by
-  conda-build API's ``get_or_merge_config()`` function.
-  """
+    Returns: A dictionary containing the merged configuration, as produced by
+    conda-build API's ``get_or_merge_config()`` function.
+    """
 
     from conda_build.conda_interface import url_path
 
@@ -187,39 +185,38 @@ def make_conda_config(config, python, append_file, condarc_options):
 
 
 def get_output_path(metadata, config):
-    """Renders the recipe and returns the name of the output file"""
+    """Renders the recipe and returns the name of the output file."""
 
     return conda_build.api.get_output_file_paths(metadata, config=config)[0]
 
 
 def get_rendered_metadata(recipe_dir, config):
-    """Renders the recipe and returns the interpreted YAML file"""
+    """Renders the recipe and returns the interpreted YAML file."""
 
     return conda_build.api.render(recipe_dir, config=config)
 
 
 def get_parsed_recipe(metadata):
-    """Renders the recipe and returns the interpreted YAML file"""
+    """Renders the recipe and returns the interpreted YAML file."""
 
     output = conda_build.api.output_yaml(metadata[0][0])
     return yaml.load(output, Loader=yaml.FullLoader)
 
 
 def exists_on_channel(channel_url, basename):
-    """Checks on the given channel if a package with the specs exist
-
-  This procedure always ignores the package hash code, if one is set
+    """Checks on the given channel if a package with the specs exist.
 
-  Args:
+    This procedure always ignores the package hash code, if one is set
 
-    channel_url: The URL where to look for packages clashes (normally a beta
-      channel)
-    basename: The basename of the tarball to search for
+    Args:
 
-  Returns: A complete package url, if the package already exists in the channel
-  or ``None`` otherwise.
+      channel_url: The URL where to look for packages clashes (normally a beta
+        channel)
+      basename: The basename of the tarball to search for
 
-  """
+    Returns: A complete package url, if the package already exists in the channel
+    or ``None`` otherwise.
+    """
 
     build_number, urls = next_build_number(channel_url, basename)
 
@@ -266,7 +263,7 @@ def parse_dependencies(recipe_dir, config):
 
 
 def get_env_directory(conda, name):
-    """Get the directory of a particular conda environment or fail silently"""
+    """Get the directory of a particular conda environment or fail silently."""
 
     cmd = [conda, "env", "list", "--json"]
     output = subprocess.check_output(cmd)
@@ -291,23 +288,23 @@ def get_env_directory(conda, name):
 
 
 def conda_create(conda, name, overwrite, condarc, packages, dry_run, use_local):
-    """Creates a new conda environment following package specifications
-
-  This command can create a new conda environment following the list of input
-  packages.  It will overwrite an existing environment if indicated.
-
-  Args:
-    conda: path to the main conda executable of the installation
-    name: the name of the environment to create or overwrite
-    overwrite: if set to ```True``, overwrite potentially existing environments
-      with the same name
-    condarc: a dictionary of options for conda, including channel urls
-    packages: the package list specification
-    dry_run: if set, then don't execute anything, just print stuff
-    use_local: include the local conda-bld directory as a possible installation
-      channel (useful for testing multiple interdependent recipes that are
-      built locally)
-  """
+    """Creates a new conda environment following package specifications.
+
+    This command can create a new conda environment following the list of input
+    packages.  It will overwrite an existing environment if indicated.
+
+    Args:
+      conda: path to the main conda executable of the installation
+      name: the name of the environment to create or overwrite
+      overwrite: if set to ```True``, overwrite potentially existing environments
+        with the same name
+      condarc: a dictionary of options for conda, including channel urls
+      packages: the package list specification
+      dry_run: if set, then don't execute anything, just print stuff
+      use_local: include the local conda-bld directory as a possible installation
+        channel (useful for testing multiple interdependent recipes that are
+        built locally)
+    """
 
     from .bootstrap import run_cmdline
 
@@ -360,38 +357,37 @@ def conda_create(conda, name, overwrite, condarc, packages, dry_run, use_local):
 
 
 def get_docserver_setup(public, stable, server, intranet, group):
-    """Returns a setup for BOB_DOCUMENTATION_SERVER
+    """Returns a setup for BOB_DOCUMENTATION_SERVER.
 
-  What is available to build the documentation depends on the setup of
-  ``public`` and ``stable``:
+    What is available to build the documentation depends on the setup of
+    ``public`` and ``stable``:
 
-  * public and stable: only returns the public stable channel(s)
-  * public and not stable: returns both public stable and beta channels
-  * not public and stable: returns both public and private stable channels
-  * not public and not stable: returns all channels
+    * public and stable: only returns the public stable channel(s)
+    * public and not stable: returns both public stable and beta channels
+    * not public and stable: returns both public and private stable channels
+    * not public and not stable: returns all channels
 
-  Beta channels have priority over stable channels, if returned.  Private
-  channels have priority over public channles, if turned.
+    Beta channels have priority over stable channels, if returned.  Private
+    channels have priority over public channles, if turned.
 
 
-  Args:
+    Args:
 
-    public: Boolean indicating if we're supposed to include only public
-      channels
-    stable: Boolean indicating if we're supposed to include only stable
-      channels
-    server: The base address of the server containing our conda channels
-    intranet: Boolean indicating if we should add "private"/"public" prefixes
-      on the returned paths
-    group: The group of packages (gitlab namespace) the package we're compiling
-      is part of.  Values should match URL namespaces currently available on
-      our internal webserver.  Currently, only "bob" or "beat" will work.
+      public: Boolean indicating if we're supposed to include only public
+        channels
+      stable: Boolean indicating if we're supposed to include only stable
+        channels
+      server: The base address of the server containing our conda channels
+      intranet: Boolean indicating if we should add "private"/"public" prefixes
+        on the returned paths
+      group: The group of packages (gitlab namespace) the package we're compiling
+        is part of.  Values should match URL namespaces currently available on
+        our internal webserver.  Currently, only "bob" or "beat" will work.
 
 
-  Returns: a string to be used by bob.extension to find dependent
-  documentation projects.
-
-  """
+    Returns: a string to be used by bob.extension to find dependent
+    documentation projects.
+    """
 
     if (not public) and (not intranet):
         raise RuntimeError(
@@ -429,25 +425,25 @@ def get_docserver_setup(public, stable, server, intranet, group):
 
 
 def check_version(workdir, envtag):
-    """Checks if the version being built and the value reported match
+    """Checks if the version being built and the value reported match.
 
-  This method will read the contents of the file ``version.txt`` and compare it
-  to the potentially set ``envtag`` (may be ``None``).  If the value of
-  ``envtag`` is different than ``None``, ensure it matches the value in
-  ``version.txt`` or raises an exception.
+    This method will read the contents of the file ``version.txt`` and compare it
+    to the potentially set ``envtag`` (may be ``None``).  If the value of
+    ``envtag`` is different than ``None``, ensure it matches the value in
+    ``version.txt`` or raises an exception.
 
 
-  Args:
+    Args:
 
-    workdir: The work directory where the repo of the package being built was
-      checked-out
-    envtag: (optional) tag provided by the environment
+      workdir: The work directory where the repo of the package being built was
+        checked-out
+      envtag: (optional) tag provided by the environment
 
 
-  Returns: A tuple with the version of the package that we're currently
-  building and a boolean flag indicating if the version number represents a
-  pre-release or a stable release.
-  """
+    Returns: A tuple with the version of the package that we're currently
+    building and a boolean flag indicating if the version number represents a
+    pre-release or a stable release.
+    """
 
     version = open(os.path.join(workdir, "version.txt"), "rt").read().rstrip()
 
@@ -483,15 +479,14 @@ def check_version(workdir, envtag):
 
 
 def git_clean_build(runner, verbose):
-    """Runs git-clean to clean-up build products
-
-  Args:
+    """Runs git-clean to clean-up build products.
 
-    runner: A pointer to the ``run_cmdline()`` function
-    verbose: A boolean flag indicating if the git command should report erased
-      files or not
+    Args:
 
-  """
+      runner: A pointer to the ``run_cmdline()`` function
+      verbose: A boolean flag indicating if the git command should report erased
+        files or not
+    """
 
     # glob wild card entries we'd like to keep
     exclude_from_cleanup = [
@@ -533,42 +528,42 @@ def base_build(
     python_version,
     condarc_options,
 ):
-    """Builds a non-beat/non-bob software dependence that doesn't exist on defaults
-
-  This function will build a software dependence that is required for our
-  software stack, but does not (yet) exist on the defaults channels.  It first
-  check if the build should run for the current architecture, checks if the
-  package is not already built on our public channel and, if that is true, then
-  proceeds with the build of the dependence.
-
-
-  Args:
-
-    bootstrap: Module that should be pre-loaded so this function can be used
-      in a pre-bdt build
-    server: The base address of the server containing our conda channels
-    intranet: Boolean indicating if we should add "private"/"public" prefixes
-      on the returned paths
-    group: The group of packages (gitlab namespace) the package we're compiling
-      is part of.  Values should match URL namespaces currently available on
-      our internal webserver.  Currently, only "bob" or "beat" will work.
-    recipe_dir: The directory containing the recipe's ``meta.yaml`` file
-    conda_build_config: Path to the ``conda_build_config.yaml`` file to use
-    python_version: String with the python version to build for, in the format
-      ``x.y`` (should be passed even if not building a python package).  It
-      can also be set to ``noarch``, or ``None``.  If set to ``None``, then we
-      don't assume there is a python-specific version being built.  If set to
-      ``noarch``, then it is a python package without a specific build.
-    condarc_options: Pre-parsed condarc options loaded from the respective YAML
-      file
-
-
-  Returns:
-
-    list: The list of built packages, as returned by
-    ``conda_build.api.build()``
-
-  """
+    """Builds a non-beat/non-bob software dependence that doesn't exist on
+    defaults.
+
+    This function will build a software dependence that is required for our
+    software stack, but does not (yet) exist on the defaults channels.  It first
+    check if the build should run for the current architecture, checks if the
+    package is not already built on our public channel and, if that is true, then
+    proceeds with the build of the dependence.
+
+
+    Args:
+
+      bootstrap: Module that should be pre-loaded so this function can be used
+        in a pre-bdt build
+      server: The base address of the server containing our conda channels
+      intranet: Boolean indicating if we should add "private"/"public" prefixes
+        on the returned paths
+      group: The group of packages (gitlab namespace) the package we're compiling
+        is part of.  Values should match URL namespaces currently available on
+        our internal webserver.  Currently, only "bob" or "beat" will work.
+      recipe_dir: The directory containing the recipe's ``meta.yaml`` file
+      conda_build_config: Path to the ``conda_build_config.yaml`` file to use
+      python_version: String with the python version to build for, in the format
+        ``x.y`` (should be passed even if not building a python package).  It
+        can also be set to ``noarch``, or ``None``.  If set to ``None``, then we
+        don't assume there is a python-specific version being built.  If set to
+        ``noarch``, then it is a python package without a specific build.
+      condarc_options: Pre-parsed condarc options loaded from the respective YAML
+        file
+
+
+    Returns:
+
+      list: The list of built packages, as returned by
+      ``conda_build.api.build()``
+    """
 
     # if you get to this point, tries to build the package
     public_channels = bootstrap.get_channels(
diff --git a/bob/devtools/changelog.py b/bob/devtools/changelog.py
index 8f5653ac39dd32ed12da2e243ce2d558f86aa46c..ddba8b29fb077415c633b0ab5a892d4d301861a8 100644
--- a/bob/devtools/changelog.py
+++ b/bob/devtools/changelog.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Utilities for retrieving, parsing and auto-generating changelogs"""
+"""Utilities for retrieving, parsing and auto-generating changelogs."""
 
 import io
 import datetime
@@ -23,7 +23,7 @@ def parse_date(d):
 
 
 def _sort_commits(commits, reverse):
-    """Sorts gitlab commit objects using their ``committed_date`` attribute"""
+    """Sorts gitlab commit objects using their ``committed_date`` attribute."""
 
     return sorted(
         commits, key=lambda x: parse_date(x.committed_date), reverse=reverse
@@ -31,7 +31,7 @@ def _sort_commits(commits, reverse):
 
 
 def _sort_tags(tags, reverse):
-    """Sorts gitlab tag objects using their ``committed_date`` attribute"""
+    """Sorts gitlab tag objects using their ``committed_date`` attribute."""
 
     return sorted(
         tags,
@@ -41,13 +41,13 @@ def _sort_tags(tags, reverse):
 
 
 def get_file_from_gitlab(gitpkg, path, ref="master"):
-    """Retrieves a file from a Gitlab repository, returns a (StringIO) file"""
+    """Retrieves a file from a Gitlab repository, returns a (StringIO) file."""
 
     return io.StringIO(gitpkg.files.get(file_path=path, ref=branch).decode())
 
 
 def get_last_tag(package):
-    """Returns the last (gitlab object) tag for the given package
+    """Returns the last (gitlab object) tag for the given package.
 
     Args:
 
@@ -68,7 +68,7 @@ def get_last_tag(package):
 
 
 def get_last_tag_date(package):
-    """Returns the last release date for the given package
+    """Returns the last release date for the given package.
 
     Falls back to the first commit date if the package has not yet been tagged
 
@@ -135,14 +135,13 @@ def _get_tag_changelog(tag):
 
 
 def _write_one_tag(f, pkg_name, tag):
-    """Prints commit information for a single tag of a given package
+    """Prints commit information for a single tag of a given package.
 
     Args:
 
         f: A :py:class:`File` ready to be written at
         pkg_name: The name of the package we are writing tags of
         tag: The tag value
-
     """
 
     git_date = parse_date(tag.commit["committed_date"])
@@ -164,14 +163,14 @@ def _write_one_tag(f, pkg_name, tag):
 
 
 def _write_commits_range(f, pkg_name, commits):
-    """Writes all commits of a given package within a range, to the output file
+    """Writes all commits of a given package within a range, to the output
+    file.
 
     Args:
 
         f: A :py:class:`File` ready to be written at
         pkg_name: The name of the package we are writing tags of
         commits: List of commits to be written
-
     """
 
     for commit in commits:
@@ -195,14 +194,13 @@ def _write_commits_range(f, pkg_name, commits):
 
 def _write_mergerequests_range(f, pkg_name, mrs):
     """Writes all merge-requests of a given package, with a range, to the
-    output file
+    output file.
 
     Args:
 
         f: A :py:class:`File` ready to be written at
         pkg_name: The name of the package we are writing tags of
         mrs: The list of merge requests to write
-
     """
 
     for mr in mrs:
@@ -232,7 +230,7 @@ def _write_mergerequests_range(f, pkg_name, mrs):
 
 
 def write_tags_with_commits(f, gitpkg, since, mode):
-    """Writes all tags and commits of a given package to the output file
+    """Writes all tags and commits of a given package to the output file.
 
     Args:
 
@@ -241,7 +239,6 @@ def write_tags_with_commits(f, gitpkg, since, mode):
         since: Starting date (as a datetime object)
         mode: One of mrs (merge-requests), commits or tags indicating how to
               list entries in the changelog for this package
-
     """
 
     # get tags since release and sort them
@@ -332,14 +329,13 @@ def write_tags_with_commits(f, gitpkg, since, mode):
 
 
 def write_tags(f, gitpkg, since):
-    """Writes all tags of a given package to the output file
+    """Writes all tags of a given package to the output file.
 
     Args:
 
         f: A :py:class:`File` ready to be written at
         gitpkg: A pointer to the gitlab package object
         since: Starting date as a datetime object
-
     """
 
     tags = gitpkg.tags.list()
diff --git a/bob/devtools/ci.py b/bob/devtools/ci.py
index dd6489de8f50e8f7bb2ac8c96176fab6f0be8e93..0dea4c9cdb705627346f20c5017f9454cdc201d7 100644
--- a/bob/devtools/ci.py
+++ b/bob/devtools/ci.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Tools to help CI-based builds and artifact deployment"""
+"""Tools to help CI-based builds and artifact deployment."""
 
 
 import git
@@ -14,21 +14,21 @@ logger = get_logger(__name__)
 
 
 def is_master(refname, tag, repodir):
-    """Tells if we're on the master branch via ref_name or tag
+    """Tells if we're on the master branch via ref_name or tag.
 
-  This function checks if the name of the branch being built is "master".  If a
-  tag is set, then it checks if the tag is on the master branch.  If so, then
-  also returns ``True``, otherwise, ``False``.
+    This function checks if the name of the branch being built is "master".  If a
+    tag is set, then it checks if the tag is on the master branch.  If so, then
+    also returns ``True``, otherwise, ``False``.
 
-  Args:
+    Args:
 
-    refname: The value of the environment variable ``CI_COMMIT_REF_NAME``
-    tag: The value of the environment variable ``CI_COMMIT_TAG`` - (may be
-      ``None``)
+      refname: The value of the environment variable ``CI_COMMIT_REF_NAME``
+      tag: The value of the environment variable ``CI_COMMIT_TAG`` - (may be
+        ``None``)
 
-  Returns: a boolean, indicating we're building the master branch **or** that
-  the tag being built was issued on the master branch.
-  """
+    Returns: a boolean, indicating we're building the master branch **or** that
+    the tag being built was issued on the master branch.
+    """
 
     if tag is not None:
         repo = git.Repo(repodir)
@@ -39,22 +39,22 @@ def is_master(refname, tag, repodir):
 
 
 def is_stable(package, refname, tag, repodir):
-    """Determines if the package being published is stable
+    """Determines if the package being published is stable.
 
-  This is done by checking if a tag was set for the package.  If that is the
-  case, we still cross-check the tag is on the "master" branch.  If everything
-  checks out, we return ``True``.  Else, ``False``.
+    This is done by checking if a tag was set for the package.  If that is the
+    case, we still cross-check the tag is on the "master" branch.  If everything
+    checks out, we return ``True``.  Else, ``False``.
 
-  Args:
+    Args:
 
-    package: Package name in the format "group/name"
-    refname: The current value of the environment ``CI_COMMIT_REF_NAME``
-    tag: The current value of the enviroment ``CI_COMMIT_TAG`` (may be
-      ``None``)
-    repodir: The directory that contains the clone of the git repository
+      package: Package name in the format "group/name"
+      refname: The current value of the environment ``CI_COMMIT_REF_NAME``
+      tag: The current value of the enviroment ``CI_COMMIT_TAG`` (may be
+        ``None``)
+      repodir: The directory that contains the clone of the git repository
 
-  Returns: a boolean, indicating if the current build is for a stable release
-  """
+    Returns: a boolean, indicating if the current build is for a stable release
+    """
 
     if tag is not None:
         logger.info('Project %s tag is "%s"', package, tag)
@@ -81,11 +81,11 @@ def is_stable(package, refname, tag, repodir):
 
 
 def read_packages(filename):
-    """
-  Return a python list of tuples (repository, branch), given a file containing
-  one package (and branch) per line.  Comments are excluded
+    """Return a python list of tuples (repository, branch), given a file
+    containing one package (and branch) per line.
 
-  """
+    Comments are excluded
+    """
 
     lines = load_order_file(filename)
 
@@ -101,7 +101,7 @@ def read_packages(filename):
 
 
 def uniq(seq, idfun=None):
-    """Very fast, order preserving uniq function"""
+    """Very fast, order preserving uniq function."""
 
     # order preserving
     if idfun is None:
@@ -124,37 +124,36 @@ def uniq(seq, idfun=None):
 
 
 def select_build_file(basename, paths, branch):
-    """Selects the file to use for a build
-
-  This method will return the name of the most adequate build-accessory file
-  (conda_build_config.yaml, recipe_append.yaml) for a given build, in this
-  order of priority:
+    """Selects the file to use for a build.
 
-  1. The first file found is returned
-  2. We first search for a *specific* file if ``branch`` is set
-  3. If that file does not exist, returns the unbranded filename if that exists
-     in one of the paths
-  4. If no candidates exists, returns ``None``
+    This method will return the name of the most adequate build-accessory file
+    (conda_build_config.yaml, recipe_append.yaml) for a given build, in this
+    order of priority:
 
-  The candidate filename is built using
-  ``os.path.splitext(os.path.basename(basename))[0]``.
+    1. The first file found is returned
+    2. We first search for a *specific* file if ``branch`` is set
+    3. If that file does not exist, returns the unbranded filename if that exists
+       in one of the paths
+    4. If no candidates exists, returns ``None``
 
-  Args:
+    The candidate filename is built using
+    ``os.path.splitext(os.path.basename(basename))[0]``.
 
-    basename: Name of the file to use for the search
-    paths (list): A list of paths leading to the location of the variants file
-      to use.  Priority is given to paths that come first
-    branch (str): Optional key to be set when searching for the variants file
-      to use.  This is typically the git-branch name of the current branch of
-      the repo being built.
+    Args:
 
+      basename: Name of the file to use for the search
+      paths (list): A list of paths leading to the location of the variants file
+        to use.  Priority is given to paths that come first
+      branch (str): Optional key to be set when searching for the variants file
+        to use.  This is typically the git-branch name of the current branch of
+        the repo being built.
 
-  Returns:
 
-    str: A string containing the full, resolved path of the file to use.
-    Returns ``None``, if no candidate is found
+    Returns:
 
-  """
+      str: A string containing the full, resolved path of the file to use.
+      Returns ``None``, if no candidate is found
+    """
 
     import os
 
@@ -180,10 +179,11 @@ def select_build_file(basename, paths, branch):
 def select_conda_build_config(paths, branch):
     """Selects the default conda_build_config.yaml.
 
-  See :py:func:`select_build_file` for implementation details.  If no build
-  config file is found by :py:func:`select_build_file`, then returns the
-  default ``conda_build_config.yaml`` shipped with this package.
-  """
+    See :py:func:`select_build_file` for implementation details.  If no
+    build config file is found by :py:func:`select_build_file`, then
+    returns the default ``conda_build_config.yaml`` shipped with this
+    package.
+    """
 
     from .constants import CONDA_BUILD_CONFIG as default
 
@@ -193,10 +193,11 @@ def select_conda_build_config(paths, branch):
 def select_conda_recipe_append(paths, branch):
     """Selects the default recipe_append.yaml.
 
-  See :py:func:`select_build_file` for implementation details.  If no recipe
-  append file is found by :py:func:`select_build_file`, then returns the
-  default ``recipe_append.yaml`` shipped with this package.
-  """
+    See :py:func:`select_build_file` for implementation details.  If no
+    recipe append file is found by :py:func:`select_build_file`, then
+    returns the default ``recipe_append.yaml`` shipped with this
+    package.
+    """
 
     from .constants import CONDA_RECIPE_APPEND as default
 
@@ -206,8 +207,9 @@ def select_conda_recipe_append(paths, branch):
 def select_user_condarc(paths, branch):
     """Selects the user condarc file to read (if any)
 
-  See :py:func:`select_build_file` for implementation details.  If no recipe
-  condarc is found by :py:func:`select_build_file`, then returns ``None``.
-  """
+    See :py:func:`select_build_file` for implementation details.  If no
+    recipe condarc is found by :py:func:`select_build_file`, then
+    returns ``None``.
+    """
 
     return select_build_file("condarc", paths, branch)
diff --git a/bob/devtools/constants.py b/bob/devtools/constants.py
index 6163ffa60e607b6de8727908656235d1123ee4f6..32b0194820ea5adbc1914ab4afc4726d8d6a3d06 100644
--- a/bob/devtools/constants.py
+++ b/bob/devtools/constants.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Constants used for building and more"""
+"""Constants used for building and more."""
 
 import os
 import pkg_resources
diff --git a/bob/devtools/deploy.py b/bob/devtools/deploy.py
index aa9bd1bd1938da2aa69c8414b1531d6f0bb0c858..9c7782902346e8f2914d71b88321a949ddd3af4d 100644
--- a/bob/devtools/deploy.py
+++ b/bob/devtools/deploy.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Deployment utilities for conda packages and documentation via webDAV"""
+"""Deployment utilities for conda packages and documentation via webDAV."""
 
 
 import os
@@ -13,7 +13,7 @@ logger = get_logger(__name__)
 
 
 def _setup_webdav_client(server, root, username, password):
-    """Configures and checks the webdav client"""
+    """Configures and checks the webdav client."""
 
     # setup webdav connection
     webdav_options = dict(
@@ -34,28 +34,27 @@ def _setup_webdav_client(server, root, username, password):
 def deploy_conda_package(
     package, arch, stable, public, username, password, overwrite, dry_run
 ):
-    """Deploys a single conda package on the appropriate path
-
-  Args:
-
-    package (str): Path leading to the conda package to be deployed
-    arch (str): The conda architecture to deploy to (``linux-64``, ``osx-64``,
-      ``noarch``, or ``None`` - in which case the architecture is going to be
-      guessed from the directory where the package sits)
-    stable (bool): Indicates if the package should be deployed on a stable
-      (``True``) or beta (``False``) channel
-    public (bool): Indicates if the package is supposed to be distributed
-      publicly or privatly (within Idiap network)
-    username (str): The name of the user on the webDAV server to use for
-      uploading the package
-    password (str): The password of the user on the webDAV server to use for
-      uploading the package
-    overwrite (bool): If we should overwrite a package with equal name existing
-      on the destination directory.  Otherwise, an exception is raised.
-    dry_run (bool): If we're supposed to really do the actions, or just log
-      messages.
-
-  """
+    """Deploys a single conda package on the appropriate path.
+
+    Args:
+
+      package (str): Path leading to the conda package to be deployed
+      arch (str): The conda architecture to deploy to (``linux-64``, ``osx-64``,
+        ``noarch``, or ``None`` - in which case the architecture is going to be
+        guessed from the directory where the package sits)
+      stable (bool): Indicates if the package should be deployed on a stable
+        (``True``) or beta (``False``) channel
+      public (bool): Indicates if the package is supposed to be distributed
+        publicly or privatly (within Idiap network)
+      username (str): The name of the user on the webDAV server to use for
+        uploading the package
+      password (str): The password of the user on the webDAV server to use for
+        uploading the package
+      overwrite (bool): If we should overwrite a package with equal name existing
+        on the destination directory.  Otherwise, an exception is raised.
+      dry_run (bool): If we're supposed to really do the actions, or just log
+        messages.
+    """
 
     server_info = WEBDAV_PATHS[stable][public]
     davclient = _setup_webdav_client(
@@ -101,31 +100,30 @@ def deploy_documentation(
     password,
     dry_run,
 ):
-    """Deploys sphinx documentation to the appropriate webdav locations
-
-  Args:
-
-    path (str): Path leading to the root of the documentation to be deployed
-    package (str): Full name (with namespace) of the package being treated
-    stable (bool): Indicates if the documentation corresponds to the latest
-      stable build
-    latest (bool): Indicates if the documentation being deployed correspond to
-      the latest stable for the package or not.  In case the documentation
-      comes from a patch release which is not on the master branch, please set
-      this flag to ``False``, which will make us avoid deployment of the
-      documentation to ``master`` and ``stable`` sub-directories.
-    public (bool): Indicates if the documentation is supposed to be distributed
-      publicly or privatly (within Idiap network)
-    branch (str): The name of the branch for the current build
-    tag (str): The name of the tag currently built (may be ``None``)
-    username (str): The name of the user on the webDAV server to use for
-      uploading the package
-    password (str): The password of the user on the webDAV server to use for
-      uploading the package
-    dry_run (bool): If we're supposed to really do the actions, or just log
-      messages.
-
-  """
+    """Deploys sphinx documentation to the appropriate webdav locations.
+
+    Args:
+
+      path (str): Path leading to the root of the documentation to be deployed
+      package (str): Full name (with namespace) of the package being treated
+      stable (bool): Indicates if the documentation corresponds to the latest
+        stable build
+      latest (bool): Indicates if the documentation being deployed correspond to
+        the latest stable for the package or not.  In case the documentation
+        comes from a patch release which is not on the master branch, please set
+        this flag to ``False``, which will make us avoid deployment of the
+        documentation to ``master`` and ``stable`` sub-directories.
+      public (bool): Indicates if the documentation is supposed to be distributed
+        publicly or privatly (within Idiap network)
+      branch (str): The name of the branch for the current build
+      tag (str): The name of the tag currently built (may be ``None``)
+      username (str): The name of the user on the webDAV server to use for
+        uploading the package
+      password (str): The password of the user on the webDAV server to use for
+        uploading the package
+      dry_run (bool): If we're supposed to really do the actions, or just log
+        messages.
+    """
 
     # uploads documentation artifacts
     if not os.path.exists(path):
diff --git a/bob/devtools/log.py b/bob/devtools/log.py
index f3edc28bdf0a553d54e8d678875ab14d6b52bb87..894f74ee685f906d75d0101f565ca0dc3508d934 100644
--- a/bob/devtools/log.py
+++ b/bob/devtools/log.py
@@ -1,8 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Logging utilities
-"""
+"""Logging utilities."""
 
 import sys
 import logging
@@ -46,10 +45,8 @@ COLORMAP = dict(
 
 
 def _supports_color():
-    """
-  Returns True if the running system's terminal supports color, and False
-  otherwise.
-  """
+    """Returns True if the running system's terminal supports color, and False
+    otherwise."""
     plat = sys.platform
     supported_platform = plat != "Pocket PC" and (
         plat != "win32" or "ANSICON" in os.environ
@@ -62,7 +59,7 @@ def _supports_color():
 
 
 class ColorLog(object):
-    """Colorizes logging colors"""
+    """Colorizes logging colors."""
 
     def __init__(self, logger):
         self._log = logger
@@ -88,7 +85,7 @@ class ColorLog(object):
 
 
 def get_logger(name):
-    """Returns the default logger as setup by this module"""
+    """Returns the default logger as setup by this module."""
 
     return ColorLog(logging.getLogger(name))
 
@@ -96,17 +93,17 @@ def get_logger(name):
 def _echo(text, *args, **kwargs):
     """Provides a colorized version of :py:func:`click.echo` (for terminals)
 
-  The color is stripped off if outputting to a file or piping the results of
-  a command using this function.
+    The color is stripped off if outputting to a file or piping the results of
+    a command using this function.
 
-  Parameters:
+    Parameters:
 
-    text (str): The text to be printed
-    args (tuple): Tuple of attributes directly passed to
-      :py:func:`termcolor.colored`
-    kwargs (dict): Dictionary of attributes directly passed to
-      :py:func:`termcolor.colored`
-  """
+      text (str): The text to be printed
+      args (tuple): Tuple of attributes directly passed to
+        :py:func:`termcolor.colored`
+      kwargs (dict): Dictionary of attributes directly passed to
+        :py:func:`termcolor.colored`
+    """
 
     click.echo(termcolor.colored(text, *args, **kwargs))
 
@@ -134,23 +131,23 @@ def setup(
     logger_name, format="%(levelname)s:%(name)s@%(asctime)s: %(message)s"
 ):
     """This function returns a logger object that is set up to perform logging
-  using Bob loggers.
-
-  Parameters
-  ----------
-  logger_name : str
-      The name of the module to generate logs for
-  format : :obj:`str`, optional
-      The format of the logs, see :py:class:`logging.LogRecord` for more
-      details. By default, the log contains the logger name, the log time, the
-      log level and the massage.
-
-  Returns
-  -------
-  logger : :py:class:`logging.Logger`
-      The logger configured for logging. The same logger can be retrieved using
-      the :py:func:`logging.getLogger` function.
-  """
+    using Bob loggers.
+
+    Parameters
+    ----------
+    logger_name : str
+        The name of the module to generate logs for
+    format : :obj:`str`, optional
+        The format of the logs, see :py:class:`logging.LogRecord` for more
+        details. By default, the log contains the logger name, the log time, the
+        log level and the massage.
+
+    Returns
+    -------
+    logger : :py:class:`logging.Logger`
+        The logger configured for logging. The same logger can be retrieved using
+        the :py:func:`logging.getLogger` function.
+    """
     # generate new logger object
     logger = logging.getLogger(logger_name)
 
@@ -176,19 +173,19 @@ def setup(
 def set_verbosity_level(logger, level):
     """Sets the log level for the given logger.
 
-  Parameters
-  ----------
-  logger : :py:class:`logging.Logger` or str
-      The logger to generate logs for, or the name  of the module to generate
-      logs for.
-  level : int
-      Possible log levels are: 0: Error; 1: Warning; 2: Info; 3: Debug.
-
-  Raises
-  ------
-  ValueError
-      If the level is not in range(0, 4).
-  """
+    Parameters
+    ----------
+    logger : :py:class:`logging.Logger` or str
+        The logger to generate logs for, or the name  of the module to generate
+        logs for.
+    level : int
+        Possible log levels are: 0: Error; 1: Warning; 2: Info; 3: Debug.
+
+    Raises
+    ------
+    ValueError
+        If the level is not in range(0, 4).
+    """
     if level not in range(0, 4):
         raise ValueError(
             "The verbosity level %d does not exist. Please reduce the number of "
diff --git a/bob/devtools/release.py b/bob/devtools/release.py
index 1d69e41aaefcdca0ea047c7ff26ebb889d3dd468..707c144c96467e06b22aff281e9c12e7f3f37460 100644
--- a/bob/devtools/release.py
+++ b/bob/devtools/release.py
@@ -1,7 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Utilities to needed to release packages"""
+"""Utilities to needed to release packages."""
 
 import os
 import re
@@ -17,7 +17,7 @@ from distutils.version import StrictVersion
 
 
 def download_path(package, path, output=None, ref="master"):
-    """Downloads paths from gitlab, with an optional recurse
+    """Downloads paths from gitlab, with an optional recurse.
 
     This method will download an archive of the repository from chosen
     reference, and then it will search insize the zip blob for the path to be
@@ -33,7 +33,6 @@ def download_path(package, path, output=None, ref="master"):
         the basename of ``path`` as storage point with respect to the current
         directory
       ref: the name of the git reference (branch, tag or commit hash) to use
-
     """
     from io import BytesIO
     import tarfile
@@ -60,7 +59,7 @@ def download_path(package, path, output=None, ref="master"):
 
 
 def get_gitlab_instance():
-    """Returns an instance of the gitlab object for remote operations"""
+    """Returns an instance of the gitlab object for remote operations."""
 
     # tries to figure if we can authenticate using a global configuration
     cfgs = ["~/.python-gitlab.cfg", "/etc/python-gitlab.cfg"]
@@ -83,8 +82,7 @@ def get_gitlab_instance():
 
 
 def _update_readme(readme, version):
-    """
-    Inside text of the readme, replaces parts of the links to the provided
+    """Inside text of the readme, replaces parts of the links to the provided
     version. If version is not provided, replace to `stable` or `master`.
 
     Args:
@@ -125,7 +123,8 @@ def _update_readme(readme, version):
 
 
 def get_latest_tag_name(gitpkg):
-    """Find the name of the latest tag for a given package in the format '#.#.#'
+    """Find the name of the latest tag for a given package in the format
+    '#.#.#'.
 
     Args:
         gitpkg: gitlab package object
@@ -153,9 +152,8 @@ def get_latest_tag_name(gitpkg):
 
 
 def get_parsed_tag(gitpkg, tag):
-    """
-    An older tag is formatted as 'v2.1.3 (Sep 22, 2017 10:37)', from which we
-    need only v2.1.3
+    """An older tag is formatted as 'v2.1.3 (Sep 22, 2017 10:37)', from which
+    we need only v2.1.3.
 
     The latest tag is either patch, minor, major, or none
     """
@@ -256,7 +254,7 @@ def update_tag_comments(gitpkg, tag_name, tag_comments_list, dry_run=False):
 def update_files_with_mr(
     gitpkg, files_dict, message, branch, automerge, dry_run, user_id
 ):
-    """Update (via a commit) files of a given gitlab package, through an MR
+    """Update (via a commit) files of a given gitlab package, through an MR.
 
     This function can update a file in a gitlab package, but will do this
     through a formal merge request.  You can auto-merge this request
@@ -271,7 +269,6 @@ def update_files_with_mr(
           created MR
         dry_run: If True, nothing will be pushed to gitlab
         user_id: The integer which numbers the user to attribute this MR to
-
     """
 
     data = {
@@ -344,7 +341,6 @@ def update_files_at_master(gitpkg, files_dict, message, dry_run):
         files_dict: Dictionary of file names and their contents (as text)
         message: Commit message
         dry_run: If True, nothing will be committed or pushed to GitLab
-
     """
 
     data = {"branch": "master", "commit_message": message, "actions": []}  # v4
@@ -370,7 +366,7 @@ def update_files_at_master(gitpkg, files_dict, message, dry_run):
 
 
 def get_last_pipeline(gitpkg):
-    """Returns the last pipeline of the project
+    """Returns the last pipeline of the project.
 
     Args:
 
@@ -388,7 +384,7 @@ def get_last_pipeline(gitpkg):
 
 
 def just_build_package(gitpkg, dry_run=False):
-    """Creates the pipeline with the latest tag and starts it
+    """Creates the pipeline with the latest tag and starts it.
 
     Args:
 
@@ -396,7 +392,6 @@ def just_build_package(gitpkg, dry_run=False):
         dry_run: If True, the pipeline will not be created on GitLab
 
     Returns:
-
     """
 
     # get the latest tag
@@ -424,7 +419,6 @@ def wait_for_pipeline_to_finish(gitpkg, pipeline_id, dry_run=False):
         pipeline_id: id of the pipeline for which we are waiting to finish
         dry_run: If True, outputs log message and exit. There wil be no
                  waiting.
-
     """
 
     sleep_step = 30
@@ -478,12 +472,11 @@ def wait_for_pipeline_to_finish(gitpkg, pipeline_id, dry_run=False):
 
 
 def cancel_last_pipeline(gitpkg):
-    """ Cancel the last started pipeline of a package
+    """Cancel the last started pipeline of a package.
 
     Args:
 
         gitpkg: gitlab package object
-
     """
 
     pipeline = get_last_pipeline(gitpkg)
@@ -496,7 +489,7 @@ def cancel_last_pipeline(gitpkg):
 
 
 def release_package(gitpkg, tag_name, tag_comments_list, dry_run=False):
-    """Release package
+    """Release package.
 
     The provided tag will be annotated with a given list of comments.
     README.rst and version.txt files will also be updated according to the
@@ -508,7 +501,6 @@ def release_package(gitpkg, tag_name, tag_comments_list, dry_run=False):
         tag_name: The name of the release tag
         tag_comments_list: New annotations for this tag in a form of list
         dry_run: If True, nothing will be committed or pushed to GitLab
-
     """
 
     # if there is nothing to release, just rebuild the package
@@ -569,7 +561,7 @@ def release_package(gitpkg, tag_name, tag_comments_list, dry_run=False):
 
 
 def parse_and_process_package_changelog(gl, gitpkg, package_changelog, dry_run):
-    """Process the changelog of a single package
+    """Process the changelog of a single package.
 
     Parse the log following specific format.  Update annotations of the
     provided older tags and release the package by following the last tag
@@ -584,7 +576,6 @@ def parse_and_process_package_changelog(gl, gitpkg, package_changelog, dry_run):
 
     Returns: the name of the latest tag, and tag's
     comments
-
     """
 
     cur_tag = None
@@ -610,7 +601,7 @@ def parse_and_process_package_changelog(gl, gitpkg, package_changelog, dry_run):
 
 
 def release_bob(changelog_file):
-    """Process the changelog and releases the ``bob`` metapackage"""
+    """Process the changelog and releases the ``bob`` metapackage."""
 
     logger.info(
         'Read the section "Releasing the Bob meta package" '
diff --git a/bob/devtools/scripts/bdt.py b/bob/devtools/scripts/bdt.py
index b43f7baf191598de3f6fa61a57545a6cba819aae..2943070b772ccd90e761cf95c512496b7fe342f1 100644
--- a/bob/devtools/scripts/bdt.py
+++ b/bob/devtools/scripts/bdt.py
@@ -1,8 +1,7 @@
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-"""Main entry point for bdt
-"""
+"""Main entry point for bdt."""
 
 import os
 import pkg_resources
@@ -16,7 +15,7 @@ logger = setup("bob")
 
 
 class AliasedGroup(click.Group):
-    """ Class that handles prefix aliasing for commands """
+    """Class that handles prefix aliasing for commands."""
 
     def get_command(self, ctx, cmd_name):
         rv = click.Group.get_command(self, ctx, cmd_name)
@@ -33,8 +32,8 @@ class AliasedGroup(click.Group):
 def raise_on_error(view_func):
     """Raise a click exception if returned value is not zero.
 
-    Click exits successfully if anything is returned, in order to exit properly
-    when something went wrong an exception must be raised.
+    Click exits successfully if anything is returned, in order to exit
+    properly when something went wrong an exception must be raised.
     """
 
     from functools import wraps
diff --git a/bob/devtools/scripts/build.py b/bob/devtools/scripts/build.py
index c95456a0bce9fc4426620071dfff102c30ef4fd0..193b8e596a93f9fc8cda03d538c55d26e91f92d9 100644
--- a/bob/devtools/scripts/build.py
+++ b/bob/devtools/scripts/build.py
@@ -157,12 +157,12 @@ def build(
     dry_run,
     ci,
 ):
-    """Builds package through conda-build with stock configuration
+    """Builds package through conda-build with stock configuration.
 
-  This command wraps the execution of conda-build so that you use the same
-  conda configuration we use for our CI.  It always set
-  ``--no-anaconda-upload``.
-  """
+    This command wraps the execution of conda-build so that you use the
+    same conda configuration we use for our CI.  It always set ``--no-
+    anaconda-upload``.
+    """
 
     # if we are in a dry-run mode, let's let it be known
     if dry_run:
diff --git a/bob/devtools/scripts/caupdate.py b/bob/devtools/scripts/caupdate.py
index 14eff420b6bfa9ac76e18e6487d3efe8914f9464..9330c81bfb6809029b4f61e1b13c22f4adb474f5 100644
--- a/bob/devtools/scripts/caupdate.py
+++ b/bob/devtools/scripts/caupdate.py
@@ -26,11 +26,11 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def caupdate():
-    """Updates the root certificate authority bundle on the distribution
+    """Updates the root certificate authority bundle on the distribution.
 
     This script will download the latest CA bundle from curl at
-    https://curl.haxx.se/ca/cacert.pem and will append Idiap's Root CA to the
-    bundle, so we can use https://gitlab.idiap.ch transparently.
+    https://curl.haxx.se/ca/cacert.pem and will append Idiap's Root CA
+    to the bundle, so we can use https://gitlab.idiap.ch transparently.
     """
 
     import requests
diff --git a/bob/devtools/scripts/changelog.py b/bob/devtools/scripts/changelog.py
index 761f300d1986611d4f610f9147c95ca4fffa235c..186b4e35eb0a2886b48d4c6d9b68ea82ed7124d3 100644
--- a/bob/devtools/scripts/changelog.py
+++ b/bob/devtools/scripts/changelog.py
@@ -102,9 +102,9 @@ def changelog(target, changelog, group, mode, since):
     an existing file containing a list of packages that will be iterated on.
 
     For each package, we will contact the Gitlab server and create a changelog
-		using merge-requests (default), tags or commits since a given date.  If a
-		starting date is not passed, we'll use the date of the last tagged value or
-		the date of the first commit, if no tags are available in the package.
+                using merge-requests (default), tags or commits since a given date.  If a
+                starting date is not passed, we'll use the date of the last tagged value or
+                the date of the first commit, if no tags are available in the package.
     """
 
     gl = get_gitlab_instance()
diff --git a/bob/devtools/scripts/ci.py b/bob/devtools/scripts/ci.py
index 8d35b3dbd8f72b81638d6e464dd6832b86def2aa..cffe0c09ec437a8a4317c4ecf05ad10f2b031a64 100644
--- a/bob/devtools/scripts/ci.py
+++ b/bob/devtools/scripts/ci.py
@@ -30,13 +30,13 @@ logger = get_logger(__name__)
 @with_plugins(pkg_resources.iter_entry_points("bdt.ci.cli"))
 @click.group(cls=bdt.AliasedGroup)
 def ci():
-    """Commands for building packages and handling CI activities
+    """Commands for building packages and handling CI activities.
 
-  Commands defined here are supposed to run on our CI, where a number of
-  variables that define their behavior is correctly defined.  Do **NOT**
-  attempt to run these commands in your own installation.  Unexpected errors
-  may occur.
-  """
+    Commands defined here are supposed to run on our CI, where a number
+    of variables that define their behavior is correctly defined.  Do
+    **NOT** attempt to run these commands in your own installation.
+    Unexpected errors may occur.
+    """
     pass
 
 
@@ -61,10 +61,11 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def base_deploy(dry_run):
-    """Deploys dependencies not available at the defaults channel
+    """Deploys dependencies not available at the defaults channel.
 
     Deployment happens to our public channel directly, as these are
-    dependencies are required for proper bob/beat package runtime environments.
+    dependencies are required for proper bob/beat package runtime
+    environments.
     """
 
     if dry_run:
@@ -217,11 +218,11 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def readme(package):
-    """Checks setup.py's ``long_description`` syntax
+    """Checks setup.py's ``long_description`` syntax.
 
-    This program checks the syntax of the contents of the ``long_description``
-    field at the package's ``setup()`` function.  It verifies it will be
-    correctly displayed at PyPI.
+    This program checks the syntax of the contents of the
+    ``long_description`` field at the package's ``setup()`` function.
+    It verifies it will be correctly displayed at PyPI.
     """
 
     for k in package:
@@ -271,8 +272,8 @@ def pypi(package, dry_run):
     """Deploys build artifacts (python packages to PyPI)
 
     Deployment is only allowed for packages in which the visibility is
-    "public".  This check prevents publishing of private resources to the
-    (public) PyPI webserver.
+    "public".  This check prevents publishing of private resources to
+    the (public) PyPI webserver.
     """
 
     if dry_run:
@@ -359,12 +360,12 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def base_build(order, group, python, dry_run):
-    """Builds base (dependence) packages
+    """Builds base (dependence) packages.
 
-  This command builds dependence packages (packages that are not Bob/BEAT
-  packages) in the CI infrastructure.  It is **not** meant to be used outside
-  this context.
-  """
+    This command builds dependence packages (packages that are not
+    Bob/BEAT packages) in the CI infrastructure.  It is **not** meant to
+    be used outside this context.
+    """
 
     condarc = select_user_condarc(
         paths=[os.curdir], branch=os.environ.get("CI_COMMIT_REF_NAME")
@@ -467,11 +468,11 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def test(ctx, dry_run):
-    """Tests packages
+    """Tests packages.
 
-  This command tests packages in the CI infrastructure.  It is **not** meant
-  to be used outside this context.
-  """
+    This command tests packages in the CI infrastructure.  It is **not**
+    meant to be used outside this context.
+    """
 
     group = os.environ["CI_PROJECT_NAMESPACE"]
     if group not in ("bob", "beat"):
@@ -552,11 +553,11 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def build(ctx, dry_run, recipe_dir):
-    """Builds packages
+    """Builds packages.
 
-  This command builds packages in the CI infrastructure.  It is **not** meant
-  to be used outside this context.
-  """
+    This command builds packages in the CI infrastructure.  It is
+    **not** meant to be used outside this context.
+    """
 
     group = os.environ["CI_PROJECT_NAMESPACE"]
     if group not in ("bob", "beat"):
@@ -616,11 +617,11 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def clean(ctx):
-    """Cleans builds
+    """Cleans builds.
 
-  This command cleans builds in the CI infrastructure.  It is **not** meant
-  to be used outside this context.
-  """
+    This command cleans builds in the CI infrastructure.  It is **not**
+    meant to be used outside this context.
+    """
 
     from ..build import git_clean_build
     from ..bootstrap import run_cmdline
@@ -656,24 +657,24 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def nightlies(ctx, order, dry_run):
-    """Runs nightly builds
+    """Runs nightly builds.
 
-  This command can run nightly builds for packages listed on a file.
+    This command can run nightly builds for packages listed on a file.
 
-  The build or each package happens in a few phases:
+    The build or each package happens in a few phases:
 
-  1. Package is checked out and switched to the requested branch (master if not
-     set otherwise)
-  2. A build string is calculated from current dependencies.  If the package
-     has already been compiled, it is downloaded from the respective conda
-     channel and tested.  If the test does not pass, the package is completely
-     rebuilt
-  3. If the rebuild is successful, the new package is uploaded to the
-     respective conda channel, and the program continues with the next package
+    1. Package is checked out and switched to the requested branch (master if not
+       set otherwise)
+    2. A build string is calculated from current dependencies.  If the package
+       has already been compiled, it is downloaded from the respective conda
+       channel and tested.  If the test does not pass, the package is completely
+       rebuilt
+    3. If the rebuild is successful, the new package is uploaded to the
+       respective conda channel, and the program continues with the next package
 
-  Dependencies are searched with priority to locally built packages.  For this
-  reason, the input file **must** be provided in the right dependence order.
-  """
+    Dependencies are searched with priority to locally built packages.  For this
+    reason, the input file **must** be provided in the right dependence order.
+    """
 
     # loads dirnames from order file (accepts # comments and empty lines)
     packages = read_packages(order)
@@ -816,21 +817,20 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def docs(ctx, requirement, dry_run):
-    """Prepares documentation build
+    """Prepares documentation build.
 
-  This command:
-    \b
+    This command:
+      \b
 
-    1. Clones all the necessary packages necessary to build the bob/beat
-       documentation
-    \b
+      1. Clones all the necessary packages necessary to build the bob/beat
+         documentation
+      \b
 
-    2. Generates the `extra-intersphinx.txt` and `nitpick-exceptions.txt` file
-    \b
+      2. Generates the `extra-intersphinx.txt` and `nitpick-exceptions.txt` file
+      \b
 
-  This command is supposed to be run **instead** of `bdt ci build...`
-
-  """
+    This command is supposed to be run **instead** of `bdt ci build...`
+    """
 
     packages = read_packages(requirement)
 
diff --git a/bob/devtools/scripts/commitfile.py b/bob/devtools/scripts/commitfile.py
index dfd542fdeae338d6259ac4d5e0cef3127cfdd524..678bd7ea843374db736f9bd94a10d9a16bec958a 100644
--- a/bob/devtools/scripts/commitfile.py
+++ b/bob/devtools/scripts/commitfile.py
@@ -74,8 +74,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def commitfile(package, message, file, path, branch, auto_merge, dry_run):
-    """Changes a file on a given package, directly on master or through MR
-    """
+    """Changes a file on a given package, directly on master or through MR."""
 
     if "/" not in package:
         raise RuntimeError('PACKAGE should be specified as "group/name"')
diff --git a/bob/devtools/scripts/create.py b/bob/devtools/scripts/create.py
index dcd6c2333ca890430f623dead8a3dac375127b6c..835064d01ac5fd083dccb5cd113aa7c08dc0c05e 100644
--- a/bob/devtools/scripts/create.py
+++ b/bob/devtools/scripts/create.py
@@ -163,22 +163,22 @@ def create(
     stable,
     dry_run,
 ):
-    """Creates a development environment for a recipe
-
-  It uses the conda render API to render a recipe and install an environment
-  containing all build/host, run and test dependencies of a package. It does
-  **not** build the package itself, just install dependencies so you can build
-  the package by hand, possibly using buildout or similar. If you'd like to
-  conda-build your package, just use `conda build` instead.
-
-  Once the environment is created, a copy of the used `condarc' file is placed
-  on the root of the environment. Installing or updating packages on the newly
-  created environment should be possible without further configuration. Notice
-  that beta packages quickly get outdated and upgrading may no longer be
-  possible for aging development environments. You're advised to always re-use
-  this app and use the flag `--overwrite` to re-create from scratch the
-  development environment.
-  """
+    """Creates a development environment for a recipe.
+
+    It uses the conda render API to render a recipe and install an environment
+    containing all build/host, run and test dependencies of a package. It does
+    **not** build the package itself, just install dependencies so you can build
+    the package by hand, possibly using buildout or similar. If you'd like to
+    conda-build your package, just use `conda build` instead.
+
+    Once the environment is created, a copy of the used `condarc' file is placed
+    on the root of the environment. Installing or updating packages on the newly
+    created environment should be possible without further configuration. Notice
+    that beta packages quickly get outdated and upgrading may no longer be
+    possible for aging development environments. You're advised to always re-use
+    this app and use the flag `--overwrite` to re-create from scratch the
+    development environment.
+    """
 
     recipe_dir = recipe_dir or os.path.join(os.path.realpath("."), "conda")
 
diff --git a/bob/devtools/scripts/dumpsphinx.py b/bob/devtools/scripts/dumpsphinx.py
index 8668dd6e7ed28d998e9d7dcf8264ee12fce5676e..1882802fe7ffe24fed3e91fe4a5581e2f84b0c88 100644
--- a/bob/devtools/scripts/dumpsphinx.py
+++ b/bob/devtools/scripts/dumpsphinx.py
@@ -36,9 +36,9 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def dumpsphinx(url):
-    """Dumps all the objects given an sphinx catalog/inventory URL
+    """Dumps all the objects given an sphinx catalog/inventory URL.
 
-  This command is useful when you are struggling to do proper links from your
-  documentation.
-  """
+    This command is useful when you are struggling to do proper links
+    from your documentation.
+    """
     intersphinx.inspect_main([url])
diff --git a/bob/devtools/scripts/getpath.py b/bob/devtools/scripts/getpath.py
index 3f3b71aeb66d0c61a2ae3f43ff5c21ee9bbb21ae..04cba7715af3049bebe0451dacd2d00c5a79f821 100644
--- a/bob/devtools/scripts/getpath.py
+++ b/bob/devtools/scripts/getpath.py
@@ -44,7 +44,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def getpath(package, path, output, ref):
-    """Downloads files and directories from gitlab
+    """Downloads files and directories from gitlab.
 
     Files are downloaded and stored.  Directories are recursed and fully
     downloaded to the client.
diff --git a/bob/devtools/scripts/gitlab.py b/bob/devtools/scripts/gitlab.py
index 2374eac8dbf6b178ec6248c44624ad1e2f9cba76..90afda5183a82fd33a0c10c8866e8c12ebaeed05 100644
--- a/bob/devtools/scripts/gitlab.py
+++ b/bob/devtools/scripts/gitlab.py
@@ -13,9 +13,9 @@ from . import bdt
 @with_plugins(pkg_resources.iter_entry_points("bdt.gitlab.cli"))
 @click.group(cls=bdt.AliasedGroup)
 def gitlab():
-    """Commands for that interact with gitlab
+    """Commands for that interact with gitlab.
 
-  Commands defined here are supposed to interact with gitlab, and
-  add/modify/remove resources on it directly.
-  """
+    Commands defined here are supposed to interact with gitlab, and
+    add/modify/remove resources on it directly.
+    """
     pass
diff --git a/bob/devtools/scripts/jobs.py b/bob/devtools/scripts/jobs.py
index 6f59274276bcde967688301f8d52eba8efa621c6..05352f30a70e5dc7740c1fdfa198e5c54819d085 100644
--- a/bob/devtools/scripts/jobs.py
+++ b/bob/devtools/scripts/jobs.py
@@ -40,8 +40,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def jobs(name, status):
-    """Lists jobs on a given runner identified by description
-    """
+    """Lists jobs on a given runner identified by description."""
 
     gl = get_gitlab_instance()
     gl.auth()
diff --git a/bob/devtools/scripts/lasttag.py b/bob/devtools/scripts/lasttag.py
index 9f4ba4ba26d676126dc3f041171b9f0731355117..356f3ee766606b73727ce137ab49cc1d4fc9de84 100644
--- a/bob/devtools/scripts/lasttag.py
+++ b/bob/devtools/scripts/lasttag.py
@@ -33,8 +33,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def lasttag(package):
-    """Returns the last tag information on a given PACKAGE
-    """
+    """Returns the last tag information on a given PACKAGE."""
 
     if "/" not in package:
         raise RuntimeError('PACKAGE should be specified as "group/name"')
diff --git a/bob/devtools/scripts/local.py b/bob/devtools/scripts/local.py
index ea3c7ace20cbf9d01ca4c3a57ff51237b1caab77..d7bacd6a9598e0bcf080832852dcaff69a1469ce 100644
--- a/bob/devtools/scripts/local.py
+++ b/bob/devtools/scripts/local.py
@@ -20,10 +20,8 @@ logger = get_logger(__name__)
 def set_up_environment_variables(
     python, name_space, project_dir=".", project_visibility="public"
 ):
-    """
-  This function sets up the proper environment variables when user wants to run the commands usually run on ci
-  locally
-  """
+    """This function sets up the proper environment variables when user wants
+    to run the commands usually run on ci locally."""
     os.environ["CI_JOB_TOKEN"] = gitlab.Gitlab.from_config(
         "idiap"
     ).private_token
@@ -38,10 +36,10 @@ def set_up_environment_variables(
 @click.group(cls=bdt.AliasedGroup)
 def local():
     """Commands for building packages and handling certain activities locally
-  it requires a proper set up for ~/.python-gitlab.cfg
+    it requires a proper set up for ~/.python-gitlab.cfg.
 
-  Commands defined here can be run in your own installation.
-  """
+    Commands defined here can be run in your own installation.
+    """
     pass
 
 
@@ -87,21 +85,20 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def docs(ctx, requirement, dry_run, python, group):
-    """Prepares documentation build
-
-  This command:
-    \b
+    """Prepares documentation build.
 
-    1. Clones all the necessary packages necessary to build the bob/beat
-       documentation
+    This command:
+      \b
 
-    \b
+      1. Clones all the necessary packages necessary to build the bob/beat
+         documentation
 
-    2. Generates the `extra-intersphinx.txt` and `nitpick-exceptions.txt` file
+      \b
 
-    \b
+      2. Generates the `extra-intersphinx.txt` and `nitpick-exceptions.txt` file
 
-  """
+      \b
+    """
     set_up_environment_variables(python=python, name_space=group)
 
     ctx.invoke(ci.docs, requirement=requirement, dry_run=dry_run)
@@ -149,8 +146,7 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def build(ctx, dry_run, recipe_dir, python, group):
-    """Run the CI build step locally
-    """
+    """Run the CI build step locally."""
     set_up_environment_variables(python=python, name_space=group)
 
     ctx.invoke(ci.build, dry_run=dry_run, recipe_dir=recipe_dir)
@@ -198,8 +194,7 @@ Examples:
 @bdt.raise_on_error
 @click.pass_context
 def base_build(ctx, order, dry_run, python, group):
-    """Run the CI build step locally
-    """
+    """Run the CI build step locally."""
     set_up_environment_variables(python=python, name_space=group)
 
     ctx.invoke(
diff --git a/bob/devtools/scripts/new.py b/bob/devtools/scripts/new.py
index 7e79f6643fd2620ef1bd0d852a465a1191406741..2fca5cb0279ffd6e865fd8160516ba34a0150ced 100644
--- a/bob/devtools/scripts/new.py
+++ b/bob/devtools/scripts/new.py
@@ -16,13 +16,13 @@ logger = get_logger(__name__)
 
 
 def copy_file(template, output_dir):
-    """Copies a file from the template directory to the output directory
+    """Copies a file from the template directory to the output directory.
 
-  Args:
+    Args:
 
-    template: The path to the template, from the internal templates directory
-    output_dir: Where to save the output
-  """
+      template: The path to the template, from the internal templates directory
+      output_dir: Where to save the output
+    """
 
     template_file = pkg_resources.resource_filename(
         __name__, os.path.join("..", "templates", template)
@@ -39,15 +39,15 @@ def copy_file(template, output_dir):
 
 
 def render_template(jenv, template, context, output_dir):
-    """Renders a template to the output directory using specific context
+    """Renders a template to the output directory using specific context.
 
-  Args:
+    Args:
 
-    jenv: The Jinja2 environment to use for rendering the template
-    template: The path to the template, from the internal templates directory
-    context: A dictionary with the context to render the template with
-    output_dir: Where to save the output
-  """
+      jenv: The Jinja2 environment to use for rendering the template
+      template: The path to the template, from the internal templates directory
+      context: A dictionary with the context to render the template with
+      output_dir: Where to save the output
+    """
 
     output_file = os.path.join(output_dir, template)
 
@@ -100,8 +100,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def new(package, author, email, title, license, output_dir):
-    """Creates a folder structure for a new Bob/BEAT package
-    """
+    """Creates a folder structure for a new Bob/BEAT package."""
 
     if "/" not in package:
         raise RuntimeError('PACKAGE should be specified as "group/name"')
diff --git a/bob/devtools/scripts/rebuild.py b/bob/devtools/scripts/rebuild.py
index 71393b0cf3368e1e3a94eb188c3a6f14d49c317a..17c019edf59a485c74d5eefe64ad9edcb39deecb 100644
--- a/bob/devtools/scripts/rebuild.py
+++ b/bob/devtools/scripts/rebuild.py
@@ -145,14 +145,16 @@ def rebuild(
     dry_run,
     ci,
 ):
-    """Tests and rebuilds packages through conda-build with stock configuration
-
-  This command wraps the execution of conda-build in two stages: first, from
-  the original package recipe and some channel look-ups, it figures out what is
-  the lastest version of the package available.  It downloads such file and
-  runs a test.  If the test suceeds, then it proceeds to the next recipe.
-  Otherwise, it rebuilds the package and uploads a new version to the channel.
-  """
+    """Tests and rebuilds packages through conda-build with stock
+    configuration.
+
+    This command wraps the execution of conda-build in two stages:
+    first, from the original package recipe and some channel look-ups,
+    it figures out what is the lastest version of the package available.
+    It downloads such file and runs a test.  If the test suceeds, then
+    it proceeds to the next recipe. Otherwise, it rebuilds the package
+    and uploads a new version to the channel.
+    """
 
     # if we are in a dry-run mode, let's let it be known
     if dry_run:
diff --git a/bob/devtools/scripts/release.py b/bob/devtools/scripts/release.py
index e55581010836567c7f2e0130b7def152b8a74909..f666bc57f636ef07dc7d35eeb90fb95d44cbc8bc 100644
--- a/bob/devtools/scripts/release.py
+++ b/bob/devtools/scripts/release.py
@@ -80,7 +80,7 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def release(changelog, group, package, resume, dry_run):
-    """Tags packages on gitlab from an input CHANGELOG in markdown formatting
+    """Tags packages on gitlab from an input CHANGELOG in markdown formatting.
 
     By using a CHANGELOG file as an input (that can be generated with the ``bdt
     changelog`` command), this script goes through all packages in CHANGELOG
diff --git a/bob/devtools/scripts/runners.py b/bob/devtools/scripts/runners.py
index dc185d5459e4d38e840aaef3ea8fa421eafc02ff..3ca015ba65bcba156f51abca8a3cf2fc8c1e7cca 100644
--- a/bob/devtools/scripts/runners.py
+++ b/bob/devtools/scripts/runners.py
@@ -46,8 +46,8 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def runners(target, cmd, name, dry_run):
-    """Enables and disables runners on whole gitlab groups or single projects
-    """
+    """Enables and disables runners on whole gitlab groups or single
+    projects."""
 
     gl = get_gitlab_instance()
     gl.auth()
diff --git a/bob/devtools/scripts/test.py b/bob/devtools/scripts/test.py
index 9d08349dae58f9be1e375c3e5056ed079058f750..3265020173e7c0d5e3da5146a88a8db2e163bfbc 100644
--- a/bob/devtools/scripts/test.py
+++ b/bob/devtools/scripts/test.py
@@ -133,12 +133,12 @@ def test(
     dry_run,
     ci,
 ):
-    """Tests (pre-built) package through conda-build with stock configuration
+    """Tests (pre-built) package through conda-build with stock configuration.
 
-  This command wraps the execution of conda-build so that you use the same
-  conda configuration we use for our CI.  It always set
-  ``--no-anaconda-upload``.
-  """
+    This command wraps the execution of conda-build so that you use the
+    same conda configuration we use for our CI.  It always set ``--no-
+    anaconda-upload``.
+    """
 
     # if we are in a dry-run mode, let's let it be known
     if dry_run:
diff --git a/bob/devtools/scripts/visibility.py b/bob/devtools/scripts/visibility.py
index 582749f21381b8947352e487ea0636e8be438d18..1ff96dbd4b52230efd2d27f1c0b85ba4139406fe 100644
--- a/bob/devtools/scripts/visibility.py
+++ b/bob/devtools/scripts/visibility.py
@@ -43,12 +43,12 @@ Examples:
 @verbosity_option()
 @bdt.raise_on_error
 def visibility(target, group):
-    """Reports visibility of gitlab repository
+    """Reports visibility of gitlab repository.
 
-    This command checks if the named package is visible to the currently logged
-    in user, and reports its visibility level ('public', 'internal',
-    'private').  If the package does not exist or it is private to the current
-    user, it says 'unknown' instead.
+    This command checks if the named package is visible to the currently
+    logged in user, and reports its visibility level ('public',
+    'internal', 'private').  If the package does not exist or it is
+    private to the current user, it says 'unknown' instead.
     """
 
     gl = get_gitlab_instance()
diff --git a/bob/devtools/webdav3/client.py b/bob/devtools/webdav3/client.py
index 7f56dcc600947180d59d35f1790d1982289ed73a..f42d0274e203205b218d25b8d585e8cc44cb924b 100644
--- a/bob/devtools/webdav3/client.py
+++ b/bob/devtools/webdav3/client.py
@@ -29,7 +29,8 @@ __version__ = "0.2"
 
 
 def listdir(directory):
-    """Returns list of nested files and directories for local directory by path
+    """Returns list of nested files and directories for local directory by
+    path.
 
     :param directory: absolute or relative path to local directory
     :return: list nested of file or directory names
@@ -46,7 +47,7 @@ def listdir(directory):
 
 
 def get_options(option_type, from_options):
-    """Extract options for specified option type from all options
+    """Extract options for specified option type from all options.
 
     :param option_type: the object of specified type of options
     :param from_options: all options dictionary
@@ -86,8 +87,8 @@ def wrap_connection_error(fn):
 
 
 class Client(object):
-    """The client for WebDAV servers provides an ability to control files on remote WebDAV server.
-    """
+    """The client for WebDAV servers provides an ability to control files on
+    remote WebDAV server."""
 
     # path to root directory of WebDAV
     root = "/"
@@ -168,7 +169,8 @@ class Client(object):
         return "{root}{path}".format(root=self.webdav.root, path=urn.path())
 
     def execute_request(self, action, path, data=None, headers_ext=None):
-        """Generate request to WebDAV server for specified action and path and execute it.
+        """Generate request to WebDAV server for specified action and path and
+        execute it.
 
         :param action: the action for WebDAV server which should be executed.
         :param path: the path to resource for action
@@ -218,7 +220,7 @@ class Client(object):
     meta_xmlns = {"https://webdav.yandex.ru": "urn:yandex:disk:meta"}
 
     def __init__(self, options):
-        """Constructor of WebDAV client
+        """Constructor of WebDAV client.
 
         :param options: the dictionary of connection options to WebDAV can include proxy server options.
             WebDev settings:
@@ -261,8 +263,9 @@ class Client(object):
 
     @wrap_connection_error
     def list(self, remote_path=root):
-        """Returns list of nested files and directories for remote WebDAV directory by path.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+        """Returns list of nested files and directories for remote WebDAV
+        directory by path. More information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND.
 
         :param remote_path: path to remote directory.
         :return: list of nested file or directory names.
@@ -286,8 +289,9 @@ class Client(object):
 
     @wrap_connection_error
     def free(self):
-        """Returns an amount of free space on remote WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+        """Returns an amount of free space on remote WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND.
 
         :return: an amount of free space in bytes.
         """
@@ -299,8 +303,9 @@ class Client(object):
 
     @wrap_connection_error
     def check(self, remote_path=root):
-        """Checks an existence of remote resource on WebDAV server by remote path.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4
+        """Checks an existence of remote resource on WebDAV server by remote
+        path. More information you can find by link
+        http://webdav.org/specs/rfc4918.html#rfc.section.9.4.
 
         :param remote_path: (optional) path to resource on WebDAV server. Defaults is root directory of WebDAV.
         :return: True if resource is exist or False otherwise
@@ -317,12 +322,11 @@ class Client(object):
 
     @wrap_connection_error
     def mkdir(self, remote_path):
-        """Makes new directory on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MKCOL
+        """Makes new directory on WebDAV server. More information you can find
+        by link http://webdav.org/specs/rfc4918.html#METHOD_MKCOL.
 
         :param remote_path: path to directory
         :return: True if request executed with code 200 or 201 and False otherwise.
-
         """
         directory_urn = Urn(remote_path, directory=True)
         if not self.check(directory_urn.parent()):
@@ -352,7 +356,8 @@ class Client(object):
 
     def download(self, remote_path, local_path, progress=None):
         """Downloads remote resource from WebDAV and save it in local path.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4
+        More information you can find by link
+        http://webdav.org/specs/rfc4918.html#rfc.section.9.4.
 
         :param remote_path: the path to remote resource for downloading can be file and directory.
         :param local_path: the path to save resource locally.
@@ -373,8 +378,9 @@ class Client(object):
             )
 
     def download_directory(self, remote_path, local_path, progress=None):
-        """Downloads directory and downloads all nested files and directories from remote WebDAV to local.
-        If there is something on local path it deletes directories and files then creates new.
+        """Downloads directory and downloads all nested files and directories
+        from remote WebDAV to local. If there is something on local path it
+        deletes directories and files then creates new.
 
         :param remote_path: the path to directory for downloading form WebDAV server.
         :param local_path: the path to local directory for saving downloaded files and directories.
@@ -402,8 +408,9 @@ class Client(object):
 
     @wrap_connection_error
     def download_file(self, remote_path, local_path, progress=None):
-        """Downloads file from WebDAV server and save it locally.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#rfc.section.9.4
+        """Downloads file from WebDAV server and save it locally. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#rfc.section.9.4.
 
         :param remote_path: the path to remote file for downloading.
         :param local_path: the path to save file locally.
@@ -436,7 +443,7 @@ class Client(object):
             callback()
 
     def download_async(self, remote_path, local_path, callback=None):
-        """Downloads remote resources from WebDAV server asynchronously
+        """Downloads remote resources from WebDAV server asynchronously.
 
         :param remote_path: the path to remote resource on WebDAV server. Can be file and directory.
         :param local_path: the path to save resource locally.
@@ -449,8 +456,9 @@ class Client(object):
 
     @wrap_connection_error
     def upload_to(self, buff, remote_path):
-        """Uploads file from buffer to remote path on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT
+        """Uploads file from buffer to remote path on WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PUT.
 
         :param buff: the buffer with content for file.
         :param remote_path: the path to save file remotely on WebDAV server.
@@ -465,9 +473,10 @@ class Client(object):
         self.execute_request(action="upload", path=urn.quote(), data=buff)
 
     def upload(self, remote_path, local_path, progress=None):
-        """Uploads resource to remote path on WebDAV server.
-        In case resource is directory it will upload all nested files and directories.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT
+        """Uploads resource to remote path on WebDAV server. In case resource
+        is directory it will upload all nested files and directories. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PUT.
 
         :param remote_path: the path for uploading resources on WebDAV server. Can be file and directory.
         :param local_path: the path to local resource for uploading.
@@ -483,9 +492,9 @@ class Client(object):
             self.upload_file(local_path=local_path, remote_path=remote_path)
 
     def upload_directory(self, remote_path, local_path, progress=None):
-        """Uploads directory to remote path on WebDAV server.
-        In case directory is exist on remote server it will delete it and then upload directory with nested files and
-        directories.
+        """Uploads directory to remote path on WebDAV server. In case directory
+        is exist on remote server it will delete it and then upload directory
+        with nested files and directories.
 
         :param remote_path: the path to directory for uploading on WebDAV server.
         :param local_path: the path to local directory for uploading.
@@ -519,8 +528,9 @@ class Client(object):
 
     @wrap_connection_error
     def upload_file(self, remote_path, local_path, progress=None):
-        """Uploads file to remote path on WebDAV server. File should be 2Gb or less.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PUT
+        """Uploads file to remote path on WebDAV server. File should be 2Gb or
+        less. More information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PUT.
 
         :param remote_path: the path to uploading file on WebDAV server.
         :param local_path: the path to local file for uploading.
@@ -551,8 +561,9 @@ class Client(object):
             )
 
     def upload_sync(self, remote_path, local_path, callback=None):
-        """Uploads resource to remote path on WebDAV server synchronously.
-        In case resource is directory it will upload all nested files and directories.
+        """Uploads resource to remote path on WebDAV server synchronously. In
+        case resource is directory it will upload all nested files and
+        directories.
 
         :param remote_path: the path for uploading resources on WebDAV server. Can be file and directory.
         :param local_path: the path to local resource for uploading.
@@ -564,8 +575,9 @@ class Client(object):
             callback()
 
     def upload_async(self, remote_path, local_path, callback=None):
-        """Uploads resource to remote path on WebDAV server asynchronously.
-        In case resource is directory it will upload all nested files and directories.
+        """Uploads resource to remote path on WebDAV server asynchronously. In
+        case resource is directory it will upload all nested files and
+        directories.
 
         :param remote_path: the path for uploading resources on WebDAV server. Can be file and directory.
         :param local_path: the path to local resource for uploading.
@@ -578,8 +590,9 @@ class Client(object):
 
     @wrap_connection_error
     def copy(self, remote_path_from, remote_path_to):
-        """Copies resource from one place to another on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_COPY
+        """Copies resource from one place to another on WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_COPY.
 
         :param remote_path_from: the path to resource which will be copied,
         :param remote_path_to: the path where resource will be copied.
@@ -603,8 +616,9 @@ class Client(object):
 
     @wrap_connection_error
     def move(self, remote_path_from, remote_path_to, overwrite=False):
-        """Moves resource from one place to another on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_MOVE
+        """Moves resource from one place to another on WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_MOVE.
 
         :param remote_path_from: the path to resource which will be moved,
         :param remote_path_to: the path where resource will be moved.
@@ -632,9 +646,10 @@ class Client(object):
 
     @wrap_connection_error
     def clean(self, remote_path):
-        """Cleans (Deletes) a remote resource on WebDAV server. The name of method is not changed for back compatibility
-        with original library.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_DELETE
+        """Cleans (Deletes) a remote resource on WebDAV server. The name of
+        method is not changed for back compatibility with original library.
+        More information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_DELETE.
 
         :param remote_path: the remote resource whisch will be deleted.
         """
@@ -643,8 +658,8 @@ class Client(object):
 
     @wrap_connection_error
     def info(self, remote_path):
-        """Gets information about resource on WebDAV.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+        """Gets information about resource on WebDAV. More information you can
+        find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND.
 
         :param remote_path: the path to remote resource.
         :return: a dictionary of information attributes and them values with following keys:
@@ -667,8 +682,8 @@ class Client(object):
 
     @wrap_connection_error
     def is_dir(self, remote_path):
-        """Checks is the remote resource directory.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+        """Checks is the remote resource directory. More information you can
+        find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND.
 
         :param remote_path: the path to remote resource.
         :return: True in case the remote resource is directory and False otherwise.
@@ -688,8 +703,9 @@ class Client(object):
 
     @wrap_connection_error
     def get_property(self, remote_path, option):
-        """Gets metadata property of remote resource on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND
+        """Gets metadata property of remote resource on WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PROPFIND.
 
         :param remote_path: the path to remote resource.
         :param option: the property attribute as dictionary with following keys:
@@ -711,8 +727,9 @@ class Client(object):
 
     @wrap_connection_error
     def set_property(self, remote_path, option):
-        """Sets metadata property of remote resource on WebDAV server.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH
+        """Sets metadata property of remote resource on WebDAV server. More
+        information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH.
 
         :param remote_path: the path to remote resource.
         :param option: the property attribute as dictionary with following keys:
@@ -724,8 +741,9 @@ class Client(object):
 
     @wrap_connection_error
     def set_property_batch(self, remote_path, option):
-        """Sets batch metadata properties of remote resource on WebDAV server in batch.
-        More information you can find by link http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH
+        """Sets batch metadata properties of remote resource on WebDAV server
+        in batch. More information you can find by link
+        http://webdav.org/specs/rfc4918.html#METHOD_PROPPATCH.
 
         :param remote_path: the path to remote resource.
         :param option: the property attributes as list of dictionaries with following keys:
@@ -934,7 +952,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def parse_get_list_response(content):
-        """Parses of response content XML from WebDAV server and extract file and directory names.
+        """Parses of response content XML from WebDAV server and extract file
+        and directory names.
 
         :param content: the XML content of HTTP response from WebDAV server for getting list of files by remote path.
         :return: list of extracted file or directory names.
@@ -964,7 +983,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def parse_free_space_response(content, hostname):
-        """Parses of response content XML from WebDAV server and extract an amount of free space.
+        """Parses of response content XML from WebDAV server and extract an
+        amount of free space.
 
         :param content: the XML content of HTTP response from WebDAV server for getting free space.
         :param hostname: the server hostname.
@@ -984,7 +1004,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def parse_info_response(content, path, hostname):
-        """Parses of response content XML from WebDAV server and extract an information about resource.
+        """Parses of response content XML from WebDAV server and extract an
+        information about resource.
 
         :param content: the XML content of HTTP response from WebDAV server.
         :param path: the path to resource.
@@ -1011,7 +1032,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def parse_is_dir_response(content, path, hostname):
-        """Parses of response content XML from WebDAV server and extract an information about resource.
+        """Parses of response content XML from WebDAV server and extract an
+        information about resource.
 
         :param content: the XML content of HTTP response from WebDAV server.
         :param path: the path to resource.
@@ -1030,7 +1052,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def create_get_property_request_content(option):
-        """Creates an XML for requesting of getting a property value of remote WebDAV resource.
+        """Creates an XML for requesting of getting a property value of remote
+        WebDAV resource.
 
         :param option: the property attributes as dictionary with following keys:
                        `namespace`: (optional) the namespace for XML property which will be get,
@@ -1047,7 +1070,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def parse_get_property_response(content, name):
-        """Parses of response content XML from WebDAV server for getting metadata property value for some resource.
+        """Parses of response content XML from WebDAV server for getting
+        metadata property value for some resource.
 
         :param content: the XML content of response as string.
         :param name: the name of property for finding a value in response
@@ -1058,7 +1082,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def create_set_property_batch_request_content(options):
-        """Creates an XML for requesting of setting a property values for remote WebDAV resource in batch.
+        """Creates an XML for requesting of setting a property values for
+        remote WebDAV resource in batch.
 
         :param options: the property attributes as list of dictionaries with following keys:
                        `namespace`: (optional) the namespace for XML property which will be set,
@@ -1079,7 +1104,8 @@ class WebDavXmlUtils:
 
     @staticmethod
     def etree_to_string(tree):
-        """Creates string from lxml.etree.ElementTree with XML declaration and UTF-8 encoding.
+        """Creates string from lxml.etree.ElementTree with XML declaration and
+        UTF-8 encoding.
 
         :param tree: the instance of ElementTree
         :return: the string of XML.