From 92a6df62a795decc309ee64a8721e2d41c86a774 Mon Sep 17 00:00:00 2001
From: Pavel Korshunov <pavel.korshunov@idiap.ch>
Date: Thu, 11 May 2017 18:04:49 +0200
Subject: [PATCH] re-formatted the code

---
 bob/bio/base/tools/command_line.py | 827 +++++++++++++++--------------
 1 file changed, 421 insertions(+), 406 deletions(-)

diff --git a/bob/bio/base/tools/command_line.py b/bob/bio/base/tools/command_line.py
index 00693033..22904d34 100644
--- a/bob/bio/base/tools/command_line.py
+++ b/bob/bio/base/tools/command_line.py
@@ -3,12 +3,12 @@
 
 import argparse
 import os
-import sys
 import socket
+import sys
 
+import bob.core
 import bob.extension
 
-import bob.core
 logger = bob.core.log.setup("bob.bio.base")
 
 from .. import utils
@@ -16,7 +16,7 @@ from . import FileSelector
 
 
 def is_idiap():
-  return os.path.isdir("/idiap") and "USER" in os.environ
+    return os.path.isdir("/idiap") and "USER" in os.environ
 
 
 def command_line_config_group(parser, package_prefix='bob.bio.', exclude_resources_from=[]):
@@ -74,143 +74,142 @@ def command_line_config_group(parser, package_prefix='bob.bio.', exclude_resourc
 
 
 def command_line_parser(description=__doc__, exclude_resources_from=[]):
-  """command_line_parser(description=__doc__, exclude_resources_from=[]) -> parsers
-
-  Creates an :py:class:`argparse.ArgumentParser` object that includes the minimum set of command
-  line options (which is not so few).
-  The ``description`` can be overwritten, but has a (small) default.
-
-  Included in the parser, several groups are defined.
-  Each group specifies a set of command line options.
-  For the configurations, registered resources are listed, which can be limited by the
-  ``exclude_resources_from`` list of extensions.
-
-  It returns a dictionary, containing the parser object itself (in the ``'main'`` keyword),
-  and a list of command line groups.
-
-  **Parameters:**
-
-  description : str
-    The documentation of the script.
-
-  exclude_resources_from : [str]
-    A list of extension packages, for which resources should not be listed.
-
-  **Returns:**
-
-  parsers : dict
-    A dictionary of parser groups, with the main parser under the 'main' key.
-    Feel free to add more options to any of the parser groups.
-  """
-  parser = argparse.ArgumentParser(description=description, formatter_class=argparse.ArgumentDefaultsHelpFormatter,
-                                   conflict_handler='resolve')
-
-  #######################################################################################
-  ############## options that are required to be specified #######################
-  config_group = command_line_config_group(parser, package_prefix='bob.bio.',
-                                           exclude_resources_from=exclude_resources_from)
-
-  #######################################################################################
-  ############## options to modify default directories or file names ####################
-
-  # directories differ between idiap and extern
-  temp = "/idiap/temp/%s/[database-name]/[sub-directory]" % os.environ["USER"] if is_idiap() else "temp"
-  results = "/idiap/user/%s/[database-name]/[sub-directory]" % os.environ["USER"] if is_idiap() else "results"
-  database_replacement = "%s/.bob_bio_databases.txt" % os.environ["HOME"]
-
-  dir_group = parser.add_argument_group('\nDirectories that can be changed according to your requirements')
-  dir_group.add_argument('-T', '--temp-directory', metavar = 'DIR',
-      help = 'The directory for temporary files; if --temp-directory is not specified, "%s" is used' % temp)
-  dir_group.add_argument('-R', '--result-directory', metavar = 'DIR',
-      help = 'The directory for resulting score files; if --result-directory is not specified, "%s" is used' % results)
-
-  file_group = parser.add_argument_group('\nName (maybe including a path relative to the --temp-directory, '
-                                         'if not specified otherwise) of files that will be generated. '
-                                         'Note that not all files will be used by all algorithms')
-  file_group.add_argument('--extractor-file', metavar = 'FILE', default = 'Extractor.hdf5',
-      help = 'Name of the file to write the feature extractor into.')
-  file_group.add_argument('--projector-file', metavar = 'FILE', default = 'Projector.hdf5',
-      help = 'Name of the file to write the feature projector into.')
-  file_group.add_argument('--enroller-file' , metavar = 'FILE', default = 'Enroller.hdf5',
-      help = 'Name of the file to write the model enroller into.')
-  file_group.add_argument('-G', '--gridtk-database-file', metavar = 'FILE', default = 'submitted.sql3',
-      help = 'The database file in which the submitted jobs will be written; relative to the current directory '
-             '(only valid with the --grid option).')
-  file_group.add_argument('--experiment-info-file', metavar = 'FILE', default = 'Experiment.info',
-      help = 'The file where the configuration of all parts of the experiments are written; '
-             'relative to te --result-directory.')
-  file_group.add_argument('-D', '--database-directories-file', metavar = 'FILE', default = database_replacement,
-      help = 'An optional file, where database directories are stored (to avoid changing the database configurations)')
-
-
-  sub_dir_group = parser.add_argument_group('\nSubdirectories of certain parts of the tool chain. '
-                                            'You can specify directories in case you want to reuse parts of '
-                                            'the experiments (e.g. extracted features) in other experiments. '
-                                            'Please note that these directories are relative to the --temp-directory, '
-                                            'but you can also specify absolute paths')
-  sub_dir_group.add_argument('--preprocessed-directory', metavar = 'DIR', default = 'preprocessed',
-      help = 'Name of the directory of the preprocessed data.')
-  sub_dir_group.add_argument('--extracted-directory', metavar = 'DIR', default = 'extracted',
-      help = 'Name of the directory of the extracted features.')
-  sub_dir_group.add_argument('--projected-directory', metavar = 'DIR', default = 'projected',
-      help = 'Name of the directory where the projected data should be stored.')
-  sub_dir_group.add_argument('--model-directories', metavar = 'DIR', nargs = '+', default = ['models', 'tmodels'],
-      help = 'Name of the directory where the models (and T-Norm models) should be stored')
-  sub_dir_group.add_argument('--score-directories', metavar = 'DIR', nargs = '+', default = ['nonorm', 'ztnorm'],
-      help = 'Name of the directory (relative to --result-directory) where to write the results to')
-  sub_dir_group.add_argument('--zt-directories', metavar = 'DIR', nargs = 5,
-                             default = ['zt_norm_A', 'zt_norm_B', 'zt_norm_C', 'zt_norm_D', 'zt_norm_D_sameValue'],
-                             help = 'Name of the directories (of --temp-directory) where to write the ZT-norm values; '
+    """command_line_parser(description=__doc__, exclude_resources_from=[]) -> parsers
+
+    Creates an :py:class:`argparse.ArgumentParser` object that includes the minimum set of command
+    line options (which is not so few).
+    The ``description`` can be overwritten, but has a (small) default.
+
+    Included in the parser, several groups are defined.
+    Each group specifies a set of command line options.
+    For the configurations, registered resources are listed, which can be limited by the
+    ``exclude_resources_from`` list of extensions.
+
+    It returns a dictionary, containing the parser object itself (in the ``'main'`` keyword),
+    and a list of command line groups.
+
+    **Parameters:**
+
+    description : str
+      The documentation of the script.
+
+    exclude_resources_from : [str]
+      A list of extension packages, for which resources should not be listed.
+
+    **Returns:**
+
+    parsers : dict
+      A dictionary of parser groups, with the main parser under the 'main' key.
+      Feel free to add more options to any of the parser groups.
+    """
+    parser = argparse.ArgumentParser(description=description, formatter_class=argparse.ArgumentDefaultsHelpFormatter,
+                                     conflict_handler='resolve')
+
+    #######################################################################################
+    ############## options that are required to be specified #######################
+    config_group = command_line_config_group(parser, package_prefix='bob.bio.',
+                                             exclude_resources_from=exclude_resources_from)
+
+    #######################################################################################
+    ############## options to modify default directories or file names ####################
+
+    # directories differ between idiap and extern
+    temp = "/idiap/temp/%s/[database-name]/[sub-directory]" % os.environ["USER"] if is_idiap() else "temp"
+    results = "/idiap/user/%s/[database-name]/[sub-directory]" % os.environ["USER"] if is_idiap() else "results"
+    database_replacement = "%s/.bob_bio_databases.txt" % os.environ["HOME"]
+
+    dir_group = parser.add_argument_group('\nDirectories that can be changed according to your requirements')
+    dir_group.add_argument('-T', '--temp-directory', metavar='DIR',
+                           help='The directory for temporary files; if --temp-directory is not specified, "%s" is used' % temp)
+    dir_group.add_argument('-R', '--result-directory', metavar='DIR',
+                           help='The directory for resulting score files; if --result-directory is not specified, "%s" is used' % results)
+
+    file_group = parser.add_argument_group('\nName (maybe including a path relative to the --temp-directory, '
+                                           'if not specified otherwise) of files that will be generated. '
+                                           'Note that not all files will be used by all algorithms')
+    file_group.add_argument('--extractor-file', metavar='FILE', default='Extractor.hdf5',
+                            help='Name of the file to write the feature extractor into.')
+    file_group.add_argument('--projector-file', metavar='FILE', default='Projector.hdf5',
+                            help='Name of the file to write the feature projector into.')
+    file_group.add_argument('--enroller-file', metavar='FILE', default='Enroller.hdf5',
+                            help='Name of the file to write the model enroller into.')
+    file_group.add_argument('-G', '--gridtk-database-file', metavar='FILE', default='submitted.sql3',
+                            help='The database file in which the submitted jobs will be written; relative to the current directory '
+                                 '(only valid with the --grid option).')
+    file_group.add_argument('--experiment-info-file', metavar='FILE', default='Experiment.info',
+                            help='The file where the configuration of all parts of the experiments are written; '
+                                 'relative to te --result-directory.')
+    file_group.add_argument('-D', '--database-directories-file', metavar='FILE', default=database_replacement,
+                            help='An optional file, where database directories are stored (to avoid changing the database configurations)')
+
+    sub_dir_group = parser.add_argument_group('\nSubdirectories of certain parts of the tool chain. '
+                                              'You can specify directories in case you want to reuse parts of '
+                                              'the experiments (e.g. extracted features) in other experiments. '
+                                              'Please note that these directories are relative to the --temp-directory, '
+                                              'but you can also specify absolute paths')
+    sub_dir_group.add_argument('--preprocessed-directory', metavar='DIR', default='preprocessed',
+                               help='Name of the directory of the preprocessed data.')
+    sub_dir_group.add_argument('--extracted-directory', metavar='DIR', default='extracted',
+                               help='Name of the directory of the extracted features.')
+    sub_dir_group.add_argument('--projected-directory', metavar='DIR', default='projected',
+                               help='Name of the directory where the projected data should be stored.')
+    sub_dir_group.add_argument('--model-directories', metavar='DIR', nargs='+', default=['models', 'tmodels'],
+                               help='Name of the directory where the models (and T-Norm models) should be stored')
+    sub_dir_group.add_argument('--score-directories', metavar='DIR', nargs='+', default=['nonorm', 'ztnorm'],
+                               help='Name of the directory (relative to --result-directory) where to write the results to')
+    sub_dir_group.add_argument('--zt-directories', metavar='DIR', nargs=5,
+                               default=['zt_norm_A', 'zt_norm_B', 'zt_norm_C', 'zt_norm_D', 'zt_norm_D_sameValue'],
+                               help='Name of the directories (of --temp-directory) where to write the ZT-norm values; '
                                     'only used with --zt-norm')
-  sub_dir_group.add_argument('--grid-log-directory', metavar = 'DIR', default = 'gridtk_logs',
-      help = 'Name of the directory (relative to --temp-directory) where to log files are written; '
-             'only used with --grid')
-
-  flag_group = parser.add_argument_group('\nFlags that change the behavior of the experiment')
-  bob.core.log.add_command_line_option(flag_group)
-  flag_group.add_argument('-q', '--dry-run', action='store_true',
-      help = 'Only report the commands that will be executed, but do not execute them.')
-  flag_group.add_argument('-F', '--force', action='store_true',
-      help = 'Force to erase former data if already exist')
-  flag_group.add_argument('-Z', '--write-compressed-score-files', action='store_true',
-      help = 'Writes score files which are compressed with tar.bz2.')
-  flag_group.add_argument('-S', '--stop-on-failure', action='store_true',
-      help = 'Try to recursively stop the dependent jobs from the SGE grid queue, when a job failed')
-  flag_group.add_argument('-X', '--external-dependencies', type=int, default = [], nargs='+',
-      help = 'The jobs submitted to the grid have dependencies on the given job ids.')
-  flag_group.add_argument('-B', '--timer', choices=('real', 'system', 'user'), nargs = '*',
-      help = 'Measure and report the time required by the execution of the tool chain (only on local machine)')
-  flag_group.add_argument('-L', '--run-local-scheduler', action='store_true',
-      help = 'Starts the local scheduler after submitting the jobs to the local queue (by default, '
-             'local jobs must be started by hand, e.g., using ./bin/jman --local -vv run-scheduler -x)')
-  flag_group.add_argument('-N', '--nice', type=int, default=10,
-      help = 'Runs the local scheduler with the given nice value')
-  flag_group.add_argument('-D', '--delete-jobs-finished-with-status', choices = ('all', 'failure', 'success'),
-      help = 'If selected, local scheduler jobs that finished with the given status are deleted from '
-             'the --gridtk-database-file; otherwise the jobs remain in the database')
-  flag_group.add_argument('-C', '--calibrate-scores', action='store_true',
-      help = 'Performs score calibration after the scores are computed.')
-  flag_group.add_argument('-z', '--zt-norm', action='store_true',
-      help = 'Enable the computation of ZT norms')
-  flag_group.add_argument('-A', '--allow-missing-files', action='store_true',
-      help = "If given, missing files will not stop the processing; this is helpful if not all files of the "
-             "database can be processed; missing scores will be NaN.")
-  flag_group.add_argument('-r', '--parallel', type=int,
-      help = 'This flag is a shortcut for running the commands on the local machine with the given amount of '
-             'parallel threads; equivalent to --grid bob.bio.base.grid.Grid("local", '
-             'number_of_parallel_threads=X) --run-local-scheduler --stop-on-failure.')
-
-  flag_group.add_argument('-t', '--environment', dest='env', nargs='*', default=[],
-                          help='Passes specific environment variables to the job.')
-
-  return {
-    'main' : parser,
-    'config' : config_group,
-    'dir' : dir_group,
-    'sub-dir' : sub_dir_group,
-    'file' : file_group,
-    'flag' : flag_group
-  }
+    sub_dir_group.add_argument('--grid-log-directory', metavar='DIR', default='gridtk_logs',
+                               help='Name of the directory (relative to --temp-directory) where to log files are written; '
+                                    'only used with --grid')
+
+    flag_group = parser.add_argument_group('\nFlags that change the behavior of the experiment')
+    bob.core.log.add_command_line_option(flag_group)
+    flag_group.add_argument('-q', '--dry-run', action='store_true',
+                            help='Only report the commands that will be executed, but do not execute them.')
+    flag_group.add_argument('-F', '--force', action='store_true',
+                            help='Force to erase former data if already exist')
+    flag_group.add_argument('-Z', '--write-compressed-score-files', action='store_true',
+                            help='Writes score files which are compressed with tar.bz2.')
+    flag_group.add_argument('-S', '--stop-on-failure', action='store_true',
+                            help='Try to recursively stop the dependent jobs from the SGE grid queue, when a job failed')
+    flag_group.add_argument('-X', '--external-dependencies', type=int, default=[], nargs='+',
+                            help='The jobs submitted to the grid have dependencies on the given job ids.')
+    flag_group.add_argument('-B', '--timer', choices=('real', 'system', 'user'), nargs='*',
+                            help='Measure and report the time required by the execution of the tool chain (only on local machine)')
+    flag_group.add_argument('-L', '--run-local-scheduler', action='store_true',
+                            help='Starts the local scheduler after submitting the jobs to the local queue (by default, '
+                                 'local jobs must be started by hand, e.g., using ./bin/jman --local -vv run-scheduler -x)')
+    flag_group.add_argument('-N', '--nice', type=int, default=10,
+                            help='Runs the local scheduler with the given nice value')
+    flag_group.add_argument('-D', '--delete-jobs-finished-with-status', choices=('all', 'failure', 'success'),
+                            help='If selected, local scheduler jobs that finished with the given status are deleted from '
+                                 'the --gridtk-database-file; otherwise the jobs remain in the database')
+    flag_group.add_argument('-C', '--calibrate-scores', action='store_true',
+                            help='Performs score calibration after the scores are computed.')
+    flag_group.add_argument('-z', '--zt-norm', action='store_true',
+                            help='Enable the computation of ZT norms')
+    flag_group.add_argument('-A', '--allow-missing-files', action='store_true',
+                            help="If given, missing files will not stop the processing; this is helpful if not all files of the "
+                                 "database can be processed; missing scores will be NaN.")
+    flag_group.add_argument('-r', '--parallel', type=int,
+                            help='This flag is a shortcut for running the commands on the local machine with the given amount of '
+                                 'parallel threads; equivalent to --grid bob.bio.base.grid.Grid("local", '
+                                 'number_of_parallel_threads=X) --run-local-scheduler --stop-on-failure.')
+
+    flag_group.add_argument('-t', '--environment', dest='env', nargs='*', default=[],
+                            help='Passes specific environment variables to the job.')
+
+    return {
+        'main': parser,
+        'config': config_group,
+        'dir': dir_group,
+        'sub-dir': sub_dir_group,
+        'file': file_group,
+        'flag': flag_group
+    }
 
 
 def command_line_skip_group(parsers, command_line_parameters, skips):
@@ -233,44 +232,44 @@ def command_line_skip_group(parsers, command_line_parameters, skips):
 
 
 def take_from_config_or_command_line(args, config, keyword, default, required=True, is_resource=True):
+    if getattr(args, keyword) is not None and getattr(args, keyword) != default:
+        if is_resource:
+            setattr(args, keyword, utils.load_resource(' '.join(getattr(args, keyword)), keyword,
+                                                       imports=args.imports, package_prefix=args.package_prefix,
+                                                       preferred_package=args.preferred_package))
 
-  if getattr(args, keyword) is not None and getattr(args, keyword) != default:
-    if is_resource:
-      setattr(args, keyword, utils.load_resource(' '.join(getattr(args, keyword)), keyword,
-                                                 imports=args.imports, package_prefix=args.package_prefix,
-                                                 preferred_package=args.preferred_package))
-
-  elif config is not None and hasattr(config, keyword):
+    elif config is not None and hasattr(config, keyword):
 
-    val = getattr(config, keyword)
-    if isinstance(val, str) and is_resource:
-      val = utils.load_resource(val, keyword, imports = args.imports, package_prefix=args.package_prefix,
-                                preferred_package = args.preferred_package)
-    setattr(args, keyword, val)
+        val = getattr(config, keyword)
+        if isinstance(val, str) and is_resource:
+            val = utils.load_resource(val, keyword, imports=args.imports, package_prefix=args.package_prefix,
+                                      preferred_package=args.preferred_package)
+        setattr(args, keyword, val)
 
-  elif default is not None:
-    if is_resource:
-      setattr(args, keyword, utils.load_resource(' '.join(default), keyword,
-                                                 imports=args.imports, package_prefix=args.package_prefix,
-                                                 preferred_package=args.preferred_package))
+    elif default is not None:
+        if is_resource:
+            setattr(args, keyword, utils.load_resource(' '.join(default), keyword,
+                                                       imports=args.imports, package_prefix=args.package_prefix,
+                                                       preferred_package=args.preferred_package))
 
-  elif required:
-    raise ValueError("Please specify a %s either on command line (via --%s) or in a configuration file" %
-                     (keyword, keyword))
+    elif required:
+        raise ValueError("Please specify a %s either on command line (via --%s) or in a configuration file" %
+                         (keyword, keyword))
 
-  if config is not None and hasattr(config, keyword):
-    setattr(config, keyword, None)
+    if config is not None and hasattr(config, keyword):
+        setattr(config, keyword, None)
 
 
 def check_config_consumed(config):
-  if config is not None:
-    import inspect
-    for keyword in dir(config):
-      if not keyword.startswith('_') and not keyword.isupper():
-        attr = getattr(config,keyword)
-        if attr is not None and not inspect.isclass(attr) and not inspect.ismodule(attr):
-          logger.warn("The variable '%s' in a configuration file is not known or not supported; use all "
-                      "uppercase variable names (e.g., '%s') to suppress this warning.", keyword, keyword.upper())
+    if config is not None:
+        import inspect
+        for keyword in dir(config):
+            if not keyword.startswith('_') and not keyword.isupper():
+                attr = getattr(config, keyword)
+                if attr is not None and not inspect.isclass(attr) and not inspect.ismodule(attr):
+                    logger.warn("The variable '%s' in a configuration file is not known or not supported; use all "
+                                "uppercase variable names (e.g., '%s') to suppress this warning.", keyword,
+                                keyword.upper())
 
 
 def parse_config_file(parsers, args, args_dictionary, keywords, skips):
@@ -332,7 +331,7 @@ def set_extra_flags(args):
         args.temp_directory = "/idiap/temp/%s/%s" % (os.environ["USER"], args.database.name) if is_idiap() else "temp"
     if args.result_directory is None:
         args.result_directory = "/idiap/user/%s/%s" % (
-        os.environ["USER"], args.database.name) if is_idiap() else "results"
+            os.environ["USER"], args.database.name) if is_idiap() else "results"
 
     args.temp_directory = os.path.join(args.temp_directory, args.sub_directory)
     args.result_directory = os.path.join(args.result_directory, args.sub_directory)
@@ -341,266 +340,282 @@ def set_extra_flags(args):
     return args
 
 
-def initialize(parsers, command_line_parameters = None, skips = []):
-  """initialize(parsers, command_line_parameters = None, skips = []) -> args
-
-  Parses the command line and arranges the arguments accordingly.
-  Afterward, it loads the resources for the database, preprocessor, extractor, algorithm and grid (if specified),
-  and stores the results into the returned args.
-
-  This function also initializes the :py:class:`FileSelector` instance by arranging the directories and
-  files according to the command line parameters.
-
-  If the ``skips`` are given, an '--execute-only' parameter is added to the parser, according skips are selected.
-
-  **Parameters:**
-
-  parsers : dict
-    The dictionary of command line parsers, as returned from :py:func:`command_line_parser`.
-    Additional arguments might have been added.
-
-  command_line_parameters : [str] or None
-    The command line parameters that should be interpreted.
-    By default, the parameters specified by the user on command line are considered.
-
-  skips : [str]
-    A list of possible ``--skip-...`` options to be added and evaluated automatically.
-
-  **Returns:**
-
-  args : namespace
-    A namespace of arguments as read from the command line.
-
-    .. note:: The database, preprocessor, extractor, algorithm and grid (if specified) are actual instances
-    of the according classes.
-  """
-  from bob.bio.base.database import BioDatabase
-
-  args = command_line_skip_group(parsers, command_line_parameters, skips)
-  args_dictionary = {'required': ['database', 'preprocessor', 'extractor', 'algorithm', 'sub_directory'],
-                     'common': ['protocol', 'grid', 'parallel', 'verbose', 'groups', 'temp_directory',
-                                'result_directory', 'zt_norm', 'allow_missing_files', 'dry_run', 'force'],
-                     'optional': ['preprocessed_directory', 'extracted_directory', 'projected_directory',
-                                  'model_directories', 'extractor_file', 'projector_file', 'enroller_file']
-                     }
-  keywords = (
-            "protocol",
-            "groups",
-            "parallel",
-            "preferred_package",
-            "temp_directory",
-            "result_directory",
-            "extractor_file",
-            "projector_file",
-            "enroller_file",
-            "gridtk_database_file",
-            "experiment_info_file",
-            "database_directories_file",
-            "preprocessed_directory",
-            "extracted_directory",
-            "projected_directory",
-            "model_directories",
-            "score_directories",
-            "zt_directories",
-            "grid_log_directory",
-            "verbose",
-            "dry_run",
-            "force",
-            "write_compressed_score_files",
-            "stop_on_failure",
-            "run_local_scheduler",
-            "external_dependencies",
-            "timer",
-            "nice",
-            "delete_jobs_finished_with_status",
-            "calibrate_scores",
-            "zt_norm",
-            "allow_missing_files",
-            "env",
-  )
-  args = parse_config_file(parsers, args, args_dictionary, keywords, skips)
-
-  args = set_extra_flags(args)
-
-  # protocol command line override
-  if args.protocol is not None:
-    args.database.protocol = args.protocol
-
-  protocol = 'None' if args.database.protocol is None else args.database.protocol
-
-  # result files
-  args.info_file = os.path.join(args.result_directory, protocol, args.experiment_info_file)
-
-  # sub-directorues that depend on the database
-  extractor_sub_dir = protocol if args.database.training_depends_on_protocol and \
-                                  args.extractor.requires_training else '.'
-  projector_sub_dir = protocol if args.database.training_depends_on_protocol and \
-                                  args.algorithm.requires_projector_training else extractor_sub_dir
-  enroller_sub_dir = protocol if args.database.training_depends_on_protocol and \
-                                 args.algorithm.requires_enroller_training else projector_sub_dir
-  model_sub_dir = protocol if args.database.models_depend_on_protocol else enroller_sub_dir
-
-  # Database directories, which should be automatically replaced
-  if isinstance(args.database, BioDatabase):
-    args.database.replace_directories(args.database_directories_file)
-
-  # initialize the file selector
-  FileSelector.create(
-    database = args.database,
-    extractor_file = os.path.join(args.temp_directory, extractor_sub_dir, args.extractor_file),
-    projector_file = os.path.join(args.temp_directory, projector_sub_dir, args.projector_file),
-    enroller_file = os.path.join(args.temp_directory, enroller_sub_dir, args.enroller_file),
-
-    preprocessed_directory = os.path.join(args.temp_directory, args.preprocessed_directory),
-    extracted_directory = os.path.join(args.temp_directory, extractor_sub_dir, args.extracted_directory),
-    projected_directory = os.path.join(args.temp_directory, projector_sub_dir, args.projected_directory),
-    model_directories = [os.path.join(args.temp_directory, model_sub_dir, m) for m in args.model_directories],
-    score_directories = [os.path.join(args.result_directory, protocol, z) for z in args.score_directories],
-    zt_score_directories = [os.path.join(args.temp_directory, protocol, s) for s in args.zt_directories],
-    compressed_extension = '.tar.bz2' if args.write_compressed_score_files else '',
-    default_extension = '.hdf5',
-  )
-
-  return args
+def initialize(parsers, command_line_parameters=None, skips=[]):
+    """initialize(parsers, command_line_parameters = None, skips = []) -> args
+
+    Parses the command line and arranges the arguments accordingly.
+    Afterward, it loads the resources for the database, preprocessor, extractor, algorithm and grid (if specified),
+    and stores the results into the returned args.
+
+    This function also initializes the :py:class:`FileSelector` instance by arranging the directories and
+    files according to the command line parameters.
+
+    If the ``skips`` are given, an '--execute-only' parameter is added to the parser, according skips are selected.
+
+    **Parameters:**
+
+    parsers : dict
+      The dictionary of command line parsers, as returned from :py:func:`command_line_parser`.
+      Additional arguments might have been added.
+
+    command_line_parameters : [str] or None
+      The command line parameters that should be interpreted.
+      By default, the parameters specified by the user on command line are considered.
+
+    skips : [str]
+      A list of possible ``--skip-...`` options to be added and evaluated automatically.
+
+    **Returns:**
+
+    args : namespace
+      A namespace of arguments as read from the command line.
+
+      .. note:: The database, preprocessor, extractor, algorithm and grid (if specified) are actual instances
+      of the according classes.
+    """
+
+    from bob.bio.base.database import BioDatabase
+
+    args = command_line_skip_group(parsers, command_line_parameters, skips)
+    args_dictionary = {'required': ['database', 'preprocessor', 'extractor', 'algorithm', 'sub_directory'],
+                       'common': ['protocol', 'grid', 'parallel', 'verbose', 'groups', 'temp_directory',
+                                  'result_directory', 'zt_norm', 'allow_missing_files', 'dry_run', 'force'],
+                       'optional': ['preprocessed_directory', 'extracted_directory', 'projected_directory',
+                                    'model_directories', 'extractor_file', 'projector_file', 'enroller_file']
+                       }
+    keywords = (
+        "protocol",
+        "groups",
+        "parallel",
+        "preferred_package",
+        "temp_directory",
+        "result_directory",
+        "extractor_file",
+        "projector_file",
+        "enroller_file",
+        "gridtk_database_file",
+        "experiment_info_file",
+        "database_directories_file",
+        "preprocessed_directory",
+        "extracted_directory",
+        "projected_directory",
+        "model_directories",
+        "score_directories",
+        "zt_directories",
+        "grid_log_directory",
+        "verbose",
+        "dry_run",
+        "force",
+        "write_compressed_score_files",
+        "stop_on_failure",
+        "run_local_scheduler",
+        "external_dependencies",
+        "timer",
+        "nice",
+        "delete_jobs_finished_with_status",
+        "calibrate_scores",
+        "zt_norm",
+        "allow_missing_files",
+        "env",
+    )
+    args = parse_config_file(parsers, args, args_dictionary, keywords, skips)
+
+    args = set_extra_flags(args)
+
+    # protocol command line override
+    if args.protocol is not None:
+        args.database.protocol = args.protocol
+
+    protocol = 'None' if args.database.protocol is None else args.database.protocol
+
+    # result files
+    args.info_file = os.path.join(args.result_directory, protocol, args.experiment_info_file)
+
+    # sub-directorues that depend on the database
+    extractor_sub_dir = protocol if args.database.training_depends_on_protocol and \
+                                    args.extractor.requires_training else '.'
+    projector_sub_dir = protocol if args.database.training_depends_on_protocol and \
+                                    args.algorithm.requires_projector_training else extractor_sub_dir
+    enroller_sub_dir = protocol if args.database.training_depends_on_protocol and \
+                                   args.algorithm.requires_enroller_training else projector_sub_dir
+    model_sub_dir = protocol if args.database.models_depend_on_protocol else enroller_sub_dir
+
+    # Database directories, which should be automatically replaced
+    if isinstance(args.database, BioDatabase):
+        args.database.replace_directories(args.database_directories_file)
+
+    # initialize the file selector
+    FileSelector.create(
+        database=args.database,
+        extractor_file=os.path.join(args.temp_directory, extractor_sub_dir, args.extractor_file),
+        projector_file=os.path.join(args.temp_directory, projector_sub_dir, args.projector_file),
+        enroller_file=os.path.join(args.temp_directory, enroller_sub_dir, args.enroller_file),
+
+        preprocessed_directory=os.path.join(args.temp_directory, args.preprocessed_directory),
+        extracted_directory=os.path.join(args.temp_directory, extractor_sub_dir, args.extracted_directory),
+        projected_directory=os.path.join(args.temp_directory, projector_sub_dir, args.projected_directory),
+        model_directories=[os.path.join(args.temp_directory, model_sub_dir, m) for m in args.model_directories],
+        score_directories=[os.path.join(args.result_directory, protocol, z) for z in args.score_directories],
+        zt_score_directories=[os.path.join(args.temp_directory, protocol, s) for s in args.zt_directories],
+        compressed_extension='.tar.bz2' if args.write_compressed_score_files else '',
+        default_extension='.hdf5',
+    )
+
+    return args
 
 
 def groups(args):
-  """groups(args) -> groups
+    """groups(args) -> groups
 
-  Returns the groups, for which the files must be preprocessed, and features must be extracted and projected.
-  This function should be used in order to eliminate the training files (the ``'world'`` group),
-  when no training is required in this experiment.
+    Returns the groups, for which the files must be preprocessed, and features must be extracted and projected.
+    This function should be used in order to eliminate the training files (the ``'world'`` group),
+    when no training is required in this experiment.
 
-  **Parameters:**
+    **Parameters:**
 
-  args : namespace
-    The interpreted command line arguments as returned by the :py:func:`initialize` function.
+    args : namespace
+      The interpreted command line arguments as returned by the :py:func:`initialize` function.
 
-  **Returns:**
+    **Returns:**
 
-  groups : [str]
-    A list of groups, for which data needs to be treated.
-  """
-  groups = args.groups[:]
-  if args.extractor.requires_training or args.algorithm.requires_projector_training or \
-          args.algorithm.requires_enroller_training:
-    groups.append('world')
-  return groups
+    groups : [str]
+      A list of groups, for which data needs to be treated.
+    """
+    groups = args.groups[:]
+    if args.extractor.requires_training or args.algorithm.requires_projector_training or \
+            args.algorithm.requires_enroller_training:
+        groups.append('world')
+    return groups
 
 
 def command_line(cmdline):
-  """command_line(cmdline) -> str
+    """command_line(cmdline) -> str
 
-  Converts the given options to a string that can be executed in a terminal.
-  Parameters are enclosed into ``'...'`` quotes so that the command line can interpret them (e.g.,
-  if they contain spaces or special characters).
+    Converts the given options to a string that can be executed in a terminal.
+    Parameters are enclosed into ``'...'`` quotes so that the command line can interpret them (e.g.,
+    if they contain spaces or special characters).
 
-  **Parameters:**
+    **Parameters:**
 
-  cmdline : [str]
-    A list of command line options to be converted into a string.
+    cmdline : [str]
+      A list of command line options to be converted into a string.
 
-  **Returns:**
+    **Returns:**
 
-  str : str
-    The command line string that can be copy-pasted into the terminal.
-  """
-  c = ""
-  for cmd in cmdline:
-    if cmd[0] in '/-':
-      c += "%s " % cmd
-    else:
-      c += "'%s' " % cmd
-  return c
+    str : str
+      The command line string that can be copy-pasted into the terminal.
+    """
+    c = ""
+    for cmd in cmdline:
+        if cmd[0] in '/-':
+            c += "%s " % cmd
+        else:
+            c += "'%s' " % cmd
+    return c
 
 
 def write_info(args, command_line_parameters, executable):
-  """Writes information about the current experimental setup into a file specified on command line.
-
-  **Parameters:**
-
-  args : namespace
-    The interpreted command line arguments as returned by the :py:func:`initialize` function.
-
-  command_line_parameters : [str] or ``None``
-    The command line parameters that have been interpreted.
-    If ``None``, the parameters specified by the user on command line are considered.
-
-  executable : str
-    The name of the executable (such as ``'./bin/verify.py'``) that is used to run the experiments.
-  """
-  if command_line_parameters is None:
-    command_line_parameters = sys.argv[1:]
-  # write configuration
-  try:
-    bob.io.base.create_directories_safe(os.path.dirname(args.info_file))
-    f = open(args.info_file, 'w')
-    f.write("Command line:\n")
-    f.write(command_line([executable] + command_line_parameters) + "\n\n")
-    f.write("Host: %s\n" % socket.gethostname())
-    f.write("Configuration:\n")
-    f.write("Database:\n%s\n\n" % args.database)
-    f.write("Preprocessor:\n%s\n\n" % args.preprocessor)
-    f.write("Extractor:\n%s\n\n" % args.extractor)
-    f.write("Algorithm:\n%s\n\n" % args.algorithm)
-  except IOError:
-    logger.error("Could not write the experimental setup into file '%s'", args.info_file)
+    """Writes information about the current experimental setup into a file specified on command line.
+
+    **Parameters:**
+
+    args : namespace
+      The interpreted command line arguments as returned by the :py:func:`initialize` function.
+
+    command_line_parameters : [str] or ``None``
+      The command line parameters that have been interpreted.
+      If ``None``, the parameters specified by the user on command line are considered.
+
+    executable : str
+      The name of the executable (such as ``'./bin/verify.py'``) that is used to run the experiments.
+    """
+    if command_line_parameters is None:
+        command_line_parameters = sys.argv[1:]
+    # write configuration
+    try:
+        bob.io.base.create_directories_safe(os.path.dirname(args.info_file))
+        f = open(args.info_file, 'w')
+        f.write("Command line:\n")
+        f.write(command_line([executable] + command_line_parameters) + "\n\n")
+        f.write("Host: %s\n" % socket.gethostname())
+        f.write("Configuration:\n")
+        f.write("Database:\n%s\n\n" % args.database)
+        f.write("Preprocessor:\n%s\n\n" % args.preprocessor)
+        f.write("Extractor:\n%s\n\n" % args.extractor)
+        f.write("Algorithm:\n%s\n\n" % args.algorithm)
+    except IOError:
+        logger.error("Could not write the experimental setup into file '%s'", args.info_file)
+
 
 global _required_list, _common_list, _optional_list
 _required_list = set()
 _common_list = set()
 _optional_list = set()
 
-def set_required_common_optional_arguments(required = [], common = [], optional = []):
-  _required_list.update(required)
-  _common_list.update(common)
-  _optional_list.update(optional)
+
+def set_required_common_optional_arguments(required=[], common=[], optional=[]):
+    _required_list.update(required)
+    _common_list.update(common)
+    _optional_list.update(optional)
+
 
 def create_configuration_file(parsers, args):
-  """This function writes an empty configuration file with all possible options."""
-  logger.info("Writing configuration file %s", args.create_configuration_file)
-  import datetime
-  executables = bob.extension.find_executable(os.path.basename(sys.argv[0]), prefixes = [os.path.dirname(sys.argv[0]), 'bin'])
-  if not executables:
-    executables = [sys.argv[0]]
-
-  parser = parsers['main']
-
-  bob.io.base.create_directories_safe(os.path.dirname(args.create_configuration_file))
-
-  required  = "# Configuration file automatically generated at %s for %s.\n\n" % (datetime.date.today(), executables[0])
-  required += "##################################################\n############### REQUIRED ARGUMENTS ###############\n##################################################\n\n"
-  required += "# These arguments need to be set.\n\n\n"
-  common    = "##################################################\n################ COMMON ARGUMENTS ################\n##################################################\n\n"
-  common   += "# These arguments are commonly changed.\n\n\n"
-  optional  = "##################################################\n############### OPTIONAL ARGUMENTS ###############\n##################################################\n\n"
-  optional += "# Files and directories might commonly be specified with absolute paths or relative to the temp_directory.\n# Change these options, e.g., to reuse parts of other experiments.\n\n\n"
-  rare      = "##################################################\n############ RARELY CHANGED ARGUMENTS ############\n##################################################\n\n\n"
-
-  with open(args.create_configuration_file, 'w') as f:
-
-    for action in parser._actions[3:]:
-      if action.help == "==SUPPRESS==":
-        continue
-
-      tmp = "# %s\n\n" % action.help
-      if action.nargs is None and action.type is None and action.default is not None:
-        tmp +=  "#%s = '%s'\n\n\n" % (action.dest, action.default)
-      else:
-        tmp += "#%s = %s\n\n\n" % (action.dest, action.default)
-
-      if action.dest in _required_list:
-        required += tmp
-      elif action.dest in _common_list:
-        common += tmp
-      elif action.dest in _optional_list:
-        optional += tmp
-      else:
-        rare += tmp
-
-    f.write(required)
-    f.write(common)
-    f.write(optional)
-    f.write(rare)
-
-  parser.exit(1, "Configuration file '%s' was written; exiting\n" % args.create_configuration_file)
+    """This function writes an empty configuration file with all possible options."""
+    logger.info("Writing configuration file %s", args.create_configuration_file)
+    import datetime
+    executables = bob.extension.find_executable(os.path.basename(sys.argv[0]),
+                                                prefixes=[os.path.dirname(sys.argv[0]), 'bin'])
+    if not executables:
+        executables = [sys.argv[0]]
+
+    parser = parsers['main']
+
+    bob.io.base.create_directories_safe(os.path.dirname(args.create_configuration_file))
+
+    required = "# Configuration file automatically generated at %s for %s.\n\n" % (
+    datetime.date.today(), executables[0])
+    required += "##################################################\n" \
+                "############### REQUIRED ARGUMENTS ###############\n" \
+                "##################################################\n\n"
+    required += "# These arguments need to be set.\n\n\n"
+    common = "##################################################\n" \
+             "################ COMMON ARGUMENTS ################\n" \
+             "##################################################\n\n"
+    common += "# These arguments are commonly changed.\n\n\n"
+    optional = "##################################################\n" \
+               "############### OPTIONAL ARGUMENTS ###############\n" \
+               "##################################################\n\n"
+    optional += "# Files and directories might commonly be specified with absolute paths or " \
+                "relative to the temp_directory.\n# Change these options, e.g., to reuse parts " \
+                "of other experiments.\n\n\n"
+    rare = "##################################################\n" \
+           "############ RARELY CHANGED ARGUMENTS ############\n" \
+           "##################################################\n\n\n"
+
+    with open(args.create_configuration_file, 'w') as f:
+
+        for action in parser._actions[3:]:
+            if action.help == "==SUPPRESS==":
+                continue
+
+            tmp = "# %s\n\n" % action.help
+            if action.nargs is None and action.type is None and action.default is not None:
+                tmp += "#%s = '%s'\n\n\n" % (action.dest, action.default)
+            else:
+                tmp += "#%s = %s\n\n\n" % (action.dest, action.default)
+
+            if action.dest in _required_list:
+                required += tmp
+            elif action.dest in _common_list:
+                common += tmp
+            elif action.dest in _optional_list:
+                optional += tmp
+            else:
+                rare += tmp
+
+        f.write(required)
+        f.write(common)
+        f.write(optional)
+        f.write(rare)
+
+    parser.exit(1, "Configuration file '%s' was written; exiting\n" % args.create_configuration_file)
-- 
GitLab