parsl 2024.3.11__py3-none-any.whl → 2025.1.13__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 (369) hide show
  1. parsl/__init__.py +9 -10
  2. parsl/addresses.py +29 -7
  3. parsl/app/app.py +7 -8
  4. parsl/app/bash.py +15 -8
  5. parsl/app/errors.py +10 -13
  6. parsl/app/futures.py +8 -10
  7. parsl/app/python.py +2 -1
  8. parsl/benchmark/perf.py +2 -1
  9. parsl/concurrent/__init__.py +2 -2
  10. parsl/config.py +57 -10
  11. parsl/configs/ASPIRE1.py +6 -5
  12. parsl/configs/Azure.py +9 -8
  13. parsl/configs/bridges.py +6 -4
  14. parsl/configs/cc_in2p3.py +3 -3
  15. parsl/configs/ec2.py +3 -1
  16. parsl/configs/expanse.py +4 -3
  17. parsl/configs/frontera.py +3 -4
  18. parsl/configs/htex_local.py +3 -4
  19. parsl/configs/illinoiscluster.py +3 -1
  20. parsl/configs/improv.py +34 -0
  21. parsl/configs/kubernetes.py +4 -3
  22. parsl/configs/local_threads.py +5 -1
  23. parsl/configs/midway.py +5 -3
  24. parsl/configs/osg.py +4 -2
  25. parsl/configs/polaris.py +4 -2
  26. parsl/configs/stampede2.py +6 -5
  27. parsl/configs/summit.py +3 -3
  28. parsl/configs/toss3_llnl.py +4 -3
  29. parsl/configs/vineex_local.py +6 -4
  30. parsl/configs/wqex_local.py +5 -3
  31. parsl/curvezmq.py +4 -0
  32. parsl/data_provider/data_manager.py +4 -3
  33. parsl/data_provider/file_noop.py +1 -2
  34. parsl/data_provider/files.py +3 -3
  35. parsl/data_provider/ftp.py +1 -3
  36. parsl/data_provider/globus.py +7 -6
  37. parsl/data_provider/http.py +2 -2
  38. parsl/data_provider/rsync.py +1 -1
  39. parsl/data_provider/staging.py +2 -2
  40. parsl/data_provider/zip.py +135 -0
  41. parsl/dataflow/dependency_resolvers.py +115 -0
  42. parsl/dataflow/dflow.py +262 -224
  43. parsl/dataflow/errors.py +3 -5
  44. parsl/dataflow/futures.py +27 -14
  45. parsl/dataflow/memoization.py +5 -5
  46. parsl/dataflow/rundirs.py +5 -6
  47. parsl/dataflow/taskrecord.py +4 -5
  48. parsl/executors/__init__.py +4 -2
  49. parsl/executors/base.py +45 -15
  50. parsl/executors/errors.py +13 -0
  51. parsl/executors/execute_task.py +37 -0
  52. parsl/executors/flux/execute_parsl_task.py +3 -3
  53. parsl/executors/flux/executor.py +18 -19
  54. parsl/executors/flux/flux_instance_manager.py +26 -27
  55. parsl/executors/high_throughput/errors.py +43 -3
  56. parsl/executors/high_throughput/executor.py +316 -282
  57. parsl/executors/high_throughput/interchange.py +158 -167
  58. parsl/executors/high_throughput/manager_record.py +5 -0
  59. parsl/executors/high_throughput/manager_selector.py +55 -0
  60. parsl/executors/high_throughput/monitoring_info.py +2 -1
  61. parsl/executors/high_throughput/mpi_executor.py +113 -0
  62. parsl/executors/high_throughput/mpi_prefix_composer.py +10 -11
  63. parsl/executors/high_throughput/mpi_resource_management.py +6 -17
  64. parsl/executors/high_throughput/probe.py +9 -7
  65. parsl/executors/high_throughput/process_worker_pool.py +115 -77
  66. parsl/executors/high_throughput/zmq_pipes.py +81 -23
  67. parsl/executors/radical/executor.py +130 -79
  68. parsl/executors/radical/rpex_resources.py +17 -15
  69. parsl/executors/radical/rpex_worker.py +4 -3
  70. parsl/executors/status_handling.py +157 -51
  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 +41 -57
  75. parsl/executors/taskvine/factory.py +1 -1
  76. parsl/executors/taskvine/factory_config.py +1 -1
  77. parsl/executors/taskvine/manager.py +18 -13
  78. parsl/executors/taskvine/manager_config.py +9 -5
  79. parsl/executors/threads.py +6 -6
  80. parsl/executors/workqueue/errors.py +1 -1
  81. parsl/executors/workqueue/exec_parsl_function.py +6 -5
  82. parsl/executors/workqueue/executor.py +64 -63
  83. parsl/executors/workqueue/parsl_coprocess.py +1 -1
  84. parsl/jobs/error_handlers.py +2 -2
  85. parsl/jobs/job_status_poller.py +30 -113
  86. parsl/jobs/states.py +7 -2
  87. parsl/jobs/strategy.py +43 -31
  88. parsl/launchers/__init__.py +12 -3
  89. parsl/launchers/errors.py +1 -1
  90. parsl/launchers/launchers.py +6 -12
  91. parsl/log_utils.py +9 -6
  92. parsl/monitoring/db_manager.py +59 -95
  93. parsl/monitoring/errors.py +6 -0
  94. parsl/monitoring/monitoring.py +87 -356
  95. parsl/monitoring/queries/pandas.py +1 -2
  96. parsl/monitoring/radios/base.py +13 -0
  97. parsl/monitoring/radios/filesystem.py +52 -0
  98. parsl/monitoring/radios/htex.py +57 -0
  99. parsl/monitoring/radios/multiprocessing.py +17 -0
  100. parsl/monitoring/radios/udp.py +56 -0
  101. parsl/monitoring/radios/zmq.py +17 -0
  102. parsl/monitoring/remote.py +33 -37
  103. parsl/monitoring/router.py +212 -0
  104. parsl/monitoring/types.py +5 -6
  105. parsl/monitoring/visualization/app.py +4 -2
  106. parsl/monitoring/visualization/models.py +0 -1
  107. parsl/monitoring/visualization/plots/default/workflow_plots.py +11 -4
  108. parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +1 -0
  109. parsl/monitoring/visualization/utils.py +0 -1
  110. parsl/monitoring/visualization/views.py +16 -8
  111. parsl/multiprocessing.py +0 -1
  112. parsl/process_loggers.py +1 -2
  113. parsl/providers/__init__.py +8 -17
  114. parsl/providers/aws/aws.py +2 -3
  115. parsl/providers/azure/azure.py +4 -5
  116. parsl/providers/base.py +2 -18
  117. parsl/providers/cluster_provider.py +4 -12
  118. parsl/providers/condor/condor.py +7 -17
  119. parsl/providers/errors.py +2 -2
  120. parsl/providers/googlecloud/googlecloud.py +2 -1
  121. parsl/providers/grid_engine/grid_engine.py +5 -14
  122. parsl/providers/kubernetes/kube.py +80 -40
  123. parsl/providers/local/local.py +13 -26
  124. parsl/providers/lsf/lsf.py +5 -23
  125. parsl/providers/pbspro/pbspro.py +5 -17
  126. parsl/providers/slurm/slurm.py +81 -39
  127. parsl/providers/torque/torque.py +3 -14
  128. parsl/serialize/__init__.py +8 -3
  129. parsl/serialize/base.py +1 -2
  130. parsl/serialize/concretes.py +5 -4
  131. parsl/serialize/facade.py +3 -3
  132. parsl/serialize/proxystore.py +3 -2
  133. parsl/tests/__init__.py +1 -1
  134. parsl/tests/configs/azure_single_node.py +4 -5
  135. parsl/tests/configs/bridges.py +3 -2
  136. parsl/tests/configs/cc_in2p3.py +1 -3
  137. parsl/tests/configs/comet.py +2 -1
  138. parsl/tests/configs/ec2_single_node.py +1 -2
  139. parsl/tests/configs/ec2_spot.py +1 -2
  140. parsl/tests/configs/flux_local.py +11 -0
  141. parsl/tests/configs/frontera.py +2 -3
  142. parsl/tests/configs/htex_local.py +3 -5
  143. parsl/tests/configs/htex_local_alternate.py +11 -15
  144. parsl/tests/configs/htex_local_intask_staging.py +5 -9
  145. parsl/tests/configs/htex_local_rsync_staging.py +4 -8
  146. parsl/tests/configs/local_radical.py +1 -3
  147. parsl/tests/configs/local_radical_mpi.py +2 -2
  148. parsl/tests/configs/local_threads_checkpoint_periodic.py +8 -10
  149. parsl/tests/configs/local_threads_monitoring.py +0 -1
  150. parsl/tests/configs/midway.py +2 -2
  151. parsl/tests/configs/nscc_singapore.py +3 -3
  152. parsl/tests/configs/osg_htex.py +1 -1
  153. parsl/tests/configs/petrelkube.py +3 -2
  154. parsl/tests/configs/slurm_local.py +24 -0
  155. parsl/tests/configs/summit.py +1 -0
  156. parsl/tests/configs/taskvine_ex.py +4 -7
  157. parsl/tests/configs/user_opts.py +2 -8
  158. parsl/tests/configs/workqueue_ex.py +4 -6
  159. parsl/tests/conftest.py +27 -13
  160. parsl/tests/integration/test_stress/test_python_simple.py +3 -4
  161. parsl/tests/integration/test_stress/test_python_threads.py +3 -5
  162. parsl/tests/manual_tests/htex_local.py +4 -6
  163. parsl/tests/manual_tests/test_basic.py +1 -0
  164. parsl/tests/manual_tests/test_log_filter.py +3 -1
  165. parsl/tests/manual_tests/test_memory_limits.py +6 -8
  166. parsl/tests/manual_tests/test_regression_220.py +2 -1
  167. parsl/tests/manual_tests/test_udp_simple.py +4 -4
  168. parsl/tests/manual_tests/test_worker_count.py +3 -2
  169. parsl/tests/scaling_tests/htex_local.py +2 -4
  170. parsl/tests/scaling_tests/test_scale.py +0 -9
  171. parsl/tests/scaling_tests/vineex_condor.py +1 -2
  172. parsl/tests/scaling_tests/vineex_local.py +1 -2
  173. parsl/tests/site_tests/site_config_selector.py +1 -6
  174. parsl/tests/site_tests/test_provider.py +4 -2
  175. parsl/tests/site_tests/test_site.py +2 -0
  176. parsl/tests/sites/test_affinity.py +7 -7
  177. parsl/tests/sites/test_dynamic_executor.py +3 -4
  178. parsl/tests/sites/test_ec2.py +3 -2
  179. parsl/tests/sites/test_worker_info.py +4 -5
  180. parsl/tests/test_aalst_patterns.py +0 -1
  181. parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
  182. parsl/tests/test_bash_apps/test_basic.py +10 -4
  183. parsl/tests/test_bash_apps/test_error_codes.py +5 -7
  184. parsl/tests/test_bash_apps/test_inputs_default.py +25 -0
  185. parsl/tests/test_bash_apps/test_kwarg_storage.py +1 -1
  186. parsl/tests/test_bash_apps/test_memoize.py +2 -8
  187. parsl/tests/test_bash_apps/test_memoize_ignore_args.py +9 -14
  188. parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +9 -14
  189. parsl/tests/test_bash_apps/test_multiline.py +1 -1
  190. parsl/tests/test_bash_apps/test_pipeline.py +1 -1
  191. parsl/tests/test_bash_apps/test_std_uri.py +123 -0
  192. parsl/tests/test_bash_apps/test_stdout.py +33 -8
  193. parsl/tests/test_callables.py +2 -2
  194. parsl/tests/test_checkpointing/test_periodic.py +21 -39
  195. parsl/tests/test_checkpointing/test_python_checkpoint_1.py +1 -0
  196. parsl/tests/test_checkpointing/test_python_checkpoint_2.py +2 -2
  197. parsl/tests/test_checkpointing/test_python_checkpoint_3.py +0 -1
  198. parsl/tests/test_checkpointing/test_regression_239.py +1 -1
  199. parsl/tests/test_checkpointing/test_task_exit.py +2 -3
  200. parsl/tests/test_docs/test_from_slides.py +5 -2
  201. parsl/tests/test_docs/test_kwargs.py +4 -1
  202. parsl/tests/test_docs/test_tutorial_1.py +1 -2
  203. parsl/tests/test_docs/test_workflow1.py +2 -2
  204. parsl/tests/test_docs/test_workflow2.py +0 -1
  205. parsl/tests/test_error_handling/test_rand_fail.py +2 -2
  206. parsl/tests/test_error_handling/test_resource_spec.py +10 -12
  207. parsl/tests/test_error_handling/test_retries.py +6 -16
  208. parsl/tests/test_error_handling/test_retry_handler.py +1 -0
  209. parsl/tests/test_error_handling/test_retry_handler_failure.py +2 -1
  210. parsl/tests/test_error_handling/test_serialization_fail.py +1 -1
  211. parsl/tests/test_error_handling/test_wrap_with_logs.py +1 -0
  212. parsl/tests/test_execute_task.py +29 -0
  213. parsl/tests/test_flux.py +1 -1
  214. parsl/tests/test_htex/test_basic.py +2 -3
  215. parsl/tests/test_htex/test_block_manager_selector_unit.py +20 -0
  216. parsl/tests/test_htex/test_command_client_timeout.py +66 -0
  217. parsl/tests/test_htex/test_connected_blocks.py +3 -2
  218. parsl/tests/test_htex/test_cpu_affinity_explicit.py +6 -10
  219. parsl/tests/test_htex/test_disconnected_blocks.py +6 -5
  220. parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +71 -0
  221. parsl/tests/test_htex/test_drain.py +79 -0
  222. parsl/tests/test_htex/test_htex.py +51 -25
  223. parsl/tests/test_htex/test_manager_failure.py +0 -1
  224. parsl/tests/test_htex/test_manager_selector_by_block.py +51 -0
  225. parsl/tests/test_htex/test_managers_command.py +36 -0
  226. parsl/tests/test_htex/test_missing_worker.py +2 -12
  227. parsl/tests/test_htex/test_multiple_disconnected_blocks.py +9 -9
  228. parsl/tests/test_htex/test_resource_spec_validation.py +45 -0
  229. parsl/tests/test_htex/test_zmq_binding.py +29 -8
  230. parsl/tests/test_monitoring/test_app_names.py +86 -0
  231. parsl/tests/test_monitoring/test_basic.py +73 -25
  232. parsl/tests/test_monitoring/test_db_locks.py +6 -4
  233. parsl/tests/test_monitoring/test_fuzz_zmq.py +19 -8
  234. parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +80 -0
  235. parsl/tests/test_monitoring/test_incomplete_futures.py +5 -4
  236. parsl/tests/test_monitoring/test_memoization_representation.py +4 -2
  237. parsl/tests/test_monitoring/test_stdouterr.py +134 -0
  238. parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
  239. parsl/tests/test_mpi_apps/test_bad_mpi_config.py +33 -26
  240. parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +28 -11
  241. parsl/tests/test_mpi_apps/test_mpi_prefix.py +4 -4
  242. parsl/tests/test_mpi_apps/test_mpi_scheduler.py +7 -2
  243. parsl/tests/test_mpi_apps/test_mpiex.py +64 -0
  244. parsl/tests/test_mpi_apps/test_resource_spec.py +42 -49
  245. parsl/tests/test_providers/test_kubernetes_provider.py +102 -0
  246. parsl/tests/test_providers/test_local_provider.py +3 -132
  247. parsl/tests/test_providers/test_pbspro_template.py +2 -3
  248. parsl/tests/test_providers/test_slurm_template.py +2 -3
  249. parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
  250. parsl/tests/test_python_apps/test_context_manager.py +128 -0
  251. parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
  252. parsl/tests/test_python_apps/test_dependencies_deep.py +59 -0
  253. parsl/tests/test_python_apps/test_fail.py +0 -25
  254. parsl/tests/test_python_apps/test_futures.py +2 -1
  255. parsl/tests/test_python_apps/test_inputs_default.py +22 -0
  256. parsl/tests/test_python_apps/test_join.py +0 -1
  257. parsl/tests/test_python_apps/test_lifted.py +11 -7
  258. parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +1 -0
  259. parsl/tests/test_python_apps/test_outputs.py +1 -1
  260. parsl/tests/test_python_apps/test_pluggable_future_resolution.py +161 -0
  261. parsl/tests/test_radical/test_mpi_funcs.py +1 -2
  262. parsl/tests/test_regression/test_1480.py +2 -1
  263. parsl/tests/test_regression/test_1653.py +2 -1
  264. parsl/tests/test_regression/test_226.py +1 -0
  265. parsl/tests/test_regression/test_2652.py +1 -0
  266. parsl/tests/test_regression/test_69a.py +0 -1
  267. parsl/tests/test_regression/test_854.py +4 -2
  268. parsl/tests/test_regression/test_97_parallelism_0.py +1 -2
  269. parsl/tests/test_regression/test_98.py +0 -1
  270. parsl/tests/test_scaling/test_block_error_handler.py +9 -4
  271. parsl/tests/test_scaling/test_regression_1621.py +11 -15
  272. parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +84 -0
  273. parsl/tests/test_scaling/test_regression_3696_oscillation.py +103 -0
  274. parsl/tests/test_scaling/test_scale_down.py +2 -5
  275. parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +6 -18
  276. parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +71 -0
  277. parsl/tests/test_scaling/test_shutdown_scalein.py +73 -0
  278. parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +90 -0
  279. parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
  280. parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +47 -0
  281. parsl/tests/test_serialization/test_basic.py +2 -1
  282. parsl/tests/test_serialization/test_htex_code_cache.py +3 -4
  283. parsl/tests/test_serialization/test_pack_resource_spec.py +2 -1
  284. parsl/tests/test_serialization/test_proxystore_configured.py +10 -6
  285. parsl/tests/test_serialization/test_proxystore_impl.py +5 -3
  286. parsl/tests/test_shutdown/test_kill_monitoring.py +64 -0
  287. parsl/tests/test_staging/staging_provider.py +2 -2
  288. parsl/tests/test_staging/test_1316.py +3 -4
  289. parsl/tests/test_staging/test_docs_1.py +2 -1
  290. parsl/tests/test_staging/test_docs_2.py +2 -1
  291. parsl/tests/test_staging/test_elaborate_noop_file.py +2 -3
  292. parsl/tests/{test_data → test_staging}/test_file.py +6 -6
  293. parsl/tests/{test_data → test_staging}/test_output_chain_filenames.py +3 -0
  294. parsl/tests/test_staging/test_staging_ftp.py +1 -0
  295. parsl/tests/test_staging/test_staging_https.py +5 -2
  296. parsl/tests/test_staging/test_staging_stdout.py +64 -0
  297. parsl/tests/test_staging/test_zip_in.py +39 -0
  298. parsl/tests/test_staging/test_zip_out.py +110 -0
  299. parsl/tests/test_staging/test_zip_to_zip.py +41 -0
  300. parsl/tests/test_summary.py +2 -2
  301. parsl/tests/test_thread_parallelism.py +0 -1
  302. parsl/tests/test_threads/test_configs.py +1 -2
  303. parsl/tests/test_threads/test_lazy_errors.py +2 -2
  304. parsl/tests/test_utils/test_execute_wait.py +35 -0
  305. parsl/tests/test_utils/test_sanitize_dns.py +76 -0
  306. parsl/tests/unit/test_address.py +20 -0
  307. parsl/tests/unit/test_file.py +99 -0
  308. parsl/tests/unit/test_usage_tracking.py +66 -0
  309. parsl/usage_tracking/api.py +65 -0
  310. parsl/usage_tracking/levels.py +6 -0
  311. parsl/usage_tracking/usage.py +104 -62
  312. parsl/utils.py +139 -6
  313. parsl/version.py +1 -1
  314. {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/exec_parsl_function.py +6 -5
  315. parsl-2025.1.13.data/scripts/interchange.py +649 -0
  316. {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/process_worker_pool.py +115 -77
  317. parsl-2025.1.13.dist-info/METADATA +96 -0
  318. parsl-2025.1.13.dist-info/RECORD +462 -0
  319. {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/WHEEL +1 -1
  320. parsl/channels/__init__.py +0 -7
  321. parsl/channels/base.py +0 -141
  322. parsl/channels/errors.py +0 -113
  323. parsl/channels/local/local.py +0 -164
  324. parsl/channels/oauth_ssh/oauth_ssh.py +0 -110
  325. parsl/channels/ssh/ssh.py +0 -276
  326. parsl/channels/ssh_il/__init__.py +0 -0
  327. parsl/channels/ssh_il/ssh_il.py +0 -74
  328. parsl/configs/ad_hoc.py +0 -35
  329. parsl/executors/radical/rpex_master.py +0 -42
  330. parsl/monitoring/radios.py +0 -175
  331. parsl/providers/ad_hoc/__init__.py +0 -0
  332. parsl/providers/ad_hoc/ad_hoc.py +0 -248
  333. parsl/providers/cobalt/__init__.py +0 -0
  334. parsl/providers/cobalt/cobalt.py +0 -236
  335. parsl/providers/cobalt/template.py +0 -17
  336. parsl/tests/configs/ad_hoc_cluster_htex.py +0 -35
  337. parsl/tests/configs/cooley_htex.py +0 -37
  338. parsl/tests/configs/htex_ad_hoc_cluster.py +0 -28
  339. parsl/tests/configs/local_adhoc.py +0 -18
  340. parsl/tests/configs/swan_htex.py +0 -43
  341. parsl/tests/configs/theta.py +0 -37
  342. parsl/tests/integration/test_channels/__init__.py +0 -0
  343. parsl/tests/integration/test_channels/test_channels.py +0 -17
  344. parsl/tests/integration/test_channels/test_local_channel.py +0 -42
  345. parsl/tests/integration/test_channels/test_scp_1.py +0 -45
  346. parsl/tests/integration/test_channels/test_ssh_1.py +0 -40
  347. parsl/tests/integration/test_channels/test_ssh_errors.py +0 -46
  348. parsl/tests/integration/test_channels/test_ssh_file_transport.py +0 -41
  349. parsl/tests/integration/test_channels/test_ssh_interactive.py +0 -24
  350. parsl/tests/manual_tests/test_ad_hoc_htex.py +0 -48
  351. parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +0 -88
  352. parsl/tests/manual_tests/test_oauth_ssh.py +0 -13
  353. parsl/tests/sites/test_local_adhoc.py +0 -61
  354. parsl/tests/test_channels/__init__.py +0 -0
  355. parsl/tests/test_channels/test_large_output.py +0 -22
  356. parsl/tests/test_data/__init__.py +0 -0
  357. parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +0 -51
  358. parsl/tests/test_providers/test_cobalt_deprecation_warning.py +0 -16
  359. parsl-2024.3.11.dist-info/METADATA +0 -98
  360. parsl-2024.3.11.dist-info/RECORD +0 -447
  361. parsl/{channels/local → monitoring/radios}/__init__.py +0 -0
  362. parsl/{channels/oauth_ssh → tests/test_shutdown}/__init__.py +0 -0
  363. parsl/tests/{test_data → test_staging}/test_file_apps.py +0 -0
  364. parsl/tests/{test_data → test_staging}/test_file_staging.py +0 -0
  365. parsl/{channels/ssh → tests/unit}/__init__.py +0 -0
  366. {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/parsl_coprocess.py +1 -1
  367. {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/LICENSE +0 -0
  368. {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/entry_points.txt +0 -0
  369. {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/top_level.txt +0 -0
@@ -1,22 +1,12 @@
1
- import argparse
2
- import time
3
-
4
1
  import pytest
5
2
 
6
3
  import parsl
7
4
  from parsl.app.app import python_app
8
- from parsl.tests.configs.local_threads_checkpoint_periodic import config
5
+ from parsl.tests.configs.local_threads_checkpoint_periodic import fresh_config
9
6
 
10
7
 
11
8
  def local_setup():
12
- global dfk
13
- dfk = parsl.load(config)
14
-
15
-
16
- def local_teardown():
17
- # explicit clear without dfk.cleanup here, because the
18
- # test does that already
19
- parsl.clear()
9
+ parsl.load(fresh_config())
20
10
 
21
11
 
22
12
  @python_app(cache=True)
@@ -27,40 +17,32 @@ def slow_double(x, sleep_dur=1):
27
17
 
28
18
 
29
19
  def tstamp_to_seconds(line):
30
- print("Parsing line: ", line)
31
20
  f = line.partition(" ")[0]
32
21
  return float(f)
33
22
 
34
23
 
35
24
  @pytest.mark.local
36
- def test_periodic(n=4):
25
+ def test_periodic():
37
26
  """Test checkpointing with task_periodic behavior
38
27
  """
39
-
40
- d = {}
41
-
42
- print("Launching : ", n)
43
- for i in range(0, n):
44
- d[i] = slow_double(i)
45
- print("Done launching")
46
-
47
- for i in range(0, n):
48
- d[i].result()
49
- print("Done sleeping")
50
-
51
- time.sleep(16)
52
- dfk.cleanup()
28
+ h, m, s = map(int, parsl.dfk().config.checkpoint_period.split(":"))
29
+ assert h == 0, "Verify test setup"
30
+ assert m == 0, "Verify test setup"
31
+ assert s > 0, "Verify test setup"
32
+ sleep_for = s + 1
33
+ with parsl.dfk():
34
+ futs = [slow_double(sleep_for) for _ in range(4)]
35
+ [f.result() for f in futs]
36
+ run_dir = parsl.dfk().run_dir
53
37
 
54
38
  # Here we will check if the loglines came back with 5 seconds deltas
55
- print("Rundir: ", dfk.run_dir)
56
-
57
- with open("{}/parsl.log".format(dfk.run_dir), 'r') as f:
39
+ with open("{}/parsl.log".format(run_dir)) as f:
58
40
  log_lines = f.readlines()
59
- expected_msg = " Done checkpointing"
60
- expected_msg2 = " No tasks checkpointed in this pass"
61
-
62
- lines = [line for line in log_lines if expected_msg in line or expected_msg2 in line]
63
- assert len(lines) >= 3, "Insufficient checkpoint lines in logfile"
64
- deltas = [tstamp_to_seconds(line) for line in lines]
65
- assert deltas[1] - deltas[0] < 5.5, "Delta between checkpoints exceeded period"
66
- assert deltas[2] - deltas[1] < 5.5, "Delta between checkpoints exceeded period"
41
+ expected_msg = " Done checkpointing"
42
+ expected_msg2 = " No tasks checkpointed in this pass"
43
+
44
+ lines = [line for line in log_lines if expected_msg in line or expected_msg2 in line]
45
+ assert len(lines) >= 3, "Insufficient checkpoint lines in logfile"
46
+ deltas = [tstamp_to_seconds(line) for line in lines]
47
+ assert deltas[1] - deltas[0] < 5.5, "Delta between checkpoints exceeded period"
48
+ assert deltas[2] - deltas[1] < 5.5, "Delta between checkpoints exceeded period"
@@ -1,4 +1,5 @@
1
1
  import os
2
+
2
3
  import pytest
3
4
 
4
5
  import parsl
@@ -1,9 +1,10 @@
1
1
  import contextlib
2
2
  import os
3
+
3
4
  import pytest
5
+
4
6
  import parsl
5
7
  from parsl import python_app
6
-
7
8
  from parsl.tests.configs.local_threads_checkpoint import fresh_config
8
9
 
9
10
 
@@ -19,7 +20,6 @@ def parsl_configured(run_dir, **kw):
19
20
  yield dfk
20
21
 
21
22
  parsl.dfk().cleanup()
22
- parsl.clear()
23
23
 
24
24
 
25
25
  @python_app(cache=True)
@@ -14,7 +14,6 @@ def local_setup():
14
14
 
15
15
  def local_teardown():
16
16
  parsl.dfk().cleanup()
17
- parsl.clear()
18
17
 
19
18
 
20
19
  @python_app
@@ -2,7 +2,7 @@ import pickle
2
2
 
3
3
  import pytest
4
4
 
5
- from parsl import python_app, DataFlowKernel
5
+ from parsl import DataFlowKernel, python_app
6
6
  from parsl.utils import time_limited_open
7
7
 
8
8
 
@@ -5,8 +5,8 @@ import pytest
5
5
 
6
6
  import parsl
7
7
  from parsl.app.app import python_app
8
- from parsl.utils import time_limited_open
9
8
  from parsl.tests.configs.local_threads_checkpoint_task_exit import config
9
+ from parsl.utils import time_limited_open
10
10
 
11
11
 
12
12
  def local_setup():
@@ -15,8 +15,7 @@ def local_setup():
15
15
 
16
16
 
17
17
  def local_teardown():
18
- parsl.dfk().cleanup
19
- parsl.clear()
18
+ parsl.dfk().cleanup()
20
19
 
21
20
 
22
21
  @python_app(cache=True)
@@ -1,8 +1,10 @@
1
+ import os
2
+
3
+ import pytest
4
+
1
5
  from parsl.app.app import bash_app, python_app
2
6
  from parsl.data_provider.files import File
3
7
 
4
- import os
5
-
6
8
 
7
9
  @bash_app
8
10
  def echo(message, outputs=[]):
@@ -15,6 +17,7 @@ def cat(inputs=[]):
15
17
  return f.readlines()
16
18
 
17
19
 
20
+ @pytest.mark.staging_required
18
21
  def test_slides():
19
22
  """Testing code snippet from slides """
20
23
 
@@ -1,7 +1,9 @@
1
1
  """Functions used to explain kwargs"""
2
2
  from pathlib import Path
3
3
 
4
- from parsl import python_app, File
4
+ import pytest
5
+
6
+ from parsl import File, python_app
5
7
 
6
8
 
7
9
  def test_inputs():
@@ -19,6 +21,7 @@ def test_inputs():
19
21
  assert reduce_future.result() == 6
20
22
 
21
23
 
24
+ @pytest.mark.shared_fs
22
25
  def test_outputs(tmpd_cwd):
23
26
  @python_app()
24
27
  def write_app(message, outputs=()):
@@ -1,12 +1,11 @@
1
1
  import argparse
2
- import parsl
3
2
 
4
3
  import pytest
5
4
 
5
+ import parsl
6
6
  from parsl.app.app import bash_app
7
7
  from parsl.tests.configs.local_threads import config
8
8
 
9
-
10
9
  local_config = config
11
10
 
12
11
 
@@ -1,12 +1,12 @@
1
1
  import os
2
+
2
3
  import pytest
3
- import parsl
4
4
 
5
+ import parsl
5
6
  from parsl.app.app import bash_app, python_app
6
7
  from parsl.data_provider.files import File
7
8
  from parsl.tests.configs.local_threads import config
8
9
 
9
-
10
10
  # parsl.set_stream_logger()
11
11
 
12
12
 
@@ -5,7 +5,6 @@ import pytest
5
5
  from parsl.app.app import python_app
6
6
  from parsl.tests.configs.local_threads import config
7
7
 
8
-
9
8
  local_config = config
10
9
 
11
10
 
@@ -15,8 +15,8 @@ def local_config():
15
15
 
16
16
  @python_app
17
17
  def sleep_fail(sleep_dur, sleep_rand_max, fail_prob, inputs=[]):
18
- import time
19
18
  import random
19
+ import time
20
20
 
21
21
  s = sleep_dur + random.randint(-sleep_rand_max, sleep_rand_max)
22
22
 
@@ -144,8 +144,8 @@ def test_deps(numtasks=10):
144
144
 
145
145
  @python_app
146
146
  def sleep_then_fail(sleep_dur=0.1):
147
- import time
148
147
  import math
148
+ import time
149
149
  time.sleep(sleep_dur)
150
150
  math.ceil("Trigger TypeError")
151
151
  return 0
@@ -1,9 +1,9 @@
1
1
  import parsl
2
2
  from parsl.app.app import python_app
3
- from parsl.executors.errors import UnsupportedFeatureError, ExecutorError
4
3
  from parsl.executors import WorkQueueExecutor
5
- from parsl.executors.high_throughput.mpi_prefix_composer import InvalidResourceSpecification
4
+ from parsl.executors.errors import InvalidResourceSpecification
6
5
  from parsl.executors.high_throughput.executor import HighThroughputExecutor
6
+ from parsl.executors.threads import ThreadPoolExecutor
7
7
 
8
8
 
9
9
  @python_app
@@ -25,11 +25,10 @@ def test_resource(n=2):
25
25
  try:
26
26
  fut.result()
27
27
  except InvalidResourceSpecification:
28
- assert isinstance(executor, HighThroughputExecutor)
29
- except UnsupportedFeatureError:
30
- assert not isinstance(executor, WorkQueueExecutor)
31
- except Exception as e:
32
- assert isinstance(e, ExecutorError)
28
+ assert (
29
+ isinstance(executor, HighThroughputExecutor) or
30
+ isinstance(executor, WorkQueueExecutor) or
31
+ isinstance(executor, ThreadPoolExecutor))
33
32
 
34
33
  # Specify resources with wrong types
35
34
  # 'cpus' is incorrect, should be 'cores'
@@ -38,8 +37,7 @@ def test_resource(n=2):
38
37
  try:
39
38
  fut.result()
40
39
  except InvalidResourceSpecification:
41
- assert isinstance(executor, HighThroughputExecutor)
42
- except UnsupportedFeatureError:
43
- assert not isinstance(executor, WorkQueueExecutor)
44
- except Exception as e:
45
- assert isinstance(e, ExecutorError)
40
+ assert (
41
+ isinstance(executor, HighThroughputExecutor) or
42
+ isinstance(executor, WorkQueueExecutor) or
43
+ isinstance(executor, ThreadPoolExecutor))
@@ -1,8 +1,7 @@
1
- import argparse
2
1
  import os
2
+
3
3
  import pytest
4
4
 
5
- import parsl
6
5
  from parsl import bash_app, python_app
7
6
  from parsl.tests.configs.local_threads import fresh_config
8
7
 
@@ -15,8 +14,8 @@ def local_config():
15
14
 
16
15
  @python_app
17
16
  def sleep_then_fail(inputs=[], sleep_dur=0.1):
18
- import time
19
17
  import math
18
+ import time
20
19
  time.sleep(sleep_dur)
21
20
  math.ceil("Trigger TypeError")
22
21
  return 0
@@ -67,8 +66,6 @@ def test_fail_nowait(numtasks=10):
67
66
  assert isinstance(
68
67
  e, TypeError), "Expected a TypeError, got {}".format(e)
69
68
 
70
- print("Done")
71
-
72
69
 
73
70
  @pytest.mark.local
74
71
  def test_fail_delayed(numtasks=10):
@@ -93,19 +90,12 @@ def test_fail_delayed(numtasks=10):
93
90
  assert isinstance(
94
91
  e, TypeError), "Expected a TypeError, got {}".format(e)
95
92
 
96
- print("Done")
97
-
98
93
 
99
94
  @pytest.mark.local
100
- def test_retry():
95
+ def test_retry(tmpd_cwd):
101
96
  """Test retries via app that succeeds on the Nth retry.
102
97
  """
103
98
 
104
- fname = "retry.out"
105
- try:
106
- os.remove(fname)
107
- except OSError:
108
- pass
109
- fu = succeed_on_retry(fname)
110
-
111
- fu.result()
99
+ fpath = tmpd_cwd / "retry.out"
100
+ sout = str(tmpd_cwd / "stdout")
101
+ succeed_on_retry(str(fpath), stdout=sout).result()
@@ -1,4 +1,5 @@
1
1
  import os
2
+
2
3
  import pytest
3
4
 
4
5
  import parsl
@@ -1,6 +1,7 @@
1
- import parsl
2
1
  import pytest
3
2
 
3
+ import parsl
4
+
4
5
 
5
6
  @parsl.python_app
6
7
  def always_fails():
@@ -1,8 +1,8 @@
1
1
  import pytest
2
2
 
3
3
  from parsl import python_app
4
- from parsl.tests.configs.htex_local import fresh_config
5
4
  from parsl.serialize.errors import SerializationError
5
+ from parsl.tests.configs.htex_local import fresh_config
6
6
 
7
7
 
8
8
  def local_config():
@@ -1,4 +1,5 @@
1
1
  import logging
2
+
2
3
  import pytest
3
4
 
4
5
  from parsl.process_loggers import wrap_with_logs
@@ -0,0 +1,29 @@
1
+ import os
2
+
3
+ import pytest
4
+
5
+ from parsl.executors.execute_task import execute_task
6
+ from parsl.serialize.facade import pack_res_spec_apply_message
7
+
8
+
9
+ def addemup(*args: int, name: str = "apples"):
10
+ total = sum(args)
11
+ return f"{total} {name}"
12
+
13
+
14
+ @pytest.mark.local
15
+ def test_execute_task():
16
+ args = (1, 2, 3)
17
+ kwargs = {"name": "boots"}
18
+ buff = pack_res_spec_apply_message(addemup, args, kwargs, {})
19
+ res = execute_task(buff)
20
+ assert res == addemup(*args, **kwargs)
21
+
22
+
23
+ @pytest.mark.local
24
+ def test_execute_task_resource_spec():
25
+ resource_spec = {"num_nodes": 2, "ranks_per_node": 2, "num_ranks": 4}
26
+ buff = pack_res_spec_apply_message(addemup, (1, 2), {}, resource_spec)
27
+ execute_task(buff)
28
+ for key, val in resource_spec.items():
29
+ assert os.environ[f"PARSL_{key.upper()}"] == str(val)
parsl/tests/test_flux.py CHANGED
@@ -1,5 +1,5 @@
1
- import os
2
1
  import concurrent.futures as cf
2
+ import os
3
3
 
4
4
  import pytest
5
5
 
@@ -14,7 +14,6 @@ def local_setup():
14
14
 
15
15
  def local_teardown():
16
16
  parsl.dfk().cleanup()
17
- parsl.clear()
18
17
 
19
18
 
20
19
  @python_app
@@ -23,6 +22,6 @@ def dummy():
23
22
 
24
23
 
25
24
  @pytest.mark.local
26
- def test_that_it_fails():
25
+ def test_app():
27
26
  x = dummy()
28
- x.result()
27
+ assert x.result() is None
@@ -0,0 +1,20 @@
1
+ import pytest
2
+
3
+ from parsl.executors.high_throughput.manager_record import ManagerRecord
4
+ from parsl.executors.high_throughput.manager_selector import BlockIdManagerSelector
5
+
6
+
7
+ @pytest.mark.local
8
+ def test_sort_managers():
9
+ ready_managers = {
10
+ b'manager1': {'block_id': 1},
11
+ b'manager2': {'block_id': None},
12
+ b'manager3': {'block_id': 3},
13
+ b'manager4': {'block_id': 2}
14
+ }
15
+
16
+ manager_list = {b'manager1', b'manager2', b'manager3', b'manager4'}
17
+ expected_sorted_list = [b'manager2', b'manager1', b'manager4', b'manager3']
18
+ manager_selector = BlockIdManagerSelector()
19
+ sorted_managers = manager_selector.sort_managers(ready_managers, manager_list)
20
+ assert sorted_managers == expected_sorted_list
@@ -0,0 +1,66 @@
1
+ import threading
2
+ import time
3
+
4
+ import pytest
5
+ import zmq
6
+
7
+ from parsl import curvezmq
8
+ from parsl.executors.high_throughput.errors import (
9
+ CommandClientBadError,
10
+ CommandClientTimeoutError,
11
+ )
12
+ from parsl.executors.high_throughput.zmq_pipes import CommandClient
13
+
14
+ # Time constant used for timeout tests: various delays and
15
+ # timeouts will be appropriate multiples of this, but the
16
+ # value of T itself should not matter too much as long as
17
+ # it is big enough for zmq connections to happen successfully.
18
+ T = 0.25
19
+
20
+
21
+ @pytest.mark.local
22
+ def test_command_not_sent() -> None:
23
+ """Tests timeout on command send.
24
+ """
25
+ # RFC6335 ephemeral port range
26
+ cc = CommandClient("127.0.0.1", (49152, 65535))
27
+
28
+ # cc will now wait for a connection, but we won't do anything to make the
29
+ # other side of the connection exist, so any command given to cc should
30
+ # timeout.
31
+
32
+ with pytest.raises(CommandClientTimeoutError):
33
+ cc.run("SOMECOMMAND", timeout_s=T)
34
+
35
+ cc.close()
36
+
37
+
38
+ @pytest.mark.local
39
+ def test_command_ignored() -> None:
40
+ """Tests timeout on command response.
41
+ Tests that we timeout after a response and that the command client
42
+ sets itself into a bad state.
43
+
44
+ This only tests sequential access to the command client, even though
45
+ htex makes multithreaded use of the command client: see issue #3376 about
46
+ that lack of thread safety.
47
+ """
48
+ # RFC6335 ephemeral port range
49
+ cc = CommandClient("127.0.0.1", (49152, 65535))
50
+
51
+ ic_ctx = curvezmq.ServerContext(None)
52
+ ic_channel = ic_ctx.socket(zmq.REP)
53
+ ic_channel.connect(f"tcp://127.0.0.1:{cc.port}")
54
+
55
+ with pytest.raises(CommandClientTimeoutError):
56
+ cc.run("SLOW_COMMAND", timeout_s=T)
57
+
58
+ req = ic_channel.recv_pyobj()
59
+ assert req == "SLOW_COMMAND", "Should have received command on interchange side"
60
+ assert not cc.ok, "CommandClient should have set itself to bad"
61
+
62
+ with pytest.raises(CommandClientBadError):
63
+ cc.run("ANOTHER_COMMAND")
64
+
65
+ cc.close()
66
+ ic_channel.close()
@@ -1,7 +1,8 @@
1
- import parsl
2
1
  import pytest
3
- from parsl.executors import HighThroughputExecutor
2
+
3
+ import parsl
4
4
  from parsl import Config
5
+ from parsl.executors import HighThroughputExecutor
5
6
  from parsl.providers import LocalProvider
6
7
 
7
8
 
@@ -1,8 +1,10 @@
1
1
  import logging
2
2
  import os
3
- import parsl
4
- import pytest
5
3
  import random
4
+
5
+ import pytest
6
+
7
+ import parsl
6
8
  from parsl.tests.configs.htex_local import fresh_config
7
9
 
8
10
  logger = logging.getLogger(__name__)
@@ -18,6 +20,7 @@ def my_affinity():
18
20
 
19
21
  @pytest.mark.local
20
22
  @pytest.mark.multiple_cores_required
23
+ @pytest.mark.skipif('sched_getaffinity' not in dir(os), reason='System does not support sched_setaffinity')
21
24
  def test_cpu_affinity_explicit():
22
25
  available_cores = os.sched_getaffinity(0)
23
26
 
@@ -37,16 +40,9 @@ def test_cpu_affinity_explicit():
37
40
  config.executors[0].max_workers_per_node = 1
38
41
 
39
42
  logger.debug(f"config: {config}")
40
- # TODO: is there a `with` style for this, to properly deal with exceptions?
41
-
42
- parsl.load(config)
43
- try:
44
43
 
44
+ with parsl.load(config):
45
45
  worker_affinity = my_affinity().result()
46
46
  logger.debug(f"worker reported this affinity: {worker_affinity}")
47
47
  assert len(worker_affinity) == 1
48
48
  assert worker_affinity == set((single_core,))
49
-
50
- finally:
51
- parsl.dfk().cleanup()
52
- parsl.clear()
@@ -1,11 +1,13 @@
1
1
  import logging
2
- import parsl
2
+
3
3
  import pytest
4
- from parsl.executors import HighThroughputExecutor
4
+
5
+ import parsl
5
6
  from parsl import Config
6
- from parsl.providers import LocalProvider
7
+ from parsl.executors import HighThroughputExecutor
7
8
  from parsl.executors.errors import BadStateException
8
- from parsl.jobs.states import JobStatus, JobState
9
+ from parsl.jobs.states import JobState, JobStatus
10
+ from parsl.providers import LocalProvider
9
11
 
10
12
 
11
13
  def local_config():
@@ -26,7 +28,6 @@ def local_config():
26
28
  ),
27
29
  )
28
30
  ],
29
- run_dir="/tmp/test_htex",
30
31
  max_idletime=0.5,
31
32
  strategy='htex_auto_scale',
32
33
  )
@@ -0,0 +1,71 @@
1
+ import logging
2
+
3
+ import pytest
4
+
5
+ import parsl
6
+ from parsl import Config
7
+ from parsl.executors import HighThroughputExecutor
8
+ from parsl.executors.errors import BadStateException
9
+ from parsl.jobs.states import JobState, JobStatus
10
+ from parsl.providers import LocalProvider
11
+
12
+
13
+ class FailingProvider(LocalProvider):
14
+ def submit(*args, **kwargs):
15
+ raise RuntimeError("Deliberate failure of provider.submit")
16
+
17
+
18
+ def local_config():
19
+ """Config to simulate failing blocks without connecting"""
20
+ return Config(
21
+ executors=[
22
+ HighThroughputExecutor(
23
+ label="HTEX",
24
+ heartbeat_period=1,
25
+ heartbeat_threshold=2,
26
+ poll_period=100,
27
+ max_workers_per_node=1,
28
+ provider=FailingProvider(
29
+ init_blocks=0,
30
+ max_blocks=2,
31
+ min_blocks=0,
32
+ ),
33
+ )
34
+ ],
35
+ max_idletime=0.5,
36
+ strategy='htex_auto_scale',
37
+ strategy_period=0.1
38
+ # this strategy period needs to be a few times smaller than the
39
+ # status_polling_interval of FailingProvider, which is 5s at
40
+ # time of writing
41
+ )
42
+
43
+
44
+ @parsl.python_app
45
+ def double(x):
46
+ return x * 2
47
+
48
+
49
+ @pytest.mark.local
50
+ def test_disconnected_blocks():
51
+ """Test reporting of blocks that fail to connect from HTEX"""
52
+ dfk = parsl.dfk()
53
+ executor = dfk.executors["HTEX"]
54
+
55
+ connected_blocks = executor.connected_blocks()
56
+ assert not connected_blocks, "Expected 0 blocks"
57
+
58
+ future = double(5)
59
+ with pytest.raises(BadStateException):
60
+ future.result()
61
+
62
+ assert isinstance(future.exception(), BadStateException)
63
+
64
+ status_dict = executor.status()
65
+ assert len(status_dict) == 1, "Expected exactly 1 block"
66
+ for status in status_dict.values():
67
+ assert isinstance(status, JobStatus)
68
+ assert status.state == JobState.MISSING
69
+
70
+ connected_blocks = executor.connected_blocks()
71
+ assert connected_blocks == [], "Expected exactly 0 connected blocks"