docs: def list_jobs(ext_source=None,
                outputter=None,
                search_metadata=None,
                search_function=None,
                search_target=None,
                start_time=None,
                end_time=None,
                display_progress=False):
      '''
      List all detectable jobs and associated functions
  
      ext_source
          If provided, specifies which external job cache to use.
  
      **FILTER OPTIONS**
  
      .. note::
          If more than one of the below options are used, only jobs which match
          *all* of the filters will be returned.
  
      search_metadata
          Specify a dictionary to match to the job's metadata. If any of the
          key-value pairs in this dictionary match, the job will be returned.
          Example:
  
          .. code-block:: bash
  
              salt-run jobs.list_jobs search_metadata='{"foo": "bar", "baz": "qux"}'
  
      search_function
          Can be passed as a string or a list. Returns jobs which match the
          specified function. Globbing is allowed. Example:
  
          .. code-block:: bash
  
              salt-run jobs.list_jobs search_function='test.*'
              salt-run jobs.list_jobs search_function='["test.*", "pkg.install"]'
  
          .. versionchanged:: 2015.8.8
              Multiple targets can now also be passed as a comma-separated list.
              For example:
  
              .. code-block:: bash
  
                  salt-run jobs.list_jobs search_function='test.*,pkg.install'
  
      search_target
          Can be passed as a string or a list. Returns jobs which match the
          specified minion name. Globbing is allowed. Example:
  
          .. code-block:: bash
  
              salt-run jobs.list_jobs search_target='*.mydomain.tld'
              salt-run jobs.list_jobs search_target='["db*", "myminion"]'
  
          .. versionchanged:: 2015.8.8
              Multiple targets can now also be passed as a comma-separated list.
              For example:
  
              .. code-block:: bash
  
                  salt-run jobs.list_jobs search_target='db*,myminion'
  
      start_time
          Accepts any timestamp supported by the dateutil_ Python module (if this
          module is not installed, this argument will be ignored). Returns jobs
          which started after this timestamp.
  
      end_time
          Accepts any timestamp supported by the dateutil_ Python module (if this
          module is not installed, this argument will be ignored). Returns jobs
          which started before this timestamp.
  
      .. _dateutil: https://pypi.python.org/pypi/python-dateutil
  
      CLI Example:
  
      .. code-block:: bash
  
          salt-run jobs.list_jobs
          salt-run jobs.list_jobs search_function='test.*' search_target='localhost' search_metadata='{"bar": "foo"}'
          salt-run jobs.list_jobs start_time='2015, Mar 16 19:00' end_time='2015, Mar 18 22:00'
  
      '''
      returner = _get_returner((
          __opts__['ext_job_cache'],
          ext_source,
          __opts__['master_job_cache']
      ))
      if display_progress:
          __jid_event__.fire_event(
              {'message': 'Querying returner {0} for jobs.'.format(returner)},
              'progress'
          )
      mminion = salt.minion.MasterMinion(__opts__)
  
      ret = mminion.returners['{0}.get_jids'.format(returner)]()
  
      mret = {}
      for item in ret:
          _match = True
          if search_metadata:
              _match = False
              if 'Metadata' in ret[item]:
                  if isinstance(search_metadata, dict):
                      for key in search_metadata:
                          if key in ret[item]['Metadata']:
                              if ret[item]['Metadata'][key] == search_metadata[key]:
                                  _match = True
                  else:
                      log.info('The search_metadata parameter must be specified'
                               ' as a dictionary.  Ignoring.')
          if search_target and _match:
              _match = False
              if 'Target' in ret[item]:
                  targets = ret[item]['Target']
                  if isinstance(targets, six.string_types):
                      targets = [targets]
                  for target in targets:
                      for key in salt.utils.args.split_input(search_target):
                          if fnmatch.fnmatch(target, key):
                              _match = True
  
          if search_function and _match:
              _match = False
              if 'Function' in ret[item]:
                  for key in salt.utils.args.split_input(search_function):
                      if fnmatch.fnmatch(ret[item]['Function'], key):
                          _match = True
  
          if start_time and _match:
              _match = False
              if DATEUTIL_SUPPORT:
                  parsed_start_time = dateutil_parser.parse(start_time)
                  _start_time = dateutil_parser.parse(ret[item]['StartTime'])
                  if _start_time >= parsed_start_time:
                      _match = True
              else:
                  log.error(
                      '\'dateutil\' library not available, skipping start_time '
                      'comparison.'
                  )
  
          if end_time and _match:
              _match = False
              if DATEUTIL_SUPPORT:
                  parsed_end_time = dateutil_parser.parse(end_time)
                  _start_time = dateutil_parser.parse(ret[item]['StartTime'])
                  if _start_time <= parsed_end_time:
                      _match = True
              else:
                  log.error(
                      '\'dateutil\' library not available, skipping end_time '
                      'comparison.'
                  )
  
          if _match:
              mret[item] = ret[item]
  
      if outputter:
          return {'outputter': outputter, 'data': mret}
      else:
          return mret