toil 6.1.0a1__py3-none-any.whl → 8.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (193) hide show
  1. toil/__init__.py +122 -315
  2. toil/batchSystems/__init__.py +1 -0
  3. toil/batchSystems/abstractBatchSystem.py +173 -89
  4. toil/batchSystems/abstractGridEngineBatchSystem.py +272 -148
  5. toil/batchSystems/awsBatch.py +244 -135
  6. toil/batchSystems/cleanup_support.py +26 -16
  7. toil/batchSystems/contained_executor.py +31 -28
  8. toil/batchSystems/gridengine.py +86 -50
  9. toil/batchSystems/htcondor.py +166 -89
  10. toil/batchSystems/kubernetes.py +632 -382
  11. toil/batchSystems/local_support.py +20 -15
  12. toil/batchSystems/lsf.py +134 -81
  13. toil/batchSystems/lsfHelper.py +13 -11
  14. toil/batchSystems/mesos/__init__.py +41 -29
  15. toil/batchSystems/mesos/batchSystem.py +290 -151
  16. toil/batchSystems/mesos/executor.py +79 -50
  17. toil/batchSystems/mesos/test/__init__.py +31 -23
  18. toil/batchSystems/options.py +46 -28
  19. toil/batchSystems/registry.py +53 -19
  20. toil/batchSystems/singleMachine.py +296 -125
  21. toil/batchSystems/slurm.py +603 -138
  22. toil/batchSystems/torque.py +47 -33
  23. toil/bus.py +186 -76
  24. toil/common.py +664 -368
  25. toil/cwl/__init__.py +1 -1
  26. toil/cwl/cwltoil.py +1136 -483
  27. toil/cwl/utils.py +17 -22
  28. toil/deferred.py +63 -42
  29. toil/exceptions.py +5 -3
  30. toil/fileStores/__init__.py +5 -5
  31. toil/fileStores/abstractFileStore.py +140 -60
  32. toil/fileStores/cachingFileStore.py +717 -269
  33. toil/fileStores/nonCachingFileStore.py +116 -87
  34. toil/job.py +1225 -368
  35. toil/jobStores/abstractJobStore.py +416 -266
  36. toil/jobStores/aws/jobStore.py +863 -477
  37. toil/jobStores/aws/utils.py +201 -120
  38. toil/jobStores/conftest.py +3 -2
  39. toil/jobStores/fileJobStore.py +292 -154
  40. toil/jobStores/googleJobStore.py +140 -74
  41. toil/jobStores/utils.py +36 -15
  42. toil/leader.py +668 -272
  43. toil/lib/accelerators.py +115 -18
  44. toil/lib/aws/__init__.py +74 -31
  45. toil/lib/aws/ami.py +122 -87
  46. toil/lib/aws/iam.py +284 -108
  47. toil/lib/aws/s3.py +31 -0
  48. toil/lib/aws/session.py +214 -39
  49. toil/lib/aws/utils.py +287 -231
  50. toil/lib/bioio.py +13 -5
  51. toil/lib/compatibility.py +11 -6
  52. toil/lib/conversions.py +104 -47
  53. toil/lib/docker.py +131 -103
  54. toil/lib/ec2.py +361 -199
  55. toil/lib/ec2nodes.py +174 -106
  56. toil/lib/encryption/_dummy.py +5 -3
  57. toil/lib/encryption/_nacl.py +10 -6
  58. toil/lib/encryption/conftest.py +1 -0
  59. toil/lib/exceptions.py +26 -7
  60. toil/lib/expando.py +5 -3
  61. toil/lib/ftp_utils.py +217 -0
  62. toil/lib/generatedEC2Lists.py +127 -19
  63. toil/lib/humanize.py +6 -2
  64. toil/lib/integration.py +341 -0
  65. toil/lib/io.py +141 -15
  66. toil/lib/iterables.py +4 -2
  67. toil/lib/memoize.py +12 -8
  68. toil/lib/misc.py +66 -21
  69. toil/lib/objects.py +2 -2
  70. toil/lib/resources.py +68 -15
  71. toil/lib/retry.py +126 -81
  72. toil/lib/threading.py +299 -82
  73. toil/lib/throttle.py +16 -15
  74. toil/options/common.py +843 -409
  75. toil/options/cwl.py +175 -90
  76. toil/options/runner.py +50 -0
  77. toil/options/wdl.py +73 -17
  78. toil/provisioners/__init__.py +117 -46
  79. toil/provisioners/abstractProvisioner.py +332 -157
  80. toil/provisioners/aws/__init__.py +70 -33
  81. toil/provisioners/aws/awsProvisioner.py +1145 -715
  82. toil/provisioners/clusterScaler.py +541 -279
  83. toil/provisioners/gceProvisioner.py +282 -179
  84. toil/provisioners/node.py +155 -79
  85. toil/realtimeLogger.py +34 -22
  86. toil/resource.py +137 -75
  87. toil/server/app.py +128 -62
  88. toil/server/celery_app.py +3 -1
  89. toil/server/cli/wes_cwl_runner.py +82 -53
  90. toil/server/utils.py +54 -28
  91. toil/server/wes/abstract_backend.py +64 -26
  92. toil/server/wes/amazon_wes_utils.py +21 -15
  93. toil/server/wes/tasks.py +121 -63
  94. toil/server/wes/toil_backend.py +142 -107
  95. toil/server/wsgi_app.py +4 -3
  96. toil/serviceManager.py +58 -22
  97. toil/statsAndLogging.py +224 -70
  98. toil/test/__init__.py +282 -183
  99. toil/test/batchSystems/batchSystemTest.py +460 -210
  100. toil/test/batchSystems/batch_system_plugin_test.py +90 -0
  101. toil/test/batchSystems/test_gridengine.py +173 -0
  102. toil/test/batchSystems/test_lsf_helper.py +67 -58
  103. toil/test/batchSystems/test_slurm.py +110 -49
  104. toil/test/cactus/__init__.py +0 -0
  105. toil/test/cactus/test_cactus_integration.py +56 -0
  106. toil/test/cwl/cwlTest.py +496 -287
  107. toil/test/cwl/measure_default_memory.cwl +12 -0
  108. toil/test/cwl/not_run_required_input.cwl +29 -0
  109. toil/test/cwl/scatter_duplicate_outputs.cwl +40 -0
  110. toil/test/cwl/seqtk_seq.cwl +1 -1
  111. toil/test/docs/scriptsTest.py +69 -46
  112. toil/test/jobStores/jobStoreTest.py +427 -264
  113. toil/test/lib/aws/test_iam.py +118 -50
  114. toil/test/lib/aws/test_s3.py +16 -9
  115. toil/test/lib/aws/test_utils.py +5 -6
  116. toil/test/lib/dockerTest.py +118 -141
  117. toil/test/lib/test_conversions.py +113 -115
  118. toil/test/lib/test_ec2.py +58 -50
  119. toil/test/lib/test_integration.py +104 -0
  120. toil/test/lib/test_misc.py +12 -5
  121. toil/test/mesos/MesosDataStructuresTest.py +23 -10
  122. toil/test/mesos/helloWorld.py +7 -6
  123. toil/test/mesos/stress.py +25 -20
  124. toil/test/options/__init__.py +13 -0
  125. toil/test/options/options.py +42 -0
  126. toil/test/provisioners/aws/awsProvisionerTest.py +320 -150
  127. toil/test/provisioners/clusterScalerTest.py +440 -250
  128. toil/test/provisioners/clusterTest.py +166 -44
  129. toil/test/provisioners/gceProvisionerTest.py +174 -100
  130. toil/test/provisioners/provisionerTest.py +25 -13
  131. toil/test/provisioners/restartScript.py +5 -4
  132. toil/test/server/serverTest.py +188 -141
  133. toil/test/sort/restart_sort.py +137 -68
  134. toil/test/sort/sort.py +134 -66
  135. toil/test/sort/sortTest.py +91 -49
  136. toil/test/src/autoDeploymentTest.py +141 -101
  137. toil/test/src/busTest.py +20 -18
  138. toil/test/src/checkpointTest.py +8 -2
  139. toil/test/src/deferredFunctionTest.py +49 -35
  140. toil/test/src/dockerCheckTest.py +32 -24
  141. toil/test/src/environmentTest.py +135 -0
  142. toil/test/src/fileStoreTest.py +539 -272
  143. toil/test/src/helloWorldTest.py +7 -4
  144. toil/test/src/importExportFileTest.py +61 -31
  145. toil/test/src/jobDescriptionTest.py +46 -21
  146. toil/test/src/jobEncapsulationTest.py +2 -0
  147. toil/test/src/jobFileStoreTest.py +74 -50
  148. toil/test/src/jobServiceTest.py +187 -73
  149. toil/test/src/jobTest.py +121 -71
  150. toil/test/src/miscTests.py +19 -18
  151. toil/test/src/promisedRequirementTest.py +82 -36
  152. toil/test/src/promisesTest.py +7 -6
  153. toil/test/src/realtimeLoggerTest.py +10 -6
  154. toil/test/src/regularLogTest.py +71 -37
  155. toil/test/src/resourceTest.py +80 -49
  156. toil/test/src/restartDAGTest.py +36 -22
  157. toil/test/src/resumabilityTest.py +9 -2
  158. toil/test/src/retainTempDirTest.py +45 -14
  159. toil/test/src/systemTest.py +12 -8
  160. toil/test/src/threadingTest.py +44 -25
  161. toil/test/src/toilContextManagerTest.py +10 -7
  162. toil/test/src/userDefinedJobArgTypeTest.py +8 -5
  163. toil/test/src/workerTest.py +73 -23
  164. toil/test/utils/toilDebugTest.py +103 -33
  165. toil/test/utils/toilKillTest.py +4 -5
  166. toil/test/utils/utilsTest.py +245 -106
  167. toil/test/wdl/wdltoil_test.py +818 -149
  168. toil/test/wdl/wdltoil_test_kubernetes.py +91 -0
  169. toil/toilState.py +120 -35
  170. toil/utils/toilConfig.py +13 -4
  171. toil/utils/toilDebugFile.py +44 -27
  172. toil/utils/toilDebugJob.py +214 -27
  173. toil/utils/toilDestroyCluster.py +11 -6
  174. toil/utils/toilKill.py +8 -3
  175. toil/utils/toilLaunchCluster.py +256 -140
  176. toil/utils/toilMain.py +37 -16
  177. toil/utils/toilRsyncCluster.py +32 -14
  178. toil/utils/toilSshCluster.py +49 -22
  179. toil/utils/toilStats.py +356 -273
  180. toil/utils/toilStatus.py +292 -139
  181. toil/utils/toilUpdateEC2Instances.py +3 -1
  182. toil/version.py +12 -12
  183. toil/wdl/utils.py +5 -5
  184. toil/wdl/wdltoil.py +3913 -1033
  185. toil/worker.py +367 -184
  186. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/LICENSE +25 -0
  187. toil-8.0.0.dist-info/METADATA +173 -0
  188. toil-8.0.0.dist-info/RECORD +253 -0
  189. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/WHEEL +1 -1
  190. toil-6.1.0a1.dist-info/METADATA +0 -125
  191. toil-6.1.0a1.dist-info/RECORD +0 -237
  192. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/entry_points.txt +0 -0
  193. {toil-6.1.0a1.dist-info → toil-8.0.0.dist-info}/top_level.txt +0 -0
@@ -13,9 +13,7 @@
13
13
  # limitations under the License.
14
14
  import logging
15
15
 
16
- from toil.lib.conversions import (convert_units,
17
- hms_duration_to_seconds,
18
- human2bytes)
16
+ from toil.lib.conversions import convert_units, hms_duration_to_seconds, human2bytes
19
17
  from toil.test import ToilTest
20
18
 
21
19
  logger = logging.getLogger(__name__)
@@ -79,135 +77,135 @@ class ConversionTest(ToilTest):
79
77
  "11234234 KB": "0.0112 TB",
80
78
  "11234234 MB": "11.2342 TB",
81
79
  "11234234 GB": "11234.2340 TB",
82
- "11234234 TB": "11234234.0000 TB"
80
+ "11234234 TB": "11234234.0000 TB",
83
81
  }
84
82
  results = {}
85
83
  for i in (0, 0.1, 0.5, 0.9, 1, 7, 7.42423, 10, 100, 1000, 11234234):
86
- for src_unit in ['B', 'KB', 'MB', 'GB', 'TB']:
87
- for dst_unit in ['B', 'KB', 'MB', 'GB', 'TB']:
84
+ for src_unit in ["B", "KB", "MB", "GB", "TB"]:
85
+ for dst_unit in ["B", "KB", "MB", "GB", "TB"]:
88
86
  converted = convert_units(i, src_unit, dst_unit)
89
- results[f'{i} {src_unit}'] = f'{converted:.4f} {dst_unit}'
87
+ results[f"{i} {src_unit}"] = f"{converted:.4f} {dst_unit}"
90
88
  self.assertEqual(results, expected_conversions)
91
89
 
92
90
  def test_human2bytes(self):
93
91
  expected_results = {
94
- '0 b': 0,
95
- '0 Ki': 0,
96
- '0 Mi': 0,
97
- '0 Gi': 0,
98
- '0 Ti': 0,
99
- '0 K': 0,
100
- '0 M': 0,
101
- '0 G': 0,
102
- '0 T': 0,
103
- '0.1 b': 0,
104
- '0.1 Ki': 102,
105
- '0.1 Mi': 104857,
106
- '0.1 Gi': 107374182,
107
- '0.1 Ti': 109951162777,
108
- '0.1 K': 100,
109
- '0.1 M': 100000,
110
- '0.1 G': 100000000,
111
- '0.1 T': 100000000000,
112
- '0.5 b': 0,
113
- '0.5 Ki': 512,
114
- '0.5 Mi': 524288,
115
- '0.5 Gi': 536870912,
116
- '0.5 Ti': 549755813888,
117
- '0.5 K': 500,
118
- '0.5 M': 500000,
119
- '0.5 G': 500000000,
120
- '0.5 T': 500000000000,
121
- '0.9 b': 0,
122
- '0.9 Ki': 921,
123
- '0.9 Mi': 943718,
124
- '0.9 Gi': 966367641,
125
- '0.9 Ti': 989560464998,
126
- '0.9 K': 900,
127
- '0.9 M': 900000,
128
- '0.9 G': 900000000,
129
- '0.9 T': 900000000000,
130
- '1 b': 1,
131
- '1 Ki': 1024,
132
- '1 Mi': 1048576,
133
- '1 Gi': 1073741824,
134
- '1 Ti': 1099511627776,
135
- '1 K': 1000,
136
- '1 M': 1000000,
137
- '1 G': 1000000000,
138
- '1 T': 1000000000000,
139
- '7 b': 7,
140
- '7 Ki': 7168,
141
- '7 Mi': 7340032,
142
- '7 Gi': 7516192768,
143
- '7 Ti': 7696581394432,
144
- '7 K': 7000,
145
- '7 M': 7000000,
146
- '7 G': 7000000000,
147
- '7 T': 7000000000000,
148
- '7.42423 b': 7,
149
- '7.42423 Ki': 7602,
150
- '7.42423 Mi': 7784869,
151
- '7.42423 Gi': 7971706261,
152
- '7.42423 Ti': 8163027212283,
153
- '7.42423 K': 7424,
154
- '7.42423 M': 7424230,
155
- '7.42423 G': 7424230000,
156
- '7.42423 T': 7424230000000,
157
- '10 b': 10,
158
- '10 Ki': 10240,
159
- '10 Mi': 10485760,
160
- '10 Gi': 10737418240,
161
- '10 Ti': 10995116277760,
162
- '10 K': 10000,
163
- '10 M': 10000000,
164
- '10 G': 10000000000,
165
- '10 T': 10000000000000,
166
- '100 b': 100,
167
- '100 Ki': 102400,
168
- '100 Mi': 104857600,
169
- '100 Gi': 107374182400,
170
- '100 Ti': 109951162777600,
171
- '100 K': 100000,
172
- '100 M': 100000000,
173
- '100 G': 100000000000,
174
- '100 T': 100000000000000,
175
- '1000 b': 1000,
176
- '1000 Ki': 1024000,
177
- '1000 Mi': 1048576000,
178
- '1000 Gi': 1073741824000,
179
- '1000 Ti': 1099511627776000,
180
- '1000 K': 1000000,
181
- '1000 M': 1000000000,
182
- '1000 G': 1000000000000,
183
- '1000 T': 1000000000000000,
184
- '11234234 b': 11234234,
185
- '11234234 Ki': 11503855616,
186
- '11234234 Mi': 11779948150784,
187
- '11234234 Gi': 12062666906402816,
188
- '11234234 Ti': 12352170912156483584,
189
- '11234234 K': 11234234000,
190
- '11234234 M': 11234234000000,
191
- '11234234 G': 11234234000000000,
192
- '11234234 T': 11234234000000000000
92
+ "0 b": 0,
93
+ "0 Ki": 0,
94
+ "0 Mi": 0,
95
+ "0 Gi": 0,
96
+ "0 Ti": 0,
97
+ "0 K": 0,
98
+ "0 M": 0,
99
+ "0 G": 0,
100
+ "0 T": 0,
101
+ "0.1 b": 0,
102
+ "0.1 Ki": 102,
103
+ "0.1 Mi": 104857,
104
+ "0.1 Gi": 107374182,
105
+ "0.1 Ti": 109951162777,
106
+ "0.1 K": 100,
107
+ "0.1 M": 100000,
108
+ "0.1 G": 100000000,
109
+ "0.1 T": 100000000000,
110
+ "0.5 b": 0,
111
+ "0.5 Ki": 512,
112
+ "0.5 Mi": 524288,
113
+ "0.5 Gi": 536870912,
114
+ "0.5 Ti": 549755813888,
115
+ "0.5 K": 500,
116
+ "0.5 M": 500000,
117
+ "0.5 G": 500000000,
118
+ "0.5 T": 500000000000,
119
+ "0.9 b": 0,
120
+ "0.9 Ki": 921,
121
+ "0.9 Mi": 943718,
122
+ "0.9 Gi": 966367641,
123
+ "0.9 Ti": 989560464998,
124
+ "0.9 K": 900,
125
+ "0.9 M": 900000,
126
+ "0.9 G": 900000000,
127
+ "0.9 T": 900000000000,
128
+ "1 b": 1,
129
+ "1 Ki": 1024,
130
+ "1 Mi": 1048576,
131
+ "1 Gi": 1073741824,
132
+ "1 Ti": 1099511627776,
133
+ "1 K": 1000,
134
+ "1 M": 1000000,
135
+ "1 G": 1000000000,
136
+ "1 T": 1000000000000,
137
+ "7 b": 7,
138
+ "7 Ki": 7168,
139
+ "7 Mi": 7340032,
140
+ "7 Gi": 7516192768,
141
+ "7 Ti": 7696581394432,
142
+ "7 K": 7000,
143
+ "7 M": 7000000,
144
+ "7 G": 7000000000,
145
+ "7 T": 7000000000000,
146
+ "7.42423 b": 7,
147
+ "7.42423 Ki": 7602,
148
+ "7.42423 Mi": 7784869,
149
+ "7.42423 Gi": 7971706261,
150
+ "7.42423 Ti": 8163027212283,
151
+ "7.42423 K": 7424,
152
+ "7.42423 M": 7424230,
153
+ "7.42423 G": 7424230000,
154
+ "7.42423 T": 7424230000000,
155
+ "10 b": 10,
156
+ "10 Ki": 10240,
157
+ "10 Mi": 10485760,
158
+ "10 Gi": 10737418240,
159
+ "10 Ti": 10995116277760,
160
+ "10 K": 10000,
161
+ "10 M": 10000000,
162
+ "10 G": 10000000000,
163
+ "10 T": 10000000000000,
164
+ "100 b": 100,
165
+ "100 Ki": 102400,
166
+ "100 Mi": 104857600,
167
+ "100 Gi": 107374182400,
168
+ "100 Ti": 109951162777600,
169
+ "100 K": 100000,
170
+ "100 M": 100000000,
171
+ "100 G": 100000000000,
172
+ "100 T": 100000000000000,
173
+ "1000 b": 1000,
174
+ "1000 Ki": 1024000,
175
+ "1000 Mi": 1048576000,
176
+ "1000 Gi": 1073741824000,
177
+ "1000 Ti": 1099511627776000,
178
+ "1000 K": 1000000,
179
+ "1000 M": 1000000000,
180
+ "1000 G": 1000000000000,
181
+ "1000 T": 1000000000000000,
182
+ "11234234 b": 11234234,
183
+ "11234234 Ki": 11503855616,
184
+ "11234234 Mi": 11779948150784,
185
+ "11234234 Gi": 12062666906402816,
186
+ "11234234 Ti": 12352170912156483584,
187
+ "11234234 K": 11234234000,
188
+ "11234234 M": 11234234000000,
189
+ "11234234 G": 11234234000000000,
190
+ "11234234 T": 11234234000000000000,
193
191
  }
194
192
 
195
193
  results = {}
196
194
  for i in (0, 0.1, 0.5, 0.9, 1, 7, 7.42423, 10, 100, 1000, 11234234):
197
- for src_unit in ['b', 'Ki', 'Mi', 'Gi', 'Ti', 'K', 'M', 'G', 'T']:
198
- results[f'{i} {src_unit}'] = human2bytes(f'{i} {src_unit}')
195
+ for src_unit in ["b", "Ki", "Mi", "Gi", "Ti", "K", "M", "G", "T"]:
196
+ results[f"{i} {src_unit}"] = human2bytes(f"{i} {src_unit}")
199
197
  self.assertEqual(results, expected_results)
200
198
 
201
199
  def test_hms_duration_to_seconds(self):
202
200
  expected_results = {
203
- '0:0:0' : 0.0,
204
- '00:00:00' : 0.0,
205
- '1:1:1' : 3661.0,
206
- '20:14:33' : 72873.0,
207
- '72:80:112' : 264112.0,
201
+ "0:0:0": 0.0,
202
+ "00:00:00": 0.0,
203
+ "1:1:1": 3661.0,
204
+ "20:14:33": 72873.0,
205
+ "72:80:112": 264112.0,
208
206
  }
209
207
  results = {}
210
208
  for key in expected_results.keys():
211
- results[key] = hms_duration_to_seconds(f'{key}')
212
-
209
+ results[key] = hms_duration_to_seconds(f"{key}")
210
+
213
211
  self.assertEqual(results, expected_results)
toil/test/lib/test_ec2.py CHANGED
@@ -14,18 +14,21 @@
14
14
  import logging
15
15
  import os
16
16
 
17
- import pytest
17
+ from unittest import mock
18
18
 
19
- from toil.lib.aws.ami import (aws_marketplace_flatcar_ami_search,
20
- feed_flatcar_ami_release,
21
- flatcar_release_feed_amis,
22
- get_flatcar_ami)
23
- from toil.lib.aws.session import establish_boto3_session
19
+ from toil.lib.aws.ami import (
20
+ aws_marketplace_flatcar_ami_search,
21
+ feed_flatcar_ami_release,
22
+ flatcar_release_feed_ami,
23
+ get_flatcar_ami,
24
+ ReleaseFeedUnavailableError
25
+ )
24
26
  from toil.test import ToilTest, needs_aws_ec2, needs_online
25
27
 
26
28
  logger = logging.getLogger(__name__)
27
29
  logging.basicConfig(level=logging.DEBUG)
28
30
 
31
+
29
32
  @needs_online
30
33
  class FlatcarFeedTest(ToilTest):
31
34
  """Test accessing the Flatcar AMI release feed, independent of the AWS API"""
@@ -36,61 +39,66 @@ class FlatcarFeedTest(ToilTest):
36
39
 
37
40
  def test_parse_archive_feed(self):
38
41
  """Make sure we can get a Flatcar release from the Internet Archive."""
39
- amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'archive'))
40
- for ami in amis:
41
- self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
42
- self.assertTrue(ami.startswith('ami-'))
43
-
42
+ ami = flatcar_release_feed_ami("us-west-2", "amd64", "archive")
43
+ self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
44
+ self.assertTrue(ami.startswith("ami-"))
45
+
44
46
  def test_parse_beta_feed(self):
45
47
  """Make sure we can get a Flatcar release from the beta channel."""
46
- amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'beta'))
47
- for ami in amis:
48
- self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
49
- self.assertTrue(ami.startswith('ami-'))
50
-
48
+ ami = flatcar_release_feed_ami("us-west-2", "amd64", "beta")
49
+ self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
50
+ self.assertTrue(ami.startswith("ami-"))
51
+
51
52
  def test_parse_stable_feed(self):
52
53
  """Make sure we can get a Flatcar release from the stable channel."""
53
- amis = list(flatcar_release_feed_amis('us-west-2', 'amd64', 'stable'))
54
- for ami in amis:
55
- self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
56
- self.assertTrue(ami.startswith('ami-'))
57
-
54
+ ami = flatcar_release_feed_ami("us-west-2", "amd64", "stable")
55
+ self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
56
+ self.assertTrue(ami.startswith("ami-"))
57
+
58
+
58
59
  @needs_aws_ec2
59
60
  class AMITest(ToilTest):
60
61
  @classmethod
61
62
  def setUpClass(cls):
62
- session = establish_boto3_session(region_name='us-west-2')
63
- cls.ec2_client = session.client('ec2')
63
+ from toil.lib.aws.session import establish_boto3_session
64
+
65
+ session = establish_boto3_session(region_name="us-west-2")
66
+ cls.ec2_client = session.client("ec2")
64
67
 
65
68
  def test_fetch_flatcar(self):
66
- with self.subTest('Test flatcar AMI from user is prioritized.'):
67
- os.environ['TOIL_AWS_AMI'] = 'overridden'
68
- ami = get_flatcar_ami(self.ec2_client)
69
- self.assertEqual(ami, 'overridden')
70
- del os.environ['TOIL_AWS_AMI']
71
-
72
- with self.subTest('Test flatcar AMI returns an AMI-looking AMI.'):
73
- ami = get_flatcar_ami(self.ec2_client)
74
- self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
75
- self.assertTrue(ami.startswith('ami-'))
76
-
77
- with self.subTest('Test feed_flatcar_ami_release() returns an AMI-looking AMI.'):
78
- ami = feed_flatcar_ami_release(self.ec2_client, source='archive')
79
- self.assertTrue(ami is None or len(ami) == len('ami-02b46c73fed689d1c'))
80
- self.assertTrue(ami is None or ami.startswith('ami-'))
81
-
82
- with self.subTest('Test aws_marketplace_flatcar_ami_search() returns an AMI-looking AMI.'):
69
+ with self.subTest("Test flatcar AMI from user is prioritized."):
70
+ with mock.patch.dict(os.environ, {"TOIL_AWS_AMI": "overridden"}):
71
+ ami = get_flatcar_ami(self.ec2_client)
72
+ self.assertEqual(ami, "overridden")
73
+
74
+ with self.subTest("Test flatcar AMI returns an AMI-looking AMI."):
75
+ try:
76
+ ami = get_flatcar_ami(self.ec2_client)
77
+ self.assertEqual(len(ami), len("ami-02b46c73fed689d1c"))
78
+ self.assertTrue(ami.startswith("ami-"))
79
+ except ReleaseFeedUnavailableError:
80
+ # Ignore any remote systems being down.
81
+ pass
82
+
83
+ with self.subTest(
84
+ "Test feed_flatcar_ami_release() returns an AMI-looking AMI."
85
+ ):
86
+ ami = feed_flatcar_ami_release(self.ec2_client, source="archive")
87
+ self.assertTrue(ami is None or len(ami) == len("ami-02b46c73fed689d1c"))
88
+ self.assertTrue(ami is None or ami.startswith("ami-"))
89
+
90
+ with self.subTest(
91
+ "Test aws_marketplace_flatcar_ami_search() returns an AMI-looking AMI."
92
+ ):
83
93
  ami = aws_marketplace_flatcar_ami_search(self.ec2_client)
84
- self.assertEqual(len(ami), len('ami-02b46c73fed689d1c'))
85
- self.assertTrue(ami.startswith('ami-'))
94
+ self.assertTrue(ami is None or len(ami), len("ami-02b46c73fed689d1c"))
95
+ self.assertTrue(ami is None or ami.startswith("ami-"))
86
96
 
87
- # TODO: This will fail until https://github.com/flatcar/Flatcar/issues/962 is fixed
88
- @pytest.mark.xfail
89
97
  def test_fetch_arm_flatcar(self):
90
98
  """Test flatcar AMI finder architecture parameter."""
91
- amis = set()
92
- for arch in ['amd64', 'arm64']:
93
- ami = get_flatcar_ami(self.ec2_client, architecture=arch)
94
- self.assertTrue(ami.startswith('ami-'))
95
- amis.add(ami)
96
- self.assertTrue(len(amis) == 2)
99
+ try:
100
+ ami = get_flatcar_ami(self.ec2_client, architecture="arm64")
101
+ self.assertTrue(ami.startswith("ami-"))
102
+ except ReleaseFeedUnavailableError:
103
+ # Ignore any remote systems being down.
104
+ pass
@@ -0,0 +1,104 @@
1
+ # Copyright (C) 2015-2024 Regents of the University of California
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ import io
16
+ import logging
17
+ import pytest
18
+ from typing import IO
19
+ import urllib.request
20
+ from urllib.error import URLError
21
+
22
+ from toil.lib.retry import retry
23
+ from toil.lib.integration import get_workflow_root_from_dockstore
24
+ from toil.test import ToilTest, needs_online
25
+
26
+ logger = logging.getLogger(__name__)
27
+ logging.basicConfig(level=logging.DEBUG)
28
+
29
+ @pytest.mark.integrative
30
+ @needs_online
31
+ class DockstoreLookupTest(ToilTest):
32
+ """
33
+ Make sure we can look up workflows on Dockstore.
34
+ """
35
+
36
+ @retry(errors=[URLError, RuntimeError])
37
+ def read_result(self, url_or_path: str) -> IO[bytes]:
38
+ """
39
+ Read a file or URL.
40
+
41
+ Binary mode to allow testing for binary file support.
42
+
43
+ This lets us test that we have the right workflow contents and not care
44
+ how we are being shown them.
45
+ """
46
+ if url_or_path.startswith("http://") or url_or_path.startswith("https://"):
47
+ response = urllib.request.urlopen(url_or_path)
48
+ if response.status != 200:
49
+ raise RuntimeError(f"HTTP error response: {response}")
50
+ return response
51
+ else:
52
+ return open(url_or_path, "rb")
53
+
54
+ # TODO: Tests that definitely test a clear cache
55
+
56
+ def test_lookup_from_page_url(self) -> None:
57
+ PAGE_URL = "https://dockstore.org/workflows/github.com/dockstore/bcc2020-training/HelloWorld:master?tab=info"
58
+ # If we go in through the website we get an extra refs/heads/ on the branch name.
59
+ WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore/bcc2020-training/master/wdl-training/exercise1/HelloWorld.wdl"
60
+ looked_up = get_workflow_root_from_dockstore(PAGE_URL)
61
+
62
+ data_from_lookup = self.read_result(looked_up).read()
63
+ data_from_source = self.read_result(WORKFLOW_URL).read()
64
+ self.assertEqual(data_from_lookup, data_from_source)
65
+
66
+ def test_lookup_from_trs(self) -> None:
67
+ TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
68
+ # Despite "-checker" in the ID, this actually refers to the base md5sum
69
+ # workflow that just happens to have a checker *available*, not to the
70
+ # checker workflow itself.
71
+ WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
72
+ looked_up = get_workflow_root_from_dockstore(TRS_ID)
73
+
74
+ data_from_lookup = self.read_result(looked_up).read()
75
+ data_from_source = self.read_result(WORKFLOW_URL).read()
76
+ self.assertEqual(data_from_lookup, data_from_source)
77
+
78
+ def test_lookup_from_trs_cached(self) -> None:
79
+ TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker"
80
+ WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/master/md5sum/md5sum-workflow.cwl"
81
+ # This lookup may or may not be cached
82
+ get_workflow_root_from_dockstore(TRS_ID)
83
+ # This lookup is definitely cached
84
+ looked_up = get_workflow_root_from_dockstore(TRS_ID)
85
+
86
+ data_from_lookup = self.read_result(looked_up).read()
87
+ data_from_source = self.read_result(WORKFLOW_URL).read()
88
+ self.assertEqual(data_from_lookup, data_from_source)
89
+
90
+ def test_lookup_from_trs_with_version(self) -> None:
91
+ TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:workflowWithHTTPImport"
92
+ WORKFLOW_URL = "https://raw.githubusercontent.com/dockstore-testing/md5sum-checker/workflowWithHTTPImport/md5sum/md5sum-workflow.cwl"
93
+ looked_up = get_workflow_root_from_dockstore(TRS_ID)
94
+
95
+ data_from_lookup = self.read_result(looked_up).read()
96
+ data_from_source = self.read_result(WORKFLOW_URL).read()
97
+ self.assertEqual(data_from_lookup, data_from_source)
98
+
99
+ def test_lookup_from_trs_nonexistent_version(self) -> None:
100
+ TRS_ID = "#workflow/github.com/dockstore-testing/md5sum-checker:notARealVersion"
101
+ with self.assertRaises(RuntimeError):
102
+ looked_up = get_workflow_root_from_dockstore(TRS_ID)
103
+
104
+
@@ -32,6 +32,7 @@ class UserNameAvailableTest(ToilTest):
32
32
  apparent_user_name = get_user_name()
33
33
  self.assertEqual(apparent_user_name, real_user_name)
34
34
 
35
+
35
36
  class UserNameUnvailableTest(ToilTest):
36
37
  """
37
38
  Make sure we can get something for a user name when user names are not
@@ -42,9 +43,12 @@ class UserNameUnvailableTest(ToilTest):
42
43
  super().setUp()
43
44
  # Monkey patch getpass.getuser to fail
44
45
  self.original_getuser = getpass.getuser
46
+
45
47
  def fake_getuser():
46
- raise KeyError('Fake key error')
48
+ raise KeyError("Fake key error")
49
+
47
50
  getpass.getuser = fake_getuser
51
+
48
52
  def tearDown(self):
49
53
  # Fix the module we hacked up
50
54
  getpass.getuser = self.original_getuser
@@ -54,7 +58,8 @@ class UserNameUnvailableTest(ToilTest):
54
58
  apparent_user_name = get_user_name()
55
59
  # Make sure we got something
56
60
  self.assertTrue(isinstance(apparent_user_name, str))
57
- self.assertNotEqual(apparent_user_name, '')
61
+ self.assertNotEqual(apparent_user_name, "")
62
+
58
63
 
59
64
  class UserNameVeryBrokenTest(ToilTest):
60
65
  """
@@ -66,9 +71,12 @@ class UserNameVeryBrokenTest(ToilTest):
66
71
  super().setUp()
67
72
  # Monkey patch getpass.getuser to fail
68
73
  self.original_getuser = getpass.getuser
74
+
69
75
  def fake_getuser():
70
- raise RuntimeError('Fake error that we did not anticipate')
76
+ raise RuntimeError("Fake error that we did not anticipate")
77
+
71
78
  getpass.getuser = fake_getuser
79
+
72
80
  def tearDown(self):
73
81
  # Fix the module we hacked up
74
82
  getpass.getuser = self.original_getuser
@@ -78,5 +86,4 @@ class UserNameVeryBrokenTest(ToilTest):
78
86
  apparent_user_name = get_user_name()
79
87
  # Make sure we got something
80
88
  self.assertTrue(isinstance(apparent_user_name, str))
81
- self.assertNotEqual(apparent_user_name, '')
82
-
89
+ self.assertNotEqual(apparent_user_name, "")
@@ -21,15 +21,19 @@ class DataStructuresTest(ToilTest):
21
21
  def _getJob(self, cores=1, memory=1000, disk=5000, preemptible=True):
22
22
  from toil.batchSystems.mesos import MesosShape, ToilJob
23
23
 
24
- resources = MesosShape(wallTime=0, cores=cores, memory=memory, disk=disk, preemptible=preemptible)
24
+ resources = MesosShape(
25
+ wallTime=0, cores=cores, memory=memory, disk=disk, preemptible=preemptible
26
+ )
25
27
 
26
- job = ToilJob(jobID=str(uuid.uuid4()),
27
- name=str(uuid.uuid4()),
28
- resources=resources,
29
- command="do nothing",
30
- userScript=None,
31
- environment=None,
32
- workerCleanupInfo=None)
28
+ job = ToilJob(
29
+ jobID=str(uuid.uuid4()),
30
+ name=str(uuid.uuid4()),
31
+ resources=resources,
32
+ command="do nothing",
33
+ userScript=None,
34
+ environment=None,
35
+ workerCleanupInfo=None,
36
+ )
33
37
  return job
34
38
 
35
39
  def testJobQueue(self, testJobs=1000):
@@ -39,15 +43,24 @@ class DataStructuresTest(ToilTest):
39
43
  non-preemptible jobs groups first, with priority given to large jobs.
40
44
  """
41
45
  from toil.batchSystems.mesos import JobQueue
46
+
42
47
  jobQueue = JobQueue()
43
48
 
44
49
  for jobNum in range(0, testJobs):
45
- testJob = self._getJob(cores=random.choice(list(range(10))), preemptible=random.choice([True, False]))
50
+ testJob = self._getJob(
51
+ cores=random.choice(list(range(10))),
52
+ preemptible=random.choice([True, False]),
53
+ )
46
54
  jobQueue.insertJob(testJob, testJob.resources)
47
55
 
48
56
  sortedTypes = jobQueue.sortedTypes
49
57
  self.assertGreaterEqual(20, len(sortedTypes))
50
- self.assertTrue(all(sortedTypes[i] <= sortedTypes[i + 1] for i in range(len(sortedTypes) - 1)))
58
+ self.assertTrue(
59
+ all(
60
+ sortedTypes[i] <= sortedTypes[i + 1]
61
+ for i in range(len(sortedTypes) - 1)
62
+ )
63
+ )
51
64
 
52
65
  preemptible = sortedTypes.pop(0).preemptible
53
66
  for jtype in sortedTypes: