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
@@ -0,0 +1,59 @@
1
+ import inspect
2
+ from concurrent.futures import Future
3
+ from typing import Any, Callable, Dict
4
+
5
+ import pytest
6
+
7
+ import parsl
8
+ from parsl.executors.base import ParslExecutor
9
+
10
+ # N is the number of tasks to chain
11
+ # With mid-2024 Parsl, N>140 causes Parsl to hang
12
+ N = 100
13
+
14
+ # MAX_STACK is the maximum Python stack depth allowed for either
15
+ # task submission to an executor or execution of a task.
16
+ # With mid-2024 Parsl, 2-3 stack entries will be used per
17
+ # recursively launched parsl task. So this should be smaller than
18
+ # 2*N, but big enough to allow regular pytest+parsl stuff to
19
+ # happen.
20
+ MAX_STACK = 50
21
+
22
+
23
+ def local_config():
24
+ return parsl.Config(executors=[ImmediateExecutor()])
25
+
26
+
27
+ class ImmediateExecutor(ParslExecutor):
28
+ def start(self):
29
+ pass
30
+
31
+ def shutdown(self):
32
+ pass
33
+
34
+ def submit(self, func: Callable, resource_specification: Dict[str, Any], *args: Any, **kwargs: Any) -> Future:
35
+ stack_depth = len(inspect.stack())
36
+ assert stack_depth < MAX_STACK, "tasks should not be launched deep in the Python stack"
37
+ fut: Future[None] = Future()
38
+ res = func(*args, **kwargs)
39
+ fut.set_result(res)
40
+ return fut
41
+
42
+
43
+ @parsl.python_app
44
+ def chain(upstream):
45
+ stack_depth = len(inspect.stack())
46
+ assert stack_depth < MAX_STACK, "chained dependencies should not be launched deep in the Python stack"
47
+
48
+
49
+ @pytest.mark.local
50
+ def test_deep_dependency_stack_depth():
51
+
52
+ fut = Future()
53
+ here = fut
54
+
55
+ for _ in range(N):
56
+ here = chain(here)
57
+
58
+ fut.set_result(None)
59
+ here.result()
@@ -41,28 +41,3 @@ def test_fail_sequence(fail_probs):
41
41
 
42
42
  with pytest.raises(DependencyError):
43
43
  t_final.result()
44
-
45
-
46
- def test_deps(width=3):
47
- """Random failures in branches of Map -> Map -> reduce"""
48
- # App1 App2 ... AppN
49
- futs = [random_fail(fail_prob=0.4) for _ in range(width)]
50
-
51
- # App1 App2 ... AppN
52
- # | | |
53
- # V V V
54
- # App1 App2 ... AppN
55
-
56
- futs = [random_fail(fail_prob=0.8, inputs=[f]) for f in futs]
57
-
58
- # App1 App2 ... AppN
59
- # | | |
60
- # V V V
61
- # App1 App2 ... AppN
62
- # \ | /
63
- # \ | /
64
- # App_Final
65
- try:
66
- random_fail(fail_prob=0, inputs=futs).result()
67
- except DependencyError:
68
- pass
@@ -11,9 +11,10 @@ Same applies to datafutures, and we need to know the behavior wrt.
11
11
  2. done() called on 1, vs 2
12
12
 
13
13
  """
14
- import pytest
15
14
  from os.path import basename
16
15
 
16
+ import pytest
17
+
17
18
  from parsl.app.app import python_app
18
19
  from parsl.data_provider.files import File
19
20
 
@@ -0,0 +1,22 @@
1
+ import pytest
2
+
3
+ import parsl
4
+ from parsl import python_app
5
+ from parsl.executors.threads import ThreadPoolExecutor
6
+
7
+
8
+ def local_config():
9
+ return parsl.Config(executors=[ThreadPoolExecutor()])
10
+
11
+
12
+ @pytest.mark.local
13
+ def test_default_inputs():
14
+ @python_app
15
+ def identity(inp):
16
+ return inp
17
+
18
+ @python_app
19
+ def add_inputs(inputs=[identity(1), identity(2)]):
20
+ return sum(inputs)
21
+
22
+ assert add_inputs().result() == 3
@@ -3,7 +3,6 @@ import pytest
3
3
  from parsl import join_app, python_app
4
4
  from parsl.dataflow.errors import JoinError
5
5
 
6
-
7
6
  RESULT_CONSTANT = 3
8
7
 
9
8
 
@@ -1,26 +1,30 @@
1
+ from concurrent.futures import Future
2
+ from typing import TypeVar
3
+
1
4
  import pytest
2
5
 
3
- from concurrent.futures import Future
4
6
  from parsl import python_app
5
7
 
8
+ T = TypeVar('T')
9
+
6
10
 
7
11
  @python_app
8
- def returns_a_dict():
12
+ def returns_a_dict() -> dict:
9
13
  return {"a": "X", "b": "Y"}
10
14
 
11
15
 
12
16
  @python_app
13
- def returns_a_list():
17
+ def returns_a_list() -> list:
14
18
  return ["X", "Y"]
15
19
 
16
20
 
17
21
  @python_app
18
- def returns_a_tuple():
22
+ def returns_a_tuple() -> tuple:
19
23
  return ("X", "Y")
20
24
 
21
25
 
22
26
  @python_app
23
- def returns_a_class():
27
+ def returns_a_class() -> type:
24
28
  from dataclasses import dataclass
25
29
 
26
30
  @dataclass
@@ -38,7 +42,7 @@ class MyOuterClass():
38
42
 
39
43
 
40
44
  @python_app
41
- def returns_a_class_instance():
45
+ def returns_a_class_instance() -> object:
42
46
  return MyOuterClass()
43
47
 
44
48
 
@@ -110,7 +114,7 @@ def test_returns_a_class():
110
114
 
111
115
 
112
116
  @python_app
113
- def passthrough(v):
117
+ def passthrough(v: T) -> T:
114
118
  return v
115
119
 
116
120
 
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from parsl import python_app
3
4
  from parsl.dataflow.memoization import id_for_memo
4
5
 
@@ -16,7 +16,7 @@ def double(x, outputs=[]):
16
16
  whitelist = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'configs', '*threads*')
17
17
 
18
18
 
19
- @pytest.mark.issue363
19
+ @pytest.mark.shared_fs
20
20
  def test_launch_apps(tmpd_cwd, n=2):
21
21
  outdir = tmpd_cwd / "outputs"
22
22
  outdir.mkdir()
@@ -0,0 +1,161 @@
1
+ from concurrent.futures import Future
2
+ from pathlib import Path
3
+ from threading import Event
4
+ from typing import Sequence
5
+
6
+ import pytest
7
+
8
+ import parsl
9
+ from parsl.config import Config
10
+ from parsl.dataflow.dependency_resolvers import DEEP_DEPENDENCY_RESOLVER
11
+ from parsl.dataflow.errors import DependencyError
12
+
13
+
14
+ def local_config():
15
+ return Config(dependency_resolver=DEEP_DEPENDENCY_RESOLVER)
16
+
17
+
18
+ @parsl.python_app
19
+ def a(event):
20
+ event.wait()
21
+ return 7
22
+
23
+
24
+ @parsl.python_app
25
+ def b(x: int):
26
+ return x + 1
27
+
28
+
29
+ @pytest.mark.local
30
+ def test_simple_pos_arg():
31
+ e = Event()
32
+ s = a(e)
33
+ f_b = b(s)
34
+ e.set()
35
+
36
+ assert f_b.result() == 8
37
+
38
+
39
+ @parsl.python_app
40
+ def b_first(x: Sequence[int]):
41
+ return x[0] + 1
42
+
43
+
44
+ @pytest.mark.local
45
+ def test_tuple_pos_arg():
46
+ e = Event()
47
+ s = (a(e),)
48
+ f_b = b_first(s)
49
+ e.set()
50
+ assert f_b.result() == 8
51
+
52
+
53
+ @pytest.mark.local
54
+ def test_list_exception():
55
+ a = Future()
56
+ a.set_exception(RuntimeError("artificial error"))
57
+ f_b = b([a])
58
+ assert isinstance(f_b.exception(), DependencyError)
59
+
60
+
61
+ @parsl.python_app
62
+ def make_path(s: str):
63
+ return Path(s)
64
+
65
+
66
+ @parsl.python_app
67
+ def append_paths(iterable, end_str: str = "end"):
68
+ type_ = type(iterable)
69
+ return type_([Path(s, end_str) for s in iterable])
70
+
71
+
72
+ @pytest.mark.local
73
+ @pytest.mark.parametrize(
74
+ "type_",
75
+ [
76
+ tuple,
77
+ list,
78
+ set,
79
+ ],
80
+ )
81
+ def test_resolving_iterables(type_):
82
+ output1 = make_path("test1")
83
+ output2 = make_path("test2")
84
+ output3 = append_paths(type_([output1, output2]), end_str="end")
85
+ assert output3.result() == type_([Path("test1", "end"), Path("test2", "end")])
86
+
87
+
88
+ @parsl.python_app
89
+ def append_paths_dict(iterable: dict, end_str: str = "end"):
90
+ return {Path(k, end_str): Path(v, end_str) for k, v in iterable.items()}
91
+
92
+
93
+ @pytest.mark.local
94
+ def test_resolving_dict():
95
+ output1 = make_path("test1")
96
+ output2 = make_path("test2")
97
+ output3 = append_paths_dict({output1: output2}, end_str="end")
98
+ assert output3.result() == {Path("test1", "end"): Path("test2", "end")}
99
+
100
+
101
+ @parsl.python_app
102
+ def extract_deep(struct: list):
103
+ return struct[0][0][0][0][0]
104
+
105
+
106
+ @pytest.mark.local
107
+ def test_deeper_list():
108
+ f = Future()
109
+ f.set_result(7)
110
+ f_b = extract_deep([[[[[f]]]]])
111
+
112
+ assert f_b.result() == 7
113
+
114
+
115
+ @pytest.mark.local
116
+ def test_deeper_list_and_tuple():
117
+ f = Future()
118
+ f.set_result(7)
119
+ f_b = extract_deep([([([f],)],)])
120
+
121
+ assert f_b.result() == 7
122
+
123
+
124
+ @parsl.python_app
125
+ def dictionary_checker(d):
126
+ assert d["a"] == [30, 10]
127
+ assert d["b"] == 20
128
+
129
+
130
+ @pytest.mark.local
131
+ def test_dictionary():
132
+ k1 = Future()
133
+ k1.set_result("a")
134
+ k2 = Future()
135
+ k2.set_result("b")
136
+ v1 = Future()
137
+ v1.set_result(10)
138
+
139
+ # this .result() will fail if the asserts fail
140
+ dictionary_checker({k1: [30, v1], k2: 20}).result()
141
+
142
+
143
+ @pytest.mark.local
144
+ def test_dictionary_later():
145
+ k1 = Future()
146
+ k2 = Future()
147
+ v1 = Future()
148
+
149
+ f1 = dictionary_checker({k1: [30, v1], k2: 20})
150
+
151
+ assert not f1.done()
152
+ k1.set_result("a")
153
+ k2.set_result("b")
154
+ v1.set_result(10)
155
+
156
+ # having set the results, f1 should fairly rapidly complete (but not
157
+ # instantly) so we can't assert on done() here... but we can
158
+ # check that f1 does "eventually" complete... meaning that
159
+ # none of the assertions inside test_dictionary have failed
160
+
161
+ assert f1.result() is None
@@ -1,6 +1,6 @@
1
- import parsl
2
1
  import pytest
3
2
 
3
+ import parsl
4
4
  from parsl.tests.configs.local_radical_mpi import fresh_config as local_config
5
5
 
6
6
 
@@ -16,7 +16,6 @@ def some_mpi_func(msg, sleep, comm=None, parsl_resource_specification={}):
16
16
  apps = []
17
17
 
18
18
 
19
- @pytest.mark.skip("hangs in CI - waiting for resolution of issue #3029")
20
19
  @pytest.mark.local
21
20
  @pytest.mark.radical
22
21
  def test_radical_mpi(n=7):
@@ -1,5 +1,6 @@
1
- from parsl import python_app
2
1
  import pytest
2
+
3
+ from parsl import python_app
3
4
  from parsl.tests.configs.htex_local import fresh_config as local_config
4
5
 
5
6
 
@@ -1,5 +1,6 @@
1
- from parsl import python_app
2
1
  import pytest
2
+
3
+ from parsl import python_app
3
4
  from parsl.tests.configs.htex_local import fresh_config as local_config
4
5
 
5
6
 
@@ -53,6 +53,7 @@ def test_get_dataframe():
53
53
  assert res.equals(data), 'Unexpected dataframe'
54
54
 
55
55
 
56
+ @pytest.mark.shared_fs
56
57
  def test_bash_default_arg():
57
58
  if os.path.exists('std.out'):
58
59
  os.remove('std.out')
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from parsl.jobs.states import JobState
3
4
 
4
5
 
@@ -6,7 +6,6 @@ import pytest
6
6
  from parsl.app.app import bash_app, python_app
7
7
  from parsl.tests.configs.local_threads import config
8
8
 
9
-
10
9
  local_config = config
11
10
 
12
11
 
@@ -1,8 +1,10 @@
1
- import time
2
1
  import multiprocessing
2
+ import random
3
+ import time
4
+
3
5
  import pytest
6
+
4
7
  from parsl.multiprocessing import MacSafeQueue
5
- import random
6
8
 
7
9
 
8
10
  def consumer(in_q, out_q, delay=0):
@@ -1,11 +1,10 @@
1
1
  import pytest
2
2
 
3
3
  import parsl
4
-
5
4
  from parsl.config import Config
6
5
  from parsl.executors import HighThroughputExecutor
7
- from parsl.providers import LocalProvider
8
6
  from parsl.launchers import SimpleLauncher
7
+ from parsl.providers import LocalProvider
9
8
 
10
9
 
11
10
  def local_config() -> Config:
@@ -6,7 +6,6 @@ import argparse
6
6
  import pytest
7
7
 
8
8
  import parsl
9
-
10
9
  from parsl.dataflow.dflow import DataFlowKernel
11
10
  from parsl.tests.configs.local_threads import config
12
11
 
@@ -1,11 +1,16 @@
1
+ from functools import partial
2
+ from unittest.mock import Mock
3
+
1
4
  import pytest
2
5
 
3
6
  from parsl.executors import HighThroughputExecutor
7
+ from parsl.jobs.error_handlers import (
8
+ noop_error_handler,
9
+ simple_error_handler,
10
+ windowed_error_handler,
11
+ )
12
+ from parsl.jobs.states import JobState, JobStatus
4
13
  from parsl.providers import LocalProvider
5
- from unittest.mock import Mock
6
- from parsl.jobs.states import JobStatus, JobState
7
- from parsl.jobs.error_handlers import simple_error_handler, windowed_error_handler, noop_error_handler
8
- from functools import partial
9
14
 
10
15
 
11
16
  @pytest.mark.local
@@ -3,12 +3,19 @@ import threading
3
3
  import pytest
4
4
 
5
5
  import parsl
6
- from parsl.channels import LocalChannel
7
6
  from parsl.config import Config
8
7
  from parsl.executors import HighThroughputExecutor
9
8
  from parsl.launchers import SimpleLauncher
10
9
  from parsl.providers import LocalProvider
11
10
 
11
+ # Timing notes:
12
+ # The configured strategy_period must be much smaller than the delay in
13
+ # app() so that multiple iterations of the strategy have had a chance
14
+ # to (mis)behave.
15
+ # The status polling interval in OneShotLocalProvider must be much bigger
16
+ # than the above times, so that the job status cached from the provider
17
+ # will not be updated while the single invocation of app() runs.
18
+
12
19
 
13
20
  @parsl.python_app
14
21
  def app():
@@ -35,7 +42,6 @@ def test_one_block(tmpd_cwd):
35
42
  one app is invoked. this is a regression test.
36
43
  """
37
44
  oneshot_provider = OneShotLocalProvider(
38
- channel=LocalChannel(),
39
45
  init_blocks=0,
40
46
  min_blocks=0,
41
47
  max_blocks=10,
@@ -55,20 +61,10 @@ def test_one_block(tmpd_cwd):
55
61
  )
56
62
  ],
57
63
  strategy='simple',
64
+ strategy_period=0.1
58
65
  )
59
66
 
60
- parsl.load(config)
61
- dfk = parsl.dfk()
62
-
63
- def poller():
64
- import time
65
- while True:
66
- dfk.job_status_poller.poll()
67
- time.sleep(0.1)
68
-
69
- threading.Thread(target=poller, daemon=True).start()
70
- app().result()
71
- parsl.dfk().cleanup()
72
- parsl.clear()
67
+ with parsl.load(config):
68
+ app().result()
73
69
 
74
70
  assert oneshot_provider.recorded_submits == 1
@@ -0,0 +1,84 @@
1
+ import time
2
+
3
+ import pytest
4
+
5
+ import parsl
6
+ from parsl.config import Config
7
+ from parsl.executors import HighThroughputExecutor
8
+ from parsl.launchers import WrappedLauncher
9
+ from parsl.providers import LocalProvider
10
+
11
+
12
+ def local_config():
13
+ # see the comments inside test_regression for reasoning about why each
14
+ # of these parameters is set why it is.
15
+ return Config(
16
+ max_idletime=1,
17
+
18
+ strategy='htex_auto_scale',
19
+ strategy_period=1,
20
+
21
+ executors=[
22
+ HighThroughputExecutor(
23
+ label="htex_local",
24
+ encrypted=True,
25
+ provider=LocalProvider(
26
+ init_blocks=1,
27
+ min_blocks=0,
28
+ max_blocks=1,
29
+ launcher=WrappedLauncher(prepend="sleep inf ; "),
30
+ ),
31
+ )
32
+ ],
33
+ )
34
+
35
+
36
+ @parsl.python_app
37
+ def task():
38
+ return 7
39
+
40
+
41
+ @pytest.mark.local
42
+ def test_regression(try_assert):
43
+ # The above config means that we should start scaling out one initial
44
+ # block, but then scale it back in after a second or so if the executor
45
+ # is kept idle (which this test does using try_assert).
46
+
47
+ # Because of 'sleep inf' in the WrappedLaucher, the block will not ever
48
+ # register.
49
+
50
+ # The bug being tested is about mistreatment of blocks which are scaled in
51
+ # before they have a chance to register, and the above forces that to
52
+ # happen.
53
+
54
+ # After that scaling in has happened, we should see that we have one block
55
+ # and it should be in a terminal state. The below try_assert waits for
56
+ # that to become true.
57
+
58
+ # At that time, we should also see htex reporting no blocks registered - as
59
+ # mentioned above, that is a necessary part of the bug being tested here.
60
+
61
+ # Give 10 strategy periods for the above to happen: each step of scale up,
62
+ # and scale down due to idleness isn't guaranteed to happen in exactly one
63
+ # scaling step.
64
+
65
+ htex = parsl.dfk().executors['htex_local']
66
+
67
+ try_assert(lambda: len(htex.status_facade) == 1 and htex.status_facade['0'].terminal,
68
+ timeout_ms=10000)
69
+
70
+ assert htex.connected_blocks() == [], "No block should have connected to interchange"
71
+
72
+ # Now we can reconfigure the launcher to let subsequent blocks launch ok,
73
+ # and run a trivial task. That trivial task will scale up a new block and
74
+ # run the task successfully.
75
+
76
+ # Prior to issue #3568, the bug was that the scale in of the first
77
+ # block earlier in the test case would have incorrectly been treated as a
78
+ # failure, and then the block error handler would have treated that failure
79
+ # as a permanent htex failure, and so the task execution below would raise
80
+ # a BadStateException rather than attempt to run the task.
81
+
82
+ assert htex.provider.launcher.prepend != "", "Pre-req: prepend attribute should exist and be non-empty"
83
+ htex.provider.launcher.prepend = ""
84
+ assert task().result() == 7