docstr: Schedule jobs that are ready, maximizing cpu usage.
docstr_tok: ["Schedule","jobs","that","are","ready",",","maximizing","cpu","usage","."]
code: def schedule(self):
      """Schedule jobs that are ready, maximizing cpu usage."""
      try:
          while True:
              # work around so that the wait does not prevent keyboard interrupts
              # while not self._open_jobs.acquire(False):
              #    time.sleep(1)
              self._open_jobs.acquire()
  
              # obtain needrun and running jobs in a thread-safe way
              with self._lock:
                  self._finish_jobs()
                  self._error_jobs()
                  needrun = set(self.open_jobs)
                  running = list(self.running)
                  errors = self._errors
                  executor_error = self._executor_error
                  user_kill = self._user_kill
  
              # handle errors
              if (
                  user_kill
                  or (not self.keepgoing and errors)
                  or executor_error
              ):
                  if user_kill == "graceful":
                      logger.info(
                          "Will exit after finishing currently running jobs (scheduler)."
                      )
  
                  if executor_error:
                      print_exception(
                          executor_error, self.workflow.linemaps
                      )
  
                  if executor_error or not running:
                      logger.info(
                          "Shutting down, this might take some time."
                      )
                      self._executor.shutdown()
                      if not user_kill:
                          logger.error(_ERROR_MSG_FINAL)
                      return False
                  continue
  
              # all runnable jobs have finished, normal shutdown
              if not needrun and (
                  not running
                  or self.workflow.remote_execution_settings.immediate_submit
              ):
                  self._executor.shutdown()
                  if errors:
                      logger.error(_ERROR_MSG_FINAL)
                  # we still have unfinished jobs. this is not good. direct
                  # user to github issue
                  if self.remaining_jobs and not self.keepgoing:
                      logger.error(_ERROR_MSG_ISSUE_823)
                      logger.error(
                          "Remaining jobs:\n"
                          + "\n".join(
                              " - "
                              + str(job)
                              + ": "
                              + ", ".join(job.output)
                              for job in self.remaining_jobs
                          )
                      )
                      return False
                  return not errors
  
              # continue if no new job needs to be executed
              if not needrun:
                  continue
  
              # select jobs by solving knapsack problem (omit with dryrun)
              if self.dryrun:
                  run = needrun
              else:
                  # Reset params and resources because they might still contain TBDs
                  # or old values from before files have been regenerated.
                  # Now, they can be recalculated as all input is present and up to date.
                  for job in needrun:
                      job.reset_params_and_resources()
  
                  logger.debug(
                      f"Resources before job selection: {self.resources}"
                  )
                  logger.debug(
                      f"Ready jobs ({len(needrun)})"
                      # + "\n\t".join(map(str, needrun))
                  )
  
                  if not self._last_job_selection_empty:
                      logger.info("Select jobs to execute...")
                  run = self.job_selector(needrun)
                  self._last_job_selection_empty = not run
  
                  logger.debug(
                      f"Selected jobs ({len(run)})"
                      # + "\n\t".join(map(str, run))
                  )
                  logger.debug(
                      f"Resources after job selection: {self.resources}"
                  )
  
              # update running jobs
              with self._lock:
                  self.running.update(run)
                  # remove from ready_jobs
                  self.workflow.dag.register_running(run)
  
              logger.info(f"Execute {len(run)} jobs...")
  
              # actually run jobs
              local_runjobs = [job for job in run if job.is_local]
              runjobs = [job for job in run if not job.is_local]
              if local_runjobs:
                  self.run(
                      local_runjobs,
                      executor=self._local_executor or self._executor,
                  )
              if runjobs:
                  self.run(runjobs)
      except (KeyboardInterrupt, SystemExit):
          logger.info(
              "Terminating processes on user request, this might take some time."
          )
          self._executor.cancel()
          return False
  
imports: import asyncio
  from collections import defaultdict
  import math
  import os, signal, sys
  import threading
  from functools import partial
  from itertools import chain, accumulate
  from contextlib import ContextDecorator
  from snakemake_interface_executor_plugins.scheduler import JobSchedulerExecutorInterface
  from snakemake_interface_executor_plugins.registry import ExecutorPluginRegistry
  from snakemake_interface_executor_plugins.registry import Plugin
  from snakemake_interface_executor_plugins.settings import ExecMode
  from snakemake.common import async_run
  from snakemake.exceptions import RuleException, WorkflowError, print_exception
  from snakemake.logging import logger
  from fractions import Fraction
label_desc: Use image node_id 6 for calling the JobScheduler obj's underlying member method code with example usage: obj.schedule() and returns: False, unknown, False, False