parsl 2025.10.13__tar.gz → 2025.10.27__tar.gz

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.

Potentially problematic release.


This version of parsl might be problematic. Click here for more details.

Files changed (468) hide show
  1. {parsl-2025.10.13/parsl.egg-info → parsl-2025.10.27}/PKG-INFO +3 -2
  2. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/bash.py +1 -1
  3. parsl-2025.10.27/parsl/concurrent/__init__.py +166 -0
  4. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/globus.py +3 -1
  5. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/dflow.py +92 -192
  6. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/memoization.py +126 -2
  7. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/states.py +5 -5
  8. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/interchange.py +4 -7
  9. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/strategy.py +7 -6
  10. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_globus.py +18 -14
  11. parsl-2025.10.27/parsl/tests/sites/test_concurrent.py +96 -0
  12. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_priority_queue.py +18 -1
  13. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_basic.py +0 -14
  14. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_depfail_propagation.py +11 -1
  15. parsl-2025.10.27/parsl/tests/test_python_apps/test_exception.py +19 -0
  16. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_3696_oscillation.py +1 -0
  17. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_globus.py +2 -2
  18. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_globus_compute_executor.py +11 -2
  19. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/version.py +1 -1
  20. {parsl-2025.10.13 → parsl-2025.10.27/parsl.egg-info}/PKG-INFO +3 -2
  21. {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/SOURCES.txt +1 -0
  22. {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/requires.txt +4 -1
  23. {parsl-2025.10.13 → parsl-2025.10.27}/requirements.txt +0 -1
  24. {parsl-2025.10.13 → parsl-2025.10.27}/setup.py +1 -0
  25. parsl-2025.10.13/parsl/concurrent/__init__.py +0 -85
  26. parsl-2025.10.13/parsl/tests/sites/test_concurrent.py +0 -48
  27. {parsl-2025.10.13 → parsl-2025.10.27}/LICENSE +0 -0
  28. {parsl-2025.10.13 → parsl-2025.10.27}/MANIFEST.in +0 -0
  29. {parsl-2025.10.13 → parsl-2025.10.27}/README.rst +0 -0
  30. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/__init__.py +0 -0
  31. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/addresses.py +0 -0
  32. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/__init__.py +0 -0
  33. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/app.py +0 -0
  34. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/errors.py +0 -0
  35. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/futures.py +0 -0
  36. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/python.py +0 -0
  37. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/benchmark/__init__.py +0 -0
  38. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/benchmark/perf.py +0 -0
  39. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/config.py +0 -0
  40. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/ASPIRE1.py +0 -0
  41. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/Azure.py +0 -0
  42. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/__init__.py +0 -0
  43. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/anvil.py +0 -0
  44. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/bridges.py +0 -0
  45. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/cc_in2p3.py +0 -0
  46. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/delta.py +0 -0
  47. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/ec2.py +0 -0
  48. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/expanse.py +0 -0
  49. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/frontera.py +0 -0
  50. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/gc_multisite.py +0 -0
  51. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/gc_tutorial.py +0 -0
  52. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/htex_local.py +0 -0
  53. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/illinoiscluster.py +0 -0
  54. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/improv.py +0 -0
  55. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/kubernetes.py +0 -0
  56. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/local_threads.py +0 -0
  57. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/midway.py +0 -0
  58. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/osg.py +0 -0
  59. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/polaris.py +0 -0
  60. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/stampede2.py +0 -0
  61. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/summit.py +0 -0
  62. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/toss3_llnl.py +0 -0
  63. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/vineex_local.py +0 -0
  64. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/wqex_local.py +0 -0
  65. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/curvezmq.py +0 -0
  66. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/__init__.py +0 -0
  67. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/data_manager.py +0 -0
  68. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/file_noop.py +0 -0
  69. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/files.py +0 -0
  70. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/ftp.py +0 -0
  71. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/http.py +0 -0
  72. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/rsync.py +0 -0
  73. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/staging.py +0 -0
  74. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/zip.py +0 -0
  75. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/__init__.py +0 -0
  76. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/dependency_resolvers.py +0 -0
  77. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/errors.py +0 -0
  78. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/futures.py +0 -0
  79. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/rundirs.py +0 -0
  80. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/taskrecord.py +0 -0
  81. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/errors.py +0 -0
  82. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/__init__.py +0 -0
  83. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/base.py +0 -0
  84. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/errors.py +0 -0
  85. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/execute_task.py +0 -0
  86. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/__init__.py +0 -0
  87. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/execute_parsl_task.py +0 -0
  88. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/executor.py +0 -0
  89. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/flux_instance_manager.py +0 -0
  90. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/globus_compute.py +0 -0
  91. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/__init__.py +0 -0
  92. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/errors.py +0 -0
  93. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/executor.py +0 -0
  94. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/manager_record.py +0 -0
  95. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/manager_selector.py +0 -0
  96. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/monitoring_info.py +0 -0
  97. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_executor.py +0 -0
  98. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
  99. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_resource_management.py +0 -0
  100. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/probe.py +0 -0
  101. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/process_worker_pool.py +0 -0
  102. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/zmq_pipes.py +0 -0
  103. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/__init__.py +0 -0
  104. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/executor.py +0 -0
  105. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/rpex_resources.py +0 -0
  106. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/rpex_worker.py +0 -0
  107. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/status_handling.py +0 -0
  108. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/__init__.py +0 -0
  109. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/errors.py +0 -0
  110. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
  111. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/executor.py +0 -0
  112. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/factory.py +0 -0
  113. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/factory_config.py +0 -0
  114. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/manager.py +0 -0
  115. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/manager_config.py +0 -0
  116. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/utils.py +0 -0
  117. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/threads.py +0 -0
  118. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/__init__.py +0 -0
  119. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/errors.py +0 -0
  120. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
  121. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/executor.py +0 -0
  122. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
  123. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
  124. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/__init__.py +0 -0
  125. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/error_handlers.py +0 -0
  126. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/errors.py +0 -0
  127. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/job_status_poller.py +0 -0
  128. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/states.py +0 -0
  129. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/__init__.py +0 -0
  130. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/base.py +0 -0
  131. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/errors.py +0 -0
  132. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/launchers.py +0 -0
  133. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/log_utils.py +0 -0
  134. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/__init__.py +0 -0
  135. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/db_manager.py +0 -0
  136. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/errors.py +0 -0
  137. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/message_type.py +0 -0
  138. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/monitoring.py +0 -0
  139. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/queries/__init__.py +0 -0
  140. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/queries/pandas.py +0 -0
  141. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/__init__.py +0 -0
  142. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/base.py +0 -0
  143. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/filesystem.py +0 -0
  144. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/filesystem_router.py +0 -0
  145. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/htex.py +0 -0
  146. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/multiprocessing.py +0 -0
  147. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/udp.py +0 -0
  148. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/udp_router.py +0 -0
  149. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/zmq.py +0 -0
  150. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/zmq_router.py +0 -0
  151. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/remote.py +0 -0
  152. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/types.py +0 -0
  153. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/__init__.py +0 -0
  154. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/app.py +0 -0
  155. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/models.py +0 -0
  156. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/__init__.py +0 -0
  157. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
  158. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
  159. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
  160. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
  161. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
  162. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
  163. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/app.html +0 -0
  164. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/dag.html +0 -0
  165. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/error.html +0 -0
  166. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/layout.html +0 -0
  167. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
  168. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/task.html +0 -0
  169. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/workflow.html +0 -0
  170. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
  171. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/utils.py +0 -0
  172. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/version.py +0 -0
  173. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/views.py +0 -0
  174. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/multiprocessing.py +0 -0
  175. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/process_loggers.py +0 -0
  176. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/__init__.py +0 -0
  177. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/__init__.py +0 -0
  178. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/aws.py +0 -0
  179. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/template.py +0 -0
  180. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/__init__.py +0 -0
  181. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/azure.py +0 -0
  182. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/template.py +0 -0
  183. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/base.py +0 -0
  184. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/cluster_provider.py +0 -0
  185. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/__init__.py +0 -0
  186. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/condor.py +0 -0
  187. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/template.py +0 -0
  188. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/errors.py +0 -0
  189. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/googlecloud/__init__.py +0 -0
  190. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/googlecloud/googlecloud.py +0 -0
  191. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/__init__.py +0 -0
  192. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/grid_engine.py +0 -0
  193. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/template.py +0 -0
  194. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/__init__.py +0 -0
  195. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/kube.py +0 -0
  196. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/template.py +0 -0
  197. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/local/__init__.py +0 -0
  198. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/local/local.py +0 -0
  199. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/__init__.py +0 -0
  200. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/lsf.py +0 -0
  201. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/template.py +0 -0
  202. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/__init__.py +0 -0
  203. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/pbspro.py +0 -0
  204. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/template.py +0 -0
  205. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/__init__.py +0 -0
  206. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/slurm.py +0 -0
  207. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/template.py +0 -0
  208. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/__init__.py +0 -0
  209. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/template.py +0 -0
  210. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/torque.py +0 -0
  211. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/py.typed +0 -0
  212. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/__init__.py +0 -0
  213. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/base.py +0 -0
  214. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/concretes.py +0 -0
  215. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/errors.py +0 -0
  216. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/facade.py +0 -0
  217. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/proxystore.py +0 -0
  218. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/__init__.py +0 -0
  219. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/callables_helper.py +0 -0
  220. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/__init__.py +0 -0
  221. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/azure_single_node.py +0 -0
  222. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/bluewaters.py +0 -0
  223. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/bridges.py +0 -0
  224. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/cc_in2p3.py +0 -0
  225. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/comet.py +0 -0
  226. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/ec2_single_node.py +0 -0
  227. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/ec2_spot.py +0 -0
  228. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/flux_local.py +0 -0
  229. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/frontera.py +0 -0
  230. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/globus_compute.py +0 -0
  231. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local.py +0 -0
  232. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_alternate.py +0 -0
  233. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
  234. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
  235. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_radical.py +0 -0
  236. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_radical_mpi.py +0 -0
  237. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads.py +0 -0
  238. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
  239. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
  240. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
  241. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
  242. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
  243. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/midway.py +0 -0
  244. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/nscc_singapore.py +0 -0
  245. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/osg_htex.py +0 -0
  246. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/petrelkube.py +0 -0
  247. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/slurm_local.py +0 -0
  248. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/summit.py +0 -0
  249. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/taskvine_ex.py +0 -0
  250. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/user_opts.py +0 -0
  251. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/workqueue_ex.py +0 -0
  252. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/conftest.py +0 -0
  253. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/__init__.py +0 -0
  254. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/latency.py +0 -0
  255. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_apps/__init__.py +0 -0
  256. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
  257. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/__init__.py +0 -0
  258. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
  259. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
  260. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/__init__.py +0 -0
  261. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/htex_local.py +0 -0
  262. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_basic.py +0 -0
  263. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_log_filter.py +0 -0
  264. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
  265. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_regression_220.py +0 -0
  266. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_worker_count.py +0 -0
  267. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/site_tests/__init__.py +0 -0
  268. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/site_tests/site_config_selector.py +0 -0
  269. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/__init__.py +0 -0
  270. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_affinity.py +0 -0
  271. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_dynamic_executor.py +0 -0
  272. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_ec2.py +0 -0
  273. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_launchers.py +0 -0
  274. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_mpi/__init__.py +0 -0
  275. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_worker_info.py +0 -0
  276. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/__init__.py +0 -0
  277. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
  278. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_basic.py +0 -0
  279. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
  280. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_inputs_default.py +0 -0
  281. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
  282. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
  283. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
  284. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
  285. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
  286. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
  287. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
  288. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_std_uri.py +0 -0
  289. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
  290. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_callables.py +0 -0
  291. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/__init__.py +0 -0
  292. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_periodic.py +0 -0
  293. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
  294. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
  295. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
  296. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
  297. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
  298. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
  299. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_curvezmq.py +0 -0
  300. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/__init__.py +0 -0
  301. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_from_slides.py +0 -0
  302. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_kwargs.py +0 -0
  303. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
  304. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_workflow1.py +0 -0
  305. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_workflow4.py +0 -0
  306. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/__init__.py +0 -0
  307. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_fail.py +0 -0
  308. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
  309. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
  310. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retries.py +0 -0
  311. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
  312. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
  313. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
  314. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
  315. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_execute_task.py +0 -0
  316. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_flowcontrol/__init__.py +0 -0
  317. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_flux.py +0 -0
  318. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/__init__.py +0 -0
  319. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_basic.py +0 -0
  320. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_block_manager_selector_unit.py +0 -0
  321. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_command_client_timeout.py +0 -0
  322. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_command_concurrency_regression_1321.py +0 -0
  323. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
  324. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
  325. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -0
  326. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +0 -0
  327. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_drain.py +0 -0
  328. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_htex.py +0 -0
  329. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_interchange_exit_bad_registration.py +0 -0
  330. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_manager_failure.py +0 -0
  331. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_manager_selector_by_block.py +0 -0
  332. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_managers_command.py +0 -0
  333. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_missing_worker.py +0 -0
  334. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
  335. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_resource_spec_validation.py +0 -0
  336. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_worker_failure.py +0 -0
  337. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
  338. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/__init__.py +0 -0
  339. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_app_names.py +0 -0
  340. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_basic.py +0 -0
  341. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
  342. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_exit_helper.py +0 -0
  343. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_htex_fuzz_zmq.py +0 -0
  344. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -0
  345. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
  346. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
  347. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_filesystem.py +0 -0
  348. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_multiprocessing.py +0 -0
  349. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_udp.py +0 -0
  350. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_zmq.py +0 -0
  351. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_stdouterr.py +0 -0
  352. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
  353. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/__init__.py +0 -0
  354. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
  355. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
  356. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
  357. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +0 -0
  358. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpiex.py +0 -0
  359. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
  360. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/__init__.py +0 -0
  361. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_kubernetes_provider.py +0 -0
  362. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_local_provider.py +0 -0
  363. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
  364. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
  365. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_slurm_template.py +0 -0
  366. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
  367. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/__init__.py +0 -0
  368. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
  369. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_context_manager.py +0 -0
  370. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
  371. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
  372. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dependencies_deep.py +0 -0
  373. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fail.py +0 -0
  374. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
  375. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
  376. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_futures.py +0 -0
  377. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
  378. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
  379. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_inputs_default.py +0 -0
  380. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_join.py +0 -0
  381. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_lifted.py +0 -0
  382. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_mapred.py +0 -0
  383. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
  384. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
  385. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
  386. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
  387. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_exception.py +0 -0
  388. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
  389. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
  390. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_outputs.py +0 -0
  391. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_overview.py +0 -0
  392. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
  393. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_pluggable_future_resolution.py +0 -0
  394. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_simple.py +0 -0
  395. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_timeout.py +0 -0
  396. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_type5.py +0 -0
  397. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_radical/__init__.py +0 -0
  398. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
  399. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/__init__.py +0 -0
  400. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1480.py +0 -0
  401. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
  402. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1653.py +0 -0
  403. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_221.py +0 -0
  404. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_226.py +0 -0
  405. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_2652.py +0 -0
  406. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_3874.py +0 -0
  407. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_69a.py +0 -0
  408. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
  409. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_98.py +0 -0
  410. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/__init__.py +0 -0
  411. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
  412. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
  413. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -0
  414. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down.py +0 -0
  415. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
  416. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -0
  417. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_shutdown_scalein.py +0 -0
  418. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +0 -0
  419. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/__init__.py +0 -0
  420. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
  421. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +0 -0
  422. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_basic.py +0 -0
  423. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
  424. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
  425. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
  426. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_shutdown/__init__.py +0 -0
  427. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_shutdown/test_kill_monitoring.py +0 -0
  428. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/__init__.py +0 -0
  429. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/staging_provider.py +0 -0
  430. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_1316.py +0 -0
  431. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_docs_1.py +0 -0
  432. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_docs_2.py +0 -0
  433. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
  434. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file.py +0 -0
  435. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file_apps.py +0 -0
  436. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file_staging.py +0 -0
  437. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_output_chain_filenames.py +0 -0
  438. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
  439. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
  440. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_https.py +0 -0
  441. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_stdout.py +0 -0
  442. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_in.py +0 -0
  443. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_out.py +0 -0
  444. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_to_zip.py +0 -0
  445. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_summary.py +0 -0
  446. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_thread_parallelism.py +0 -0
  447. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/__init__.py +0 -0
  448. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/test_configs.py +0 -0
  449. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
  450. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/__init__.py +0 -0
  451. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_execute_wait.py +0 -0
  452. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_logutils.py +0 -0
  453. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
  454. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_sanitize_dns.py +0 -0
  455. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/__init__.py +0 -0
  456. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_address.py +0 -0
  457. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_file.py +0 -0
  458. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_usage_tracking.py +0 -0
  459. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/utils.py +0 -0
  460. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/__init__.py +0 -0
  461. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/api.py +0 -0
  462. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/levels.py +0 -0
  463. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/usage.py +0 -0
  464. {parsl-2025.10.13 → parsl-2025.10.27}/parsl/utils.py +0 -0
  465. {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/dependency_links.txt +0 -0
  466. {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/entry_points.txt +0 -0
  467. {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/top_level.txt +0 -0
  468. {parsl-2025.10.13 → parsl-2025.10.27}/setup.cfg +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: parsl
3
- Version: 2025.10.13
3
+ Version: 2025.10.27
4
4
  Summary: Simple data dependent workflows in Python
5
5
  Home-page: https://github.com/Parsl/parsl
6
- Download-URL: https://github.com/Parsl/parsl/archive/2025.10.13.tar.gz
6
+ Download-URL: https://github.com/Parsl/parsl/archive/2025.10.27.tar.gz
7
7
  Author: The Parsl Team
8
8
  Author-email: parsl@googlegroups.com
9
9
  License: Apache 2.0
@@ -28,6 +28,7 @@ Provides-Extra: flux
28
28
  Provides-Extra: proxystore
29
29
  Provides-Extra: radical-pilot
30
30
  Provides-Extra: globus_compute
31
+ Provides-Extra: globus_transfer
31
32
  Provides-Extra: all
32
33
  License-File: LICENSE
33
34
 
@@ -88,7 +88,7 @@ def remote_side_bash_executor(func, *args, **kwargs):
88
88
  raise pe.AppTimeout(f"App {func_name} exceeded walltime: {timeout} seconds")
89
89
 
90
90
  except Exception as e:
91
- raise pe.AppException(f"App {func_name} caught exception with returncode: {returncode}", e)
91
+ raise pe.AppException(f"App {func_name} caught exception", e)
92
92
 
93
93
  if returncode != 0:
94
94
  raise pe.BashExitFailure(func_name, proc.returncode)
@@ -0,0 +1,166 @@
1
+ """Interfaces modeled after Python's `concurrent library <https://docs.python.org/3/library/concurrent.html>`_"""
2
+ import time
3
+ from concurrent.futures import Executor
4
+ from contextlib import AbstractContextManager
5
+ from typing import Callable, Dict, Iterable, Iterator, Literal, Optional
6
+ from warnings import warn
7
+
8
+ from parsl import Config, DataFlowKernel, load
9
+ from parsl.app.python import PythonApp
10
+
11
+
12
+ class ParslPoolExecutor(Executor, AbstractContextManager):
13
+ """An executor that uses a pool of workers managed by Parsl
14
+
15
+ Works just like a :class:`~concurrent.futures.ProcessPoolExecutor` except that tasks
16
+ are distributed across workers that can be on different machines.
17
+
18
+ Create a new executor using one of two methods:
19
+
20
+ 1. Supplying a Parsl :class:`~parsl.Config` that defines how to create new workers.
21
+ The executor will start a new Parsl Data Flow Kernel (DFK) when it is entered as a context manager.
22
+
23
+ 2. Supplying an already-started Parsl :class:`~parsl.DataFlowKernel` (DFK).
24
+ The executor assumes you will start and stop the Parsl DFK outside the Executor.
25
+
26
+ The futures returned by :meth:`submit` and :meth:`map` are Parsl futures and will work
27
+ with the same function chaining mechanisms as when using Parsl with decorators.
28
+
29
+ .. code-block:: python
30
+
31
+ def f(x):
32
+ return x + 1
33
+
34
+ @python_app
35
+ def parity(x):
36
+ return 'odd' if x % 2 == 1 else 'even'
37
+
38
+ with ParslPoolExecutor(config=my_parsl_config) as executor:
39
+ future_1 = executor.submit(f, 1)
40
+ assert parity(future_1) == 'even' # Function chaining, as expected
41
+
42
+ future_2 = executor.submit(f, future_1)
43
+ assert future_2.result() == 3 # Chaining works with `submit` too
44
+
45
+ Parsl does not support canceling tasks. The :meth:`map` method does not cancel work
46
+ when one member of the run fails or a timeout is reached
47
+ and :meth:`shutdown` does not cancel work on completion.
48
+ """
49
+
50
+ def __init__(self, config: Config | None = None, dfk: DataFlowKernel | None = None, executors: Literal['all'] | list[str] = 'all'):
51
+ """Create the executor
52
+
53
+ Args:
54
+ config: Configuration for the Parsl Data Flow Kernel (DFK)
55
+ dfk: DataFlowKernel of an already-started parsl
56
+ executors: List of executors to use for supplied functions
57
+ """
58
+ if (config is not None) and (dfk is not None):
59
+ raise ValueError('Specify only one of config or dfk')
60
+ if (config is None) and (dfk is None):
61
+ raise ValueError('Must specify one of config or dfk')
62
+ self._config = config
63
+ self._app_cache: Dict[Callable, PythonApp] = {} # Cache specific to this instance: https://stackoverflow.com/questions/33672412
64
+ self._dfk = dfk
65
+ self.executors = executors
66
+
67
+ # Start workers immediately
68
+ if self._config is not None:
69
+ self._dfk = load(self._config)
70
+
71
+ def __exit__(self, exc_type, exc_val, exc_tb):
72
+ if self._dfk is None: # Nothing has been started, do nothing
73
+ return
74
+ elif self._config is not None: # The executors are being managed by this class, shut them down
75
+ self.shutdown(wait=True)
76
+ return
77
+ else: # The DFK is managed elsewhere, do nothing
78
+ return
79
+
80
+ @property
81
+ def app_count(self):
82
+ """Number of functions currently registered with the executor"""
83
+ return len(self._app_cache)
84
+
85
+ def get_app(self, fn: Callable) -> PythonApp:
86
+ """Create a PythonApp for a function
87
+
88
+ Args:
89
+ fn: Function to be turned into a Parsl app
90
+ Returns:
91
+ PythonApp version of that function
92
+ """
93
+ if fn in self._app_cache:
94
+ return self._app_cache[fn]
95
+ app = PythonApp(fn, data_flow_kernel=self._dfk, executors=self.executors)
96
+ self._app_cache[fn] = app
97
+ return app
98
+
99
+ def submit(self, fn, *args, **kwargs):
100
+ """Submits a callable to be executed with the given arguments.
101
+
102
+ Schedules the callable to be executed as ``fn(*args, **kwargs)`` and returns
103
+ a Future instance representing the execution of the callable.
104
+
105
+ Returns:
106
+ A Future representing the given call.
107
+ """
108
+
109
+ if self._dfk is None:
110
+ raise RuntimeError('Executor has been shut down.')
111
+ app = self.get_app(fn)
112
+ return app(*args, **kwargs)
113
+
114
+ # TODO (wardlt): This override can go away when Parsl supports cancel
115
+ def map(self, fn: Callable, *iterables: Iterable, timeout: Optional[float] = None, chunksize: int = 1) -> Iterator:
116
+ """Returns an iterator equivalent to map(fn, iter).
117
+
118
+ Args:
119
+ fn: A callable that will take as many arguments as there are
120
+ passed iterables.
121
+ timeout: The maximum number of seconds to wait. If None, then there
122
+ is no limit on the wait time.
123
+ chunksize: If greater than one, the iterables will be chopped into
124
+ chunks of size chunksize and submitted to the process pool.
125
+ If set to one, the items in the list will be sent one at a time.
126
+
127
+ Returns:
128
+ An iterator equivalent to: map(func, ``*iterables``) but the calls may
129
+ be evaluated out-of-order.
130
+
131
+ Raises:
132
+ TimeoutError: If the entire result iterator could not be generated
133
+ before the given timeout.
134
+ Exception: If ``fn(*args)`` raises for any values.
135
+ """
136
+ # This is a version of the CPython 3.9 `.map` implementation modified to not use `cancel`
137
+ if timeout is not None:
138
+ end_time = timeout + time.monotonic()
139
+
140
+ # Submit the applications
141
+ app = self.get_app(fn)
142
+ fs = [app(*args) for args in zip(*iterables)]
143
+
144
+ # Yield the futures as completed
145
+ def result_iterator():
146
+ # reverse to keep finishing order
147
+ fs.reverse()
148
+ while fs:
149
+ # Careful not to keep a reference to the popped future
150
+ if timeout is None:
151
+ yield fs.pop().result()
152
+ else:
153
+ yield fs.pop().result(end_time - time.monotonic())
154
+
155
+ return result_iterator()
156
+
157
+ def shutdown(self, wait: bool = True, *, cancel_futures: bool = False) -> None:
158
+ if self._dfk is None:
159
+ return # Do nothing. Nothing is active
160
+ if cancel_futures:
161
+ warn(message="Canceling on-going tasks is not supported in Parsl")
162
+ if wait:
163
+ self._dfk.wait_for_current_tasks()
164
+ if self._config is not None: # The executors are being managed
165
+ self._dfk.cleanup() # Shutdown the DFK
166
+ self._dfk = None
@@ -4,7 +4,6 @@ import os
4
4
  from functools import partial
5
5
  from typing import Optional
6
6
 
7
- import globus_sdk
8
7
  import typeguard
9
8
 
10
9
  import parsl
@@ -79,6 +78,7 @@ class Globus:
79
78
 
80
79
  @classmethod
81
80
  def transfer_file(cls, src_ep, dst_ep, src_path, dst_path):
81
+ import globus_sdk
82
82
  tc = globus_sdk.TransferClient(authorizer=cls.authorizer)
83
83
  td = globus_sdk.TransferData(tc, src_ep, dst_ep)
84
84
  td.add_item(src_path, dst_path)
@@ -140,6 +140,7 @@ class Globus:
140
140
  def _do_native_app_authentication(cls, client_id, redirect_uri,
141
141
  requested_scopes=None):
142
142
 
143
+ import globus_sdk
143
144
  client = globus_sdk.NativeAppAuthClient(client_id=client_id)
144
145
  client.oauth2_start_flow(
145
146
  requested_scopes=requested_scopes,
@@ -154,6 +155,7 @@ class Globus:
154
155
 
155
156
  @classmethod
156
157
  def _get_native_app_authorizer(cls, client_id):
158
+ import globus_sdk
157
159
  tokens = None
158
160
  try:
159
161
  tokens = cls._load_tokens_from_file(cls.TOKEN_FILE)
@@ -6,7 +6,6 @@ import datetime
6
6
  import inspect
7
7
  import logging
8
8
  import os
9
- import pickle
10
9
  import random
11
10
  import sys
12
11
  import threading
@@ -50,7 +49,7 @@ from parsl.monitoring.radios.multiprocessing import MultiprocessingQueueRadioSen
50
49
  from parsl.monitoring.remote import monitor_wrapper
51
50
  from parsl.process_loggers import wrap_with_logs
52
51
  from parsl.usage_tracking.usage import UsageTracker
53
- from parsl.utils import Timer, get_all_checkpoints, get_std_fname_mode, get_version
52
+ from parsl.utils import get_std_fname_mode, get_version
54
53
 
55
54
  logger = logging.getLogger(__name__)
56
55
 
@@ -101,8 +100,6 @@ class DataFlowKernel:
101
100
 
102
101
  logger.info("Parsl version: {}".format(get_version()))
103
102
 
104
- self.checkpoint_lock = threading.Lock()
105
-
106
103
  self.usage_tracker = UsageTracker(self)
107
104
  self.usage_tracker.send_start_message()
108
105
 
@@ -168,18 +165,12 @@ class DataFlowKernel:
168
165
  self.monitoring_radio.send((MessageType.WORKFLOW_INFO,
169
166
  workflow_info))
170
167
 
171
- if config.checkpoint_files is not None:
172
- checkpoint_files = config.checkpoint_files
173
- elif config.checkpoint_files is None and config.checkpoint_mode is not None:
174
- checkpoint_files = get_all_checkpoints(self.run_dir)
175
- else:
176
- checkpoint_files = []
177
-
178
- self.memoizer = Memoizer(memoize=config.app_cache, checkpoint_files=checkpoint_files)
179
- self.checkpointed_tasks = 0
180
- self._checkpoint_timer = None
181
- self.checkpoint_mode = config.checkpoint_mode
182
- self.checkpointable_tasks: List[TaskRecord] = []
168
+ self.memoizer = Memoizer(memoize=config.app_cache,
169
+ checkpoint_mode=config.checkpoint_mode,
170
+ checkpoint_files=config.checkpoint_files,
171
+ checkpoint_period=config.checkpoint_period)
172
+ self.memoizer.run_dir = self.run_dir
173
+ self.memoizer.start()
183
174
 
184
175
  # this must be set before executors are added since add_executors calls
185
176
  # job_status_poller.add_executors.
@@ -195,22 +186,11 @@ class DataFlowKernel:
195
186
  self.add_executors(config.executors)
196
187
  self.add_executors([parsl_internal_executor])
197
188
 
198
- if self.checkpoint_mode == "periodic":
199
- if config.checkpoint_period is None:
200
- raise ConfigurationError("Checkpoint period must be specified with periodic checkpoint mode")
201
- else:
202
- try:
203
- h, m, s = map(int, config.checkpoint_period.split(':'))
204
- except Exception:
205
- raise ConfigurationError("invalid checkpoint_period provided: {0} expected HH:MM:SS".format(config.checkpoint_period))
206
- checkpoint_period = (h * 3600) + (m * 60) + s
207
- self._checkpoint_timer = Timer(self.checkpoint, interval=checkpoint_period, name="Checkpoint")
208
-
209
189
  self.task_count = 0
210
190
  self.tasks: Dict[int, TaskRecord] = {}
211
191
  self.submitter_lock = threading.Lock()
212
192
 
213
- self.dependency_launch_pool = cf.ThreadPoolExecutor(max_workers=1, thread_name_prefix="Dependency-Launch")
193
+ self._task_launch_pool = cf.ThreadPoolExecutor(max_workers=1, thread_name_prefix="Task-Launch")
214
194
 
215
195
  self.dependency_resolver = self.config.dependency_resolver if self.config.dependency_resolver is not None \
216
196
  else SHALLOW_DEPENDENCY_RESOLVER
@@ -371,13 +351,9 @@ class DataFlowKernel:
371
351
  else:
372
352
  task_record['fail_cost'] += 1
373
353
 
374
- if task_record['status'] == States.dep_fail:
354
+ if isinstance(e, DependencyError):
375
355
  logger.info("Task {} failed due to dependency failure so skipping retries".format(task_id))
376
- task_record['time_returned'] = datetime.datetime.now()
377
- self._send_task_log_info(task_record)
378
- self.memoizer.update_memo(task_record)
379
- with task_record['app_fu']._update_lock:
380
- task_record['app_fu'].set_exception(e)
356
+ self._complete_task_exception(task_record, States.dep_fail, e)
381
357
 
382
358
  elif task_record['fail_cost'] <= self._config.retries:
383
359
 
@@ -397,61 +373,48 @@ class DataFlowKernel:
397
373
  else:
398
374
  logger.exception("Task {} failed after {} retry attempts".format(task_id,
399
375
  task_record['try_id']))
400
- task_record['time_returned'] = datetime.datetime.now()
401
- self.update_task_state(task_record, States.failed)
402
- task_record['time_returned'] = datetime.datetime.now()
403
- self._send_task_log_info(task_record)
404
- self.memoizer.update_memo(task_record)
405
- with task_record['app_fu']._update_lock:
406
- task_record['app_fu'].set_exception(e)
376
+ self._complete_task_exception(task_record, States.failed, e)
407
377
 
408
378
  else:
409
379
  if task_record['from_memo']:
410
- self._complete_task(task_record, States.memo_done, res)
411
- self._send_task_log_info(task_record)
380
+ self._complete_task_result(task_record, States.memo_done, res)
381
+ elif not task_record['join']:
382
+ self._complete_task_result(task_record, States.exec_done, res)
412
383
  else:
413
- if not task_record['join']:
414
- self._complete_task(task_record, States.exec_done, res)
384
+ # This is a join task, and the original task's function code has
385
+ # completed. That means that the future returned by that code
386
+ # will be available inside the executor future, so we can now
387
+ # record the inner app ID in monitoring, and add a completion
388
+ # listener to that inner future.
389
+
390
+ joinable = future.result()
391
+
392
+ # Fail with a TypeError if the joinapp python body returned
393
+ # something we can't join on.
394
+ if isinstance(joinable, Future):
395
+ self.update_task_state(task_record, States.joining)
396
+ task_record['joins'] = joinable
397
+ task_record['join_lock'] = threading.Lock()
398
+ self._send_task_log_info(task_record)
399
+ joinable.add_done_callback(partial(self.handle_join_update, task_record))
400
+ elif joinable == []: # got a list, but it had no entries, and specifically, no Futures.
401
+ self.update_task_state(task_record, States.joining)
402
+ task_record['joins'] = joinable
403
+ task_record['join_lock'] = threading.Lock()
415
404
  self._send_task_log_info(task_record)
405
+ self.handle_join_update(task_record, None)
406
+ elif isinstance(joinable, list) and [j for j in joinable if not isinstance(j, Future)] == []:
407
+ self.update_task_state(task_record, States.joining)
408
+ task_record['joins'] = joinable
409
+ task_record['join_lock'] = threading.Lock()
410
+ self._send_task_log_info(task_record)
411
+ for inner_future in joinable:
412
+ inner_future.add_done_callback(partial(self.handle_join_update, task_record))
416
413
  else:
417
- # This is a join task, and the original task's function code has
418
- # completed. That means that the future returned by that code
419
- # will be available inside the executor future, so we can now
420
- # record the inner app ID in monitoring, and add a completion
421
- # listener to that inner future.
422
-
423
- joinable = future.result()
424
-
425
- # Fail with a TypeError if the joinapp python body returned
426
- # something we can't join on.
427
- if isinstance(joinable, Future):
428
- self.update_task_state(task_record, States.joining)
429
- task_record['joins'] = joinable
430
- task_record['join_lock'] = threading.Lock()
431
- self._send_task_log_info(task_record)
432
- joinable.add_done_callback(partial(self.handle_join_update, task_record))
433
- elif joinable == []: # got a list, but it had no entries, and specifically, no Futures.
434
- self.update_task_state(task_record, States.joining)
435
- task_record['joins'] = joinable
436
- task_record['join_lock'] = threading.Lock()
437
- self._send_task_log_info(task_record)
438
- self.handle_join_update(task_record, None)
439
- elif isinstance(joinable, list) and [j for j in joinable if not isinstance(j, Future)] == []:
440
- self.update_task_state(task_record, States.joining)
441
- task_record['joins'] = joinable
442
- task_record['join_lock'] = threading.Lock()
443
- self._send_task_log_info(task_record)
444
- for inner_future in joinable:
445
- inner_future.add_done_callback(partial(self.handle_join_update, task_record))
446
- else:
447
- task_record['time_returned'] = datetime.datetime.now()
448
- self.update_task_state(task_record, States.failed)
449
- task_record['time_returned'] = datetime.datetime.now()
450
- self._send_task_log_info(task_record)
451
- self.memoizer.update_memo(task_record)
452
- with task_record['app_fu']._update_lock:
453
- task_record['app_fu'].set_exception(
454
- TypeError(f"join_app body must return a Future or list of Futures, got {joinable} of type {type(joinable)}"))
414
+ self._complete_task_exception(
415
+ task_record,
416
+ States.failed,
417
+ TypeError(f"join_app body must return a Future or list of Futures, got {joinable} of type {type(joinable)}"))
455
418
 
456
419
  self._log_std_streams(task_record)
457
420
 
@@ -522,11 +485,7 @@ class DataFlowKernel:
522
485
  # no need to update the fail cost because join apps are never
523
486
  # retried
524
487
 
525
- self.update_task_state(task_record, States.failed)
526
- task_record['time_returned'] = datetime.datetime.now()
527
- self.memoizer.update_memo(task_record)
528
- with task_record['app_fu']._update_lock:
529
- task_record['app_fu'].set_exception(e)
488
+ self._complete_task_exception(task_record, States.failed, e)
530
489
 
531
490
  else:
532
491
  # all the joinables succeeded, so construct a result:
@@ -539,12 +498,10 @@ class DataFlowKernel:
539
498
  res.append(future.result())
540
499
  else:
541
500
  raise TypeError(f"Unknown joinable type {type(joinable)}")
542
- self._complete_task(task_record, States.exec_done, res)
501
+ self._complete_task_result(task_record, States.exec_done, res)
543
502
 
544
503
  self._log_std_streams(task_record)
545
504
 
546
- self._send_task_log_info(task_record)
547
-
548
505
  def handle_app_update(self, task_record: TaskRecord, future: AppFuture) -> None:
549
506
  """This function is called as a callback when an AppFuture
550
507
  is in its final state.
@@ -565,23 +522,12 @@ class DataFlowKernel:
565
522
  if not task_record['app_fu'] == future:
566
523
  logger.error("Internal consistency error: callback future is not the app_fu in task structure, for task {}".format(task_id))
567
524
 
568
- # Cover all checkpointing cases here:
569
- # Do we need to checkpoint now, or queue for later,
570
- # or do nothing?
571
- if self.checkpoint_mode == 'task_exit':
572
- self.checkpoint(tasks=[task_record])
573
- elif self.checkpoint_mode in ('manual', 'periodic', 'dfk_exit'):
574
- with self.checkpoint_lock:
575
- self.checkpointable_tasks.append(task_record)
576
- elif self.checkpoint_mode is None:
577
- pass
578
- else:
579
- raise InternalConsistencyError(f"Invalid checkpoint mode {self.checkpoint_mode}")
525
+ self.memoizer.update_checkpoint(task_record)
580
526
 
581
527
  self.wipe_task(task_id)
582
528
  return
583
529
 
584
- def _complete_task(self, task_record: TaskRecord, new_state: States, result: Any) -> None:
530
+ def _complete_task_result(self, task_record: TaskRecord, new_state: States, result: Any) -> None:
585
531
  """Set a task into a completed state
586
532
  """
587
533
  assert new_state in FINAL_STATES
@@ -594,9 +540,31 @@ class DataFlowKernel:
594
540
  task_record['time_returned'] = datetime.datetime.now()
595
541
 
596
542
  self.memoizer.update_memo(task_record)
543
+
544
+ self._send_task_log_info(task_record)
545
+
597
546
  with task_record['app_fu']._update_lock:
598
547
  task_record['app_fu'].set_result(result)
599
548
 
549
+ def _complete_task_exception(self, task_record: TaskRecord, new_state: States, exception: BaseException) -> None:
550
+ """Set a task into a failure state
551
+ """
552
+ assert new_state in FINAL_STATES
553
+ assert new_state in FINAL_FAILURE_STATES
554
+ old_state = task_record['status']
555
+
556
+ self.update_task_state(task_record, new_state)
557
+
558
+ logger.info(f"Task {task_record['id']} failed ({old_state.name} -> {new_state.name})")
559
+ task_record['time_returned'] = datetime.datetime.now()
560
+
561
+ self.memoizer.update_memo(task_record)
562
+
563
+ self._send_task_log_info(task_record)
564
+
565
+ with task_record['app_fu']._update_lock:
566
+ task_record['app_fu'].set_exception(exception)
567
+
600
568
  def update_task_state(self, task_record: TaskRecord, new_state: States) -> None:
601
569
  """Updates a task record state, and recording an appropriate change
602
570
  to task state counters.
@@ -640,7 +608,7 @@ class DataFlowKernel:
640
608
  launch_if_ready is thread safe, so may be called from any thread
641
609
  or callback.
642
610
  """
643
- self.dependency_launch_pool.submit(self._launch_if_ready_async, task_record)
611
+ self._task_launch_pool.submit(self._launch_if_ready_async, task_record)
644
612
 
645
613
  @wrap_with_logs
646
614
  def _launch_if_ready_async(self, task_record: TaskRecord) -> None:
@@ -648,7 +616,7 @@ class DataFlowKernel:
648
616
  _launch_if_ready will launch the specified task, if it is ready
649
617
  to run (for example, without dependencies, and in pending state).
650
618
  """
651
- exec_fu = None
619
+ exec_fu: Future
652
620
 
653
621
  task_id = task_record['id']
654
622
  with task_record['task_launch_lock']:
@@ -687,28 +655,24 @@ class DataFlowKernel:
687
655
  else:
688
656
  logger.info(
689
657
  "Task {} failed due to dependency failure".format(task_id))
690
- # Raise a dependency exception
691
- self.update_task_state(task_record, States.dep_fail)
692
-
693
- self._send_task_log_info(task_record)
694
658
 
695
659
  exec_fu = Future()
696
660
  exec_fu.set_exception(DependencyError(exceptions_tids,
697
661
  task_id))
698
662
 
699
- if exec_fu:
700
- assert isinstance(exec_fu, Future)
701
- try:
702
- exec_fu.add_done_callback(partial(self.handle_exec_update, task_record))
703
- except Exception:
704
- # this exception is ignored here because it is assumed that exception
705
- # comes from directly executing handle_exec_update (because exec_fu is
706
- # done already). If the callback executes later, then any exception
707
- # coming out of the callback will be ignored and not propate anywhere,
708
- # so this block attempts to keep the same behaviour here.
709
- logger.error("add_done_callback got an exception which will be ignored", exc_info=True)
663
+ assert isinstance(exec_fu, Future), "Every code path leading here needs to define exec_fu"
710
664
 
711
- task_record['exec_fu'] = exec_fu
665
+ try:
666
+ exec_fu.add_done_callback(partial(self.handle_exec_update, task_record))
667
+ except Exception:
668
+ # this exception is ignored here because it is assumed that exception
669
+ # comes from directly executing handle_exec_update (because exec_fu is
670
+ # done already). If the callback executes later, then any exception
671
+ # coming out of the callback will be ignored and not propate anywhere,
672
+ # so this block attempts to keep the same behaviour here.
673
+ logger.error("add_done_callback got an exception which will be ignored", exc_info=True)
674
+
675
+ task_record['exec_fu'] = exec_fu
712
676
 
713
677
  def launch_task(self, task_record: TaskRecord) -> Future:
714
678
  """Handle the actual submission of the task to the executor layer.
@@ -1205,13 +1169,7 @@ class DataFlowKernel:
1205
1169
 
1206
1170
  self.log_task_states()
1207
1171
 
1208
- # checkpoint if any valid checkpoint method is specified
1209
- if self.checkpoint_mode is not None:
1210
- self.checkpoint()
1211
-
1212
- if self._checkpoint_timer:
1213
- logger.info("Stopping checkpoint timer")
1214
- self._checkpoint_timer.close()
1172
+ self.memoizer.close()
1215
1173
 
1216
1174
  # Send final stats
1217
1175
  self.usage_tracker.send_end_message()
@@ -1245,9 +1203,9 @@ class DataFlowKernel:
1245
1203
  self.monitoring.close()
1246
1204
  logger.info("Terminated monitoring")
1247
1205
 
1248
- logger.info("Terminating dependency launch pool")
1249
- self.dependency_launch_pool.shutdown()
1250
- logger.info("Terminated dependency launch pool")
1206
+ logger.info("Terminating task launch pool")
1207
+ self._task_launch_pool.shutdown()
1208
+ logger.info("Terminated task launch pool")
1251
1209
 
1252
1210
  logger.info("Unregistering atexit hook")
1253
1211
  atexit.unregister(self.atexit_cleanup)
@@ -1269,66 +1227,8 @@ class DataFlowKernel:
1269
1227
  # should still see it.
1270
1228
  logger.info("DFK cleanup complete")
1271
1229
 
1272
- def checkpoint(self, tasks: Optional[Sequence[TaskRecord]] = None) -> None:
1273
- """Checkpoint the dfk incrementally to a checkpoint file.
1274
-
1275
- When called, every task that has been completed yet not
1276
- checkpointed is checkpointed to a file.
1277
-
1278
- Kwargs:
1279
- - tasks (List of task records) : List of task ids to checkpoint. Default=None
1280
- if set to None, we iterate over all tasks held by the DFK.
1281
-
1282
- .. note::
1283
- Checkpointing only works if memoization is enabled
1284
-
1285
- Returns:
1286
- Checkpoint dir if checkpoints were written successfully.
1287
- By default the checkpoints are written to the RUNDIR of the current
1288
- run under RUNDIR/checkpoints/tasks.pkl
1289
- """
1290
- with self.checkpoint_lock:
1291
- if tasks:
1292
- checkpoint_queue = tasks
1293
- else:
1294
- checkpoint_queue = self.checkpointable_tasks
1295
- self.checkpointable_tasks = []
1296
-
1297
- checkpoint_dir = '{0}/checkpoint'.format(self.run_dir)
1298
- checkpoint_tasks = checkpoint_dir + '/tasks.pkl'
1299
-
1300
- if not os.path.exists(checkpoint_dir):
1301
- os.makedirs(checkpoint_dir, exist_ok=True)
1302
-
1303
- count = 0
1304
-
1305
- with open(checkpoint_tasks, 'ab') as f:
1306
- for task_record in checkpoint_queue:
1307
- task_id = task_record['id']
1308
-
1309
- app_fu = task_record['app_fu']
1310
-
1311
- if app_fu.done() and app_fu.exception() is None:
1312
- hashsum = task_record['hashsum']
1313
- if not hashsum:
1314
- continue
1315
- t = {'hash': hashsum, 'exception': None, 'result': app_fu.result()}
1316
-
1317
- # We are using pickle here since pickle dumps to a file in 'ab'
1318
- # mode behave like a incremental log.
1319
- pickle.dump(t, f)
1320
- count += 1
1321
- logger.debug("Task {} checkpointed".format(task_id))
1322
-
1323
- self.checkpointed_tasks += count
1324
-
1325
- if count == 0:
1326
- if self.checkpointed_tasks == 0:
1327
- logger.warning("No tasks checkpointed so far in this run. Please ensure caching is enabled")
1328
- else:
1329
- logger.debug("No tasks checkpointed in this pass.")
1330
- else:
1331
- logger.info("Done checkpointing {} tasks".format(count))
1230
+ def checkpoint(self) -> None:
1231
+ self.memoizer.checkpoint()
1332
1232
 
1333
1233
  @staticmethod
1334
1234
  def _log_std_streams(task_record: TaskRecord) -> None: