def update_needrun(self):
    ' Update the information whether a job needs to be executed. '
    output_mintime = dict()

    def update_output_mintime(job):
        try:
            return output_mintime[job]
        except KeyError:
            for job_ in chain([job], self.depending[job]):
                try:
                    t = output_mintime[job_]
                except KeyError:
                    t = job_.output_mintime
                if (t is not None):
                    output_mintime[job] = t
                    return
            output_mintime[job] = None

    def update_needrun(job):
        reason = self.reason(job)
        noinitreason = (not reason)
        updated_subworkflow_input = self.updated_subworkflow_files.intersection(job.input)
        if (((job not in self.omitforce) and (job.rule in self.forcerules)) or (not self.forcefiles.isdisjoint(job.output))):
            reason.forced = True
        elif updated_subworkflow_input:
            reason.updated_input.update(updated_subworkflow_input)
        elif (job in self.targetjobs):
            if ((not job.output) and (not job.benchmark)):
                if job.input:
                    if job.rule.norun:
                        reason.updated_input_run.update([f for f in job.input if (not f.exists)])
                    else:
                        reason.nooutput = True
                else:
                    reason.noio = True
            else:
                if (job.rule in self.targetrules):
                    missing_output = job.missing_output()
                else:
                    missing_output = job.missing_output(requested=(set(chain(*self.depending[job].values())) | self.targetfiles))
                reason.missing_output.update(missing_output)
        if (not reason):
            output_mintime_ = output_mintime.get(job)
            if output_mintime_:
                updated_input = [f for f in job.input if (f.exists and f.is_newer(output_mintime_))]
                reason.updated_input.update(updated_input)
        if (noinitreason and reason):
            reason.derived = False
    reason = self.reason
    _needrun = self._needrun
    dependencies = self.dependencies
    depending = self.depending
    _needrun.clear()
    candidates = list(self.jobs)
    for job in candidates:
        update_output_mintime(job)
    for job in candidates:
        update_needrun(job)
    queue = list(filter(reason, candidates))
    visited = set(queue)
    while queue:
        job = queue.pop(0)
        _needrun.add(job)
        for (job_, files) in dependencies[job].items():
            missing_output = job_.missing_output(requested=files)
            reason(job_).missing_output.update(missing_output)
            if (missing_output and (not (job_ in visited))):
                visited.add(job_)
                queue.append(job_)
        for (job_, files) in depending[job].items():
            if (job_ in candidates):
                reason(job_).updated_input_run.update(files)
                if (not (job_ in visited)):
                    visited.add(job_)
                    queue.append(job_)
    self._len = len((self._finished | self._needrun))
Update the information whether a job needs to be executed.
def update_needrun(self):
    '  '
    output_mintime = dict()

    def update_output_mintime(job):
        try:
            return output_mintime[job]
        except KeyError:
            for job_ in chain([job], self.depending[job]):
                try:
                    t = output_mintime[job_]
                except KeyError:
                    t = job_.output_mintime
                if (t is not None):
                    output_mintime[job] = t
                    return
            output_mintime[job] = None

    def update_needrun(job):
        reason = self.reason(job)
        noinitreason = (not reason)
        updated_subworkflow_input = self.updated_subworkflow_files.intersection(job.input)
        if (((job not in self.omitforce) and (job.rule in self.forcerules)) or (not self.forcefiles.isdisjoint(job.output))):
            reason.forced = True
        elif updated_subworkflow_input:
            reason.updated_input.update(updated_subworkflow_input)
        elif (job in self.targetjobs):
            if ((not job.output) and (not job.benchmark)):
                if job.input:
                    if job.rule.norun:
                        reason.updated_input_run.update([f for f in job.input if (not f.exists)])
                    else:
                        reason.nooutput = True
                else:
                    reason.noio = True
            else:
                if (job.rule in self.targetrules):
                    missing_output = job.missing_output()
                else:
                    missing_output = job.missing_output(requested=(set(chain(*self.depending[job].values())) | self.targetfiles))
                reason.missing_output.update(missing_output)
        if (not reason):
            output_mintime_ = output_mintime.get(job)
            if output_mintime_:
                updated_input = [f for f in job.input if (f.exists and f.is_newer(output_mintime_))]
                reason.updated_input.update(updated_input)
        if (noinitreason and reason):
            reason.derived = False
    reason = self.reason
    _needrun = self._needrun
    dependencies = self.dependencies
    depending = self.depending
    _needrun.clear()
    candidates = list(self.jobs)
    for job in candidates:
        update_output_mintime(job)
    for job in candidates:
        update_needrun(job)
    queue = list(filter(reason, candidates))
    visited = set(queue)
    while queue:
        job = queue.pop(0)
        _needrun.add(job)
        for (job_, files) in dependencies[job].items():
            missing_output = job_.missing_output(requested=files)
            reason(job_).missing_output.update(missing_output)
            if (missing_output and (not (job_ in visited))):
                visited.add(job_)
                queue.append(job_)
        for (job_, files) in depending[job].items():
            if (job_ in candidates):
                reason(job_).updated_input_run.update(files)
                if (not (job_ in visited)):
                    visited.add(job_)
                    queue.append(job_)
    self._len = len((self._finished | self._needrun))