class_docstr: Experiment Class - create and run an experiment
  
  :param exp_config: configuration of the experiment
  :type exp_config: BasicConfig.BasicConfig
  :param username: username, default: None - will use login username
  :type username: str
  :param connector: connector to database
  :type connector: AbstractConnector
  :param auppath: Auptimizer env.ini file folder, default is either ``./.aup`` or ``~/.aup``
  :type auppath: str
  :param sleep_time: time to pause between jobs
  :type sleep_time: int
class_docstr_tok: ["Experiment","Class","-","create","and","run","an","experiment",":","param","exp_config",":","configuration","of","the","experiment",":","type","exp_config",":","BasicConfig.BasicConfig",":","param","username",":","username",",","default",":","None","-","will","use","login","username",":","type","username",":","str",":","param","connector",":","connector","to","database",":","type","connector",":","AbstractConnector",":","param","auppath",":","Auptimizer","env.ini","file","folder",",","default","is","either","``",".\/.aup","``","or","``","~\/.aup","``",":","type","auppath",":","str",":","param","sleep_time",":","time","to","pause","between","jobs",":","type","sleep_time",":","int"]
docstr: Callback function passed to :mod:`aup.EE.Resource.AbstractResourceManager` to
   update the job history (also proposer and connector)
  
  :param score: score returned from job (using :func:`aup.utils.print_result`)
  :type score: float
  :param jid: job id
  :type jid: int
docstr_tok: ["Callback","function","passed","to",":","mod",":","`","aup.EE.Resource.AbstractResourceManager","`","to","update","the","job","history","(","also","proposer","and","connector",")",":","param","score",":","score","returned","from","job","(","using",":","func",":","`","aup.utils.print_result","`",")",":","type","score",":","float",":","param","jid",":","job","id",":","type","jid",":","int"]
code: def update(self, score, jid):
      """
      Callback function passed to :mod:`aup.EE.Resource.AbstractResourceManager` to
       update the job history (also proposer and connector)
  
      :param score: score returned from job (using :func:`aup.utils.print_result`)
      :type score: float
      :param jid: job id
      :type jid: int
      """
      if score == "ERROR":
          job = self.pending_jobs.pop(jid)
          if (
              job.jid in self.resource_manager.jobs
              and job.curr_retries < job.retries
          ):
              rid = self.resource_manager.jobs[jid]
              job.rid_blacklist.add(rid)
              self.resource_manager.connector.job_failed(rid, jid)
              job.curr_retries += 1
              logger.info(
                  "Retrying job %d (%d/%d)"
                  % (jid, job.curr_retries, job.retries)
              )
              self.submit_job(job, rid_blacklist=job.rid_blacklist)
          elif not self.fail_safe:
              self.resource_manager.finish_job(jid, None, "FAILED")
              self.proposer.set_status(ProposerStatus.FAILED)
              logger.fatal(
                  "Stop Experiment due to job failure (ignore_fail flag set to false)"
              )
          else:
              self.resource_manager.finish_job(jid, None, "FAILED")
              try:
                  self.proposer.failed(job)
              except Exception as ex:
                  self.proposer.set_status(ProposerStatus.FAILED)
                  logger.fatal(
                      "Stop Experiment due to job failure (failed jobs unsupported by proposer)"
                  )
              logger.info("Job %d is finished (failed)" % (jid))
              if self.proposer.get_status() == ProposerStatus.RUNNING:
                  self.start()
      elif score == "EARLY STOPPED":
          self.pending_jobs.pop(jid)
          self.resource_manager.finish_job(jid, score, "EARLY_STOPPED")
          logger.info("Job %d was early stopped" % (jid))
          if self.proposer.get_status() == ProposerStatus.RUNNING:
              self.start()
      else:
          self.proposer.update(score, self.pending_jobs[jid])
          self.pending_jobs.pop(jid)
          self.resource_manager.finish_job(jid, score, "FINISHED")
          logger.info(
              "Job %d is finished with result %s" % (jid, score)
          )
  
          if self.proposer.get_status() == ProposerStatus.RUNNING:
              self.start()
  
imports: import json
  import logging
  import os
  import signal
  import sys
  import _thread
  import threading
  import time
  from ..Proposer import get_proposer, SPECIAL_EXIT_PROPOSERS
  from .Job import Job
  from .Resource import get_resource_manager
  from ..aup import BasicConfig
  from ..utils import set_default_keyvalue, check_missing_key, get_default_connector, get_default_username
  from ..compression.utils import *
  from ..Proposer import ProposerStatus
label_desc: Use image node_id 8 for calling the Experiment obj's underlying member method code with example usage: obj.update(score, jid) without return types