idmtools 0.0.0.dev0__py3-none-any.whl → 0.0.2__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 (118) hide show
  1. idmtools/__init__.py +27 -8
  2. idmtools/analysis/__init__.py +5 -0
  3. idmtools/analysis/add_analyzer.py +89 -0
  4. idmtools/analysis/analyze_manager.py +490 -0
  5. idmtools/analysis/csv_analyzer.py +103 -0
  6. idmtools/analysis/download_analyzer.py +96 -0
  7. idmtools/analysis/map_worker_entry.py +100 -0
  8. idmtools/analysis/platform_analysis_bootstrap.py +94 -0
  9. idmtools/analysis/platform_anaylsis.py +291 -0
  10. idmtools/analysis/tags_analyzer.py +93 -0
  11. idmtools/assets/__init__.py +9 -0
  12. idmtools/assets/asset.py +453 -0
  13. idmtools/assets/asset_collection.py +514 -0
  14. idmtools/assets/content_handlers.py +19 -0
  15. idmtools/assets/errors.py +23 -0
  16. idmtools/assets/file_list.py +191 -0
  17. idmtools/builders/__init__.py +11 -0
  18. idmtools/builders/arm_simulation_builder.py +152 -0
  19. idmtools/builders/csv_simulation_builder.py +76 -0
  20. idmtools/builders/simulation_builder.py +348 -0
  21. idmtools/builders/sweep_arm.py +109 -0
  22. idmtools/builders/yaml_simulation_builder.py +82 -0
  23. idmtools/config/__init__.py +7 -0
  24. idmtools/config/idm_config_parser.py +486 -0
  25. idmtools/core/__init__.py +10 -0
  26. idmtools/core/cache_enabled.py +114 -0
  27. idmtools/core/context.py +68 -0
  28. idmtools/core/docker_task.py +207 -0
  29. idmtools/core/enums.py +51 -0
  30. idmtools/core/exceptions.py +91 -0
  31. idmtools/core/experiment_factory.py +71 -0
  32. idmtools/core/id_file.py +70 -0
  33. idmtools/core/interfaces/__init__.py +5 -0
  34. idmtools/core/interfaces/entity_container.py +64 -0
  35. idmtools/core/interfaces/iassets_enabled.py +58 -0
  36. idmtools/core/interfaces/ientity.py +331 -0
  37. idmtools/core/interfaces/iitem.py +206 -0
  38. idmtools/core/interfaces/imetadata_operations.py +89 -0
  39. idmtools/core/interfaces/inamed_entity.py +17 -0
  40. idmtools/core/interfaces/irunnable_entity.py +159 -0
  41. idmtools/core/logging.py +387 -0
  42. idmtools/core/platform_factory.py +316 -0
  43. idmtools/core/system_information.py +104 -0
  44. idmtools/core/task_factory.py +145 -0
  45. idmtools/entities/__init__.py +10 -0
  46. idmtools/entities/command_line.py +229 -0
  47. idmtools/entities/command_task.py +155 -0
  48. idmtools/entities/experiment.py +787 -0
  49. idmtools/entities/generic_workitem.py +43 -0
  50. idmtools/entities/ianalyzer.py +163 -0
  51. idmtools/entities/iplatform.py +1106 -0
  52. idmtools/entities/iplatform_default.py +39 -0
  53. idmtools/entities/iplatform_ops/__init__.py +5 -0
  54. idmtools/entities/iplatform_ops/iplatform_asset_collection_operations.py +148 -0
  55. idmtools/entities/iplatform_ops/iplatform_experiment_operations.py +415 -0
  56. idmtools/entities/iplatform_ops/iplatform_simulation_operations.py +315 -0
  57. idmtools/entities/iplatform_ops/iplatform_suite_operations.py +322 -0
  58. idmtools/entities/iplatform_ops/iplatform_workflowitem_operations.py +301 -0
  59. idmtools/entities/iplatform_ops/utils.py +185 -0
  60. idmtools/entities/itask.py +316 -0
  61. idmtools/entities/iworkflow_item.py +167 -0
  62. idmtools/entities/platform_requirements.py +20 -0
  63. idmtools/entities/relation_type.py +14 -0
  64. idmtools/entities/simulation.py +255 -0
  65. idmtools/entities/suite.py +188 -0
  66. idmtools/entities/task_proxy.py +37 -0
  67. idmtools/entities/templated_simulation.py +325 -0
  68. idmtools/frozen/frozen_dict.py +71 -0
  69. idmtools/frozen/frozen_list.py +66 -0
  70. idmtools/frozen/frozen_set.py +86 -0
  71. idmtools/frozen/frozen_tuple.py +18 -0
  72. idmtools/frozen/frozen_utils.py +179 -0
  73. idmtools/frozen/ifrozen.py +66 -0
  74. idmtools/plugins/__init__.py +5 -0
  75. idmtools/plugins/git_commit.py +117 -0
  76. idmtools/registry/__init__.py +4 -0
  77. idmtools/registry/experiment_specification.py +105 -0
  78. idmtools/registry/functions.py +28 -0
  79. idmtools/registry/hook_specs.py +132 -0
  80. idmtools/registry/master_plugin_registry.py +51 -0
  81. idmtools/registry/platform_specification.py +138 -0
  82. idmtools/registry/plugin_specification.py +129 -0
  83. idmtools/registry/task_specification.py +104 -0
  84. idmtools/registry/utils.py +119 -0
  85. idmtools/services/__init__.py +5 -0
  86. idmtools/services/ipersistance_service.py +135 -0
  87. idmtools/services/platforms.py +13 -0
  88. idmtools/utils/__init__.py +5 -0
  89. idmtools/utils/caller.py +24 -0
  90. idmtools/utils/collections.py +246 -0
  91. idmtools/utils/command_line.py +45 -0
  92. idmtools/utils/decorators.py +300 -0
  93. idmtools/utils/display/__init__.py +22 -0
  94. idmtools/utils/display/displays.py +181 -0
  95. idmtools/utils/display/settings.py +25 -0
  96. idmtools/utils/dropbox_location.py +30 -0
  97. idmtools/utils/entities.py +127 -0
  98. idmtools/utils/file.py +72 -0
  99. idmtools/utils/file_parser.py +151 -0
  100. idmtools/utils/filter_simulations.py +182 -0
  101. idmtools/utils/filters/__init__.py +5 -0
  102. idmtools/utils/filters/asset_filters.py +88 -0
  103. idmtools/utils/general.py +286 -0
  104. idmtools/utils/gitrepo.py +336 -0
  105. idmtools/utils/hashing.py +239 -0
  106. idmtools/utils/info.py +124 -0
  107. idmtools/utils/json.py +82 -0
  108. idmtools/utils/language.py +107 -0
  109. idmtools/utils/local_os.py +40 -0
  110. idmtools/utils/time.py +22 -0
  111. idmtools-0.0.2.dist-info/METADATA +120 -0
  112. idmtools-0.0.2.dist-info/RECORD +116 -0
  113. idmtools-0.0.2.dist-info/entry_points.txt +9 -0
  114. idmtools-0.0.2.dist-info/licenses/LICENSE.TXT +3 -0
  115. idmtools-0.0.0.dev0.dist-info/METADATA +0 -41
  116. idmtools-0.0.0.dev0.dist-info/RECORD +0 -5
  117. {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.2.dist-info}/WHEEL +0 -0
  118. {idmtools-0.0.0.dev0.dist-info → idmtools-0.0.2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,301 @@
1
+ """
2
+ IPlatformWorkflowItemOperations defines workflow item operations interface.
3
+
4
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
5
+ """
6
+ from abc import ABC, abstractmethod
7
+ from dataclasses import dataclass
8
+ from logging import DEBUG
9
+ from typing import Type, Any, List, Tuple, Dict, NoReturn, TYPE_CHECKING
10
+ from idmtools.assets import Asset
11
+ from idmtools.core import CacheEnabled, getLogger
12
+ from idmtools.entities.iplatform_ops.utils import batch_create_items
13
+ from idmtools.entities.iworkflow_item import IWorkflowItem
14
+ from idmtools.registry.functions import FunctionPluginManager
15
+
16
+ if TYPE_CHECKING: # pragma: no cover
17
+ from idmtools.entities.iplatform import IPlatform
18
+
19
+ logger = getLogger(__name__)
20
+
21
+
22
+ @dataclass
23
+ class IPlatformWorkflowItemOperations(CacheEnabled, ABC):
24
+ """
25
+ IPlatformWorkflowItemOperations defines workflow item operations interface.
26
+ """
27
+ platform: 'IPlatform' # noqa: F821
28
+ platform_type: Type
29
+
30
+ @abstractmethod
31
+ def get(self, workflow_item_id: str, **kwargs) -> Any:
32
+ """
33
+ Returns the platform representation of an WorkflowItem.
34
+
35
+ Args:
36
+ workflow_item_id: Item id of WorkflowItems
37
+ **kwargs:
38
+
39
+ Returns:
40
+ Platform Representation of an workflow_item
41
+ """
42
+ pass
43
+
44
+ def batch_create(self, workflow_items: List[IWorkflowItem], display_progress: bool = True, **kwargs) -> List[Any]:
45
+ """
46
+ Provides a method to batch create workflow items.
47
+
48
+ Args:
49
+ workflow_items: List of worfklow items to create
50
+ display_progress: Whether to display progress bar
51
+ **kwargs:
52
+
53
+ Returns:
54
+ List of tuples containing the create object and id of item that was created.
55
+ """
56
+ return batch_create_items(workflow_items, create_func=self.create, display_progress=display_progress,
57
+ progress_description="Creating WorkItems", unit="workitem", **kwargs)
58
+
59
+ def pre_create(self, workflow_item: IWorkflowItem, **kwargs) -> NoReturn:
60
+ """
61
+ Run the platform/workflow item post creation events.
62
+
63
+ Args:
64
+ workflow_item: IWorkflowItem to run post-creation events
65
+ **kwargs: Optional arguments mainly for extensibility
66
+
67
+ Returns:
68
+ NoReturn
69
+ """
70
+ if logger.isEnabledFor(DEBUG):
71
+ logger.debug("Calling idmtools_platform_pre_create_item")
72
+ FunctionPluginManager.instance().hook.idmtools_platform_pre_create_item(item=workflow_item, kwargs=kwargs)
73
+ if logger.isEnabledFor(DEBUG):
74
+ logger.debug("Calling pre_creation")
75
+ workflow_item.pre_creation(self.platform)
76
+
77
+ def post_create(self, workflow_item: IWorkflowItem, **kwargs) -> NoReturn:
78
+ """
79
+ Run the platform/workflow item post creation events.
80
+
81
+ Args:
82
+ workflow_item: IWorkflowItem to run post-creation events
83
+ **kwargs: Optional arguments mainly for extensibility
84
+
85
+ Returns:
86
+ NoReturn
87
+ """
88
+ if logger.isEnabledFor(DEBUG):
89
+ logger.debug("Calling idmtools_platform_post_create_item hooks")
90
+ FunctionPluginManager.instance().hook.idmtools_platform_post_create_item(item=workflow_item, kwargs=kwargs)
91
+ if logger.isEnabledFor(DEBUG):
92
+ logger.debug("Calling post_creation")
93
+ workflow_item.post_creation(self.platform)
94
+
95
+ def create(self, workflow_item: IWorkflowItem, do_pre: bool = True, do_post: bool = True, **kwargs) -> Any:
96
+ """
97
+ Creates an workflow item from an IDMTools IWorkflowItem object.
98
+
99
+ Also performs pre-creation and post-creation locally and on platform.
100
+
101
+ Args:
102
+ workflow_item: Suite to create
103
+ do_pre: Perform Pre creation events for item
104
+ do_post: Perform Post creation events for item
105
+ **kwargs: Optional arguments mainly for extensibility
106
+
107
+ Returns:
108
+ Created platform item and the UUID of said item
109
+ """
110
+ if workflow_item.status is not None:
111
+ return workflow_item._platform_object, workflow_item.uid
112
+ if do_pre:
113
+ if logger.isEnabledFor(DEBUG):
114
+ logger.debug("Calling pre_create")
115
+ self.pre_create(workflow_item, **kwargs)
116
+ if logger.isEnabledFor(DEBUG):
117
+ logger.debug("Calling platform_create")
118
+ ret = self.platform_create(workflow_item, **kwargs)
119
+ workflow_item.platform = self.platform
120
+ if do_post:
121
+ if logger.isEnabledFor(DEBUG):
122
+ logger.debug("Calling post_create")
123
+ self.post_create(workflow_item, **kwargs)
124
+ return ret
125
+
126
+ @abstractmethod
127
+ def platform_create(self, workflow_item: IWorkflowItem, **kwargs) -> Tuple[Any, str]:
128
+ """
129
+ Creates an workflow_item from an IDMTools workflow_item object.
130
+
131
+ Args:
132
+ workflow_item: WorkflowItem to create
133
+ **kwargs: Optional arguments mainly for extensibility
134
+
135
+ Returns:
136
+ Created platform item and the id of said item
137
+ """
138
+ pass
139
+
140
+ def pre_run_item(self, workflow_item: IWorkflowItem, **kwargs):
141
+ """
142
+ Trigger right before commissioning experiment on platform.
143
+
144
+ This ensures that the item is created. It also ensures that the children(simulations) have also been created.
145
+
146
+ Args:
147
+ workflow_item: Experiment to commission
148
+
149
+ Returns:
150
+ None
151
+ """
152
+ # ensure the item is created before running
153
+ # TODO what status are valid here? Create only?
154
+ if workflow_item.status is None:
155
+ if logger.isEnabledFor(DEBUG):
156
+ logger.debug("Calling create")
157
+ self.create(workflow_item)
158
+
159
+ def post_run_item(self, workflow_item: IWorkflowItem, **kwargs):
160
+ """
161
+ Trigger right after commissioning workflow item on platform.
162
+
163
+ Args:
164
+ workflow_item: Experiment just commissioned
165
+
166
+ Returns:
167
+ None
168
+ """
169
+ if logger.isEnabledFor(DEBUG):
170
+ logger.debug("Calling idmtools_platform_post_run hooks")
171
+ FunctionPluginManager.instance().hook.idmtools_platform_post_run(item=workflow_item, kwargs=kwargs)
172
+
173
+ def run_item(self, workflow_item: IWorkflowItem, **kwargs):
174
+ """
175
+ Called during commissioning of an item. This should create the remote resource.
176
+
177
+ Args:
178
+ workflow_item:
179
+
180
+ Returns:
181
+ None
182
+ """
183
+ if logger.isEnabledFor(DEBUG):
184
+ logger.debug("Calling pre_run_item")
185
+ self.pre_run_item(workflow_item, **kwargs)
186
+ if logger.isEnabledFor(DEBUG):
187
+ logger.debug("Calling platform_run_item")
188
+ self.platform_run_item(workflow_item, **kwargs)
189
+ if logger.isEnabledFor(DEBUG):
190
+ logger.debug("Calling post_run_item")
191
+ self.post_run_item(workflow_item, **kwargs)
192
+
193
+ @abstractmethod
194
+ def platform_run_item(self, workflow_item: IWorkflowItem, **kwargs):
195
+ """
196
+ Called during commissioning of an item. This should perform what is needed to commission job on platform.
197
+
198
+ Args:
199
+ workflow_item:
200
+
201
+ Returns:
202
+ None
203
+ """
204
+ pass
205
+
206
+ @abstractmethod
207
+ def get_parent(self, workflow_item: Any, **kwargs) -> Any:
208
+ """
209
+ Returns the parent of item. If the platform doesn't support parents, you should throw a TopLevelItem error.
210
+
211
+ Args:
212
+ workflow_item: Workflow item to get parent of
213
+ **kwargs:
214
+
215
+ Returns:
216
+ Parent of Worktflow item
217
+
218
+ Raise:
219
+ TopLevelItem
220
+ """
221
+ pass
222
+
223
+ @abstractmethod
224
+ def get_children(self, workflow_item: Any, **kwargs) -> List[Any]:
225
+ """
226
+ Returns the children of an workflow_item object.
227
+
228
+ Args:
229
+ workflow_item: WorkflowItem object
230
+ **kwargs: Optional arguments mainly for extensibility
231
+
232
+ Returns:
233
+ Children of workflow_item object
234
+ """
235
+ pass
236
+
237
+ def to_entity(self, workflow_item: Any, **kwargs) -> IWorkflowItem:
238
+ """
239
+ Converts the platform representation of workflow_item to idmtools representation.
240
+
241
+ Args:
242
+ workflow_item:Platform workflow_item object
243
+
244
+ Returns:
245
+ IDMTools workflow_item object
246
+ """
247
+ return workflow_item
248
+
249
+ @abstractmethod
250
+ def refresh_status(self, workflow_item: IWorkflowItem, **kwargs):
251
+ """
252
+ Refresh status for workflow item.
253
+
254
+ Args:
255
+ workflow_item: Item to refresh status for
256
+
257
+ Returns:
258
+ None
259
+ """
260
+ pass
261
+
262
+ @abstractmethod
263
+ def send_assets(self, workflow_item: Any, **kwargs):
264
+ """
265
+ Send assets for workflow item to platform.
266
+
267
+ Args:
268
+ workflow_item: Item to send assets for
269
+
270
+ Returns:
271
+ None
272
+ """
273
+ pass
274
+
275
+ @abstractmethod
276
+ def get_assets(self, workflow_item: IWorkflowItem, files: List[str], **kwargs) -> Dict[str, bytearray]:
277
+ """
278
+ Load assets for workflow item.
279
+
280
+ Args:
281
+ workflow_item: Item
282
+ files: List of files to load
283
+ **kwargs:
284
+
285
+ Returns:
286
+ Dictionary with filename as key and value as binary content
287
+ """
288
+ pass
289
+
290
+ @abstractmethod
291
+ def list_assets(self, workflow_item: IWorkflowItem, **kwargs) -> List[Asset]:
292
+ """
293
+ List available assets for a workflow item.
294
+
295
+ Args:
296
+ workflow_item: workflow item to list files for
297
+
298
+ Returns:
299
+ List of filenames
300
+ """
301
+ pass
@@ -0,0 +1,185 @@
1
+ """
2
+ Utils for platform operations.
3
+
4
+ Here we have mostly utilities to handle batch operations which tend to overlap across different item types.
5
+
6
+ Copyright 2021, Bill & Melinda Gates Foundation. All rights reserved.
7
+ """
8
+ from concurrent.futures import as_completed, Future
9
+ from concurrent.futures.process import ProcessPoolExecutor
10
+ from concurrent.futures.thread import ThreadPoolExecutor
11
+ from functools import partial
12
+ from logging import getLogger, DEBUG
13
+ from os import cpu_count
14
+ from typing import List, Union, Generator, Iterable, Callable, Any
15
+ from more_itertools import chunked
16
+ from idmtools.core import EntityContainer
17
+ from idmtools.entities.templated_simulation import TemplatedSimulations
18
+
19
+ logger = getLogger(__name__)
20
+ user_logger = getLogger('user')
21
+ # Global executor
22
+ EXECUTOR = None
23
+
24
+
25
+ def batch_items(items: Union[Iterable, Generator], batch_size=16):
26
+ """
27
+ Batch items.
28
+
29
+ Args:
30
+ items: Items to batch
31
+ batch_size: Size of the batch
32
+
33
+ Returns:
34
+ Generator
35
+
36
+ Raises:
37
+ StopIteration
38
+ """
39
+ for item_chunk in chunked(items, batch_size):
40
+ logger.info('created chunk')
41
+ yield item_chunk
42
+ raise StopIteration
43
+
44
+
45
+ def item_batch_worker_thread(create_func: Callable, items: Union[List], **kwargs) -> List:
46
+ """
47
+ Default batch worker thread function. It just calls create on each item.
48
+
49
+ Args:
50
+ create_func: Create function for item
51
+ items: Items to create
52
+
53
+ Returns:
54
+ List of items created
55
+ """
56
+ if logger.isEnabledFor(DEBUG):
57
+ logger.debug(f'Create {len(items)}')
58
+
59
+ ret = []
60
+ for item in items:
61
+ ret.append(create_func(item, **kwargs))
62
+
63
+ return ret
64
+
65
+
66
+ def batch_create_items(items: Union[Iterable, Generator], batch_worker_thread_func: Callable[[List], List] = None,
67
+ create_func: Callable[..., Any] = None, display_progress: bool = True,
68
+ progress_description: str = "Commissioning items", unit: str = None, **kwargs):
69
+ """
70
+ Batch create items. You must specify either batch_worker_thread_func or create_func.
71
+
72
+ Args:
73
+ items: Items to create
74
+ batch_worker_thread_func: Optional Function to execute. Should take a list and return a list
75
+ create_func: Optional Create function
76
+ display_progress: Enable progress bar
77
+ progress_description: Description to show in progress bar
78
+ unit: Unit for progress bar
79
+ **kwargs:
80
+
81
+ Returns:
82
+ Batches crated results
83
+ """
84
+ global EXECUTOR
85
+ from idmtools.config import IdmConfigParser
86
+ from idmtools.utils.collections import ExperimentParentIterator
87
+
88
+ max_workers = kwargs.get('max_workers', None)
89
+
90
+ # Consider values from the block that Platform uses
91
+ _batch_size = int(IdmConfigParser.get_option(None, "batch_size", fallback=16))
92
+
93
+ batch_size = kwargs.get('batch_size', None)
94
+ if batch_size is not None:
95
+ _batch_size = batch_size
96
+
97
+ if display_progress and not IdmConfigParser.is_progress_bar_disabled():
98
+ from tqdm import tqdm
99
+ extra_args = dict(unit=unit) if unit else dict()
100
+ prog = tqdm(desc="Initializing objects for creation", **extra_args)
101
+ else:
102
+ prog = None
103
+
104
+ if EXECUTOR is None:
105
+ _workers_per_cpu = IdmConfigParser.get_option(None, "workers_per_cpu", fallback=None)
106
+ if _workers_per_cpu:
107
+ _max_workers = int(_workers_per_cpu) * cpu_count()
108
+ if logger.isEnabledFor(DEBUG):
109
+ logger.debug(f"workers set by cpu: {_workers_per_cpu} * {cpu_count()}")
110
+ else:
111
+ _max_workers = int(IdmConfigParser.get_option(None, "max_workers", fallback=16))
112
+
113
+ if max_workers is not None:
114
+ _max_workers = max_workers
115
+
116
+ logger.info(f'Creating {_max_workers} Platform Workers')
117
+ default_pool_executor = IdmConfigParser.get_option(None, "default_pool_executor", fallback="thread").lower()
118
+ if default_pool_executor == "process":
119
+ EXECUTOR = ProcessPoolExecutor(max_workers=_max_workers)
120
+ else:
121
+ EXECUTOR = ThreadPoolExecutor(max_workers=_max_workers)
122
+
123
+ if batch_worker_thread_func is None:
124
+
125
+ if create_func is None:
126
+ raise ValueError("You must provide either an item create callback or a item batch worker thread callback to"
127
+ " perform batches")
128
+ batch_worker_thread_func = partial(item_batch_worker_thread, create_func, **kwargs)
129
+ if logger.isEnabledFor(DEBUG):
130
+ logger.debug(f'Batching creation by {_batch_size}')
131
+
132
+ futures = []
133
+
134
+ total = 0
135
+ parent = None
136
+ if isinstance(items, ExperimentParentIterator) and isinstance(items.items, TemplatedSimulations):
137
+ parent = items.parent
138
+ i = items.items.simulations().generator
139
+ elif isinstance(items, ExperimentParentIterator) and isinstance(items.items, EntityContainer):
140
+ parent = items.parent
141
+ i = items.items
142
+ else:
143
+ i = items
144
+ if display_progress and not IdmConfigParser.is_progress_bar_disabled() and hasattr(items, '__len__'):
145
+ prog.total = len(items)
146
+ for chunk in chunked(i, _batch_size):
147
+ total += len(chunk)
148
+ if parent:
149
+ for c in chunk:
150
+ c.parent = parent
151
+ if logger.isEnabledFor(DEBUG):
152
+ logger.debug(f"Submitting chunk: {len(chunk)}")
153
+ if display_progress and not IdmConfigParser.is_progress_bar_disabled():
154
+ prog.update(len(chunk))
155
+ futures.append(EXECUTOR.submit(batch_worker_thread_func, chunk))
156
+
157
+ results = []
158
+ if display_progress and not IdmConfigParser.is_progress_bar_disabled():
159
+ prog.set_description(progress_description)
160
+ prog.reset(total)
161
+ results = show_progress_of_batch(prog, futures)
162
+ else:
163
+ for future in futures:
164
+ results.extend(future.result())
165
+
166
+ return results
167
+
168
+
169
+ def show_progress_of_batch(progress_bar: 'tqdm', futures: List[Future]) -> List: # noqa: F821
170
+ """
171
+ Show progress bar for batch.
172
+
173
+ Args:
174
+ progress_bar: Progress bar
175
+ futures: List of futures that are still running/queued
176
+
177
+ Returns:
178
+ Returns results
179
+ """
180
+ results = []
181
+ for future in as_completed(futures):
182
+ result = future.result()
183
+ progress_bar.update(len(result))
184
+ results.extend(future.result())
185
+ return results