Repository: Parsl/parsl

Issue:
Simple strategy is broken since PR #1519
**Describe the bug**
As of 6d66cab31bda9f0f7a3c0d081ce8cf658c10643a (PR #1519) the following exception has started being logged from the simple strategy, and I think probably simple strategy does not function properly.

```
2020-01-09 13:51:29.561 parsl.dataflow.flow_control:142 [ERROR]  Flow control callback threw an exception
- logging and proceeding anyway
Traceback (most recent call last):
  File "/home/benc/parsl/src/parsl/parsl/dataflow/flow_control.py", line 140, in make_callback
    self.callback(tasks=self._event_buffer, kind=kind)
  File "/home/benc/parsl/src/parsl/parsl/dataflow/strategy.py", line 192, in _strategy_simple
    running = sum([1 for x in status if x.state == JobState.RUNNING])
  File "/home/benc/parsl/src/parsl/parsl/dataflow/strategy.py", line 192, in <listcomp>
    running = sum([1 for x in status if x.state == JobState.RUNNING])
AttributeError: 'int' object has no attribute 'state'
```

It looks like this comes from changing the type of `executor.status()` in #1519 from a List of job statuses to a dict; and so now the keys of the dict are being iterated over rather than the job statuses in the simple strategy, because iteration over a dict happens over keys not values.



**To Reproduce**
```
$ git checkout 6d66cab31bda9f0f7a3c0d081ce8cf658c10643a
$ pytest parsl/ --config parsl/tests/configs/htex_local_alternate.py ; grep "Flow control callback threw" runinfo_*/000/parsl.log
```
**Expected behavior**
This exception should not be happening.

**Environment**
My laptop



Discussion:
This might be a better type signature that, rather than allowing Anything to be done with a key, instead means that almost nothing can be done with a key by code getting a dictionary from `status` - Although in `master`, the simple strategy is not typechecked statically, that change finds this bug in `benc-mypy` branch.

```
diff --git a/parsl/executors/base.py b/parsl/executors/base.py
index 309e3aa7b..cb459e059 100644
--- a/parsl/executors/base.py
+++ b/parsl/executors/base.py
@@ -123,7 +123,7 @@ class ParslExecutor(metaclass=ABCMeta):
         pass
 
     @abstractmethod
-    def status(self) -> Dict[Any, JobStatus]:
+    def status(self) -> Dict[object, JobStatus]:
         """Return the status of all jobs/blocks currently known to this executor.
```

I'll try to have a PR ready later today to fix this.

WRT Any vs. object, that was a bit of a misunderstanding on my part. You are indeed correct in that 'object' is what is needed here.

Resolving patch:
diff --git a/parsl/dataflow/strategy.py b/parsl/dataflow/strategy.py
--- a/parsl/dataflow/strategy.py
+++ b/parsl/dataflow/strategy.py
@@ -189,8 +189,8 @@ def _strategy_simple(self, tasks, *args, kind=None, **kwargs):
             nodes_per_block = executor.provider.nodes_per_block
             parallelism = executor.provider.parallelism
 
-            running = sum([1 for x in status if x.state == JobState.RUNNING])
-            pending = sum([1 for x in status if x.state == JobState.PENDING])
+            running = sum([1 for x in status.values() if x.state == JobState.RUNNING])
+            pending = sum([1 for x in status.values() if x.state == JobState.PENDING])
             active_blocks = running + pending
             active_slots = active_blocks * tasks_per_node * nodes_per_block
 


Test patch: