parsl 2024.3.18__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 +26 -6
  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 +53 -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 +259 -223
  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 +307 -285
  57. parsl/executors/high_throughput/interchange.py +137 -168
  58. parsl/executors/high_throughput/manager_record.py +4 -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 +77 -75
  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 +38 -55
  75. parsl/executors/taskvine/factory.py +1 -1
  76. parsl/executors/taskvine/factory_config.py +1 -1
  77. parsl/executors/taskvine/manager.py +17 -13
  78. parsl/executors/taskvine/manager_config.py +7 -2
  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 +28 -112
  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 +0 -6
  91. parsl/log_utils.py +1 -2
  92. parsl/monitoring/db_manager.py +55 -93
  93. parsl/monitoring/errors.py +6 -0
  94. parsl/monitoring/monitoring.py +85 -311
  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 +8 -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 -9
  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 +3 -9
  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 +0 -7
  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 +11 -10
  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 +5 -5
  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 +5 -8
  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 +137 -4
  313. parsl/version.py +1 -1
  314. {parsl-2024.3.18.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.18.data → parsl-2025.1.13.data}/scripts/process_worker_pool.py +77 -75
  317. parsl-2025.1.13.dist-info/METADATA +96 -0
  318. parsl-2025.1.13.dist-info/RECORD +462 -0
  319. {parsl-2024.3.18.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.18.dist-info/METADATA +0 -98
  360. parsl-2024.3.18.dist-info/RECORD +0 -449
  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.18.data → parsl-2025.1.13.data}/scripts/parsl_coprocess.py +1 -1
  367. {parsl-2024.3.18.dist-info → parsl-2025.1.13.dist-info}/LICENSE +0 -0
  368. {parsl-2024.3.18.dist-info → parsl-2025.1.13.dist-info}/entry_points.txt +0 -0
  369. {parsl-2024.3.18.dist-info → parsl-2025.1.13.dist-info}/top_level.txt +0 -0
@@ -1,236 +0,0 @@
1
- import logging
2
- import os
3
- import time
4
- import warnings
5
-
6
- from parsl.providers.errors import ScaleOutFailed
7
- from parsl.channels import LocalChannel
8
- from parsl.launchers import AprunLauncher
9
- from parsl.providers.cobalt.template import template_string
10
- from parsl.providers.cluster_provider import ClusterProvider
11
- from parsl.jobs.states import JobState, JobStatus
12
- from parsl.utils import RepresentationMixin, wtime_to_minutes
13
-
14
- logger = logging.getLogger(__name__)
15
-
16
- translate_table = {
17
- 'QUEUED': JobState.PENDING,
18
- 'STARTING': JobState.PENDING,
19
- 'RUNNING': JobState.RUNNING,
20
- 'EXITING': JobState.COMPLETED,
21
- 'KILLING': JobState.COMPLETED
22
- }
23
-
24
-
25
- class CobaltProvider(ClusterProvider, RepresentationMixin):
26
- """ Cobalt Execution Provider
27
-
28
- WARNING: CobaltProvider is deprecated and will be removed by 2024.04
29
-
30
- This provider uses cobalt to submit (qsub), obtain the status of (qstat), and cancel (qdel)
31
- jobs. Theo script to be used is created from a template file in this
32
- same module.
33
-
34
- Parameters
35
- ----------
36
- channel : Channel
37
- Channel for accessing this provider. Possible channels include
38
- :class:`~parsl.channels.LocalChannel` (the default),
39
- :class:`~parsl.channels.SSHChannel`, or
40
- :class:`~parsl.channels.SSHInteractiveLoginChannel`.
41
- nodes_per_block : int
42
- Nodes to provision per block.
43
- min_blocks : int
44
- Minimum number of blocks to maintain.
45
- max_blocks : int
46
- Maximum number of blocks to maintain.
47
- walltime : str
48
- Walltime requested per block in HH:MM:SS.
49
- account : str
50
- Account that the job will be charged against.
51
- queue : str
52
- Torque queue to request blocks from.
53
- scheduler_options : str
54
- String to prepend to the submit script to the scheduler.
55
- worker_init : str
56
- Command to be run before starting a worker, such as 'module load Anaconda; source activate env'.
57
- launcher : Launcher
58
- Launcher for this provider. Possible launchers include
59
- :class:`~parsl.launchers.AprunLauncher` (the default) or,
60
- :class:`~parsl.launchers.SingleNodeLauncher`
61
- """
62
- def __init__(self,
63
- channel=LocalChannel(),
64
- nodes_per_block=1,
65
- init_blocks=0,
66
- min_blocks=0,
67
- max_blocks=1,
68
- parallelism=1,
69
- walltime="00:10:00",
70
- account=None,
71
- queue=None,
72
- scheduler_options='',
73
- worker_init='',
74
- launcher=AprunLauncher(),
75
- cmd_timeout=10):
76
- label = 'cobalt'
77
- super().__init__(label,
78
- channel=channel,
79
- nodes_per_block=nodes_per_block,
80
- init_blocks=init_blocks,
81
- min_blocks=min_blocks,
82
- max_blocks=max_blocks,
83
- parallelism=parallelism,
84
- walltime=walltime,
85
- launcher=launcher,
86
- cmd_timeout=cmd_timeout)
87
-
88
- self.account = account
89
- self.queue = queue
90
- self.scheduler_options = scheduler_options
91
- self.worker_init = worker_init
92
- warnings.warn("CobaltProvider is deprecated; This will be removed after 2024-04",
93
- DeprecationWarning,
94
- stacklevel=2)
95
-
96
- def _status(self):
97
- """Returns the status list for a list of job_ids
98
-
99
- Args:
100
- self
101
-
102
- Returns:
103
- [status...] : Status list of all jobs
104
- """
105
-
106
- jobs_missing = list(self.resources.keys())
107
-
108
- retcode, stdout, stderr = self.execute_wait("qstat -u $USER")
109
-
110
- # Execute_wait failed. Do no update.
111
- if retcode != 0:
112
- return
113
-
114
- for line in stdout.split('\n'):
115
- if line.startswith('='):
116
- continue
117
-
118
- parts = line.upper().split()
119
- if parts and parts[0] != 'JOBID':
120
- job_id = parts[0]
121
-
122
- if job_id not in self.resources:
123
- continue
124
-
125
- status = translate_table.get(parts[4], JobState.UNKNOWN)
126
-
127
- self.resources[job_id]['status'] = JobStatus(status)
128
- jobs_missing.remove(job_id)
129
-
130
- # squeue does not report on jobs that are not running. So we are filling in the
131
- # blanks for missing jobs, we might lose some information about why the jobs failed.
132
- for missing_job in jobs_missing:
133
- self.resources[missing_job]['status'] = JobStatus(JobState.COMPLETED)
134
-
135
- def submit(self, command, tasks_per_node, job_name="parsl.cobalt"):
136
- """ Submits the command onto an Local Resource Manager job of parallel elements.
137
- Submit returns an ID that corresponds to the task that was just submitted.
138
-
139
- If tasks_per_node < 1 : ! This is illegal. tasks_per_node should be integer
140
-
141
- If tasks_per_node == 1:
142
- A single node is provisioned
143
-
144
- If tasks_per_node > 1 :
145
- tasks_per_node number of nodes are provisioned.
146
-
147
- Args:
148
- - command :(String) Commandline invocation to be made on the remote side.
149
- - tasks_per_node (int) : command invocations to be launched per node
150
-
151
- Kwargs:
152
- - job_name (String): Name for job, must be unique
153
-
154
- Returns:
155
- - None: At capacity, cannot provision more
156
- - job_id: (string) Identifier for the job
157
-
158
- """
159
-
160
- account_opt = '-A {}'.format(self.account) if self.account is not None else ''
161
-
162
- job_name = "parsl.{0}.{1}".format(job_name, time.time())
163
-
164
- script_path = "{0}/{1}.submit".format(self.script_dir, job_name)
165
- script_path = os.path.abspath(script_path)
166
-
167
- job_config = {}
168
- job_config["scheduler_options"] = self.scheduler_options
169
- job_config["worker_init"] = self.worker_init
170
-
171
- logger.debug("Requesting nodes_per_block:%s tasks_per_node:%s",
172
- self.nodes_per_block, tasks_per_node)
173
-
174
- # Wrap the command
175
- job_config["user_script"] = self.launcher(command, tasks_per_node, self.nodes_per_block)
176
-
177
- queue_opt = '-q {}'.format(self.queue) if self.queue is not None else ''
178
-
179
- logger.debug("Writing submit script")
180
- self._write_submit_script(template_string, script_path, job_name, job_config)
181
-
182
- channel_script_path = self.channel.push_file(script_path, self.channel.script_dir)
183
-
184
- command = 'qsub -n {0} {1} -t {2} {3} {4}'.format(
185
- self.nodes_per_block, queue_opt, wtime_to_minutes(self.walltime), account_opt, channel_script_path)
186
- logger.debug("Executing {}".format(command))
187
-
188
- retcode, stdout, stderr = self.execute_wait(command)
189
-
190
- # TODO : FIX this block
191
- if retcode != 0:
192
- logger.error("Failed command: {0}".format(command))
193
- logger.error("Launch failed stdout:\n{0} \nstderr:{1}\n".format(stdout, stderr))
194
-
195
- logger.debug("Retcode:%s STDOUT:%s STDERR:%s", retcode, stdout.strip(), stderr.strip())
196
-
197
- job_id = None
198
-
199
- if retcode == 0:
200
- # We should be getting only one line back
201
- job_id = stdout.strip()
202
- self.resources[job_id] = {'job_id': job_id, 'status': JobStatus(JobState.PENDING)}
203
- else:
204
- logger.error("Submit command failed: {0}".format(stderr))
205
- raise ScaleOutFailed(self.__class__, "Request to submit job to local scheduler failed")
206
-
207
- logger.debug("Returning job id : {0}".format(job_id))
208
- return job_id
209
-
210
- def cancel(self, job_ids):
211
- """ Cancels the jobs specified by a list of job ids
212
-
213
- Args:
214
- job_ids : [<job_id> ...]
215
-
216
- Returns :
217
- [True/False...] : If the cancel operation fails the entire list will be False.
218
- """
219
-
220
- job_id_list = ' '.join(job_ids)
221
- retcode, stdout, stderr = self.execute_wait("qdel {0}".format(job_id_list))
222
- rets = None
223
- if retcode == 0:
224
- for jid in job_ids:
225
- # ???
226
- # self.resources[jid]['status'] = translate_table['KILLING'] # Setting state to cancelled
227
- self.resources[jid]['status'] = JobStatus(JobState.COMPLETED)
228
- rets = [True for i in job_ids]
229
- else:
230
- rets = [False for i in job_ids]
231
-
232
- return rets
233
-
234
- @property
235
- def status_polling_interval(self):
236
- return 60
@@ -1,17 +0,0 @@
1
- template_string = '''#!/bin/bash -el
2
- ${scheduler_options}
3
-
4
- ${worker_init}
5
-
6
- echo "Starting Cobalt job script"
7
-
8
- echo "----Cobalt Nodefile: -----"
9
- cat $$COBALT_NODEFILE
10
- echo "--------------------------"
11
-
12
- export JOBNAME="${jobname}"
13
-
14
- $user_script
15
-
16
- echo "End of Cobalt job"
17
- '''
@@ -1,35 +0,0 @@
1
- from parsl.providers import AdHocProvider
2
- from parsl.channels import SSHChannel
3
- from parsl.executors import HighThroughputExecutor
4
- from parsl.config import Config
5
-
6
- from typing import Any, Dict
7
-
8
- user_opts = {'adhoc':
9
- {'username': 'YOUR_USERNAME',
10
- 'script_dir': 'YOUR_SCRIPT_DIR',
11
- 'remote_hostnames': ['REMOTE_HOST_URL_1', 'REMOTE_HOST_URL_2']
12
- }
13
- } # type: Dict[str, Dict[str, Any]]
14
-
15
- config = Config(
16
- executors=[
17
- HighThroughputExecutor(
18
- label='remote_htex',
19
- max_workers_per_node=2,
20
- worker_logdir_root=user_opts['adhoc']['script_dir'],
21
- encrypted=True,
22
- provider=AdHocProvider(
23
- # Command to be run before starting a worker, such as:
24
- # 'module load Anaconda; source activate parsl_env'.
25
- worker_init='',
26
- channels=[SSHChannel(hostname=m,
27
- username=user_opts['adhoc']['username'],
28
- script_dir=user_opts['adhoc']['script_dir'],
29
- ) for m in user_opts['adhoc']['remote_hostnames']]
30
- )
31
- )
32
- ],
33
- # AdHoc Clusters should not be setup with scaling strategy.
34
- strategy='none',
35
- )
@@ -1,37 +0,0 @@
1
- # UNTESTED
2
-
3
- from parsl.config import Config
4
- from parsl.executors import HighThroughputExecutor
5
- from parsl.launchers import MpiRunLauncher
6
- from parsl.providers import CobaltProvider
7
-
8
- # If you are a developer running tests, make sure to update parsl/tests/configs/user_opts.py
9
- # If you are a user copying-and-pasting this as an example, make sure to either
10
- # 1) create a local `user_opts.py`, or
11
- # 2) delete the user_opts import below and replace all appearances of `user_opts` with the literal value
12
- # (i.e., user_opts['swan']['username'] -> 'your_username')
13
- from .user_opts import user_opts
14
-
15
- config = Config(
16
- executors=[
17
- HighThroughputExecutor(
18
- label="cooley_htex",
19
- worker_debug=False,
20
- cores_per_worker=1,
21
- encrypted=True,
22
- provider=CobaltProvider(
23
- queue='debug',
24
- account=user_opts['cooley']['account'],
25
- launcher=MpiRunLauncher(), # UNTESTED COMPONENT
26
- scheduler_options=user_opts['cooley']['scheduler_options'],
27
- worker_init=user_opts['cooley']['worker_init'],
28
- init_blocks=1,
29
- max_blocks=1,
30
- min_blocks=1,
31
- nodes_per_block=4,
32
- cmd_timeout=60,
33
- walltime='00:10:00',
34
- ),
35
- )
36
- ]
37
- )
@@ -1,28 +0,0 @@
1
- from parsl.providers import AdHocProvider
2
- from parsl.channels import SSHChannel
3
- from parsl.executors import HighThroughputExecutor
4
-
5
- from parsl.config import Config
6
-
7
- from parsl.tests.configs.user_opts import user_opts
8
-
9
- config = Config(
10
- executors=[
11
- HighThroughputExecutor(
12
- label='remote_htex',
13
- cores_per_worker=1,
14
- worker_debug=False,
15
- address=user_opts['public_ip'],
16
- encrypted=True,
17
- provider=AdHocProvider(
18
- move_files=False,
19
- parallelism=1,
20
- worker_init=user_opts['adhoc']['worker_init'],
21
- channels=[SSHChannel(hostname=m,
22
- username=user_opts['adhoc']['username'],
23
- script_dir=user_opts['adhoc']['script_dir'],
24
- ) for m in user_opts['adhoc']['remote_hostnames']]
25
- )
26
- )
27
- ],
28
- )
@@ -1,18 +0,0 @@
1
- from parsl.config import Config
2
- from parsl.channels import LocalChannel
3
- from parsl.executors import HighThroughputExecutor
4
- from parsl.providers import AdHocProvider
5
-
6
-
7
- def fresh_config():
8
- return Config(
9
- executors=[
10
- HighThroughputExecutor(
11
- label='AdHoc',
12
- encrypted=True,
13
- provider=AdHocProvider(
14
- channels=[LocalChannel(), LocalChannel()]
15
- )
16
- )
17
- ]
18
- )
@@ -1,43 +0,0 @@
1
- """
2
- ================== Block
3
- | ++++++++++++++ | Node
4
- | | | |
5
- | | Task | | . . .
6
- | | | |
7
- | ++++++++++++++ |
8
- ==================
9
- """
10
- from parsl.channels import SSHChannel
11
- from parsl.launchers import AprunLauncher
12
- from parsl.providers import TorqueProvider
13
- from parsl.config import Config
14
- from parsl.executors import HighThroughputExecutor
15
-
16
- # If you are a developer running tests, make sure to update parsl/tests/configs/user_opts.py
17
- # If you are a user copying-and-pasting this as an example, make sure to either
18
- # 1) create a local `user_opts.py`, or
19
- # 2) delete the user_opts import below and replace all appearances of `user_opts` with the literal value
20
- # (i.e., user_opts['swan']['username'] -> 'your_username')
21
- from .user_opts import user_opts
22
-
23
- config = Config(
24
- executors=[
25
- HighThroughputExecutor(
26
- label='swan_htex',
27
- encrypted=True,
28
- provider=TorqueProvider(
29
- channel=SSHChannel(
30
- hostname='swan.cray.com',
31
- username=user_opts['swan']['username'],
32
- script_dir=user_opts['swan']['script_dir'],
33
- ),
34
- nodes_per_block=1,
35
- init_blocks=1,
36
- max_blocks=1,
37
- launcher=AprunLauncher(),
38
- scheduler_options=user_opts['swan']['scheduler_options'],
39
- worker_init=user_opts['swan']['worker_init'],
40
- ),
41
- )
42
- ]
43
- )
@@ -1,37 +0,0 @@
1
- from parsl.config import Config
2
- from parsl.providers import CobaltProvider
3
- from parsl.launchers import AprunLauncher
4
- from parsl.executors import HighThroughputExecutor
5
-
6
- from .user_opts import user_opts
7
-
8
-
9
- def fresh_config():
10
- return Config(
11
- executors=[
12
- HighThroughputExecutor(
13
- label='theta_local_htex_multinode',
14
- max_workers_per_node=1,
15
- encrypted=True,
16
- provider=CobaltProvider(
17
- queue=user_opts['theta']['queue'],
18
- account=user_opts['theta']['account'],
19
- launcher=AprunLauncher(overrides="-d 64"),
20
- walltime='00:10:00',
21
- nodes_per_block=2,
22
- init_blocks=1,
23
- max_blocks=1,
24
- # string to prepend to #COBALT blocks in the submit
25
- # script to the scheduler eg: '#COBALT -t 50'
26
- scheduler_options='',
27
- # Command to be run before starting a worker, such as:
28
- # 'module load Anaconda; source activate parsl_env'.
29
- worker_init=user_opts['theta']['worker_init'],
30
- cmd_timeout=120,
31
- ),
32
- )
33
- ],
34
- )
35
-
36
-
37
- config = fresh_config()
File without changes
@@ -1,17 +0,0 @@
1
- from parsl.channels.local.local import LocalChannel
2
-
3
-
4
- def test_local():
5
-
6
- channel = LocalChannel(None, None)
7
-
8
- ec, out, err = channel.execute_wait('echo "pwd: $PWD"', 2)
9
-
10
- assert ec == 0, "Channel execute failed"
11
- print("Stdout: ", out)
12
- print("Stderr: ", err)
13
-
14
-
15
- if __name__ == "__main__":
16
-
17
- test_local()
@@ -1,42 +0,0 @@
1
- from parsl.channels.local.local import LocalChannel
2
-
3
-
4
- def test_env():
5
- ''' Regression testing for issue #27
6
- '''
7
-
8
- lc = LocalChannel()
9
- rc, stdout, stderr = lc.execute_wait("env", 1)
10
-
11
- stdout = stdout.split('\n')
12
- x = [s for s in stdout if s.startswith("PATH=")]
13
- assert x, "PATH not found"
14
-
15
- x = [s for s in stdout if s.startswith("HOME=")]
16
- assert x, "HOME not found"
17
-
18
- print("RC:{} \nSTDOUT:{} \nSTDERR:{}".format(rc, stdout, stderr))
19
-
20
-
21
- def test_env_mod():
22
- ''' Testing for env update at execute time.
23
- '''
24
-
25
- lc = LocalChannel()
26
- rc, stdout, stderr = lc.execute_wait("env", 1, {'TEST_ENV': 'fooo'})
27
-
28
- stdout = stdout.split('\n')
29
- x = [s for s in stdout if s.startswith("PATH=")]
30
- assert x, "PATH not found"
31
-
32
- x = [s for s in stdout if s.startswith("HOME=")]
33
- assert x, "HOME not found"
34
-
35
- x = [s for s in stdout if s.startswith("TEST_ENV=fooo")]
36
- assert x, "User set env missing"
37
-
38
-
39
- if __name__ == "__main__":
40
-
41
- test_env()
42
- test_env_mod()
@@ -1,45 +0,0 @@
1
- import os
2
-
3
- from parsl.channels.ssh.ssh import SSHChannel as SSH
4
-
5
-
6
- def connect_and_list(hostname, username):
7
- out = ''
8
- conn = SSH(hostname, username=username)
9
- conn.push_file(os.path.abspath('remote_run.sh'), '/home/davidk/')
10
- # ec, out, err = conn.execute_wait("ls /tmp/remote_run.sh; bash /tmp/remote_run.sh")
11
- conn.close()
12
- return out
13
-
14
-
15
- script = '''#!/bin/bash
16
- echo "Hostname: $HOSTNAME"
17
- echo "Cpu info -----"
18
- cat /proc/cpuinfo
19
- echo "Done----------"
20
- '''
21
-
22
-
23
- def test_connect_1():
24
- with open('remote_run.sh', 'w') as f:
25
- f.write(script)
26
-
27
- sites = {
28
- 'midway': {
29
- 'url': 'midway.rcc.uchicago.edu',
30
- 'uname': 'yadunand'
31
- },
32
- 'swift': {
33
- 'url': 'swift.rcc.uchicago.edu',
34
- 'uname': 'yadunand'
35
- }
36
- }
37
-
38
- for site in sites.values():
39
- out = connect_and_list(site['url'], site['uname'])
40
- print("Sitename :{0} hostname:{1}".format(site['url'], out))
41
-
42
-
43
- if __name__ == "__main__":
44
-
45
- test_connect_1()
@@ -1,40 +0,0 @@
1
- from parsl.channels.ssh.ssh import SSHChannel as SSH
2
-
3
-
4
- def connect_and_list(hostname, username):
5
- conn = SSH(hostname, username=username)
6
- ec, out, err = conn.execute_wait("echo $HOSTNAME")
7
- conn.close()
8
- return out
9
-
10
-
11
- def test_midway():
12
- ''' Test ssh channels to midway
13
- '''
14
- url = 'midway.rcc.uchicago.edu'
15
- uname = 'yadunand'
16
- out = connect_and_list(url, uname)
17
- print("Sitename :{0} hostname:{1}".format(url, out))
18
-
19
-
20
- def test_beagle():
21
- ''' Test ssh channels to beagle
22
- '''
23
- url = 'login04.beagle.ci.uchicago.edu'
24
- uname = 'yadunandb'
25
- out = connect_and_list(url, uname)
26
- print("Sitename :{0} hostname:{1}".format(url, out))
27
-
28
-
29
- def test_osg():
30
- ''' Test ssh connectivity to osg
31
- '''
32
- url = 'login.osgconnect.net'
33
- uname = 'yadunand'
34
- out = connect_and_list(url, uname)
35
- print("Sitename :{0} hostname:{1}".format(url, out))
36
-
37
-
38
- if __name__ == "__main__":
39
-
40
- pass
@@ -1,46 +0,0 @@
1
- from parsl.channels.errors import SSHException, BadHostKeyException
2
- from parsl.channels.ssh.ssh import SSHChannel as SSH
3
-
4
-
5
- def connect_and_list(hostname, username):
6
- conn = SSH(hostname, username=username)
7
- ec, out, err = conn.execute_wait("echo $HOSTNAME")
8
- conn.close()
9
- return out
10
-
11
-
12
- def test_error_1():
13
- try:
14
- connect_and_list("bad.url.gov", "ubuntu")
15
- except Exception as e:
16
- assert type(e) is SSHException, "Expected SSException, got: {0}".format(e)
17
-
18
-
19
- def test_error_2():
20
- try:
21
- connect_and_list("swift.rcc.uchicago.edu", "mango")
22
- except SSHException:
23
- print("Caught the right exception")
24
- else:
25
- raise Exception("Expected SSException, got: {0}".format(e))
26
-
27
-
28
- def test_error_3():
29
- ''' This should work
30
- '''
31
- try:
32
- connect_and_list("edison.nersc.gov", "yadunand")
33
- except BadHostKeyException as e:
34
- print("Caught exception BadHostKeyException: ", e)
35
- else:
36
- assert False, "Expected SSException, got: {0}".format(e)
37
-
38
-
39
- if __name__ == "__main__":
40
-
41
- tests = [test_error_1, test_error_2, test_error_3]
42
-
43
- for test in tests:
44
- print("---------Running : {0}---------------".format(test))
45
- test()
46
- print("----------------------DONE--------------------------")