Repository: DataBiosphere/toil

Issue:
`ImportError: No module named boto.sdb.domain` when `aws` extra isn't installed
```
(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
```

Regression from 4a2bd735d361966b7252f29c104d8c3bf6d4e50d which is why I'm assigning it to you, CJ.

`ImportError: No module named boto.sdb.domain` when `aws` extra isn't installed
```
(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
```

Regression from 4a2bd735d361966b7252f29c104d8c3bf6d4e50d which is why I'm assigning it to you, CJ.



Discussion:
I would fix this like this:

``` diff
Index: src/toil/leader.py
===================================================================
--- src/toil/leader.py  (revision dbbd4ed282ab8503502ac2c1650c000b91b4a686)
+++ src/toil/leader.py  (revision )
@@ -29,7 +29,6 @@

 from toil import resolveEntryPoint
 from toil.jobStores.abstractJobStore import NoSuchJobException
-from toil.jobStores.aws.jobStore import AWSJobStore
 from toil.lib.bioio import getTotalCpuTime, logStream
 from toil.provisioners.clusterScaler import ClusterScaler

@@ -278,7 +277,8 @@
             try:
                 jobWrapper = self.jobStore.load(jobStoreID)
             except NoSuchJobException:
-                if isinstance(self.jobStore, AWSJobStore):
+                # 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.
```

I would fix this like this:

``` diff
Index: src/toil/leader.py
===================================================================
--- src/toil/leader.py  (revision dbbd4ed282ab8503502ac2c1650c000b91b4a686)
+++ src/toil/leader.py  (revision )
@@ -29,7 +29,6 @@

 from toil import resolveEntryPoint
 from toil.jobStores.abstractJobStore import NoSuchJobException
-from toil.jobStores.aws.jobStore import AWSJobStore
 from toil.lib.bioio import getTotalCpuTime, logStream
 from toil.provisioners.clusterScaler import ClusterScaler

@@ -278,7 +277,8 @@
             try:
                 jobWrapper = self.jobStore.load(jobStoreID)
             except NoSuchJobException:
-                if isinstance(self.jobStore, AWSJobStore):
+                # 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.
```


Resolving patch:
diff --git a/src/toil/leader.py b/src/toil/leader.py
--- a/src/toil/leader.py
+++ b/src/toil/leader.py
@@ -29,7 +29,6 @@
 
 from toil import resolveEntryPoint
 from toil.jobStores.abstractJobStore import NoSuchJobException
-from toil.jobStores.aws.jobStore import AWSJobStore
 from toil.lib.bioio import getTotalCpuTime, logStream
 from toil.provisioners.clusterScaler import ClusterScaler
 
@@ -278,7 +277,8 @@ def processRemovedJob(jobStoreID):
             try:
                 jobWrapper = self.jobStore.load(jobStoreID)
             except NoSuchJobException:
-                if isinstance(self.jobStore, AWSJobStore):
+                # 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.


Test patch: