# Buggy code
def processFinishedJob(self, jobBatchSystemID, resultStatus, wallTime=None):
    """
    Function reads a processed jobWrapper file and updates it state.
    """

    def processRemovedJob(jobStoreID):
        if resultStatus != 0:
            logger.warn(
                "Despite the batch system claiming failure the "
                "jobWrapper %s seems to have finished and been removed",
                jobStoreID,
            )
        self._updatePredecessorStatus(jobStoreID)

    if wallTime is not None and self.clusterScaler is not None:
        issuedJob = self.jobBatchSystemIDToIssuedJob[jobBatchSystemID]
        self.clusterScaler.addCompletedJob(issuedJob, wallTime)
    jobStoreID = self.removeJobID(jobBatchSystemID)
    if self.jobStore.exists(jobStoreID):
        logger.debug("Job %s continues to exist (i.e. has more to do)" % jobStoreID)
        try:
            jobWrapper = self.jobStore.load(jobStoreID)
        except NoSuchJobException:
            if isinstance(self.jobStore, AWSJobStore):
                # We have a ghost job - the job has been deleted but a stale read from
                # SDB gave us a false positive when we checked for its existence.
                # Process the job from here as any other job removed from the job store.
                # This is a temporary work around until https://github.com/BD2KGenomics/toil/issues/1091
                # is completed
                logger.warn("Got a stale read from SDB for job %s", jobStoreID)
                processRemovedJob(jobStoreID)
                return
            else:
                raise
        if jobWrapper.logJobStoreFileID is not None:
            logger.warn(
                "The jobWrapper seems to have left a log file, indicating failure: %s",
                jobStoreID,
            )
            with jobWrapper.getLogFileHandle(self.jobStore) as logFileStream:
                logStream(logFileStream, jobStoreID, logger.warn)
        if resultStatus != 0:
            # If the batch system returned a non-zero exit code then the worker
            # is assumed not to have captured the failure of the job, so we
            # reduce the retry count here.
            if jobWrapper.logJobStoreFileID is None:
                logger.warn(
                    "No log file is present, despite jobWrapper failing: %s", jobStoreID
                )
            jobWrapper.setupJobAfterFailure(self.config)
            self.jobStore.update(jobWrapper)
        elif jobStoreID in self.toilState.hasFailedSuccessors:
            # If the job has completed okay, we can remove it from the list of jobs with failed successors
            self.toilState.hasFailedSuccessors.remove(jobStoreID)

        self.toilState.updatedJobs.add((jobWrapper, resultStatus))  # Now we know the
        # jobWrapper is done we can add it to the list of updated jobWrapper files
        logger.debug("Added jobWrapper: %s to active jobs", jobStoreID)
    else:  # The jobWrapper is done
        processRemovedJob(jobStoreID)


# Traceback (ImportError)
(venv) jenkins@ip-172-31-29-42:~/toil$ make develop
…
(venv) jenkins@ip-172-31-29-42:~/toil$ python HelloWorld.py --batchSystem gridEngine --disableCaching --logDebug ./jobStore
ip-172-31-29-42 2016-08-23 21:52:06,214 MainThread INFO toil.lib.bioio: Logging set at level: DEBUG
ip-172-31-29-42 2016-08-23 21:52:06,214 MainThread INFO toil.lib.bioio: Logging set at level: DEBUG
ip-172-31-29-42 2016-08-23 21:52:06,223 MainThread INFO toil.jobStores.fileJobStore: Path to job store directory is '/home/jenkins/toil/jobStore'.
ip-172-31-29-42 2016-08-23 21:52:06,223 MainThread INFO toil.jobStores.abstractJobStore: The workflow ID is: '0a91cea1-30dc-4968-a5f1-930414702a2d'
ip-172-31-29-42 2016-08-23 21:52:06,265 MainThread INFO toil.common: Using the gridengine batch system
ip-172-31-29-42 2016-08-23 21:52:06,334 Thread-1 DEBUG toil.batchSystems.gridengine: List of running jobs: set([])
ip-172-31-29-42 2016-08-23 21:52:06,334 MainThread INFO toil.common: Written the environment for the jobs to the environment file
ip-172-31-29-42 2016-08-23 21:52:06,334 MainThread INFO toil.common: Caching all jobs in job store
ip-172-31-29-42 2016-08-23 21:52:06,334 MainThread INFO toil.common: 0 jobs downloaded.
ip-172-31-29-42 2016-08-23 21:52:06,336 Thread-1 DEBUG toil.batchSystems.gridengine: No activity, sleeping for 1s
ip-172-31-29-42 2016-08-23 21:52:06,353 MainThread INFO toil.realtimeLogger: Real-time logging disabled
ip-172-31-29-42 2016-08-23 21:52:06,367 MainThread DEBUG toil.common: Shutting down batch system ...
ip-172-31-29-42 2016-08-23 21:52:07,338 Thread-1 DEBUG toil.batchSystems.gridengine: Received queue sentinel.
ip-172-31-29-42 2016-08-23 21:52:07,338 MainThread DEBUG toil.common: ... finished shutting down the batch system in 0.970496177673 seconds.
Traceback (most recent call last):
File "HelloWorld.py", line 11, in <module>
print Job.Runner.startToil(j, options)
File "/home/jenkins/toil/src/toil/job.py", line 542, in startToil
return toil.start(job)
File "/home/jenkins/toil/src/toil/common.py", line 580, in start
return self._runMainLoop(job)
File "/home/jenkins/toil/src/toil/common.py", line 788, in _runMainLoop
from toil.leader import mainLoop
File "/home/jenkins/toil/src/toil/leader.py", line 32, in <module>
from toil.jobStores.aws.jobStore import AWSJobStore
File "/home/jenkins/toil/src/toil/jobStores/aws/jobStore.py", line 34, in <module>
from boto.sdb.domain import Domain
ImportError: No module named boto.sdb.domain

# Fixed code
def processFinishedJob(self, jobBatchSystemID, resultStatus, wallTime=None):
    """
    Function reads a processed jobWrapper file and updates it state.
    """

    def processRemovedJob(jobStoreID):
        if resultStatus != 0:
            logger.warn(
                "Despite the batch system claiming failure the "
                "jobWrapper %s seems to have finished and been removed",
                jobStoreID,
            )
        self._updatePredecessorStatus(jobStoreID)

    if wallTime is not None and self.clusterScaler is not None:
        issuedJob = self.jobBatchSystemIDToIssuedJob[jobBatchSystemID]
        self.clusterScaler.addCompletedJob(issuedJob, wallTime)
    jobStoreID = self.removeJobID(jobBatchSystemID)
    if self.jobStore.exists(jobStoreID):
        logger.debug("Job %s continues to exist (i.e. has more to do)" % jobStoreID)
        try:
            jobWrapper = self.jobStore.load(jobStoreID)
        except NoSuchJobException:
            # Avoid importing AWSJobStore as the corresponding extra might be missing
            if self.jobStore.__class__.__name__ == "AWSJobStore":
                # We have a ghost job - the job has been deleted but a stale read from
                # SDB gave us a false positive when we checked for its existence.
                # Process the job from here as any other job removed from the job store.
                # This is a temporary work around until https://github.com/BD2KGenomics/toil/issues/1091
                # is completed
                logger.warn("Got a stale read from SDB for job %s", jobStoreID)
                processRemovedJob(jobStoreID)
                return
            else:
                raise
        if jobWrapper.logJobStoreFileID is not None:
            logger.warn(
                "The jobWrapper seems to have left a log file, indicating failure: %s",
                jobStoreID,
            )
            with jobWrapper.getLogFileHandle(self.jobStore) as logFileStream:
                logStream(logFileStream, jobStoreID, logger.warn)
        if resultStatus != 0:
            # If the batch system returned a non-zero exit code then the worker
            # is assumed not to have captured the failure of the job, so we
            # reduce the retry count here.
            if jobWrapper.logJobStoreFileID is None:
                logger.warn(
                    "No log file is present, despite jobWrapper failing: %s", jobStoreID
                )
            jobWrapper.setupJobAfterFailure(self.config)
            self.jobStore.update(jobWrapper)
        elif jobStoreID in self.toilState.hasFailedSuccessors:
            # If the job has completed okay, we can remove it from the list of jobs with failed successors
            self.toilState.hasFailedSuccessors.remove(jobStoreID)

        self.toilState.updatedJobs.add((jobWrapper, resultStatus))  # Now we know the
        # jobWrapper is done we can add it to the list of updated jobWrapper files
        logger.debug("Added jobWrapper: %s to active jobs", jobStoreID)
    else:  # The jobWrapper is done
        processRemovedJob(jobStoreID)