parsl 2024.5.27__py3-none-any.whl → 2024.6.10__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 (289) hide show
  1. parsl/__init__.py +9 -10
  2. parsl/addresses.py +6 -4
  3. parsl/app/app.py +3 -6
  4. parsl/app/bash.py +4 -4
  5. parsl/app/errors.py +5 -3
  6. parsl/app/futures.py +3 -3
  7. parsl/app/python.py +2 -1
  8. parsl/benchmark/perf.py +2 -1
  9. parsl/channels/__init__.py +2 -2
  10. parsl/channels/base.py +0 -1
  11. parsl/channels/errors.py +2 -1
  12. parsl/channels/oauth_ssh/oauth_ssh.py +4 -3
  13. parsl/channels/ssh/ssh.py +9 -1
  14. parsl/channels/ssh_il/ssh_il.py +1 -0
  15. parsl/concurrent/__init__.py +2 -2
  16. parsl/config.py +32 -9
  17. parsl/configs/ASPIRE1.py +3 -3
  18. parsl/configs/Azure.py +6 -7
  19. parsl/configs/ad_hoc.py +4 -3
  20. parsl/configs/bridges.py +3 -3
  21. parsl/configs/cc_in2p3.py +2 -2
  22. parsl/configs/ec2.py +1 -1
  23. parsl/configs/expanse.py +1 -2
  24. parsl/configs/frontera.py +2 -3
  25. parsl/configs/htex_local.py +1 -2
  26. parsl/configs/illinoiscluster.py +1 -1
  27. parsl/configs/kubernetes.py +1 -2
  28. parsl/configs/midway.py +3 -3
  29. parsl/configs/osg.py +1 -1
  30. parsl/configs/polaris.py +1 -1
  31. parsl/configs/stampede2.py +4 -5
  32. parsl/configs/summit.py +1 -3
  33. parsl/configs/toss3_llnl.py +1 -2
  34. parsl/configs/vineex_local.py +3 -3
  35. parsl/configs/wqex_local.py +2 -2
  36. parsl/data_provider/data_manager.py +3 -3
  37. parsl/data_provider/file_noop.py +1 -2
  38. parsl/data_provider/files.py +3 -3
  39. parsl/data_provider/ftp.py +1 -3
  40. parsl/data_provider/globus.py +7 -6
  41. parsl/data_provider/http.py +2 -2
  42. parsl/data_provider/rsync.py +1 -1
  43. parsl/data_provider/staging.py +2 -2
  44. parsl/data_provider/zip.py +4 -5
  45. parsl/dataflow/dflow.py +57 -26
  46. parsl/dataflow/errors.py +2 -1
  47. parsl/dataflow/futures.py +1 -2
  48. parsl/dataflow/memoization.py +5 -5
  49. parsl/dataflow/rundirs.py +1 -1
  50. parsl/dataflow/taskrecord.py +4 -5
  51. parsl/executors/__init__.py +3 -3
  52. parsl/executors/base.py +1 -0
  53. parsl/executors/flux/execute_parsl_task.py +2 -2
  54. parsl/executors/flux/executor.py +11 -12
  55. parsl/executors/flux/flux_instance_manager.py +3 -3
  56. parsl/executors/high_throughput/executor.py +31 -36
  57. parsl/executors/high_throughput/interchange.py +37 -38
  58. parsl/executors/high_throughput/manager_record.py +1 -0
  59. parsl/executors/high_throughput/monitoring_info.py +2 -1
  60. parsl/executors/high_throughput/mpi_executor.py +5 -2
  61. parsl/executors/high_throughput/mpi_prefix_composer.py +1 -1
  62. parsl/executors/high_throughput/mpi_resource_management.py +1 -2
  63. parsl/executors/high_throughput/probe.py +6 -4
  64. parsl/executors/high_throughput/process_worker_pool.py +31 -20
  65. parsl/executors/high_throughput/zmq_pipes.py +28 -14
  66. parsl/executors/radical/executor.py +15 -15
  67. parsl/executors/radical/rpex_master.py +1 -2
  68. parsl/executors/radical/rpex_resources.py +1 -2
  69. parsl/executors/radical/rpex_worker.py +2 -1
  70. parsl/executors/status_handling.py +5 -4
  71. parsl/executors/taskvine/__init__.py +1 -1
  72. parsl/executors/taskvine/errors.py +1 -1
  73. parsl/executors/taskvine/exec_parsl_function.py +2 -2
  74. parsl/executors/taskvine/executor.py +23 -24
  75. parsl/executors/taskvine/factory.py +1 -1
  76. parsl/executors/taskvine/manager.py +11 -13
  77. parsl/executors/threads.py +4 -5
  78. parsl/executors/workqueue/errors.py +1 -1
  79. parsl/executors/workqueue/exec_parsl_function.py +5 -4
  80. parsl/executors/workqueue/executor.py +26 -27
  81. parsl/executors/workqueue/parsl_coprocess.py +1 -1
  82. parsl/jobs/error_handlers.py +1 -1
  83. parsl/jobs/job_status_poller.py +2 -5
  84. parsl/jobs/states.py +1 -1
  85. parsl/jobs/strategy.py +2 -2
  86. parsl/launchers/__init__.py +12 -3
  87. parsl/launchers/errors.py +1 -1
  88. parsl/log_utils.py +1 -2
  89. parsl/monitoring/db_manager.py +16 -10
  90. parsl/monitoring/monitoring.py +11 -15
  91. parsl/monitoring/queries/pandas.py +1 -2
  92. parsl/monitoring/radios.py +2 -4
  93. parsl/monitoring/remote.py +13 -8
  94. parsl/monitoring/router.py +8 -11
  95. parsl/monitoring/types.py +2 -0
  96. parsl/monitoring/visualization/app.py +4 -2
  97. parsl/monitoring/visualization/models.py +0 -1
  98. parsl/monitoring/visualization/plots/default/workflow_plots.py +8 -4
  99. parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +1 -0
  100. parsl/monitoring/visualization/utils.py +0 -1
  101. parsl/monitoring/visualization/views.py +16 -9
  102. parsl/multiprocessing.py +0 -1
  103. parsl/process_loggers.py +1 -2
  104. parsl/providers/__init__.py +9 -12
  105. parsl/providers/ad_hoc/ad_hoc.py +1 -1
  106. parsl/providers/aws/aws.py +2 -3
  107. parsl/providers/azure/azure.py +4 -5
  108. parsl/providers/base.py +1 -1
  109. parsl/providers/cluster_provider.py +1 -1
  110. parsl/providers/cobalt/cobalt.py +3 -3
  111. parsl/providers/condor/condor.py +4 -2
  112. parsl/providers/errors.py +2 -2
  113. parsl/providers/googlecloud/googlecloud.py +2 -1
  114. parsl/providers/grid_engine/grid_engine.py +2 -2
  115. parsl/providers/kubernetes/kube.py +24 -9
  116. parsl/providers/local/local.py +5 -1
  117. parsl/providers/lsf/lsf.py +2 -2
  118. parsl/providers/pbspro/pbspro.py +1 -1
  119. parsl/providers/slurm/slurm.py +36 -27
  120. parsl/providers/torque/torque.py +1 -1
  121. parsl/serialize/__init__.py +8 -3
  122. parsl/serialize/base.py +1 -2
  123. parsl/serialize/concretes.py +5 -4
  124. parsl/serialize/proxystore.py +3 -2
  125. parsl/tests/__init__.py +1 -1
  126. parsl/tests/configs/ad_hoc_cluster_htex.py +4 -4
  127. parsl/tests/configs/azure_single_node.py +4 -5
  128. parsl/tests/configs/bridges.py +3 -2
  129. parsl/tests/configs/cc_in2p3.py +2 -2
  130. parsl/tests/configs/comet.py +2 -1
  131. parsl/tests/configs/ec2_single_node.py +1 -2
  132. parsl/tests/configs/ec2_spot.py +1 -2
  133. parsl/tests/configs/flux_local.py +11 -0
  134. parsl/tests/configs/frontera.py +3 -2
  135. parsl/tests/configs/htex_ad_hoc_cluster.py +2 -4
  136. parsl/tests/configs/htex_local.py +2 -3
  137. parsl/tests/configs/htex_local_alternate.py +8 -11
  138. parsl/tests/configs/htex_local_intask_staging.py +5 -7
  139. parsl/tests/configs/htex_local_rsync_staging.py +4 -6
  140. parsl/tests/configs/local_adhoc.py +1 -1
  141. parsl/tests/configs/local_radical.py +1 -3
  142. parsl/tests/configs/local_radical_mpi.py +2 -2
  143. parsl/tests/configs/midway.py +2 -2
  144. parsl/tests/configs/nscc_singapore.py +3 -3
  145. parsl/tests/configs/osg_htex.py +1 -1
  146. parsl/tests/configs/petrelkube.py +3 -2
  147. parsl/tests/configs/summit.py +1 -0
  148. parsl/tests/configs/swan_htex.py +2 -2
  149. parsl/tests/configs/taskvine_ex.py +3 -5
  150. parsl/tests/configs/theta.py +2 -2
  151. parsl/tests/configs/workqueue_ex.py +3 -4
  152. parsl/tests/conftest.py +8 -4
  153. parsl/tests/integration/test_channels/test_ssh_errors.py +1 -1
  154. parsl/tests/integration/test_stress/test_python_simple.py +3 -4
  155. parsl/tests/integration/test_stress/test_python_threads.py +3 -5
  156. parsl/tests/manual_tests/htex_local.py +4 -4
  157. parsl/tests/manual_tests/test_ad_hoc_htex.py +2 -1
  158. parsl/tests/manual_tests/test_basic.py +1 -0
  159. parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +4 -4
  160. parsl/tests/manual_tests/test_log_filter.py +3 -1
  161. parsl/tests/manual_tests/test_memory_limits.py +6 -6
  162. parsl/tests/manual_tests/test_regression_220.py +2 -1
  163. parsl/tests/manual_tests/test_udp_simple.py +4 -3
  164. parsl/tests/manual_tests/test_worker_count.py +3 -2
  165. parsl/tests/scaling_tests/htex_local.py +2 -2
  166. parsl/tests/scaling_tests/test_scale.py +0 -9
  167. parsl/tests/scaling_tests/vineex_condor.py +1 -2
  168. parsl/tests/scaling_tests/vineex_local.py +1 -2
  169. parsl/tests/site_tests/test_provider.py +3 -1
  170. parsl/tests/site_tests/test_site.py +2 -0
  171. parsl/tests/sites/test_affinity.py +7 -5
  172. parsl/tests/sites/test_dynamic_executor.py +3 -3
  173. parsl/tests/sites/test_ec2.py +3 -2
  174. parsl/tests/sites/test_local_adhoc.py +2 -1
  175. parsl/tests/sites/test_worker_info.py +4 -3
  176. parsl/tests/test_aalst_patterns.py +0 -1
  177. parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
  178. parsl/tests/test_bash_apps/test_error_codes.py +1 -4
  179. parsl/tests/test_bash_apps/test_memoize_ignore_args.py +1 -0
  180. parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +2 -2
  181. parsl/tests/test_bash_apps/test_pipeline.py +1 -1
  182. parsl/tests/test_bash_apps/test_std_uri.py +4 -3
  183. parsl/tests/test_bash_apps/test_stdout.py +20 -2
  184. parsl/tests/test_callables.py +2 -2
  185. parsl/tests/test_checkpointing/test_python_checkpoint_1.py +1 -0
  186. parsl/tests/test_checkpointing/test_python_checkpoint_2.py +2 -1
  187. parsl/tests/test_checkpointing/test_regression_239.py +1 -1
  188. parsl/tests/test_checkpointing/test_task_exit.py +1 -1
  189. parsl/tests/test_docs/test_from_slides.py +2 -2
  190. parsl/tests/test_docs/test_kwargs.py +1 -1
  191. parsl/tests/test_docs/test_tutorial_1.py +1 -2
  192. parsl/tests/test_docs/test_workflow1.py +2 -2
  193. parsl/tests/test_docs/test_workflow2.py +0 -1
  194. parsl/tests/test_error_handling/test_rand_fail.py +2 -2
  195. parsl/tests/test_error_handling/test_resource_spec.py +4 -2
  196. parsl/tests/test_error_handling/test_retries.py +2 -1
  197. parsl/tests/test_error_handling/test_retry_handler.py +1 -0
  198. parsl/tests/test_error_handling/test_retry_handler_failure.py +2 -1
  199. parsl/tests/test_error_handling/test_serialization_fail.py +1 -1
  200. parsl/tests/test_error_handling/test_wrap_with_logs.py +1 -0
  201. parsl/tests/test_flux.py +1 -1
  202. parsl/tests/test_htex/test_command_client_timeout.py +9 -12
  203. parsl/tests/test_htex/test_connected_blocks.py +3 -2
  204. parsl/tests/test_htex/test_cpu_affinity_explicit.py +5 -2
  205. parsl/tests/test_htex/test_disconnected_blocks.py +6 -4
  206. parsl/tests/test_htex/test_drain.py +5 -5
  207. parsl/tests/test_htex/test_htex.py +1 -2
  208. parsl/tests/test_htex/test_managers_command.py +3 -2
  209. parsl/tests/test_htex/test_multiple_disconnected_blocks.py +6 -4
  210. parsl/tests/test_htex/test_zmq_binding.py +22 -6
  211. parsl/tests/test_monitoring/test_app_names.py +3 -2
  212. parsl/tests/test_monitoring/test_basic.py +4 -4
  213. parsl/tests/test_monitoring/test_db_locks.py +6 -3
  214. parsl/tests/test_monitoring/test_fuzz_zmq.py +6 -3
  215. parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +5 -5
  216. parsl/tests/test_monitoring/test_incomplete_futures.py +5 -3
  217. parsl/tests/test_monitoring/test_memoization_representation.py +4 -1
  218. parsl/tests/test_monitoring/test_stdouterr.py +4 -4
  219. parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
  220. parsl/tests/test_mpi_apps/test_bad_mpi_config.py +1 -1
  221. parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +2 -0
  222. parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +7 -5
  223. parsl/tests/test_mpi_apps/test_mpi_prefix.py +4 -4
  224. parsl/tests/test_mpi_apps/test_mpi_scheduler.py +7 -2
  225. parsl/tests/test_mpi_apps/test_mpiex.py +4 -3
  226. parsl/tests/test_mpi_apps/test_resource_spec.py +9 -10
  227. parsl/tests/test_providers/test_cobalt_deprecation_warning.py +2 -0
  228. parsl/tests/test_providers/test_local_provider.py +2 -1
  229. parsl/tests/test_providers/test_pbspro_template.py +1 -1
  230. parsl/tests/test_providers/test_slurm_template.py +1 -1
  231. parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
  232. parsl/tests/test_python_apps/test_context_manager.py +99 -3
  233. parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
  234. parsl/tests/test_python_apps/test_dependencies_deep.py +59 -0
  235. parsl/tests/test_python_apps/test_futures.py +2 -1
  236. parsl/tests/test_python_apps/test_join.py +0 -1
  237. parsl/tests/test_python_apps/test_lifted.py +3 -3
  238. parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +1 -0
  239. parsl/tests/test_python_apps/test_pluggable_future_resolution.py +1 -1
  240. parsl/tests/test_radical/test_mpi_funcs.py +1 -2
  241. parsl/tests/test_regression/test_1480.py +2 -1
  242. parsl/tests/test_regression/test_1653.py +2 -1
  243. parsl/tests/test_regression/test_2652.py +1 -0
  244. parsl/tests/test_regression/test_69a.py +0 -1
  245. parsl/tests/test_regression/test_854.py +4 -2
  246. parsl/tests/test_regression/test_97_parallelism_0.py +1 -2
  247. parsl/tests/test_regression/test_98.py +0 -1
  248. parsl/tests/test_scaling/test_block_error_handler.py +9 -4
  249. parsl/tests/test_scaling/test_scale_down.py +2 -3
  250. parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +4 -5
  251. parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +3 -4
  252. parsl/tests/test_scaling/test_shutdown_scalein.py +1 -2
  253. parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
  254. parsl/tests/test_serialization/test_basic.py +2 -1
  255. parsl/tests/test_serialization/test_htex_code_cache.py +3 -4
  256. parsl/tests/test_serialization/test_pack_resource_spec.py +2 -1
  257. parsl/tests/test_serialization/test_proxystore_configured.py +10 -5
  258. parsl/tests/test_serialization/test_proxystore_impl.py +5 -3
  259. parsl/tests/test_shutdown/test_kill_monitoring.py +3 -2
  260. parsl/tests/test_staging/staging_provider.py +2 -2
  261. parsl/tests/test_staging/test_1316.py +3 -2
  262. parsl/tests/test_staging/test_docs_1.py +1 -1
  263. parsl/tests/test_staging/test_docs_2.py +2 -1
  264. parsl/tests/test_staging/test_elaborate_noop_file.py +2 -2
  265. parsl/tests/test_staging/test_staging_https.py +2 -2
  266. parsl/tests/test_staging/test_staging_stdout.py +4 -3
  267. parsl/tests/test_staging/test_zip_in.py +6 -8
  268. parsl/tests/test_staging/test_zip_out.py +7 -9
  269. parsl/tests/test_staging/test_zip_to_zip.py +6 -8
  270. parsl/tests/test_summary.py +2 -1
  271. parsl/tests/test_thread_parallelism.py +0 -1
  272. parsl/tests/test_threads/test_configs.py +1 -1
  273. parsl/tests/test_threads/test_lazy_errors.py +2 -1
  274. parsl/tests/unit/test_usage_tracking.py +45 -0
  275. parsl/usage_tracking/api.py +2 -3
  276. parsl/usage_tracking/levels.py +6 -0
  277. parsl/usage_tracking/usage.py +60 -39
  278. parsl/utils.py +13 -2
  279. parsl/version.py +1 -1
  280. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/exec_parsl_function.py +5 -4
  281. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/process_worker_pool.py +31 -20
  282. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/METADATA +2 -2
  283. parsl-2024.6.10.dist-info/RECORD +475 -0
  284. parsl-2024.5.27.dist-info/RECORD +0 -471
  285. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/parsl_coprocess.py +1 -1
  286. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/LICENSE +0 -0
  287. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/WHEEL +0 -0
  288. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/entry_points.txt +0 -0
  289. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,8 @@ import logging
3
3
  import os
4
4
 
5
5
  import parsl
6
-
7
- from parsl.utils import RepresentationMixin
8
6
  from parsl.data_provider.staging import Staging
9
-
7
+ from parsl.utils import RepresentationMixin
10
8
 
11
9
  logger = logging.getLogger(__name__)
12
10
 
@@ -1,15 +1,16 @@
1
- import logging
2
1
  import json
3
- import globus_sdk
2
+ import logging
4
3
  import os
5
- import parsl
6
- import typeguard
7
-
8
4
  from functools import partial
9
5
  from typing import Optional
6
+
7
+ import globus_sdk
8
+ import typeguard
9
+
10
+ import parsl
10
11
  from parsl.app.app import python_app
11
- from parsl.utils import RepresentationMixin
12
12
  from parsl.data_provider.staging import Staging
13
+ from parsl.utils import RepresentationMixin
13
14
 
14
15
  logger = logging.getLogger(__name__)
15
16
 
@@ -1,11 +1,11 @@
1
1
  import logging
2
2
  import os
3
+
3
4
  import requests
4
5
 
5
6
  import parsl
6
-
7
- from parsl.utils import RepresentationMixin
8
7
  from parsl.data_provider.staging import Staging
8
+ from parsl.utils import RepresentationMixin
9
9
 
10
10
  logger = logging.getLogger(__name__)
11
11
 
@@ -1,8 +1,8 @@
1
1
  import logging
2
2
  import os
3
3
 
4
- from parsl.utils import RepresentationMixin
5
4
  from parsl.data_provider.staging import Staging
5
+ from parsl.utils import RepresentationMixin
6
6
 
7
7
  logger = logging.getLogger(__name__)
8
8
 
@@ -1,9 +1,9 @@
1
1
  from concurrent.futures import Future
2
- from typing import Optional, Callable
2
+ from typing import TYPE_CHECKING, Callable, Optional
3
+
3
4
  from parsl.app.futures import DataFuture
4
5
  from parsl.data_provider.files import File
5
6
 
6
- from typing import TYPE_CHECKING
7
7
  if TYPE_CHECKING:
8
8
  from parsl.data_provider.data_manager import DataManager
9
9
 
@@ -1,16 +1,15 @@
1
- import filelock
2
1
  import logging
3
2
  import os
4
- import parsl
5
3
  import zipfile
6
-
7
4
  from typing import Tuple
8
5
 
9
- from parsl.data_provider.staging import Staging
6
+ import filelock
7
+
8
+ import parsl
10
9
  from parsl.data_provider.files import File
10
+ from parsl.data_provider.staging import Staging
11
11
  from parsl.errors import ParslError
12
12
 
13
-
14
13
  logger = logging.getLogger(__name__)
15
14
 
16
15
 
parsl/dataflow/dflow.py CHANGED
@@ -1,23 +1,26 @@
1
1
  from __future__ import annotations
2
+
2
3
  import atexit
4
+ import concurrent.futures as cf
5
+ import datetime
6
+ import inspect
3
7
  import logging
4
8
  import os
5
9
  import pathlib
6
10
  import pickle
7
11
  import random
8
- import time
9
- import typeguard
10
- import inspect
11
- import threading
12
12
  import sys
13
- import datetime
13
+ import threading
14
+ import time
15
+ from concurrent.futures import Future
16
+ from functools import partial
14
17
  from getpass import getuser
15
- from typeguard import typechecked
18
+ from socket import gethostname
16
19
  from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
17
20
  from uuid import uuid4
18
- from socket import gethostname
19
- from concurrent.futures import Future
20
- from functools import partial
21
+
22
+ import typeguard
23
+ from typeguard import typechecked
21
24
 
22
25
  import parsl
23
26
  from parsl.app.errors import RemoteExceptionWrapper
@@ -31,21 +34,24 @@ from parsl.dataflow.errors import BadCheckpoint, DependencyError, JoinError
31
34
  from parsl.dataflow.futures import AppFuture
32
35
  from parsl.dataflow.memoization import Memoizer
33
36
  from parsl.dataflow.rundirs import make_rundir
34
- from parsl.dataflow.states import States, FINAL_STATES, FINAL_FAILURE_STATES
37
+ from parsl.dataflow.states import FINAL_FAILURE_STATES, FINAL_STATES, States
35
38
  from parsl.dataflow.taskrecord import TaskRecord
36
- from parsl.errors import ConfigurationError, InternalConsistencyError, NoDataFlowKernelError
37
- from parsl.jobs.job_status_poller import JobStatusPoller
38
- from parsl.usage_tracking.usage import UsageTracker
39
+ from parsl.errors import (
40
+ ConfigurationError,
41
+ InternalConsistencyError,
42
+ NoDataFlowKernelError,
43
+ )
39
44
  from parsl.executors.base import ParslExecutor
40
45
  from parsl.executors.status_handling import BlockProviderExecutor
41
46
  from parsl.executors.threads import ThreadPoolExecutor
47
+ from parsl.jobs.job_status_poller import JobStatusPoller
42
48
  from parsl.monitoring import MonitoringHub
49
+ from parsl.monitoring.message_type import MessageType
43
50
  from parsl.monitoring.remote import monitor_wrapper
44
51
  from parsl.process_loggers import wrap_with_logs
45
52
  from parsl.providers.base import ExecutionProvider
46
- from parsl.utils import get_version, get_std_fname_mode, get_all_checkpoints, Timer
47
-
48
- from parsl.monitoring.message_type import MessageType
53
+ from parsl.usage_tracking.usage import UsageTracker
54
+ from parsl.utils import Timer, get_all_checkpoints, get_std_fname_mode, get_version
49
55
 
50
56
  logger = logging.getLogger(__name__)
51
57
 
@@ -204,6 +210,8 @@ class DataFlowKernel:
204
210
  self.tasks: Dict[int, TaskRecord] = {}
205
211
  self.submitter_lock = threading.Lock()
206
212
 
213
+ self.dependency_launch_pool = cf.ThreadPoolExecutor(max_workers=1, thread_name_prefix="Dependency-Launch")
214
+
207
215
  self.dependency_resolver = self.config.dependency_resolver if self.config.dependency_resolver is not None \
208
216
  else SHALLOW_DEPENDENCY_RESOLVER
209
217
 
@@ -212,9 +220,24 @@ class DataFlowKernel:
212
220
  def __enter__(self):
213
221
  return self
214
222
 
215
- def __exit__(self, exc_type, exc_value, traceback):
216
- logger.debug("Exiting the context manager, calling cleanup for DFK")
217
- self.cleanup()
223
+ def __exit__(self, exc_type, exc_value, traceback) -> None:
224
+ mode = self.config.exit_mode
225
+ logger.debug("Exiting context manager, with exit mode '%s'", mode)
226
+ if mode == "cleanup":
227
+ logger.info("Calling cleanup for DFK")
228
+ self.cleanup()
229
+ elif mode == "skip":
230
+ logger.info("Skipping all cleanup handling")
231
+ elif mode == "wait":
232
+ if exc_type is None:
233
+ logger.info("Waiting for all tasks to complete")
234
+ self.wait_for_current_tasks()
235
+ self.cleanup()
236
+ else:
237
+ logger.info("There was an exception - cleaning up without waiting for task completion")
238
+ self.cleanup()
239
+ else:
240
+ raise InternalConsistencyError(f"Exit case for {mode} should be unreachable, validated by typeguard on Config()")
218
241
 
219
242
  def _send_task_log_info(self, task_record: TaskRecord) -> None:
220
243
  if self.monitoring:
@@ -606,9 +629,9 @@ class DataFlowKernel:
606
629
  return kwargs.get('_parsl_staging_inhibit', False)
607
630
 
608
631
  def launch_if_ready(self, task_record: TaskRecord) -> None:
609
- """
610
- launch_if_ready will launch the specified task, if it is ready
611
- to run (for example, without dependencies, and in pending state).
632
+ """Schedules a task record for re-inspection to see if it is ready
633
+ for launch and for launch if it is ready. The call will return
634
+ immediately.
612
635
 
613
636
  This should be called by any piece of the DataFlowKernel that
614
637
  thinks a task may have become ready to run.
@@ -617,13 +640,17 @@ class DataFlowKernel:
617
640
  ready to run - launch_if_ready will not incorrectly launch that
618
641
  task.
619
642
 
620
- It is also not an error to call launch_if_ready on a task that has
621
- already been launched - launch_if_ready will not re-launch that
622
- task.
623
-
624
643
  launch_if_ready is thread safe, so may be called from any thread
625
644
  or callback.
626
645
  """
646
+ self.dependency_launch_pool.submit(self._launch_if_ready_async, task_record)
647
+
648
+ @wrap_with_logs
649
+ def _launch_if_ready_async(self, task_record: TaskRecord) -> None:
650
+ """
651
+ _launch_if_ready will launch the specified task, if it is ready
652
+ to run (for example, without dependencies, and in pending state).
653
+ """
627
654
  exec_fu = None
628
655
 
629
656
  task_id = task_record['id']
@@ -1266,6 +1293,10 @@ class DataFlowKernel:
1266
1293
  self.monitoring.close()
1267
1294
  logger.info("Terminated monitoring")
1268
1295
 
1296
+ logger.info("Terminating dependency launch pool")
1297
+ self.dependency_launch_pool.shutdown()
1298
+ logger.info("Terminated dependency launch pool")
1299
+
1269
1300
  logger.info("Unregistering atexit hook")
1270
1301
  atexit.unregister(self.atexit_cleanup)
1271
1302
  logger.info("Unregistered atexit hook")
parsl/dataflow/errors.py CHANGED
@@ -1,6 +1,7 @@
1
- from parsl.errors import ParslError
2
1
  from typing import Optional, Sequence, Tuple
3
2
 
3
+ from parsl.errors import ParslError
4
+
4
5
 
5
6
  class DataFlowException(ParslError):
6
7
  """Base class for all exceptions.
parsl/dataflow/futures.py CHANGED
@@ -1,12 +1,11 @@
1
1
  from __future__ import annotations
2
2
 
3
- from concurrent.futures import Future
4
3
  import logging
5
4
  import threading
5
+ from concurrent.futures import Future
6
6
  from typing import Any, Optional, Sequence, Union
7
7
 
8
8
  import parsl.app.app as app
9
-
10
9
  from parsl.app.futures import DataFuture
11
10
  from parsl.dataflow.taskrecord import TaskRecord
12
11
 
@@ -1,18 +1,18 @@
1
1
  from __future__ import annotations
2
+
2
3
  import hashlib
3
- from functools import lru_cache, singledispatch
4
4
  import logging
5
5
  import pickle
6
- from parsl.dataflow.taskrecord import TaskRecord
6
+ from functools import lru_cache, singledispatch
7
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional
7
8
 
8
- from typing import Dict, Any, List, Optional, TYPE_CHECKING
9
+ from parsl.dataflow.taskrecord import TaskRecord
9
10
 
10
11
  if TYPE_CHECKING:
11
12
  from parsl import DataFlowKernel # import loop at runtime - needed for typechecking - TODO turn into "if typing:"
12
13
 
13
- from concurrent.futures import Future
14
-
15
14
  import types
15
+ from concurrent.futures import Future
16
16
 
17
17
  logger = logging.getLogger(__name__)
18
18
 
parsl/dataflow/rundirs.py CHANGED
@@ -1,6 +1,6 @@
1
+ import logging
1
2
  import os
2
3
  from glob import glob
3
- import logging
4
4
 
5
5
  logger = logging.getLogger(__name__)
6
6
 
@@ -1,19 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
- import threading
4
3
  import datetime
5
- from typing_extensions import TypedDict
4
+ import threading
6
5
  from concurrent.futures import Future
7
6
 
8
-
9
7
  # only for type checking:
10
- from typing import Any, Callable, Dict, Optional, List, Sequence, TYPE_CHECKING, Union
8
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Union
9
+
10
+ from typing_extensions import TypedDict
11
11
 
12
12
  if TYPE_CHECKING:
13
13
  from parsl.dataflow.futures import AppFuture
14
14
 
15
15
  import parsl.dataflow.dflow as dflow
16
-
17
16
  from parsl.dataflow.states import States
18
17
 
19
18
 
@@ -1,8 +1,8 @@
1
- from parsl.executors.threads import ThreadPoolExecutor
2
- from parsl.executors.workqueue.executor import WorkQueueExecutor
1
+ from parsl.executors.flux.executor import FluxExecutor
3
2
  from parsl.executors.high_throughput.executor import HighThroughputExecutor
4
3
  from parsl.executors.high_throughput.mpi_executor import MPIExecutor
5
- from parsl.executors.flux.executor import FluxExecutor
4
+ from parsl.executors.threads import ThreadPoolExecutor
5
+ from parsl.executors.workqueue.executor import WorkQueueExecutor
6
6
 
7
7
  __all__ = ['ThreadPoolExecutor',
8
8
  'HighThroughputExecutor',
parsl/executors/base.py CHANGED
@@ -2,6 +2,7 @@ import os
2
2
  from abc import ABCMeta, abstractmethod
3
3
  from concurrent.futures import Future
4
4
  from typing import Any, Callable, Dict, Optional
5
+
5
6
  from typing_extensions import Literal, Self
6
7
 
7
8
  from parsl.monitoring.radios import MonitoringRadio
@@ -1,12 +1,12 @@
1
1
  """Script for executing tasks inside of Flux jobs."""
2
2
 
3
3
  import argparse
4
- import os
5
4
  import logging
5
+ import os
6
6
 
7
+ from parsl.executors.flux import TaskResult
7
8
  from parsl.executors.high_throughput.process_worker_pool import execute_task
8
9
  from parsl.serialize import serialize
9
- from parsl.executors.flux import TaskResult
10
10
 
11
11
 
12
12
  def main():
@@ -1,33 +1,32 @@
1
1
  """Defines the FluxExecutor class."""
2
2
 
3
+ import collections
3
4
  import concurrent.futures as cf
4
5
  import functools
6
+ import itertools
5
7
  import os
8
+ import queue
9
+ import shutil
6
10
  import sys
7
- import uuid
8
11
  import threading
9
- import itertools
10
- import shutil
11
- import queue
12
- from socket import gethostname
13
- import collections
14
- from collections.abc import Mapping, Callable
15
- from typing import Optional, Any, Dict
12
+ import uuid
16
13
  import weakref
14
+ from collections.abc import Callable, Mapping
15
+ from socket import gethostname
16
+ from typing import Any, Dict, Optional
17
17
 
18
18
  import zmq
19
19
 
20
- from parsl.utils import RepresentationMixin
20
+ from parsl.app.errors import AppException
21
21
  from parsl.executors.base import ParslExecutor
22
+ from parsl.executors.errors import ScalingFailed
22
23
  from parsl.executors.flux.execute_parsl_task import __file__ as _WORKER_PATH
23
24
  from parsl.executors.flux.flux_instance_manager import __file__ as _MANAGER_PATH
24
- from parsl.executors.errors import ScalingFailed
25
25
  from parsl.providers import LocalProvider
26
26
  from parsl.providers.base import ExecutionProvider
27
27
  from parsl.serialize import deserialize, pack_res_spec_apply_message
28
28
  from parsl.serialize.errors import SerializationError
29
- from parsl.app.errors import AppException
30
-
29
+ from parsl.utils import RepresentationMixin
31
30
 
32
31
  _WORKER_PATH = os.path.realpath(_WORKER_PATH)
33
32
  _MANAGER_PATH = os.path.realpath(_MANAGER_PATH)
@@ -1,10 +1,10 @@
1
1
  """Script meant to be the initial program of a Flux instance."""
2
2
 
3
3
  import argparse
4
+ import logging
4
5
  import os
5
6
  from os.path import dirname
6
- import logging
7
- from socket import gethostname, gethostbyname
7
+ from socket import gethostbyname, gethostname
8
8
 
9
9
  import zmq
10
10
 
@@ -16,8 +16,8 @@ def main():
16
16
  encapsulating Flux instance.
17
17
  """
18
18
  # flux imports only available when launched under Flux instance
19
- import flux.job
20
19
  import flux
20
+ import flux.job
21
21
 
22
22
  logging.basicConfig(
23
23
  level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s"
@@ -1,44 +1,39 @@
1
+ import logging
2
+ import math
3
+ import pickle
4
+ import threading
1
5
  import typing
6
+ import warnings
2
7
  from collections import defaultdict
3
8
  from concurrent.futures import Future
4
- import typeguard
5
- import logging
6
- import threading
7
- import queue
8
- import pickle
9
9
  from dataclasses import dataclass
10
- from multiprocessing import Process, Queue
11
- from typing import Dict, Sequence
12
- from typing import List, Optional, Tuple, Union, Callable
13
- import math
14
- import warnings
10
+ from multiprocessing import Process
11
+ from typing import Callable, Dict, List, Optional, Sequence, Tuple, Union
12
+
13
+ import typeguard
15
14
 
16
15
  import parsl.launchers
17
- from parsl.usage_tracking.api import UsageInformation
18
- from parsl.serialize import pack_res_spec_apply_message, deserialize
19
- from parsl.serialize.errors import SerializationError, DeserializationError
16
+ from parsl import curvezmq
17
+ from parsl.addresses import get_all_addresses
20
18
  from parsl.app.errors import RemoteExceptionWrapper
21
- from parsl.jobs.states import JobStatus, JobState, TERMINAL_STATES
22
- from parsl.executors.high_throughput import zmq_pipes
23
- from parsl.executors.high_throughput import interchange
24
- from parsl.executors.errors import (
25
- BadMessage, ScalingFailed,
26
- )
19
+ from parsl.data_provider.staging import Staging
20
+ from parsl.executors.errors import BadMessage, ScalingFailed
21
+ from parsl.executors.high_throughput import interchange, zmq_pipes
22
+ from parsl.executors.high_throughput.errors import CommandClientTimeoutError
27
23
  from parsl.executors.high_throughput.mpi_prefix_composer import (
28
24
  VALID_LAUNCHERS,
29
- validate_resource_spec
25
+ validate_resource_spec,
30
26
  )
31
-
32
- from parsl import curvezmq
33
27
  from parsl.executors.status_handling import BlockProviderExecutor
34
- from parsl.providers.base import ExecutionProvider
35
- from parsl.data_provider.staging import Staging
36
- from parsl.addresses import get_all_addresses
37
- from parsl.process_loggers import wrap_with_logs
38
-
28
+ from parsl.jobs.states import TERMINAL_STATES, JobState, JobStatus
39
29
  from parsl.multiprocessing import ForkProcess
40
- from parsl.utils import RepresentationMixin
30
+ from parsl.process_loggers import wrap_with_logs
41
31
  from parsl.providers import LocalProvider
32
+ from parsl.providers.base import ExecutionProvider
33
+ from parsl.serialize import deserialize, pack_res_spec_apply_message
34
+ from parsl.serialize.errors import DeserializationError, SerializationError
35
+ from parsl.usage_tracking.api import UsageInformation
36
+ from parsl.utils import RepresentationMixin
42
37
 
43
38
  logger = logging.getLogger(__name__)
44
39
 
@@ -415,13 +410,13 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
415
410
  )
416
411
 
417
412
  self.outgoing_q = zmq_pipes.TasksOutgoing(
418
- curvezmq.ClientContext(self.cert_dir), "127.0.0.1", self.interchange_port_range
413
+ "127.0.0.1", self.interchange_port_range, self.cert_dir
419
414
  )
420
415
  self.incoming_q = zmq_pipes.ResultsIncoming(
421
- curvezmq.ClientContext(self.cert_dir), "127.0.0.1", self.interchange_port_range
416
+ "127.0.0.1", self.interchange_port_range, self.cert_dir
422
417
  )
423
418
  self.command_client = zmq_pipes.CommandClient(
424
- curvezmq.ClientContext(self.cert_dir), "127.0.0.1", self.interchange_port_range
419
+ "127.0.0.1", self.interchange_port_range, self.cert_dir
425
420
  )
426
421
 
427
422
  self._queue_management_thread = None
@@ -531,10 +526,9 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
531
526
  Starts the interchange process locally and uses an internal command queue to
532
527
  get the worker task and result ports that the interchange has bound to.
533
528
  """
534
- comm_q = Queue(maxsize=10)
535
529
  self.interchange_proc = ForkProcess(target=interchange.starter,
536
- args=(comm_q,),
537
- kwargs={"client_ports": (self.outgoing_q.port,
530
+ kwargs={"client_address": "127.0.0.1",
531
+ "client_ports": (self.outgoing_q.port,
538
532
  self.incoming_q.port,
539
533
  self.command_client.port),
540
534
  "interchange_address": self.address,
@@ -552,9 +546,10 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
552
546
  name="HTEX-Interchange"
553
547
  )
554
548
  self.interchange_proc.start()
549
+
555
550
  try:
556
- (self.worker_task_port, self.worker_result_port) = comm_q.get(block=True, timeout=120)
557
- except queue.Empty:
551
+ (self.worker_task_port, self.worker_result_port) = self.command_client.run("WORKER_PORTS", timeout_s=120)
552
+ except CommandClientTimeoutError:
558
553
  logger.error("Interchange has not completed initialization in 120s. Aborting")
559
554
  raise Exception("Interchange failed to start")
560
555