parsl 2024.5.20__py3-none-any.whl → 2024.6.3__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 (291) 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 +12 -6
  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/dependency_resolvers.py +115 -0
  46. parsl/dataflow/dflow.py +65 -54
  47. parsl/dataflow/errors.py +2 -1
  48. parsl/dataflow/futures.py +1 -2
  49. parsl/dataflow/memoization.py +5 -5
  50. parsl/dataflow/rundirs.py +1 -1
  51. parsl/dataflow/taskrecord.py +4 -5
  52. parsl/executors/__init__.py +3 -3
  53. parsl/executors/base.py +1 -0
  54. parsl/executors/flux/execute_parsl_task.py +2 -2
  55. parsl/executors/flux/executor.py +11 -12
  56. parsl/executors/flux/flux_instance_manager.py +3 -3
  57. parsl/executors/high_throughput/errors.py +10 -0
  58. parsl/executors/high_throughput/executor.py +31 -36
  59. parsl/executors/high_throughput/interchange.py +16 -18
  60. parsl/executors/high_throughput/manager_record.py +1 -0
  61. parsl/executors/high_throughput/monitoring_info.py +2 -1
  62. parsl/executors/high_throughput/mpi_executor.py +6 -3
  63. parsl/executors/high_throughput/mpi_prefix_composer.py +19 -3
  64. parsl/executors/high_throughput/mpi_resource_management.py +1 -2
  65. parsl/executors/high_throughput/probe.py +6 -4
  66. parsl/executors/high_throughput/process_worker_pool.py +31 -20
  67. parsl/executors/high_throughput/zmq_pipes.py +63 -15
  68. parsl/executors/radical/executor.py +15 -15
  69. parsl/executors/radical/rpex_master.py +1 -2
  70. parsl/executors/radical/rpex_resources.py +4 -9
  71. parsl/executors/radical/rpex_worker.py +2 -1
  72. parsl/executors/status_handling.py +5 -4
  73. parsl/executors/taskvine/__init__.py +1 -1
  74. parsl/executors/taskvine/errors.py +1 -1
  75. parsl/executors/taskvine/exec_parsl_function.py +2 -2
  76. parsl/executors/taskvine/executor.py +23 -24
  77. parsl/executors/taskvine/factory.py +1 -1
  78. parsl/executors/taskvine/manager.py +11 -13
  79. parsl/executors/threads.py +4 -5
  80. parsl/executors/workqueue/errors.py +1 -1
  81. parsl/executors/workqueue/exec_parsl_function.py +5 -4
  82. parsl/executors/workqueue/executor.py +26 -27
  83. parsl/executors/workqueue/parsl_coprocess.py +1 -1
  84. parsl/jobs/error_handlers.py +1 -1
  85. parsl/jobs/job_status_poller.py +2 -5
  86. parsl/jobs/states.py +1 -1
  87. parsl/jobs/strategy.py +2 -2
  88. parsl/launchers/__init__.py +12 -3
  89. parsl/launchers/errors.py +1 -1
  90. parsl/log_utils.py +1 -2
  91. parsl/monitoring/db_manager.py +16 -10
  92. parsl/monitoring/monitoring.py +11 -15
  93. parsl/monitoring/queries/pandas.py +1 -2
  94. parsl/monitoring/radios.py +2 -4
  95. parsl/monitoring/remote.py +13 -8
  96. parsl/monitoring/router.py +8 -11
  97. parsl/monitoring/types.py +2 -0
  98. parsl/monitoring/visualization/app.py +4 -2
  99. parsl/monitoring/visualization/models.py +0 -1
  100. parsl/monitoring/visualization/plots/default/workflow_plots.py +8 -4
  101. parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +1 -0
  102. parsl/monitoring/visualization/utils.py +0 -1
  103. parsl/monitoring/visualization/views.py +16 -9
  104. parsl/multiprocessing.py +0 -1
  105. parsl/process_loggers.py +1 -2
  106. parsl/providers/__init__.py +9 -12
  107. parsl/providers/ad_hoc/ad_hoc.py +1 -1
  108. parsl/providers/aws/aws.py +2 -3
  109. parsl/providers/azure/azure.py +4 -5
  110. parsl/providers/base.py +1 -1
  111. parsl/providers/cluster_provider.py +1 -1
  112. parsl/providers/cobalt/cobalt.py +3 -3
  113. parsl/providers/condor/condor.py +4 -2
  114. parsl/providers/errors.py +2 -2
  115. parsl/providers/googlecloud/googlecloud.py +2 -1
  116. parsl/providers/grid_engine/grid_engine.py +2 -2
  117. parsl/providers/kubernetes/kube.py +5 -3
  118. parsl/providers/local/local.py +5 -1
  119. parsl/providers/lsf/lsf.py +2 -2
  120. parsl/providers/pbspro/pbspro.py +1 -1
  121. parsl/providers/slurm/slurm.py +5 -5
  122. parsl/providers/torque/torque.py +1 -1
  123. parsl/serialize/__init__.py +8 -3
  124. parsl/serialize/base.py +1 -2
  125. parsl/serialize/concretes.py +5 -4
  126. parsl/serialize/proxystore.py +3 -2
  127. parsl/tests/__init__.py +1 -1
  128. parsl/tests/configs/ad_hoc_cluster_htex.py +4 -4
  129. parsl/tests/configs/azure_single_node.py +4 -5
  130. parsl/tests/configs/bridges.py +3 -2
  131. parsl/tests/configs/cc_in2p3.py +2 -2
  132. parsl/tests/configs/comet.py +2 -1
  133. parsl/tests/configs/ec2_single_node.py +1 -2
  134. parsl/tests/configs/ec2_spot.py +1 -2
  135. parsl/tests/configs/frontera.py +3 -2
  136. parsl/tests/configs/htex_ad_hoc_cluster.py +2 -4
  137. parsl/tests/configs/htex_local.py +2 -3
  138. parsl/tests/configs/htex_local_alternate.py +8 -11
  139. parsl/tests/configs/htex_local_intask_staging.py +5 -7
  140. parsl/tests/configs/htex_local_rsync_staging.py +4 -6
  141. parsl/tests/configs/local_adhoc.py +1 -1
  142. parsl/tests/configs/local_radical.py +1 -3
  143. parsl/tests/configs/local_radical_mpi.py +2 -2
  144. parsl/tests/configs/midway.py +2 -2
  145. parsl/tests/configs/nscc_singapore.py +3 -3
  146. parsl/tests/configs/osg_htex.py +1 -1
  147. parsl/tests/configs/petrelkube.py +3 -2
  148. parsl/tests/configs/summit.py +1 -0
  149. parsl/tests/configs/swan_htex.py +2 -2
  150. parsl/tests/configs/taskvine_ex.py +3 -5
  151. parsl/tests/configs/theta.py +2 -2
  152. parsl/tests/configs/workqueue_ex.py +3 -4
  153. parsl/tests/conftest.py +6 -6
  154. parsl/tests/integration/test_channels/test_ssh_errors.py +1 -1
  155. parsl/tests/integration/test_stress/test_python_simple.py +3 -4
  156. parsl/tests/integration/test_stress/test_python_threads.py +3 -5
  157. parsl/tests/manual_tests/htex_local.py +4 -4
  158. parsl/tests/manual_tests/test_ad_hoc_htex.py +2 -1
  159. parsl/tests/manual_tests/test_basic.py +1 -0
  160. parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +4 -4
  161. parsl/tests/manual_tests/test_log_filter.py +3 -1
  162. parsl/tests/manual_tests/test_memory_limits.py +6 -6
  163. parsl/tests/manual_tests/test_regression_220.py +2 -1
  164. parsl/tests/manual_tests/test_udp_simple.py +4 -3
  165. parsl/tests/manual_tests/test_worker_count.py +3 -2
  166. parsl/tests/scaling_tests/htex_local.py +2 -2
  167. parsl/tests/scaling_tests/test_scale.py +0 -9
  168. parsl/tests/scaling_tests/vineex_condor.py +1 -2
  169. parsl/tests/scaling_tests/vineex_local.py +1 -2
  170. parsl/tests/site_tests/test_provider.py +3 -1
  171. parsl/tests/site_tests/test_site.py +2 -0
  172. parsl/tests/sites/test_affinity.py +7 -5
  173. parsl/tests/sites/test_dynamic_executor.py +3 -4
  174. parsl/tests/sites/test_ec2.py +3 -2
  175. parsl/tests/sites/test_local_adhoc.py +2 -1
  176. parsl/tests/sites/test_worker_info.py +4 -3
  177. parsl/tests/test_aalst_patterns.py +0 -1
  178. parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
  179. parsl/tests/test_bash_apps/test_error_codes.py +1 -4
  180. parsl/tests/test_bash_apps/test_memoize_ignore_args.py +1 -0
  181. parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +2 -2
  182. parsl/tests/test_bash_apps/test_pipeline.py +1 -1
  183. parsl/tests/test_bash_apps/test_std_uri.py +4 -9
  184. parsl/tests/test_callables.py +2 -2
  185. parsl/tests/test_checkpointing/test_periodic.py +2 -7
  186. parsl/tests/test_checkpointing/test_python_checkpoint_1.py +1 -0
  187. parsl/tests/test_checkpointing/test_python_checkpoint_2.py +2 -2
  188. parsl/tests/test_checkpointing/test_python_checkpoint_3.py +0 -1
  189. parsl/tests/test_checkpointing/test_regression_239.py +1 -1
  190. parsl/tests/test_checkpointing/test_task_exit.py +1 -2
  191. parsl/tests/test_docs/test_from_slides.py +2 -2
  192. parsl/tests/test_docs/test_kwargs.py +1 -1
  193. parsl/tests/test_docs/test_tutorial_1.py +1 -2
  194. parsl/tests/test_docs/test_workflow1.py +2 -2
  195. parsl/tests/test_docs/test_workflow2.py +0 -1
  196. parsl/tests/test_error_handling/test_rand_fail.py +2 -2
  197. parsl/tests/test_error_handling/test_resource_spec.py +4 -2
  198. parsl/tests/test_error_handling/test_retries.py +2 -1
  199. parsl/tests/test_error_handling/test_retry_handler.py +1 -0
  200. parsl/tests/test_error_handling/test_retry_handler_failure.py +2 -1
  201. parsl/tests/test_error_handling/test_serialization_fail.py +1 -1
  202. parsl/tests/test_error_handling/test_wrap_with_logs.py +1 -0
  203. parsl/tests/test_flux.py +1 -1
  204. parsl/tests/test_htex/test_basic.py +0 -1
  205. parsl/tests/test_htex/test_command_client_timeout.py +66 -0
  206. parsl/tests/test_htex/test_connected_blocks.py +3 -2
  207. parsl/tests/test_htex/test_cpu_affinity_explicit.py +6 -10
  208. parsl/tests/test_htex/test_disconnected_blocks.py +6 -4
  209. parsl/tests/test_htex/test_drain.py +5 -5
  210. parsl/tests/test_htex/test_htex.py +1 -2
  211. parsl/tests/test_htex/test_manager_failure.py +0 -1
  212. parsl/tests/test_htex/test_managers_command.py +5 -9
  213. parsl/tests/test_htex/test_missing_worker.py +2 -8
  214. parsl/tests/test_htex/test_multiple_disconnected_blocks.py +6 -4
  215. parsl/tests/test_monitoring/test_app_names.py +3 -3
  216. parsl/tests/test_monitoring/test_basic.py +4 -6
  217. parsl/tests/test_monitoring/test_db_locks.py +6 -4
  218. parsl/tests/test_monitoring/test_fuzz_zmq.py +6 -4
  219. parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +5 -7
  220. parsl/tests/test_monitoring/test_incomplete_futures.py +5 -4
  221. parsl/tests/test_monitoring/test_memoization_representation.py +4 -2
  222. parsl/tests/test_monitoring/test_stdouterr.py +4 -6
  223. parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
  224. parsl/tests/test_mpi_apps/test_bad_mpi_config.py +1 -1
  225. parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +4 -7
  226. parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +15 -4
  227. parsl/tests/test_mpi_apps/test_mpi_prefix.py +4 -4
  228. parsl/tests/test_mpi_apps/test_mpi_scheduler.py +7 -2
  229. parsl/tests/test_mpi_apps/test_mpiex.py +4 -3
  230. parsl/tests/test_mpi_apps/test_resource_spec.py +21 -17
  231. parsl/tests/test_providers/test_cobalt_deprecation_warning.py +2 -0
  232. parsl/tests/test_providers/test_local_provider.py +2 -1
  233. parsl/tests/test_providers/test_pbspro_template.py +1 -1
  234. parsl/tests/test_providers/test_slurm_template.py +1 -1
  235. parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
  236. parsl/tests/test_python_apps/test_context_manager.py +5 -12
  237. parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
  238. parsl/tests/test_python_apps/test_futures.py +2 -1
  239. parsl/tests/test_python_apps/test_join.py +0 -1
  240. parsl/tests/test_python_apps/test_lifted.py +11 -7
  241. parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +1 -0
  242. parsl/tests/test_python_apps/test_pluggable_future_resolution.py +161 -0
  243. parsl/tests/test_radical/test_mpi_funcs.py +1 -1
  244. parsl/tests/test_regression/test_1480.py +2 -1
  245. parsl/tests/test_regression/test_1653.py +2 -1
  246. parsl/tests/test_regression/test_2652.py +1 -0
  247. parsl/tests/test_regression/test_69a.py +0 -1
  248. parsl/tests/test_regression/test_854.py +4 -2
  249. parsl/tests/test_regression/test_97_parallelism_0.py +1 -2
  250. parsl/tests/test_regression/test_98.py +0 -1
  251. parsl/tests/test_scaling/test_block_error_handler.py +9 -4
  252. parsl/tests/test_scaling/test_regression_1621.py +0 -2
  253. parsl/tests/test_scaling/test_scale_down.py +2 -3
  254. parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +4 -5
  255. parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +3 -4
  256. parsl/tests/test_scaling/test_shutdown_scalein.py +1 -4
  257. parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
  258. parsl/tests/test_serialization/test_basic.py +2 -1
  259. parsl/tests/test_serialization/test_htex_code_cache.py +3 -4
  260. parsl/tests/test_serialization/test_pack_resource_spec.py +2 -1
  261. parsl/tests/test_serialization/test_proxystore_configured.py +10 -6
  262. parsl/tests/test_serialization/test_proxystore_impl.py +5 -3
  263. parsl/tests/test_shutdown/test_kill_monitoring.py +3 -4
  264. parsl/tests/test_staging/staging_provider.py +2 -2
  265. parsl/tests/test_staging/test_1316.py +3 -4
  266. parsl/tests/test_staging/test_docs_1.py +1 -1
  267. parsl/tests/test_staging/test_docs_2.py +2 -1
  268. parsl/tests/test_staging/test_elaborate_noop_file.py +2 -3
  269. parsl/tests/test_staging/test_staging_https.py +2 -2
  270. parsl/tests/test_staging/test_staging_stdout.py +4 -3
  271. parsl/tests/test_staging/test_zip_in.py +6 -8
  272. parsl/tests/test_staging/test_zip_out.py +7 -9
  273. parsl/tests/test_staging/test_zip_to_zip.py +6 -8
  274. parsl/tests/test_summary.py +2 -2
  275. parsl/tests/test_thread_parallelism.py +0 -1
  276. parsl/tests/test_threads/test_configs.py +1 -2
  277. parsl/tests/test_threads/test_lazy_errors.py +2 -2
  278. parsl/usage_tracking/api.py +2 -3
  279. parsl/usage_tracking/usage.py +8 -18
  280. parsl/utils.py +13 -2
  281. parsl/version.py +1 -1
  282. {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/exec_parsl_function.py +5 -4
  283. {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/process_worker_pool.py +31 -20
  284. {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/METADATA +6 -6
  285. parsl-2024.6.3.dist-info/RECORD +471 -0
  286. parsl-2024.5.20.dist-info/RECORD +0 -468
  287. {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/parsl_coprocess.py +1 -1
  288. {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/LICENSE +0 -0
  289. {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/WHEEL +0 -0
  290. {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/entry_points.txt +0 -0
  291. {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/top_level.txt +0 -0
@@ -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
 
@@ -0,0 +1,115 @@
1
+ from concurrent.futures import Future
2
+ from dataclasses import dataclass
3
+ from functools import singledispatch
4
+ from typing import Callable, Sequence
5
+
6
+
7
+ @dataclass
8
+ class DependencyResolver:
9
+ """A DependencyResolver describes how app dependencies can be resolved.
10
+ It is specified as two functions: `traverse_to_gather` which turns an
11
+ app parameter into a sequence of futures which must be waited for before
12
+ the task can be executed (for example, in the case of
13
+ `DEEP_DEPENDENCY_RESOLVER` this traverses structures such as lists to
14
+ find every contained ``Future``), and `traverse_to_unwrap` which turns an
15
+ app parameter into its value to be passed to the app on execution
16
+ (for example in the case of `DEEP_DEPENDENCY_RESOLVER` this replaces a
17
+ list containing futures with a new list containing the values of those
18
+ resolved futures).
19
+
20
+ By default, Parsl will use `SHALLOW_DEPENDENCY_RESOLVER` which only
21
+ resolves Futures passed directly as arguments.
22
+ """
23
+ traverse_to_gather: Callable[[object], Sequence[Future]]
24
+ traverse_to_unwrap: Callable[[object], object]
25
+
26
+
27
+ @singledispatch
28
+ def shallow_traverse_to_gather(o):
29
+ # objects in general do not expose futures that we can see
30
+ return []
31
+
32
+
33
+ @singledispatch
34
+ def shallow_traverse_to_unwrap(o):
35
+ # objects in general unwrap to themselves
36
+ return o
37
+
38
+
39
+ @shallow_traverse_to_gather.register
40
+ def _(fut: Future):
41
+ return [fut]
42
+
43
+
44
+ @shallow_traverse_to_unwrap.register
45
+ @singledispatch
46
+ def _(fut: Future):
47
+ assert fut.done()
48
+ return fut.result()
49
+
50
+
51
+ @singledispatch
52
+ def deep_traverse_to_gather(o):
53
+ # objects in general do not expose futures that we can see
54
+ return []
55
+
56
+
57
+ @singledispatch
58
+ def deep_traverse_to_unwrap(o):
59
+ # objects in general unwrap to themselves
60
+ return o
61
+
62
+
63
+ @deep_traverse_to_gather.register
64
+ def _(fut: Future):
65
+ return [fut]
66
+
67
+
68
+ @deep_traverse_to_unwrap.register
69
+ @singledispatch
70
+ def _(fut: Future):
71
+ assert fut.done()
72
+ return fut.result()
73
+
74
+
75
+ @deep_traverse_to_gather.register(tuple)
76
+ @deep_traverse_to_gather.register(list)
77
+ @deep_traverse_to_gather.register(set)
78
+ def _(iterable):
79
+ return [e for v in iterable for e in deep_traverse_to_gather(v)]
80
+
81
+
82
+ @deep_traverse_to_unwrap.register(tuple)
83
+ @deep_traverse_to_unwrap.register(list)
84
+ @deep_traverse_to_unwrap.register(set)
85
+ @singledispatch
86
+ def _(iterable):
87
+
88
+ type_ = type(iterable)
89
+ return type_(map(deep_traverse_to_unwrap, iterable))
90
+
91
+
92
+ @deep_traverse_to_gather.register(dict)
93
+ def _(dictionary):
94
+ futures = []
95
+ for key, value in dictionary.items():
96
+ futures.extend(deep_traverse_to_gather(key))
97
+ futures.extend(deep_traverse_to_gather(value))
98
+ return futures
99
+
100
+
101
+ @deep_traverse_to_unwrap.register(dict)
102
+ def _(dictionary):
103
+ unwrapped_dict = {}
104
+ for key, value in dictionary.items():
105
+ key = deep_traverse_to_unwrap(key)
106
+ value = deep_traverse_to_unwrap(value)
107
+ unwrapped_dict[key] = value
108
+ return unwrapped_dict
109
+
110
+
111
+ DEEP_DEPENDENCY_RESOLVER = DependencyResolver(traverse_to_gather=deep_traverse_to_gather,
112
+ traverse_to_unwrap=deep_traverse_to_unwrap)
113
+
114
+ SHALLOW_DEPENDENCY_RESOLVER = DependencyResolver(traverse_to_gather=shallow_traverse_to_gather,
115
+ traverse_to_unwrap=shallow_traverse_to_unwrap)
parsl/dataflow/dflow.py CHANGED
@@ -1,23 +1,25 @@
1
1
  from __future__ import annotations
2
+
2
3
  import atexit
4
+ import datetime
5
+ import inspect
3
6
  import logging
4
7
  import os
5
8
  import pathlib
6
9
  import pickle
7
10
  import random
8
- import time
9
- import typeguard
10
- import inspect
11
- import threading
12
11
  import sys
13
- import datetime
12
+ import threading
13
+ import time
14
+ from concurrent.futures import Future
15
+ from functools import partial
14
16
  from getpass import getuser
15
- from typeguard import typechecked
17
+ from socket import gethostname
16
18
  from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
17
19
  from uuid import uuid4
18
- from socket import gethostname
19
- from concurrent.futures import Future
20
- from functools import partial
20
+
21
+ import typeguard
22
+ from typeguard import typechecked
21
23
 
22
24
  import parsl
23
25
  from parsl.app.errors import RemoteExceptionWrapper
@@ -26,25 +28,29 @@ from parsl.channels import Channel
26
28
  from parsl.config import Config
27
29
  from parsl.data_provider.data_manager import DataManager
28
30
  from parsl.data_provider.files import File
31
+ from parsl.dataflow.dependency_resolvers import SHALLOW_DEPENDENCY_RESOLVER
29
32
  from parsl.dataflow.errors import BadCheckpoint, DependencyError, JoinError
30
33
  from parsl.dataflow.futures import AppFuture
31
34
  from parsl.dataflow.memoization import Memoizer
32
35
  from parsl.dataflow.rundirs import make_rundir
33
- from parsl.dataflow.states import States, FINAL_STATES, FINAL_FAILURE_STATES
36
+ from parsl.dataflow.states import FINAL_FAILURE_STATES, FINAL_STATES, States
34
37
  from parsl.dataflow.taskrecord import TaskRecord
35
- from parsl.errors import ConfigurationError, InternalConsistencyError, NoDataFlowKernelError
36
- from parsl.jobs.job_status_poller import JobStatusPoller
37
- from parsl.usage_tracking.usage import UsageTracker
38
+ from parsl.errors import (
39
+ ConfigurationError,
40
+ InternalConsistencyError,
41
+ NoDataFlowKernelError,
42
+ )
38
43
  from parsl.executors.base import ParslExecutor
39
44
  from parsl.executors.status_handling import BlockProviderExecutor
40
45
  from parsl.executors.threads import ThreadPoolExecutor
46
+ from parsl.jobs.job_status_poller import JobStatusPoller
41
47
  from parsl.monitoring import MonitoringHub
48
+ from parsl.monitoring.message_type import MessageType
42
49
  from parsl.monitoring.remote import monitor_wrapper
43
50
  from parsl.process_loggers import wrap_with_logs
44
51
  from parsl.providers.base import ExecutionProvider
45
- from parsl.utils import get_version, get_std_fname_mode, get_all_checkpoints, Timer
46
-
47
- from parsl.monitoring.message_type import MessageType
52
+ from parsl.usage_tracking.usage import UsageTracker
53
+ from parsl.utils import Timer, get_all_checkpoints, get_std_fname_mode, get_version
48
54
 
49
55
  logger = logging.getLogger(__name__)
50
56
 
@@ -203,6 +209,9 @@ class DataFlowKernel:
203
209
  self.tasks: Dict[int, TaskRecord] = {}
204
210
  self.submitter_lock = threading.Lock()
205
211
 
212
+ self.dependency_resolver = self.config.dependency_resolver if self.config.dependency_resolver is not None \
213
+ else SHALLOW_DEPENDENCY_RESOLVER
214
+
206
215
  atexit.register(self.atexit_cleanup)
207
216
 
208
217
  def __enter__(self):
@@ -852,8 +861,11 @@ class DataFlowKernel:
852
861
  depends: List[Future] = []
853
862
 
854
863
  def check_dep(d: Any) -> None:
855
- if isinstance(d, Future):
856
- depends.extend([d])
864
+ try:
865
+ depends.extend(self.dependency_resolver.traverse_to_gather(d))
866
+ except Exception:
867
+ logger.exception("Exception in dependency_resolver.traverse_to_gather")
868
+ raise
857
869
 
858
870
  # Check the positional args
859
871
  for dep in args:
@@ -870,7 +882,8 @@ class DataFlowKernel:
870
882
 
871
883
  return depends
872
884
 
873
- def _unwrap_futures(self, args, kwargs):
885
+ def _unwrap_futures(self, args: Sequence[Any], kwargs: Dict[str, Any]) \
886
+ -> Tuple[Sequence[Any], Dict[str, Any], Sequence[Tuple[Exception, str]]]:
874
887
  """This function should be called when all dependencies have completed.
875
888
 
876
889
  It will rewrite the arguments for that task, replacing each Future
@@ -891,53 +904,40 @@ class DataFlowKernel:
891
904
  """
892
905
  dep_failures = []
893
906
 
907
+ def append_failure(e: Exception, dep: Future) -> None:
908
+ # If this Future is associated with a task inside this DFK,
909
+ # then refer to the task ID.
910
+ # Otherwise make a repr of the Future object.
911
+ if hasattr(dep, 'task_record') and dep.task_record['dfk'] == self:
912
+ tid = "task " + repr(dep.task_record['id'])
913
+ else:
914
+ tid = repr(dep)
915
+ dep_failures.extend([(e, tid)])
916
+
894
917
  # Replace item in args
895
918
  new_args = []
896
919
  for dep in args:
897
- if isinstance(dep, Future):
898
- try:
899
- new_args.extend([dep.result()])
900
- except Exception as e:
901
- # If this Future is associated with a task inside this DFK,
902
- # then refer to the task ID.
903
- # Otherwise make a repr of the Future object.
904
- if hasattr(dep, 'task_record') and dep.task_record['dfk'] == self:
905
- tid = "task " + repr(dep.task_record['id'])
906
- else:
907
- tid = repr(dep)
908
- dep_failures.extend([(e, tid)])
909
- else:
910
- new_args.extend([dep])
920
+ try:
921
+ new_args.extend([self.dependency_resolver.traverse_to_unwrap(dep)])
922
+ except Exception as e:
923
+ append_failure(e, dep)
911
924
 
912
925
  # Check for explicit kwargs ex, fu_1=<fut>
913
926
  for key in kwargs:
914
927
  dep = kwargs[key]
915
- if isinstance(dep, Future):
916
- try:
917
- kwargs[key] = dep.result()
918
- except Exception as e:
919
- if hasattr(dep, 'task_record'):
920
- tid = dep.task_record['id']
921
- else:
922
- tid = None
923
- dep_failures.extend([(e, tid)])
928
+ try:
929
+ kwargs[key] = self.dependency_resolver.traverse_to_unwrap(dep)
930
+ except Exception as e:
931
+ append_failure(e, dep)
924
932
 
925
933
  # Check for futures in inputs=[<fut>...]
926
934
  if 'inputs' in kwargs:
927
935
  new_inputs = []
928
936
  for dep in kwargs['inputs']:
929
- if isinstance(dep, Future):
930
- try:
931
- new_inputs.extend([dep.result()])
932
- except Exception as e:
933
- if hasattr(dep, 'task_record'):
934
- tid = dep.task_record['id']
935
- else:
936
- tid = None
937
- dep_failures.extend([(e, tid)])
938
-
939
- else:
940
- new_inputs.extend([dep])
937
+ try:
938
+ new_inputs.extend([self.dependency_resolver.traverse_to_unwrap(dep)])
939
+ except Exception as e:
940
+ append_failure(e, dep)
941
941
  kwargs['inputs'] = new_inputs
942
942
 
943
943
  return new_args, kwargs, dep_failures
@@ -1042,6 +1042,8 @@ class DataFlowKernel:
1042
1042
 
1043
1043
  func = self._add_output_deps(executor, app_args, app_kwargs, app_fu, func)
1044
1044
 
1045
+ logger.debug("Added output dependencies")
1046
+
1045
1047
  # Replace the function invocation in the TaskRecord with whatever file-staging
1046
1048
  # substitutions have been made.
1047
1049
  task_record.update({
@@ -1053,8 +1055,10 @@ class DataFlowKernel:
1053
1055
 
1054
1056
  self.tasks[task_id] = task_record
1055
1057
 
1058
+ logger.debug("Gathering dependencies")
1056
1059
  # Get the list of dependencies for the task
1057
1060
  depends = self._gather_all_deps(app_args, app_kwargs)
1061
+ logger.debug("Gathered dependencies")
1058
1062
  task_record['depends'] = depends
1059
1063
 
1060
1064
  depend_descs = []
@@ -1271,6 +1275,13 @@ class DataFlowKernel:
1271
1275
  atexit.unregister(self.atexit_cleanup)
1272
1276
  logger.info("Unregistered atexit hook")
1273
1277
 
1278
+ if DataFlowKernelLoader._dfk is self:
1279
+ logger.info("Unregistering default DFK")
1280
+ parsl.clear()
1281
+ logger.info("Unregistered default DFK")
1282
+ else:
1283
+ logger.debug("Cleaning up non-default DFK - not unregistering")
1284
+
1274
1285
  logger.info("DFK cleanup complete")
1275
1286
 
1276
1287
  def checkpoint(self, tasks: Optional[Sequence[TaskRecord]] = None) -> str:
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"
@@ -10,3 +10,13 @@ class WorkerLost(Exception):
10
10
 
11
11
  def __str__(self):
12
12
  return self.__repr__()
13
+
14
+
15
+ class CommandClientTimeoutError(Exception):
16
+ """Raised when the command client times out waiting for a response.
17
+ """
18
+
19
+
20
+ class CommandClientBadError(Exception):
21
+ """Raised when the command client is bad from an earlier timeout.
22
+ """