# Buggy code
def _load_checkpoints(self, checkpointDirs):
    """Load a checkpoint file into a lookup table.

    The data being loaded from the pickle file mostly contains input
    attributes of the task: func, args, kwargs, env...
    To simplify the check of whether the exact task has been completed
    in the checkpoint, we hash these input params and use it as the key
    for the memoized lookup table.

    Args:
        - checkpointDirs (list) : List of filepaths to checkpoints
          Eg. ['runinfo/001', 'runinfo/002']

    Returns:
        - memoized_lookup_table (dict)
    """
    memo_lookup_table = {}

    for checkpoint_dir in checkpointDirs:
        checkpoint_file = os.path.join(checkpoint_dir, "tasks.pkl")
        try:
            with open(checkpoint_file, "rb") as f:
                while True:
                    try:
                        data = pickle.load(f)
                        # Copy and hash only the input attributes
                        memo_fu = Future()
                        if data["exception"]:
                            memo_fu.set_exception(data["exception"])
                        else:
                            memo_fu.set_result(data["result"])
                        memo_lookup_table[data["hash"]] = memo_fu

                    except EOFError:
                        # Done with the checkpoint file
                        break
        except FileNotFoundError:
            reason = "Checkpoint file was not found: {}".format(checkpoint_file)
            logger.error(reason)
            raise BadCheckpoint(reason)
        except Exception as e:
            reason = "Failed to load Checkpoint: {}".format(checkpoint_file)
            logger.error(reason)
            raise BadCheckpoint(reason)

        logger.info(
            "Completed loading checkpoint:{0} with {1} tasks".format(
                checkpoint_file, len(memo_lookup_table.keys())
            )
        )
    return memo_lookup_table


# Traceback (AttributeError)
Traceback (most recent call last):
File "test_regression_233.py", line 38, in <module>
test_checkpoint_availability()
File "test_regression_233.py", line 27, in test_checkpoint_availability
original = run_checkpointed([])
File "test_regression_233.py", line 18, in run_checkpointed
x = cached_rand(i)
File "/home/yadu/src/parsl/parsl/app/app_factory.py", line 76, in __call__
return app_obj(*args, **kwargs)
File "/home/yadu/src/parsl/parsl/app/python_app.py", line 46, in __call__
**kwargs)
File "/home/yadu/src/parsl/parsl/dataflow/dflow.py", line 499, in submit
task_id, func, *new_args, **kwargs)
File "/home/yadu/src/parsl/parsl/dataflow/dflow.py", line 322, in launch_task
exec_fu.add_done_callback(partial(self.handle_update, task_id))
File "/usr/lib/python3.5/concurrent/futures/_base.py", line 376, in add_done_callback
fn(self)
File "/home/yadu/src/parsl/parsl/dataflow/dflow.py", line 218, in handle_update
self.checkpoint(tasks=[task_id])
File "/home/yadu/src/parsl/parsl/dataflow/dflow.py", line 617, in checkpoint
if self.tasks[task_id]['app_fu'].done() and \
AttributeError: 'NoneType' object has no attribute 'done'

# Fixed code
def _load_checkpoints(self, checkpointDirs):
    """Load a checkpoint file into a lookup table.

    The data being loaded from the pickle file mostly contains input
    attributes of the task: func, args, kwargs, env...
    To simplify the check of whether the exact task has been completed
    in the checkpoint, we hash these input params and use it as the key
    for the memoized lookup table.

    Args:
        - checkpointDirs (list) : List of filepaths to checkpoints
          Eg. ['runinfo/001', 'runinfo/002']

    Returns:
        - memoized_lookup_table (dict)
    """
    memo_lookup_table = {}

    for checkpoint_dir in checkpointDirs:
        logger.info("Loading checkpoints from {}".format(checkpoint_dir))
        checkpoint_file = os.path.join(checkpoint_dir, "tasks.pkl")
        try:
            with open(checkpoint_file, "rb") as f:
                while True:
                    try:
                        data = pickle.load(f)
                        # Copy and hash only the input attributes
                        memo_fu = Future()
                        if data["exception"]:
                            memo_fu.set_exception(data["exception"])
                        else:
                            memo_fu.set_result(data["result"])
                        memo_lookup_table[data["hash"]] = memo_fu

                    except EOFError:
                        # Done with the checkpoint file
                        break
        except FileNotFoundError:
            reason = "Checkpoint file was not found: {}".format(checkpoint_file)
            logger.error(reason)
            raise BadCheckpoint(reason)
        except Exception as e:
            reason = "Failed to load Checkpoint: {}".format(checkpoint_file)
            logger.error(reason)
            raise BadCheckpoint(reason)

        logger.info(
            "Completed loading checkpoint:{0} with {1} tasks".format(
                checkpoint_file, len(memo_lookup_table.keys())
            )
        )
    return memo_lookup_table