parsl 2025.6.16__tar.gz → 2025.6.23__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.
Files changed (477) hide show
  1. {parsl-2025.6.16/parsl.egg-info → parsl-2025.6.23}/PKG-INFO +2 -2
  2. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/base.py +5 -3
  3. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/flux/executor.py +2 -0
  4. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/globus_compute.py +2 -0
  5. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/executor.py +2 -0
  6. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/mpi_executor.py +7 -0
  7. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/radical/executor.py +3 -0
  8. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/executor.py +2 -0
  9. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/threads.py +11 -2
  10. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/executor.py +2 -0
  11. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/errors.py +0 -5
  12. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/monitoring.py +19 -64
  13. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/filesystem.py +1 -1
  14. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/filesystem_router.py +35 -3
  15. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/htex.py +1 -1
  16. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/udp_router.py +75 -15
  17. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/zmq_router.py +9 -10
  18. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/conftest.py +7 -4
  19. parsl-2025.6.16/parsl/tests/test_monitoring/test_fuzz_zmq.py → parsl-2025.6.23/parsl/tests/test_monitoring/test_htex_fuzz_zmq.py +7 -2
  20. parsl-2025.6.23/parsl/tests/test_monitoring/test_radio_filesystem.py +50 -0
  21. parsl-2025.6.23/parsl/tests/test_monitoring/test_radio_udp.py +53 -0
  22. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_shutdown/test_kill_monitoring.py +1 -1
  23. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/version.py +1 -1
  24. {parsl-2025.6.16 → parsl-2025.6.23/parsl.egg-info}/PKG-INFO +2 -2
  25. {parsl-2025.6.16 → parsl-2025.6.23}/parsl.egg-info/SOURCES.txt +3 -3
  26. parsl-2025.6.16/parsl/tests/configs/local_threads_monitoring.py +0 -10
  27. parsl-2025.6.16/parsl/tests/manual_tests/test_udp_simple.py +0 -51
  28. {parsl-2025.6.16 → parsl-2025.6.23}/LICENSE +0 -0
  29. {parsl-2025.6.16 → parsl-2025.6.23}/MANIFEST.in +0 -0
  30. {parsl-2025.6.16 → parsl-2025.6.23}/README.rst +0 -0
  31. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/__init__.py +0 -0
  32. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/addresses.py +0 -0
  33. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/__init__.py +0 -0
  34. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/app.py +0 -0
  35. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/bash.py +0 -0
  36. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/errors.py +0 -0
  37. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/futures.py +0 -0
  38. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/app/python.py +0 -0
  39. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/benchmark/__init__.py +0 -0
  40. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/benchmark/perf.py +0 -0
  41. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/concurrent/__init__.py +0 -0
  42. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/config.py +0 -0
  43. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/ASPIRE1.py +0 -0
  44. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/Azure.py +0 -0
  45. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/__init__.py +0 -0
  46. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/bridges.py +0 -0
  47. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/cc_in2p3.py +0 -0
  48. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/ec2.py +0 -0
  49. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/expanse.py +0 -0
  50. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/frontera.py +0 -0
  51. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/gc_multisite.py +0 -0
  52. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/gc_tutorial.py +0 -0
  53. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/htex_local.py +0 -0
  54. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/illinoiscluster.py +0 -0
  55. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/improv.py +0 -0
  56. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/kubernetes.py +0 -0
  57. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/local_threads.py +0 -0
  58. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/midway.py +0 -0
  59. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/osg.py +0 -0
  60. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/polaris.py +0 -0
  61. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/stampede2.py +0 -0
  62. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/summit.py +0 -0
  63. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/toss3_llnl.py +0 -0
  64. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/vineex_local.py +0 -0
  65. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/configs/wqex_local.py +0 -0
  66. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/curvezmq.py +0 -0
  67. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/__init__.py +0 -0
  68. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/data_manager.py +0 -0
  69. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/file_noop.py +0 -0
  70. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/files.py +0 -0
  71. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/ftp.py +0 -0
  72. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/globus.py +0 -0
  73. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/http.py +0 -0
  74. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/rsync.py +0 -0
  75. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/staging.py +0 -0
  76. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/data_provider/zip.py +0 -0
  77. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/__init__.py +0 -0
  78. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/dependency_resolvers.py +0 -0
  79. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/dflow.py +0 -0
  80. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/errors.py +0 -0
  81. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/futures.py +0 -0
  82. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/memoization.py +0 -0
  83. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/rundirs.py +0 -0
  84. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/states.py +0 -0
  85. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/dataflow/taskrecord.py +0 -0
  86. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/errors.py +0 -0
  87. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/__init__.py +0 -0
  88. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/errors.py +0 -0
  89. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/execute_task.py +0 -0
  90. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/flux/__init__.py +0 -0
  91. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/flux/execute_parsl_task.py +0 -0
  92. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/flux/flux_instance_manager.py +0 -0
  93. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/__init__.py +0 -0
  94. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/errors.py +0 -0
  95. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/interchange.py +0 -0
  96. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/manager_record.py +0 -0
  97. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/manager_selector.py +0 -0
  98. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/monitoring_info.py +0 -0
  99. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
  100. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/mpi_resource_management.py +0 -0
  101. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/probe.py +0 -0
  102. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/process_worker_pool.py +0 -0
  103. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/high_throughput/zmq_pipes.py +0 -0
  104. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/radical/__init__.py +0 -0
  105. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/radical/rpex_resources.py +0 -0
  106. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/radical/rpex_worker.py +0 -0
  107. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/status_handling.py +0 -0
  108. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/__init__.py +0 -0
  109. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/errors.py +0 -0
  110. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
  111. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/factory.py +0 -0
  112. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/factory_config.py +0 -0
  113. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/manager.py +0 -0
  114. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/manager_config.py +0 -0
  115. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/taskvine/utils.py +0 -0
  116. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/__init__.py +0 -0
  117. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/errors.py +0 -0
  118. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
  119. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
  120. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
  121. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/__init__.py +0 -0
  122. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/error_handlers.py +0 -0
  123. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/errors.py +0 -0
  124. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/job_status_poller.py +0 -0
  125. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/states.py +0 -0
  126. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/jobs/strategy.py +0 -0
  127. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/launchers/__init__.py +0 -0
  128. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/launchers/base.py +0 -0
  129. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/launchers/errors.py +0 -0
  130. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/launchers/launchers.py +0 -0
  131. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/log_utils.py +0 -0
  132. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/__init__.py +0 -0
  133. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/db_manager.py +0 -0
  134. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/message_type.py +0 -0
  135. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/queries/__init__.py +0 -0
  136. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/queries/pandas.py +0 -0
  137. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/__init__.py +0 -0
  138. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/base.py +0 -0
  139. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/multiprocessing.py +0 -0
  140. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/udp.py +0 -0
  141. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/radios/zmq.py +0 -0
  142. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/remote.py +0 -0
  143. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/types.py +0 -0
  144. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/__init__.py +0 -0
  145. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/app.py +0 -0
  146. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/models.py +0 -0
  147. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/plots/__init__.py +0 -0
  148. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
  149. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
  150. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
  151. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
  152. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
  153. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
  154. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/app.html +0 -0
  155. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/dag.html +0 -0
  156. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/error.html +0 -0
  157. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/layout.html +0 -0
  158. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
  159. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/task.html +0 -0
  160. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/workflow.html +0 -0
  161. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
  162. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/utils.py +0 -0
  163. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/version.py +0 -0
  164. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/monitoring/visualization/views.py +0 -0
  165. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/multiprocessing.py +0 -0
  166. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/process_loggers.py +0 -0
  167. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/__init__.py +0 -0
  168. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/aws/__init__.py +0 -0
  169. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/aws/aws.py +0 -0
  170. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/aws/template.py +0 -0
  171. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/azure/__init__.py +0 -0
  172. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/azure/azure.py +0 -0
  173. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/azure/template.py +0 -0
  174. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/base.py +0 -0
  175. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/cluster_provider.py +0 -0
  176. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/condor/__init__.py +0 -0
  177. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/condor/condor.py +0 -0
  178. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/condor/template.py +0 -0
  179. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/errors.py +0 -0
  180. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/googlecloud/__init__.py +0 -0
  181. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/googlecloud/googlecloud.py +0 -0
  182. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/grid_engine/__init__.py +0 -0
  183. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/grid_engine/grid_engine.py +0 -0
  184. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/grid_engine/template.py +0 -0
  185. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/kubernetes/__init__.py +0 -0
  186. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/kubernetes/kube.py +0 -0
  187. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/kubernetes/template.py +0 -0
  188. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/local/__init__.py +0 -0
  189. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/local/local.py +0 -0
  190. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/lsf/__init__.py +0 -0
  191. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/lsf/lsf.py +0 -0
  192. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/lsf/template.py +0 -0
  193. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/pbspro/__init__.py +0 -0
  194. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/pbspro/pbspro.py +0 -0
  195. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/pbspro/template.py +0 -0
  196. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/slurm/__init__.py +0 -0
  197. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/slurm/slurm.py +0 -0
  198. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/slurm/template.py +0 -0
  199. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/torque/__init__.py +0 -0
  200. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/torque/template.py +0 -0
  201. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/providers/torque/torque.py +0 -0
  202. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/py.typed +0 -0
  203. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/__init__.py +0 -0
  204. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/base.py +0 -0
  205. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/concretes.py +0 -0
  206. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/errors.py +0 -0
  207. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/facade.py +0 -0
  208. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/serialize/proxystore.py +0 -0
  209. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/__init__.py +0 -0
  210. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/callables_helper.py +0 -0
  211. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/__init__.py +0 -0
  212. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/azure_single_node.py +0 -0
  213. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/bluewaters.py +0 -0
  214. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/bridges.py +0 -0
  215. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/cc_in2p3.py +0 -0
  216. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/comet.py +0 -0
  217. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/ec2_single_node.py +0 -0
  218. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/ec2_spot.py +0 -0
  219. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/flux_local.py +0 -0
  220. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/frontera.py +0 -0
  221. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/globus_compute.py +0 -0
  222. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/htex_local.py +0 -0
  223. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/htex_local_alternate.py +0 -0
  224. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
  225. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
  226. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_radical.py +0 -0
  227. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_radical_mpi.py +0 -0
  228. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads.py +0 -0
  229. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
  230. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
  231. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_checkpoint_periodic.py +0 -0
  232. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
  233. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
  234. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_globus.py +0 -0
  235. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
  236. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/local_threads_no_cache.py +0 -0
  237. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/midway.py +0 -0
  238. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/nscc_singapore.py +0 -0
  239. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/osg_htex.py +0 -0
  240. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/petrelkube.py +0 -0
  241. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/slurm_local.py +0 -0
  242. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/summit.py +0 -0
  243. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/taskvine_ex.py +0 -0
  244. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/user_opts.py +0 -0
  245. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/configs/workqueue_ex.py +0 -0
  246. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/__init__.py +0 -0
  247. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/latency.py +0 -0
  248. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/test_apps/__init__.py +0 -0
  249. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
  250. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/test_stress/__init__.py +0 -0
  251. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
  252. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
  253. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/__init__.py +0 -0
  254. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/htex_local.py +0 -0
  255. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/test_basic.py +0 -0
  256. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/test_log_filter.py +0 -0
  257. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
  258. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/test_regression_220.py +0 -0
  259. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/manual_tests/test_worker_count.py +0 -0
  260. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/__init__.py +0 -0
  261. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/htex_local.py +0 -0
  262. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/local_threads.py +0 -0
  263. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/test_scale.py +0 -0
  264. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/vineex_condor.py +0 -0
  265. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/vineex_local.py +0 -0
  266. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/wqex_condor.py +0 -0
  267. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/scaling_tests/wqex_local.py +0 -0
  268. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/site_tests/__init__.py +0 -0
  269. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/site_tests/site_config_selector.py +0 -0
  270. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/site_tests/test_provider.py +0 -0
  271. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/site_tests/test_site.py +0 -0
  272. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/__init__.py +0 -0
  273. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_affinity.py +0 -0
  274. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_concurrent.py +0 -0
  275. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_dynamic_executor.py +0 -0
  276. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_ec2.py +0 -0
  277. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_launchers.py +0 -0
  278. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_mpi/__init__.py +0 -0
  279. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/sites/test_worker_info.py +0 -0
  280. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_aalst_patterns.py +0 -0
  281. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/__init__.py +0 -0
  282. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
  283. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_basic.py +0 -0
  284. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
  285. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_inputs_default.py +0 -0
  286. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
  287. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
  288. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
  289. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
  290. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
  291. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
  292. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
  293. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_std_uri.py +0 -0
  294. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
  295. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_callables.py +0 -0
  296. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/__init__.py +0 -0
  297. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_periodic.py +0 -0
  298. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
  299. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
  300. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
  301. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
  302. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
  303. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
  304. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_curvezmq.py +0 -0
  305. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/__init__.py +0 -0
  306. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_from_slides.py +0 -0
  307. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_kwargs.py +0 -0
  308. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
  309. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_workflow1.py +0 -0
  310. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_workflow2.py +0 -0
  311. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_docs/test_workflow4.py +0 -0
  312. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/__init__.py +0 -0
  313. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_fail.py +0 -0
  314. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
  315. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_rand_fail.py +0 -0
  316. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
  317. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_retries.py +0 -0
  318. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
  319. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
  320. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
  321. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
  322. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_execute_task.py +0 -0
  323. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_flowcontrol/__init__.py +0 -0
  324. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_flux.py +0 -0
  325. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/__init__.py +0 -0
  326. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_basic.py +0 -0
  327. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_block_manager_selector_unit.py +0 -0
  328. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_command_client_timeout.py +0 -0
  329. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
  330. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
  331. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -0
  332. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +0 -0
  333. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_drain.py +0 -0
  334. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_htex.py +0 -0
  335. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_interchange_exit_bad_registration.py +0 -0
  336. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_manager_failure.py +0 -0
  337. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_manager_selector_by_block.py +0 -0
  338. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_managers_command.py +0 -0
  339. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_missing_worker.py +0 -0
  340. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
  341. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_priority_queue.py +0 -0
  342. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_resource_spec_validation.py +0 -0
  343. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_worker_failure.py +0 -0
  344. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
  345. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/__init__.py +0 -0
  346. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_app_names.py +0 -0
  347. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_basic.py +0 -0
  348. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
  349. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_exit_helper.py +0 -0
  350. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -0
  351. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
  352. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
  353. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_radio_zmq.py +0 -0
  354. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_stdouterr.py +0 -0
  355. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
  356. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/__init__.py +0 -0
  357. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
  358. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
  359. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
  360. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +0 -0
  361. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_mpiex.py +0 -0
  362. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
  363. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/__init__.py +0 -0
  364. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_kubernetes_provider.py +0 -0
  365. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_local_provider.py +0 -0
  366. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
  367. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
  368. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_slurm_template.py +0 -0
  369. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
  370. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/__init__.py +0 -0
  371. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
  372. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_basic.py +0 -0
  373. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_context_manager.py +0 -0
  374. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
  375. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
  376. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_dependencies_deep.py +0 -0
  377. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_depfail_propagation.py +0 -0
  378. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_fail.py +0 -0
  379. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
  380. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
  381. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_futures.py +0 -0
  382. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
  383. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
  384. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_inputs_default.py +0 -0
  385. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_join.py +0 -0
  386. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_lifted.py +0 -0
  387. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_mapred.py +0 -0
  388. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
  389. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
  390. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
  391. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
  392. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
  393. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
  394. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_outputs.py +0 -0
  395. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_overview.py +0 -0
  396. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
  397. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_pluggable_future_resolution.py +0 -0
  398. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_simple.py +0 -0
  399. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_timeout.py +0 -0
  400. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_python_apps/test_type5.py +0 -0
  401. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_radical/__init__.py +0 -0
  402. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
  403. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/__init__.py +0 -0
  404. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_1480.py +0 -0
  405. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
  406. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_1653.py +0 -0
  407. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_221.py +0 -0
  408. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_226.py +0 -0
  409. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_2652.py +0 -0
  410. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_69a.py +0 -0
  411. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_854.py +0 -0
  412. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
  413. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_regression/test_98.py +0 -0
  414. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/__init__.py +0 -0
  415. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
  416. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
  417. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -0
  418. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_regression_3696_oscillation.py +0 -0
  419. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_scale_down.py +0 -0
  420. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
  421. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -0
  422. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_shutdown_scalein.py +0 -0
  423. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +0 -0
  424. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/__init__.py +0 -0
  425. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
  426. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +0 -0
  427. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_basic.py +0 -0
  428. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
  429. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_pack_resource_spec.py +0 -0
  430. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
  431. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
  432. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_shutdown/__init__.py +0 -0
  433. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/__init__.py +0 -0
  434. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/staging_provider.py +0 -0
  435. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_1316.py +0 -0
  436. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_docs_1.py +0 -0
  437. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_docs_2.py +0 -0
  438. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
  439. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_file.py +0 -0
  440. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_file_apps.py +0 -0
  441. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_file_staging.py +0 -0
  442. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_output_chain_filenames.py +0 -0
  443. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
  444. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
  445. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_staging_globus.py +0 -0
  446. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_staging_https.py +0 -0
  447. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_staging_stdout.py +0 -0
  448. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_zip_in.py +0 -0
  449. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_zip_out.py +0 -0
  450. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_staging/test_zip_to_zip.py +0 -0
  451. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_summary.py +0 -0
  452. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_thread_parallelism.py +0 -0
  453. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_threads/__init__.py +0 -0
  454. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_threads/test_configs.py +0 -0
  455. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
  456. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_utils/__init__.py +0 -0
  457. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_utils/test_execute_wait.py +0 -0
  458. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
  459. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/test_utils/test_sanitize_dns.py +0 -0
  460. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/unit/__init__.py +0 -0
  461. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/unit/test_address.py +0 -0
  462. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/unit/test_file.py +0 -0
  463. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/unit/test_globus_compute_executor.py +0 -0
  464. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/unit/test_usage_tracking.py +0 -0
  465. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/tests/utils.py +0 -0
  466. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/usage_tracking/__init__.py +0 -0
  467. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/usage_tracking/api.py +0 -0
  468. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/usage_tracking/levels.py +0 -0
  469. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/usage_tracking/usage.py +0 -0
  470. {parsl-2025.6.16 → parsl-2025.6.23}/parsl/utils.py +0 -0
  471. {parsl-2025.6.16 → parsl-2025.6.23}/parsl.egg-info/dependency_links.txt +0 -0
  472. {parsl-2025.6.16 → parsl-2025.6.23}/parsl.egg-info/entry_points.txt +0 -0
  473. {parsl-2025.6.16 → parsl-2025.6.23}/parsl.egg-info/requires.txt +0 -0
  474. {parsl-2025.6.16 → parsl-2025.6.23}/parsl.egg-info/top_level.txt +0 -0
  475. {parsl-2025.6.16 → parsl-2025.6.23}/requirements.txt +0 -0
  476. {parsl-2025.6.16 → parsl-2025.6.23}/setup.cfg +0 -0
  477. {parsl-2025.6.16 → parsl-2025.6.23}/setup.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: parsl
3
- Version: 2025.6.16
3
+ Version: 2025.6.23
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.06.16.tar.gz
6
+ Download-URL: https://github.com/Parsl/parsl/archive/2025.06.23.tar.gz
7
7
  Author: The Parsl Team
8
8
  Author-email: parsl@googlegroups.com
9
9
  License: Apache 2.0
@@ -98,15 +98,17 @@ class ParslExecutor(metaclass=ABCMeta):
98
98
  def shutdown(self) -> None:
99
99
  """Shutdown the executor.
100
100
 
101
- This includes all attached resources such as workers and controllers.
101
+ Executors should call super().shutdown() as part of their overridden
102
+ implementation.
102
103
  """
103
104
  pass
104
105
 
105
106
  def monitor_resources(self) -> bool:
106
107
  """Should resource monitoring happen for tasks on running on this executor?
107
108
 
108
- Parsl resource monitoring conflicts with execution styles which use threads, and
109
- can deadlock while running.
109
+ Parsl resource monitoring conflicts with execution styles which do
110
+ not directly use a process tree - for example, the ThreadPoolExecutor
111
+ and the MPIExecutor.
110
112
 
111
113
  This function allows resource monitoring to be disabled per executor implementation.
112
114
  """
@@ -248,6 +248,8 @@ class FluxExecutor(ParslExecutor, RepresentationMixin):
248
248
  if wait:
249
249
  self._submission_thread.join()
250
250
 
251
+ super().shutdown()
252
+
251
253
  def submit(
252
254
  self,
253
255
  func: Callable,
@@ -134,3 +134,5 @@ class GlobusComputeExecutor(ParslExecutor, RepresentationMixin):
134
134
  self.executor.shutdown(wait=False, cancel_futures=True)
135
135
  result_watcher = self.executor._get_result_watcher()
136
136
  result_watcher.shutdown(wait=False, cancel_futures=True)
137
+
138
+ super().shutdown()
@@ -881,6 +881,8 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
881
881
  if self.zmq_monitoring:
882
882
  self.zmq_monitoring.close()
883
883
 
884
+ super().shutdown()
885
+
884
886
  logger.info("Finished HighThroughputExecutor shutdown attempt")
885
887
 
886
888
  def get_usage_information(self):
@@ -111,3 +111,10 @@ class MPIExecutor(HighThroughputExecutor):
111
111
 
112
112
  def validate_resource_spec(self, resource_specification: dict):
113
113
  return validate_resource_spec(resource_specification)
114
+
115
+ def monitor_resources(self):
116
+ """Resource monitoring does not make sense when using the
117
+ MPIExecutor, as the process tree launched for each task is spread
118
+ across multiple OS images/worker nodes.
119
+ """
120
+ return False
@@ -601,6 +601,9 @@ class RadicalPilotExecutor(ParslExecutor, RepresentationMixin):
601
601
  self._bulk_thread.join()
602
602
 
603
603
  self.session.close(download=True)
604
+
605
+ super().shutdown()
606
+
604
607
  logger.info("RadicalPilotExecutor is terminated.")
605
608
 
606
609
  return True
@@ -601,6 +601,8 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
601
601
  self._finished_task_queue.close()
602
602
  self._finished_task_queue.join_thread()
603
603
 
604
+ super().shutdown()
605
+
604
606
  logger.debug("TaskVine shutdown completed")
605
607
 
606
608
  @wrap_with_logs
@@ -73,9 +73,18 @@ class ThreadPoolExecutor(ParslExecutor, RepresentationMixin):
73
73
  """
74
74
  logger.debug("Shutting down executor, which involves waiting for running tasks to complete")
75
75
  self.executor.shutdown(wait=block)
76
+
77
+ super().shutdown()
78
+
76
79
  logger.debug("Done with executor shutdown")
77
80
 
78
81
  def monitor_resources(self):
79
- """Resource monitoring sometimes deadlocks when using threads, so this function
80
- returns false to disable it."""
82
+ """Resource monitoring does not make sense when using the
83
+ ThreadPoolExecutor, as there is no per-task process tree: all tasks
84
+ run inside the same single submitting process.
85
+
86
+ In addition, the use of fork-based multiprocessing in the remote
87
+ wrapper in parsl/monitoring/remote.py was especially prone to deadlock
88
+ with this executor.
89
+ """
81
90
  return False
@@ -714,6 +714,8 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
714
714
  self.collector_queue.close()
715
715
  self.collector_queue.join_thread()
716
716
 
717
+ super().shutdown()
718
+
717
719
  logger.debug("Work Queue shutdown completed")
718
720
 
719
721
  @wrap_with_logs
@@ -1,11 +1,6 @@
1
1
  from parsl.errors import ParslError
2
2
 
3
3
 
4
- class MonitoringHubStartError(ParslError):
5
- def __str__(self) -> str:
6
- return "Hub failed to start"
7
-
8
-
9
4
  class MonitoringRouterStartError(ParslError):
10
5
  def __str__(self) -> str:
11
6
  return "Monitoring router failed to start"
@@ -3,16 +3,14 @@ from __future__ import annotations
3
3
  import logging
4
4
  import multiprocessing.synchronize as ms
5
5
  import os
6
- import queue
7
6
  import warnings
8
7
  from multiprocessing.queues import Queue
9
- from typing import TYPE_CHECKING, Any, Optional, Union
8
+ from typing import Any, Optional, Union
10
9
 
11
10
  import typeguard
12
11
 
13
- from parsl.monitoring.errors import MonitoringHubStartError
14
- from parsl.monitoring.radios.filesystem_router import filesystem_router_starter
15
- from parsl.monitoring.radios.udp_router import udp_router_starter
12
+ from parsl.monitoring.radios.filesystem_router import start_filesystem_receiver
13
+ from parsl.monitoring.radios.udp_router import start_udp_receiver
16
14
  from parsl.monitoring.types import TaggedMonitoringMessage
17
15
  from parsl.multiprocessing import (
18
16
  SizedQueue,
@@ -119,39 +117,14 @@ class MonitoringHub(RepresentationMixin):
119
117
 
120
118
  self.monitoring_hub_active = True
121
119
 
122
- # This annotation is incompatible with typeguard 4.x instrumentation
123
- # of local variables: Queue is not subscriptable at runtime, as far
124
- # as typeguard is concerned. The more general Queue annotation works,
125
- # but does not restrict the contents of the Queue. Using TYPE_CHECKING
126
- # here allows the stricter definition to be seen by mypy, and the
127
- # simpler definition to be seen by typeguard. Hopefully at some point
128
- # in the future, Queue will allow runtime subscripts.
129
-
130
- if TYPE_CHECKING:
131
- udp_comm_q: Queue[Union[int, str]]
132
- else:
133
- udp_comm_q: Queue
134
-
135
- udp_comm_q = SizedQueue(maxsize=10)
136
-
137
120
  self.resource_msgs: Queue[TaggedMonitoringMessage]
138
121
  self.resource_msgs = SizedQueue()
139
122
 
140
- self.router_exit_event: ms.Event
141
- self.router_exit_event = SpawnEvent()
142
-
143
- self.udp_router_proc = SpawnProcess(target=udp_router_starter,
144
- kwargs={"comm_q": udp_comm_q,
145
- "resource_msgs": self.resource_msgs,
146
- "exit_event": self.router_exit_event,
147
- "udp_port": self.hub_port,
148
- "run_dir": dfk_run_dir,
149
- "logging_level": logging.DEBUG if self.monitoring_debug else logging.INFO,
150
- },
151
- name="Monitoring-UDP-Router-Process",
152
- daemon=True,
153
- )
154
- self.udp_router_proc.start()
123
+ self.udp_receiver = start_udp_receiver(debug=self.monitoring_debug,
124
+ logdir=dfk_run_dir,
125
+ monitoring_messages=self.resource_msgs,
126
+ port=self.hub_port
127
+ )
155
128
 
156
129
  self.dbm_exit_event: ms.Event
157
130
  self.dbm_exit_event = SpawnEvent()
@@ -168,32 +141,15 @@ class MonitoringHub(RepresentationMixin):
168
141
  )
169
142
  self.dbm_proc.start()
170
143
  logger.info("Started UDP router process %s and DBM process %s",
171
- self.udp_router_proc.pid, self.dbm_proc.pid)
172
-
173
- self.filesystem_proc = SpawnProcess(target=filesystem_router_starter,
174
- kwargs={"q": self.resource_msgs,
175
- "run_dir": dfk_run_dir,
176
- "exit_event": self.router_exit_event},
177
- name="Monitoring-Filesystem-Process",
178
- daemon=True
179
- )
180
- self.filesystem_proc.start()
181
- logger.info("Started filesystem radio receiver process %s", self.filesystem_proc.pid)
182
-
183
- try:
184
- udp_comm_q_result = udp_comm_q.get(block=True, timeout=120)
185
- udp_comm_q.close()
186
- udp_comm_q.join_thread()
187
- except queue.Empty:
188
- logger.error("Monitoring UDP router has not reported port in 120s. Aborting")
189
- raise MonitoringHubStartError()
190
-
191
- if isinstance(udp_comm_q_result, str):
192
- logger.error("MonitoringRouter sent an error message: %s", udp_comm_q_result)
193
- raise RuntimeError(f"MonitoringRouter failed to start: {udp_comm_q_result}")
194
-
195
- udp_port = udp_comm_q_result
196
- self.monitoring_hub_url = "udp://{}:{}".format(self.hub_address, udp_port)
144
+ self.udp_receiver.process.pid, self.dbm_proc.pid)
145
+
146
+ self.filesystem_receiver = start_filesystem_receiver(debug=self.monitoring_debug,
147
+ logdir=dfk_run_dir,
148
+ monitoring_messages=self.resource_msgs
149
+ )
150
+ logger.info("Started filesystem radio receiver process %s", self.filesystem_receiver.process.pid)
151
+
152
+ self.monitoring_hub_url = "udp://{}:{}".format(self.hub_address, self.udp_receiver.port)
197
153
 
198
154
  logger.info("Monitoring Hub initialized")
199
155
 
@@ -202,10 +158,9 @@ class MonitoringHub(RepresentationMixin):
202
158
  if self.monitoring_hub_active:
203
159
  self.monitoring_hub_active = False
204
160
  logger.info("Setting router termination event")
205
- self.router_exit_event.set()
206
161
 
207
162
  logger.info("Waiting for UDP router to terminate")
208
- join_terminate_close_proc(self.udp_router_proc)
163
+ self.udp_receiver.close()
209
164
 
210
165
  logger.debug("Finished waiting for router termination")
211
166
  logger.debug("Waiting for DB termination")
@@ -214,7 +169,7 @@ class MonitoringHub(RepresentationMixin):
214
169
  logger.debug("Finished waiting for DBM termination")
215
170
 
216
171
  logger.info("Terminating filesystem radio receiver process")
217
- join_terminate_close_proc(self.filesystem_proc)
172
+ self.filesystem_receiver.close()
218
173
 
219
174
  logger.info("Closing monitoring multiprocessing queues")
220
175
  self.resource_msgs.close()
@@ -27,7 +27,7 @@ class FilesystemRadioSender(MonitoringRadioSender):
27
27
  """
28
28
 
29
29
  def __init__(self, *, monitoring_url: str, timeout: int = 10, run_dir: str):
30
- logger.info("filesystem based monitoring channel initializing")
30
+ logger.info("filesystem based monitoring radio initializing")
31
31
  self.base_path = f"{run_dir}/monitor-fs-radio/"
32
32
  self.tmp_path = f"{self.base_path}/tmp"
33
33
  self.new_path = f"{self.base_path}/new"
@@ -4,6 +4,7 @@ import logging
4
4
  import os
5
5
  import pickle
6
6
  import time
7
+ from multiprocessing.context import SpawnProcess
7
8
  from multiprocessing.queues import Queue
8
9
  from multiprocessing.synchronize import Event
9
10
  from typing import cast
@@ -11,15 +12,17 @@ from typing import cast
11
12
  from parsl.log_utils import set_file_logger
12
13
  from parsl.monitoring.radios.multiprocessing import MultiprocessingQueueRadioSender
13
14
  from parsl.monitoring.types import TaggedMonitoringMessage
15
+ from parsl.multiprocessing import SpawnEvent, join_terminate_close_proc
14
16
  from parsl.process_loggers import wrap_with_logs
15
17
  from parsl.utils import setproctitle
16
18
 
19
+ logger = logging.getLogger(__name__)
20
+
17
21
 
18
22
  @wrap_with_logs
19
23
  def filesystem_router_starter(*, q: Queue[TaggedMonitoringMessage], run_dir: str, exit_event: Event) -> None:
20
- logger = set_file_logger(f"{run_dir}/monitoring_filesystem_radio.log",
21
- name="monitoring_filesystem_radio",
22
- level=logging.INFO)
24
+ set_file_logger(f"{run_dir}/monitoring_filesystem_radio.log",
25
+ level=logging.INFO)
23
26
 
24
27
  logger.info("Starting filesystem radio receiver")
25
28
  setproctitle("parsl: monitoring filesystem receiver")
@@ -52,3 +55,32 @@ def filesystem_router_starter(*, q: Queue[TaggedMonitoringMessage], run_dir: str
52
55
 
53
56
  time.sleep(1) # whats a good time for this poll?
54
57
  logger.info("Ending filesystem radio receiver")
58
+
59
+
60
+ class FilesystemRadioReceiver():
61
+ def __init__(self, *, process: SpawnProcess, exit_event: Event) -> None:
62
+ self.process = process
63
+ self.exit_event = exit_event
64
+
65
+ def close(self) -> None:
66
+ self.exit_event.set()
67
+ join_terminate_close_proc(self.process)
68
+
69
+
70
+ def start_filesystem_receiver(*,
71
+ monitoring_messages: Queue,
72
+ logdir: str,
73
+ debug: bool) -> FilesystemRadioReceiver:
74
+
75
+ router_exit_event = SpawnEvent()
76
+
77
+ filesystem_proc = SpawnProcess(target=filesystem_router_starter,
78
+ kwargs={"q": monitoring_messages,
79
+ "run_dir": logdir,
80
+ "exit_event": router_exit_event},
81
+ name="Monitoring-Filesystem-Process",
82
+ daemon=True
83
+ )
84
+ filesystem_proc.start()
85
+
86
+ return FilesystemRadioReceiver(process=filesystem_proc, exit_event=router_exit_event)
@@ -18,7 +18,7 @@ class HTEXRadioSender(MonitoringRadioSender):
18
18
  timeout : int
19
19
  timeout, default=10s
20
20
  """
21
- logger.info("htex-based monitoring channel initialising")
21
+ logger.info("htex-based monitoring radio initialising")
22
22
 
23
23
  def send(self, message: object) -> None:
24
24
  """ Sends a message to the UDP receiver
@@ -4,15 +4,26 @@ import logging
4
4
  import multiprocessing.queues as mpq
5
5
  import os
6
6
  import pickle
7
+ import queue
7
8
  import socket
8
9
  import time
10
+ from multiprocessing.context import SpawnProcess as SpawnProcessType
11
+ from multiprocessing.queues import Queue
9
12
  from multiprocessing.synchronize import Event
10
- from typing import Optional
13
+ from multiprocessing.synchronize import Event as EventType
14
+ from typing import Optional, Union
11
15
 
12
16
  import typeguard
13
17
 
14
18
  from parsl.log_utils import set_file_logger
19
+ from parsl.monitoring.errors import MonitoringRouterStartError
15
20
  from parsl.monitoring.radios.multiprocessing import MultiprocessingQueueRadioSender
21
+ from parsl.multiprocessing import (
22
+ SizedQueue,
23
+ SpawnEvent,
24
+ SpawnProcess,
25
+ join_terminate_close_proc,
26
+ )
16
27
  from parsl.process_loggers import wrap_with_logs
17
28
  from parsl.utils import setproctitle
18
29
 
@@ -48,10 +59,9 @@ class MonitoringRouter:
48
59
  An event that the main Parsl process will set to signal that the monitoring router should shut down.
49
60
  """
50
61
  os.makedirs(run_dir, exist_ok=True)
51
- self.logger = set_file_logger(f"{run_dir}/monitoring_udp_router.log",
52
- name="monitoring_router",
53
- level=logging_level)
54
- self.logger.debug("Monitoring router starting")
62
+ set_file_logger(f"{run_dir}/monitoring_udp_router.log",
63
+ level=logging_level)
64
+ logger.debug("Monitoring router starting")
55
65
 
56
66
  self.atexit_timeout = atexit_timeout
57
67
 
@@ -73,39 +83,39 @@ class MonitoringRouter:
73
83
  except Exception as e:
74
84
  raise RuntimeError(f"Could not bind to udp_port {udp_port} because: {e}")
75
85
  self.udp_sock.settimeout(self.loop_freq / 1000)
76
- self.logger.info("Initialized the UDP socket on 0.0.0.0:{}".format(self.udp_port))
86
+ logger.info("Initialized the UDP socket on 0.0.0.0:{}".format(self.udp_port))
77
87
 
78
88
  self.target_radio = MultiprocessingQueueRadioSender(resource_msgs)
79
89
  self.exit_event = exit_event
80
90
 
81
- @wrap_with_logs(target="monitoring_router")
91
+ @wrap_with_logs
82
92
  def start(self) -> None:
83
- self.logger.info("Starting UDP listener")
93
+ logger.info("Starting UDP listener")
84
94
  try:
85
95
  while not self.exit_event.is_set():
86
96
  try:
87
97
  data, addr = self.udp_sock.recvfrom(2048)
88
98
  resource_msg = pickle.loads(data)
89
- self.logger.debug("Got UDP Message from {}: {}".format(addr, resource_msg))
99
+ logger.debug("Got UDP Message from {}: {}".format(addr, resource_msg))
90
100
  self.target_radio.send(resource_msg)
91
101
  except socket.timeout:
92
102
  pass
93
103
 
94
- self.logger.info("UDP listener draining")
104
+ logger.info("UDP listener draining")
95
105
  last_msg_received_time = time.time()
96
106
  while time.time() - last_msg_received_time < self.atexit_timeout:
97
107
  try:
98
108
  data, addr = self.udp_sock.recvfrom(2048)
99
109
  msg = pickle.loads(data)
100
- self.logger.debug("Got UDP Message from {}: {}".format(addr, msg))
110
+ logger.debug("Got UDP Message from {}: {}".format(addr, msg))
101
111
  self.target_radio.send(msg)
102
112
  last_msg_received_time = time.time()
103
113
  except socket.timeout:
104
114
  pass
105
115
 
106
- self.logger.info("UDP listener finishing normally")
116
+ logger.info("UDP listener finishing normally")
107
117
  finally:
108
- self.logger.info("UDP listener finished")
118
+ logger.info("UDP listener finished")
109
119
 
110
120
 
111
121
  @wrap_with_logs
@@ -132,8 +142,58 @@ def udp_router_starter(*,
132
142
  else:
133
143
  comm_q.put(router.udp_port)
134
144
 
135
- router.logger.info("Starting MonitoringRouter in router_starter")
145
+ logger.info("Starting MonitoringRouter in router_starter")
136
146
  try:
137
147
  router.start()
138
148
  except Exception:
139
- router.logger.exception("UDP router start exception")
149
+ logger.exception("UDP router start exception")
150
+
151
+
152
+ class UDPRadioReceiver():
153
+ def __init__(self, *, process: SpawnProcessType, exit_event: EventType, port: int) -> None:
154
+ self.process = process
155
+ self.exit_event = exit_event
156
+ self.port = port
157
+
158
+ def close(self) -> None:
159
+ self.exit_event.set()
160
+ join_terminate_close_proc(self.process)
161
+
162
+
163
+ def start_udp_receiver(*,
164
+ monitoring_messages: Queue,
165
+ port: Optional[int],
166
+ logdir: str,
167
+ debug: bool) -> UDPRadioReceiver:
168
+
169
+ udp_comm_q: Queue[Union[int, str]]
170
+ udp_comm_q = SizedQueue(maxsize=10)
171
+
172
+ router_exit_event = SpawnEvent()
173
+
174
+ router_proc = SpawnProcess(target=udp_router_starter,
175
+ kwargs={"comm_q": udp_comm_q,
176
+ "resource_msgs": monitoring_messages,
177
+ "exit_event": router_exit_event,
178
+ "udp_port": port,
179
+ "run_dir": logdir,
180
+ "logging_level": logging.DEBUG if debug else logging.INFO,
181
+ },
182
+ name="Monitoring-UDP-Router-Process",
183
+ daemon=True,
184
+ )
185
+ router_proc.start()
186
+
187
+ try:
188
+ udp_comm_q_result = udp_comm_q.get(block=True, timeout=120)
189
+ udp_comm_q.close()
190
+ udp_comm_q.join_thread()
191
+ except queue.Empty:
192
+ logger.error("Monitoring UDP router has not reported port in 120s. Aborting")
193
+ raise MonitoringRouterStartError()
194
+
195
+ if isinstance(udp_comm_q_result, str):
196
+ logger.error("MonitoringRouter sent an error message: %s", udp_comm_q_result)
197
+ raise RuntimeError(f"MonitoringRouter failed to start: {udp_comm_q_result}")
198
+
199
+ return UDPRadioReceiver(process=router_proc, exit_event=router_exit_event, port=udp_comm_q_result)
@@ -61,10 +61,9 @@ class MonitoringRouter:
61
61
  An event that the main Parsl process will set to signal that the monitoring router should shut down.
62
62
  """
63
63
  os.makedirs(run_dir, exist_ok=True)
64
- self.logger = set_file_logger(f"{run_dir}/monitoring_zmq_router.log",
65
- name="zmq_monitoring_router",
66
- level=logging_level)
67
- self.logger.debug("Monitoring router starting")
64
+ set_file_logger(f"{run_dir}/monitoring_zmq_router.log",
65
+ level=logging_level)
66
+ logger.debug("Monitoring router starting")
68
67
 
69
68
  self.address = address
70
69
 
@@ -75,7 +74,7 @@ class MonitoringRouter:
75
74
  self.zmq_receiver_channel.setsockopt(zmq.LINGER, 0)
76
75
  self.zmq_receiver_channel.set_hwm(0)
77
76
  self.zmq_receiver_channel.RCVTIMEO = int(self.loop_freq) # in milliseconds
78
- self.logger.debug("address: {}. port_range {}".format(address, port_range))
77
+ logger.debug("address: {}. port_range {}".format(address, port_range))
79
78
  self.zmq_receiver_port = self.zmq_receiver_channel.bind_to_random_port(tcp_url(address),
80
79
  min_port=port_range[0],
81
80
  max_port=port_range[1])
@@ -83,9 +82,9 @@ class MonitoringRouter:
83
82
  self.target_radio = MultiprocessingQueueRadioSender(resource_msgs)
84
83
  self.exit_event = exit_event
85
84
 
86
- @wrap_with_logs(target="zmq_monitoring_router")
85
+ @wrap_with_logs
87
86
  def start(self) -> None:
88
- self.logger.info("Starting ZMQ listener")
87
+ logger.info("Starting ZMQ listener")
89
88
  try:
90
89
  while not self.exit_event.is_set():
91
90
  try:
@@ -107,11 +106,11 @@ class MonitoringRouter:
107
106
  # channel is broken in such a way that it always raises
108
107
  # an exception? Looping on this would maybe be the wrong
109
108
  # thing to do.
110
- self.logger.warning("Failure processing a ZMQ message", exc_info=True)
109
+ logger.warning("Failure processing a ZMQ message", exc_info=True)
111
110
 
112
- self.logger.info("ZMQ listener finishing normally")
111
+ logger.info("ZMQ listener finishing normally")
113
112
  finally:
114
- self.logger.info("ZMQ listener finished")
113
+ logger.info("ZMQ listener finished")
115
114
 
116
115
 
117
116
  @wrap_with_logs
@@ -406,13 +406,15 @@ def try_assert():
406
406
  timeout_ms: float = 5000,
407
407
  attempts: int = 0,
408
408
  check_period_ms: int = 20,
409
+ factor: float = 2,
409
410
  ):
410
411
  tb = create_traceback(start=1)
411
412
  check_period_s = abs(check_period_ms) / 1000.0
412
413
  if attempts > 0:
413
414
  for _attempt_no in range(attempts):
414
- time.sleep(random.random() * check_period_s) # jitter
415
- check_period_s *= 2
415
+ fraction = random.random()
416
+ time.sleep(fraction * check_period_s) # jitter
417
+ check_period_s *= factor ** fraction
416
418
  if test_func():
417
419
  return
418
420
  else:
@@ -427,9 +429,10 @@ def try_assert():
427
429
  timeout_s = abs(timeout_ms) / 1000.0
428
430
  end = time.monotonic() + timeout_s
429
431
  while time.monotonic() < end:
430
- wait_for = random.random() * check_period_s # jitter
432
+ fraction = random.random()
433
+ wait_for = fraction * check_period_s # jitter
431
434
  time.sleep(min(wait_for, end - time.monotonic()))
432
- check_period_s *= 2
435
+ check_period_s *= factor ** fraction
433
436
  if test_func():
434
437
  return
435
438
  att_fail = (
@@ -17,7 +17,12 @@ def this_app():
17
17
 
18
18
 
19
19
  @pytest.mark.local
20
- def test_row_counts():
20
+ def test_fuzz():
21
+ """This test sends fuzz into the ZMQ radio receiver that HTEX starts
22
+ for receiving monitoring messages from the interchange, and checks
23
+ that monitoring still records things ok.
24
+ """
25
+
21
26
  import sqlalchemy
22
27
  from sqlalchemy import text
23
28
 
@@ -44,7 +49,7 @@ def test_row_counts():
44
49
  # the latter is what i'm most suspicious of in my present investigation
45
50
 
46
51
  # dig out the interchange port...
47
- hub_address = parsl.dfk().monitoring.hub_address
52
+ hub_address = parsl.dfk().executors["htex_Local"].loopback_address
48
53
  hub_zmq_port = parsl.dfk().executors["htex_Local"].hub_zmq_port
49
54
 
50
55
  # this will send a string to a new socket connection
@@ -0,0 +1,50 @@
1
+ import pytest
2
+
3
+ from parsl.monitoring.message_type import MessageType
4
+ from parsl.monitoring.radios.filesystem import FilesystemRadioSender
5
+ from parsl.monitoring.radios.filesystem_router import start_filesystem_receiver
6
+ from parsl.multiprocessing import SpawnQueue
7
+
8
+
9
+ @pytest.mark.local
10
+ def test_filesystem(tmpd_cwd):
11
+ """Test filesystem radio/receiver pair.
12
+ This test checks that the pair can be started up locally, that a message
13
+ is conveyed from radio to receiver, and that the receiver process goes
14
+ away at shutdown.
15
+ """
16
+
17
+ resource_msgs = SpawnQueue()
18
+
19
+ # start receiver
20
+ receiver = start_filesystem_receiver(debug=True,
21
+ logdir=str(tmpd_cwd),
22
+ monitoring_messages=resource_msgs,
23
+ )
24
+
25
+ # make radio
26
+
27
+ radio_sender = FilesystemRadioSender(run_dir=str(tmpd_cwd),
28
+ monitoring_url="irrelevant:")
29
+
30
+ # send message into radio
31
+
32
+ message = (MessageType.RESOURCE_INFO, {})
33
+
34
+ radio_sender.send(message)
35
+
36
+ # verify it comes out of the receiver
37
+
38
+ m = resource_msgs.get()
39
+
40
+ assert m == message, "The sent message should appear in the queue"
41
+
42
+ # shut down router
43
+
44
+ receiver.close()
45
+
46
+ # we can't inspect the process if it has been closed properly, but
47
+ # we can verify that it raises the expected ValueError the closed
48
+ # processes raise on access.
49
+ with pytest.raises(ValueError):
50
+ receiver.process.exitcode