parsl 2024.5.27__py3-none-any.whl → 2024.6.10__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (289) hide show
  1. parsl/__init__.py +9 -10
  2. parsl/addresses.py +6 -4
  3. parsl/app/app.py +3 -6
  4. parsl/app/bash.py +4 -4
  5. parsl/app/errors.py +5 -3
  6. parsl/app/futures.py +3 -3
  7. parsl/app/python.py +2 -1
  8. parsl/benchmark/perf.py +2 -1
  9. parsl/channels/__init__.py +2 -2
  10. parsl/channels/base.py +0 -1
  11. parsl/channels/errors.py +2 -1
  12. parsl/channels/oauth_ssh/oauth_ssh.py +4 -3
  13. parsl/channels/ssh/ssh.py +9 -1
  14. parsl/channels/ssh_il/ssh_il.py +1 -0
  15. parsl/concurrent/__init__.py +2 -2
  16. parsl/config.py +32 -9
  17. parsl/configs/ASPIRE1.py +3 -3
  18. parsl/configs/Azure.py +6 -7
  19. parsl/configs/ad_hoc.py +4 -3
  20. parsl/configs/bridges.py +3 -3
  21. parsl/configs/cc_in2p3.py +2 -2
  22. parsl/configs/ec2.py +1 -1
  23. parsl/configs/expanse.py +1 -2
  24. parsl/configs/frontera.py +2 -3
  25. parsl/configs/htex_local.py +1 -2
  26. parsl/configs/illinoiscluster.py +1 -1
  27. parsl/configs/kubernetes.py +1 -2
  28. parsl/configs/midway.py +3 -3
  29. parsl/configs/osg.py +1 -1
  30. parsl/configs/polaris.py +1 -1
  31. parsl/configs/stampede2.py +4 -5
  32. parsl/configs/summit.py +1 -3
  33. parsl/configs/toss3_llnl.py +1 -2
  34. parsl/configs/vineex_local.py +3 -3
  35. parsl/configs/wqex_local.py +2 -2
  36. parsl/data_provider/data_manager.py +3 -3
  37. parsl/data_provider/file_noop.py +1 -2
  38. parsl/data_provider/files.py +3 -3
  39. parsl/data_provider/ftp.py +1 -3
  40. parsl/data_provider/globus.py +7 -6
  41. parsl/data_provider/http.py +2 -2
  42. parsl/data_provider/rsync.py +1 -1
  43. parsl/data_provider/staging.py +2 -2
  44. parsl/data_provider/zip.py +4 -5
  45. parsl/dataflow/dflow.py +57 -26
  46. parsl/dataflow/errors.py +2 -1
  47. parsl/dataflow/futures.py +1 -2
  48. parsl/dataflow/memoization.py +5 -5
  49. parsl/dataflow/rundirs.py +1 -1
  50. parsl/dataflow/taskrecord.py +4 -5
  51. parsl/executors/__init__.py +3 -3
  52. parsl/executors/base.py +1 -0
  53. parsl/executors/flux/execute_parsl_task.py +2 -2
  54. parsl/executors/flux/executor.py +11 -12
  55. parsl/executors/flux/flux_instance_manager.py +3 -3
  56. parsl/executors/high_throughput/executor.py +31 -36
  57. parsl/executors/high_throughput/interchange.py +37 -38
  58. parsl/executors/high_throughput/manager_record.py +1 -0
  59. parsl/executors/high_throughput/monitoring_info.py +2 -1
  60. parsl/executors/high_throughput/mpi_executor.py +5 -2
  61. parsl/executors/high_throughput/mpi_prefix_composer.py +1 -1
  62. parsl/executors/high_throughput/mpi_resource_management.py +1 -2
  63. parsl/executors/high_throughput/probe.py +6 -4
  64. parsl/executors/high_throughput/process_worker_pool.py +31 -20
  65. parsl/executors/high_throughput/zmq_pipes.py +28 -14
  66. parsl/executors/radical/executor.py +15 -15
  67. parsl/executors/radical/rpex_master.py +1 -2
  68. parsl/executors/radical/rpex_resources.py +1 -2
  69. parsl/executors/radical/rpex_worker.py +2 -1
  70. parsl/executors/status_handling.py +5 -4
  71. parsl/executors/taskvine/__init__.py +1 -1
  72. parsl/executors/taskvine/errors.py +1 -1
  73. parsl/executors/taskvine/exec_parsl_function.py +2 -2
  74. parsl/executors/taskvine/executor.py +23 -24
  75. parsl/executors/taskvine/factory.py +1 -1
  76. parsl/executors/taskvine/manager.py +11 -13
  77. parsl/executors/threads.py +4 -5
  78. parsl/executors/workqueue/errors.py +1 -1
  79. parsl/executors/workqueue/exec_parsl_function.py +5 -4
  80. parsl/executors/workqueue/executor.py +26 -27
  81. parsl/executors/workqueue/parsl_coprocess.py +1 -1
  82. parsl/jobs/error_handlers.py +1 -1
  83. parsl/jobs/job_status_poller.py +2 -5
  84. parsl/jobs/states.py +1 -1
  85. parsl/jobs/strategy.py +2 -2
  86. parsl/launchers/__init__.py +12 -3
  87. parsl/launchers/errors.py +1 -1
  88. parsl/log_utils.py +1 -2
  89. parsl/monitoring/db_manager.py +16 -10
  90. parsl/monitoring/monitoring.py +11 -15
  91. parsl/monitoring/queries/pandas.py +1 -2
  92. parsl/monitoring/radios.py +2 -4
  93. parsl/monitoring/remote.py +13 -8
  94. parsl/monitoring/router.py +8 -11
  95. parsl/monitoring/types.py +2 -0
  96. parsl/monitoring/visualization/app.py +4 -2
  97. parsl/monitoring/visualization/models.py +0 -1
  98. parsl/monitoring/visualization/plots/default/workflow_plots.py +8 -4
  99. parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +1 -0
  100. parsl/monitoring/visualization/utils.py +0 -1
  101. parsl/monitoring/visualization/views.py +16 -9
  102. parsl/multiprocessing.py +0 -1
  103. parsl/process_loggers.py +1 -2
  104. parsl/providers/__init__.py +9 -12
  105. parsl/providers/ad_hoc/ad_hoc.py +1 -1
  106. parsl/providers/aws/aws.py +2 -3
  107. parsl/providers/azure/azure.py +4 -5
  108. parsl/providers/base.py +1 -1
  109. parsl/providers/cluster_provider.py +1 -1
  110. parsl/providers/cobalt/cobalt.py +3 -3
  111. parsl/providers/condor/condor.py +4 -2
  112. parsl/providers/errors.py +2 -2
  113. parsl/providers/googlecloud/googlecloud.py +2 -1
  114. parsl/providers/grid_engine/grid_engine.py +2 -2
  115. parsl/providers/kubernetes/kube.py +24 -9
  116. parsl/providers/local/local.py +5 -1
  117. parsl/providers/lsf/lsf.py +2 -2
  118. parsl/providers/pbspro/pbspro.py +1 -1
  119. parsl/providers/slurm/slurm.py +36 -27
  120. parsl/providers/torque/torque.py +1 -1
  121. parsl/serialize/__init__.py +8 -3
  122. parsl/serialize/base.py +1 -2
  123. parsl/serialize/concretes.py +5 -4
  124. parsl/serialize/proxystore.py +3 -2
  125. parsl/tests/__init__.py +1 -1
  126. parsl/tests/configs/ad_hoc_cluster_htex.py +4 -4
  127. parsl/tests/configs/azure_single_node.py +4 -5
  128. parsl/tests/configs/bridges.py +3 -2
  129. parsl/tests/configs/cc_in2p3.py +2 -2
  130. parsl/tests/configs/comet.py +2 -1
  131. parsl/tests/configs/ec2_single_node.py +1 -2
  132. parsl/tests/configs/ec2_spot.py +1 -2
  133. parsl/tests/configs/flux_local.py +11 -0
  134. parsl/tests/configs/frontera.py +3 -2
  135. parsl/tests/configs/htex_ad_hoc_cluster.py +2 -4
  136. parsl/tests/configs/htex_local.py +2 -3
  137. parsl/tests/configs/htex_local_alternate.py +8 -11
  138. parsl/tests/configs/htex_local_intask_staging.py +5 -7
  139. parsl/tests/configs/htex_local_rsync_staging.py +4 -6
  140. parsl/tests/configs/local_adhoc.py +1 -1
  141. parsl/tests/configs/local_radical.py +1 -3
  142. parsl/tests/configs/local_radical_mpi.py +2 -2
  143. parsl/tests/configs/midway.py +2 -2
  144. parsl/tests/configs/nscc_singapore.py +3 -3
  145. parsl/tests/configs/osg_htex.py +1 -1
  146. parsl/tests/configs/petrelkube.py +3 -2
  147. parsl/tests/configs/summit.py +1 -0
  148. parsl/tests/configs/swan_htex.py +2 -2
  149. parsl/tests/configs/taskvine_ex.py +3 -5
  150. parsl/tests/configs/theta.py +2 -2
  151. parsl/tests/configs/workqueue_ex.py +3 -4
  152. parsl/tests/conftest.py +8 -4
  153. parsl/tests/integration/test_channels/test_ssh_errors.py +1 -1
  154. parsl/tests/integration/test_stress/test_python_simple.py +3 -4
  155. parsl/tests/integration/test_stress/test_python_threads.py +3 -5
  156. parsl/tests/manual_tests/htex_local.py +4 -4
  157. parsl/tests/manual_tests/test_ad_hoc_htex.py +2 -1
  158. parsl/tests/manual_tests/test_basic.py +1 -0
  159. parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +4 -4
  160. parsl/tests/manual_tests/test_log_filter.py +3 -1
  161. parsl/tests/manual_tests/test_memory_limits.py +6 -6
  162. parsl/tests/manual_tests/test_regression_220.py +2 -1
  163. parsl/tests/manual_tests/test_udp_simple.py +4 -3
  164. parsl/tests/manual_tests/test_worker_count.py +3 -2
  165. parsl/tests/scaling_tests/htex_local.py +2 -2
  166. parsl/tests/scaling_tests/test_scale.py +0 -9
  167. parsl/tests/scaling_tests/vineex_condor.py +1 -2
  168. parsl/tests/scaling_tests/vineex_local.py +1 -2
  169. parsl/tests/site_tests/test_provider.py +3 -1
  170. parsl/tests/site_tests/test_site.py +2 -0
  171. parsl/tests/sites/test_affinity.py +7 -5
  172. parsl/tests/sites/test_dynamic_executor.py +3 -3
  173. parsl/tests/sites/test_ec2.py +3 -2
  174. parsl/tests/sites/test_local_adhoc.py +2 -1
  175. parsl/tests/sites/test_worker_info.py +4 -3
  176. parsl/tests/test_aalst_patterns.py +0 -1
  177. parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
  178. parsl/tests/test_bash_apps/test_error_codes.py +1 -4
  179. parsl/tests/test_bash_apps/test_memoize_ignore_args.py +1 -0
  180. parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +2 -2
  181. parsl/tests/test_bash_apps/test_pipeline.py +1 -1
  182. parsl/tests/test_bash_apps/test_std_uri.py +4 -3
  183. parsl/tests/test_bash_apps/test_stdout.py +20 -2
  184. parsl/tests/test_callables.py +2 -2
  185. parsl/tests/test_checkpointing/test_python_checkpoint_1.py +1 -0
  186. parsl/tests/test_checkpointing/test_python_checkpoint_2.py +2 -1
  187. parsl/tests/test_checkpointing/test_regression_239.py +1 -1
  188. parsl/tests/test_checkpointing/test_task_exit.py +1 -1
  189. parsl/tests/test_docs/test_from_slides.py +2 -2
  190. parsl/tests/test_docs/test_kwargs.py +1 -1
  191. parsl/tests/test_docs/test_tutorial_1.py +1 -2
  192. parsl/tests/test_docs/test_workflow1.py +2 -2
  193. parsl/tests/test_docs/test_workflow2.py +0 -1
  194. parsl/tests/test_error_handling/test_rand_fail.py +2 -2
  195. parsl/tests/test_error_handling/test_resource_spec.py +4 -2
  196. parsl/tests/test_error_handling/test_retries.py +2 -1
  197. parsl/tests/test_error_handling/test_retry_handler.py +1 -0
  198. parsl/tests/test_error_handling/test_retry_handler_failure.py +2 -1
  199. parsl/tests/test_error_handling/test_serialization_fail.py +1 -1
  200. parsl/tests/test_error_handling/test_wrap_with_logs.py +1 -0
  201. parsl/tests/test_flux.py +1 -1
  202. parsl/tests/test_htex/test_command_client_timeout.py +9 -12
  203. parsl/tests/test_htex/test_connected_blocks.py +3 -2
  204. parsl/tests/test_htex/test_cpu_affinity_explicit.py +5 -2
  205. parsl/tests/test_htex/test_disconnected_blocks.py +6 -4
  206. parsl/tests/test_htex/test_drain.py +5 -5
  207. parsl/tests/test_htex/test_htex.py +1 -2
  208. parsl/tests/test_htex/test_managers_command.py +3 -2
  209. parsl/tests/test_htex/test_multiple_disconnected_blocks.py +6 -4
  210. parsl/tests/test_htex/test_zmq_binding.py +22 -6
  211. parsl/tests/test_monitoring/test_app_names.py +3 -2
  212. parsl/tests/test_monitoring/test_basic.py +4 -4
  213. parsl/tests/test_monitoring/test_db_locks.py +6 -3
  214. parsl/tests/test_monitoring/test_fuzz_zmq.py +6 -3
  215. parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +5 -5
  216. parsl/tests/test_monitoring/test_incomplete_futures.py +5 -3
  217. parsl/tests/test_monitoring/test_memoization_representation.py +4 -1
  218. parsl/tests/test_monitoring/test_stdouterr.py +4 -4
  219. parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
  220. parsl/tests/test_mpi_apps/test_bad_mpi_config.py +1 -1
  221. parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +2 -0
  222. parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +7 -5
  223. parsl/tests/test_mpi_apps/test_mpi_prefix.py +4 -4
  224. parsl/tests/test_mpi_apps/test_mpi_scheduler.py +7 -2
  225. parsl/tests/test_mpi_apps/test_mpiex.py +4 -3
  226. parsl/tests/test_mpi_apps/test_resource_spec.py +9 -10
  227. parsl/tests/test_providers/test_cobalt_deprecation_warning.py +2 -0
  228. parsl/tests/test_providers/test_local_provider.py +2 -1
  229. parsl/tests/test_providers/test_pbspro_template.py +1 -1
  230. parsl/tests/test_providers/test_slurm_template.py +1 -1
  231. parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
  232. parsl/tests/test_python_apps/test_context_manager.py +99 -3
  233. parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
  234. parsl/tests/test_python_apps/test_dependencies_deep.py +59 -0
  235. parsl/tests/test_python_apps/test_futures.py +2 -1
  236. parsl/tests/test_python_apps/test_join.py +0 -1
  237. parsl/tests/test_python_apps/test_lifted.py +3 -3
  238. parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +1 -0
  239. parsl/tests/test_python_apps/test_pluggable_future_resolution.py +1 -1
  240. parsl/tests/test_radical/test_mpi_funcs.py +1 -2
  241. parsl/tests/test_regression/test_1480.py +2 -1
  242. parsl/tests/test_regression/test_1653.py +2 -1
  243. parsl/tests/test_regression/test_2652.py +1 -0
  244. parsl/tests/test_regression/test_69a.py +0 -1
  245. parsl/tests/test_regression/test_854.py +4 -2
  246. parsl/tests/test_regression/test_97_parallelism_0.py +1 -2
  247. parsl/tests/test_regression/test_98.py +0 -1
  248. parsl/tests/test_scaling/test_block_error_handler.py +9 -4
  249. parsl/tests/test_scaling/test_scale_down.py +2 -3
  250. parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +4 -5
  251. parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +3 -4
  252. parsl/tests/test_scaling/test_shutdown_scalein.py +1 -2
  253. parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
  254. parsl/tests/test_serialization/test_basic.py +2 -1
  255. parsl/tests/test_serialization/test_htex_code_cache.py +3 -4
  256. parsl/tests/test_serialization/test_pack_resource_spec.py +2 -1
  257. parsl/tests/test_serialization/test_proxystore_configured.py +10 -5
  258. parsl/tests/test_serialization/test_proxystore_impl.py +5 -3
  259. parsl/tests/test_shutdown/test_kill_monitoring.py +3 -2
  260. parsl/tests/test_staging/staging_provider.py +2 -2
  261. parsl/tests/test_staging/test_1316.py +3 -2
  262. parsl/tests/test_staging/test_docs_1.py +1 -1
  263. parsl/tests/test_staging/test_docs_2.py +2 -1
  264. parsl/tests/test_staging/test_elaborate_noop_file.py +2 -2
  265. parsl/tests/test_staging/test_staging_https.py +2 -2
  266. parsl/tests/test_staging/test_staging_stdout.py +4 -3
  267. parsl/tests/test_staging/test_zip_in.py +6 -8
  268. parsl/tests/test_staging/test_zip_out.py +7 -9
  269. parsl/tests/test_staging/test_zip_to_zip.py +6 -8
  270. parsl/tests/test_summary.py +2 -1
  271. parsl/tests/test_thread_parallelism.py +0 -1
  272. parsl/tests/test_threads/test_configs.py +1 -1
  273. parsl/tests/test_threads/test_lazy_errors.py +2 -1
  274. parsl/tests/unit/test_usage_tracking.py +45 -0
  275. parsl/usage_tracking/api.py +2 -3
  276. parsl/usage_tracking/levels.py +6 -0
  277. parsl/usage_tracking/usage.py +60 -39
  278. parsl/utils.py +13 -2
  279. parsl/version.py +1 -1
  280. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/exec_parsl_function.py +5 -4
  281. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/process_worker_pool.py +31 -20
  282. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/METADATA +2 -2
  283. parsl-2024.6.10.dist-info/RECORD +475 -0
  284. parsl-2024.5.27.dist-info/RECORD +0 -471
  285. {parsl-2024.5.27.data → parsl-2024.6.10.data}/scripts/parsl_coprocess.py +1 -1
  286. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/LICENSE +0 -0
  287. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/WHEEL +0 -0
  288. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/entry_points.txt +0 -0
  289. {parsl-2024.5.27.dist-info → parsl-2024.6.10.dist-info}/top_level.txt +0 -0
@@ -2,26 +2,25 @@ import contextlib
2
2
  import logging
3
3
  import os
4
4
  import typing
5
-
5
+ import unittest
6
+ from typing import Dict
6
7
 
7
8
  import pytest
8
- import unittest
9
9
 
10
10
  import parsl
11
11
  from parsl.app.app import python_app
12
- from parsl.tests.configs.htex_local import fresh_config
13
- from typing import Dict
12
+ from parsl.executors.high_throughput.mpi_prefix_composer import (
13
+ InvalidResourceSpecification,
14
+ MissingResourceSpecification,
15
+ validate_resource_spec,
16
+ )
14
17
  from parsl.executors.high_throughput.mpi_resource_management import (
18
+ get_nodes_in_batchjob,
15
19
  get_pbs_hosts_list,
16
20
  get_slurm_hosts_list,
17
- get_nodes_in_batchjob,
18
21
  identify_scheduler,
19
22
  )
20
- from parsl.executors.high_throughput.mpi_prefix_composer import (
21
- validate_resource_spec,
22
- InvalidResourceSpecification,
23
- MissingResourceSpecification
24
- )
23
+ from parsl.tests.configs.htex_local import fresh_config
25
24
 
26
25
  EXECUTOR_LABEL = "MPI_TEST"
27
26
 
@@ -1,5 +1,7 @@
1
1
  import warnings
2
+
2
3
  import pytest
4
+
3
5
  from parsl.providers import CobaltProvider
4
6
 
5
7
 
@@ -1,7 +1,6 @@
1
1
  import logging
2
2
  import os
3
3
  import pathlib
4
- import pytest
5
4
  import random
6
5
  import shutil
7
6
  import socket
@@ -10,6 +9,8 @@ import tempfile
10
9
  import threading
11
10
  import time
12
11
 
12
+ import pytest
13
+
13
14
  from parsl.channels import LocalChannel, SSHChannel
14
15
  from parsl.jobs.states import JobState
15
16
  from parsl.launchers import SingleNodeLauncher
@@ -1,6 +1,6 @@
1
1
  import random
2
-
3
2
  from unittest import mock
3
+
4
4
  import pytest
5
5
 
6
6
  from parsl.channels import LocalChannel
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import random
3
-
4
3
  from unittest import mock
4
+
5
5
  import pytest
6
6
 
7
7
  from parsl.channels import LocalChannel
@@ -1,7 +1,8 @@
1
- import pytest
2
1
  import random
3
2
  import string
4
3
 
4
+ import pytest
5
+
5
6
  from parsl.providers.errors import SubmitException
6
7
 
7
8
 
@@ -1,8 +1,13 @@
1
- import parsl
2
- from parsl.tests.configs.local_threads import fresh_config
1
+ from concurrent.futures import Future
2
+ from threading import Event
3
+
3
4
  import pytest
5
+
6
+ import parsl
7
+ from parsl.config import Config
8
+ from parsl.dataflow.dflow import DataFlowKernel, DataFlowKernelLoader
4
9
  from parsl.errors import NoDataFlowKernelError
5
- from parsl.dataflow.dflow import DataFlowKernel
10
+ from parsl.tests.configs.local_threads import fresh_config
6
11
 
7
12
 
8
13
  @parsl.python_app
@@ -15,6 +20,16 @@ def foo(x, stdout='foo.stdout'):
15
20
  return f"echo {x + 1}"
16
21
 
17
22
 
23
+ @parsl.python_app
24
+ def wait_for_event(ev: Event):
25
+ ev.wait()
26
+
27
+
28
+ @parsl.python_app
29
+ def raise_app():
30
+ raise RuntimeError("raise_app deliberate failure")
31
+
32
+
18
33
  @pytest.mark.local
19
34
  def test_within_context_manger(tmpd_cwd):
20
35
  config = fresh_config()
@@ -30,3 +45,84 @@ def test_within_context_manger(tmpd_cwd):
30
45
  with pytest.raises(NoDataFlowKernelError) as excinfo:
31
46
  square(2).result()
32
47
  assert str(excinfo.value) == "Must first load config"
48
+
49
+
50
+ @pytest.mark.local
51
+ def test_exit_skip():
52
+ config = fresh_config()
53
+ config.exit_mode = "skip"
54
+
55
+ with parsl.load(config) as dfk:
56
+ ev = Event()
57
+ fut = wait_for_event(ev)
58
+ # deliberately don't wait for this to finish, so that the context
59
+ # manager can exit
60
+
61
+ assert parsl.dfk() is dfk, "global dfk should be left in place by skip mode"
62
+
63
+ assert not fut.done(), "wait_for_event should not be done yet"
64
+ ev.set()
65
+
66
+ # now we can wait for that result...
67
+ fut.result()
68
+ assert fut.done(), "wait_for_event should complete outside of context manager in 'skip' mode"
69
+
70
+ # now cleanup the DFK that the above `with` block
71
+ # deliberately avoided doing...
72
+ dfk.cleanup()
73
+
74
+
75
+ # 'wait' mode has two cases to test:
76
+ # 1. that we wait when there is no exception
77
+ # 2. that we do not wait when there is an exception
78
+ @pytest.mark.local
79
+ def test_exit_wait_no_exception():
80
+ config = fresh_config()
81
+ config.exit_mode = "wait"
82
+
83
+ with parsl.load(config) as dfk:
84
+ fut = square(1)
85
+ # deliberately don't wait for this to finish, so that the context
86
+ # manager can exit
87
+
88
+ assert fut.done(), "This future should be marked as done before the context manager exits"
89
+
90
+ assert dfk.cleanup_called, "The DFK should have been cleaned up by the context manager"
91
+ assert DataFlowKernelLoader._dfk is None, "The global DFK should have been removed"
92
+
93
+
94
+ @pytest.mark.local
95
+ def test_exit_wait_exception():
96
+ config = fresh_config()
97
+ config.exit_mode = "wait"
98
+
99
+ with pytest.raises(RuntimeError):
100
+ with parsl.load(config) as dfk:
101
+ # we'll never fire this future
102
+ fut_never = Future()
103
+
104
+ fut_raise = raise_app()
105
+
106
+ fut_depend = square(fut_never)
107
+
108
+ # this should cause an exception, which should cause the context
109
+ # manager to exit, without waiting for fut_depend to finish.
110
+ fut_raise.result()
111
+
112
+ assert dfk.cleanup_called, "The DFK should have been cleaned up by the context manager"
113
+ assert DataFlowKernelLoader._dfk is None, "The global DFK should have been removed"
114
+ assert fut_raise.exception() is not None, "fut_raise should contain an exception"
115
+ assert not fut_depend.done(), "fut_depend should have been left un-done (due to dependency failure)"
116
+
117
+
118
+ @pytest.mark.local
119
+ def test_exit_wrong_mode():
120
+
121
+ with pytest.raises(Exception) as ex:
122
+ Config(exit_mode="wrongmode")
123
+
124
+ # with typeguard 4.x this is TypeCheckError,
125
+ # with typeguard 2.x this is TypeError
126
+ # we can't instantiate TypeCheckError if we're in typeguard 2.x environment
127
+ # because it does not exist... so check name using strings.
128
+ assert ex.type.__name__ == "TypeCheckError" or ex.type.__name__ == "TypeError"
@@ -1,6 +1,7 @@
1
+ from concurrent.futures import Future
2
+
1
3
  import parsl
2
4
  from parsl.dataflow.errors import DependencyError
3
- from concurrent.futures import Future
4
5
 
5
6
 
6
7
  @parsl.python_app
@@ -0,0 +1,59 @@
1
+ import inspect
2
+ from concurrent.futures import Future
3
+ from typing import Any, Callable, Dict
4
+
5
+ import pytest
6
+
7
+ import parsl
8
+ from parsl.executors.base import ParslExecutor
9
+
10
+ # N is the number of tasks to chain
11
+ # With mid-2024 Parsl, N>140 causes Parsl to hang
12
+ N = 100
13
+
14
+ # MAX_STACK is the maximum Python stack depth allowed for either
15
+ # task submission to an executor or execution of a task.
16
+ # With mid-2024 Parsl, 2-3 stack entries will be used per
17
+ # recursively launched parsl task. So this should be smaller than
18
+ # 2*N, but big enough to allow regular pytest+parsl stuff to
19
+ # happen.
20
+ MAX_STACK = 50
21
+
22
+
23
+ def local_config():
24
+ return parsl.Config(executors=[ImmediateExecutor()])
25
+
26
+
27
+ class ImmediateExecutor(ParslExecutor):
28
+ def start(self):
29
+ pass
30
+
31
+ def shutdown(self):
32
+ pass
33
+
34
+ def submit(self, func: Callable, resource_specification: Dict[str, Any], *args: Any, **kwargs: Any) -> Future:
35
+ stack_depth = len(inspect.stack())
36
+ assert stack_depth < MAX_STACK, "tasks should not be launched deep in the Python stack"
37
+ fut: Future[None] = Future()
38
+ res = func(*args, **kwargs)
39
+ fut.set_result(res)
40
+ return fut
41
+
42
+
43
+ @parsl.python_app
44
+ def chain(upstream):
45
+ stack_depth = len(inspect.stack())
46
+ assert stack_depth < MAX_STACK, "chained dependencies should not be launched deep in the Python stack"
47
+
48
+
49
+ @pytest.mark.local
50
+ def test_deep_dependency_stack_depth():
51
+
52
+ fut = Future()
53
+ here = fut
54
+
55
+ for _ in range(N):
56
+ here = chain(here)
57
+
58
+ fut.set_result(None)
59
+ here.result()
@@ -11,9 +11,10 @@ Same applies to datafutures, and we need to know the behavior wrt.
11
11
  2. done() called on 1, vs 2
12
12
 
13
13
  """
14
- import pytest
15
14
  from os.path import basename
16
15
 
16
+ import pytest
17
+
17
18
  from parsl.app.app import python_app
18
19
  from parsl.data_provider.files import File
19
20
 
@@ -3,7 +3,6 @@ import pytest
3
3
  from parsl import join_app, python_app
4
4
  from parsl.dataflow.errors import JoinError
5
5
 
6
-
7
6
  RESULT_CONSTANT = 3
8
7
 
9
8
 
@@ -1,10 +1,10 @@
1
+ from concurrent.futures import Future
2
+ from typing import TypeVar
3
+
1
4
  import pytest
2
5
 
3
- from concurrent.futures import Future
4
6
  from parsl import python_app
5
7
 
6
- from typing import TypeVar
7
-
8
8
  T = TypeVar('T')
9
9
 
10
10
 
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from parsl import python_app
3
4
  from parsl.dataflow.memoization import id_for_memo
4
5
 
@@ -7,8 +7,8 @@ import pytest
7
7
 
8
8
  import parsl
9
9
  from parsl.config import Config
10
- from parsl.dataflow.errors import DependencyError
11
10
  from parsl.dataflow.dependency_resolvers import DEEP_DEPENDENCY_RESOLVER
11
+ from parsl.dataflow.errors import DependencyError
12
12
 
13
13
 
14
14
  def local_config():
@@ -1,6 +1,6 @@
1
- import parsl
2
1
  import pytest
3
2
 
3
+ import parsl
4
4
  from parsl.tests.configs.local_radical_mpi import fresh_config as local_config
5
5
 
6
6
 
@@ -16,7 +16,6 @@ def some_mpi_func(msg, sleep, comm=None, parsl_resource_specification={}):
16
16
  apps = []
17
17
 
18
18
 
19
- @pytest.mark.skip("hangs in CI - waiting for resolution of issue #3029")
20
19
  @pytest.mark.local
21
20
  @pytest.mark.radical
22
21
  def test_radical_mpi(n=7):
@@ -1,5 +1,6 @@
1
- from parsl import python_app
2
1
  import pytest
2
+
3
+ from parsl import python_app
3
4
  from parsl.tests.configs.htex_local import fresh_config as local_config
4
5
 
5
6
 
@@ -1,5 +1,6 @@
1
- from parsl import python_app
2
1
  import pytest
2
+
3
+ from parsl import python_app
3
4
  from parsl.tests.configs.htex_local import fresh_config as local_config
4
5
 
5
6
 
@@ -1,4 +1,5 @@
1
1
  import pytest
2
+
2
3
  from parsl.jobs.states import JobState
3
4
 
4
5
 
@@ -6,7 +6,6 @@ import pytest
6
6
  from parsl.app.app import bash_app, python_app
7
7
  from parsl.tests.configs.local_threads import config
8
8
 
9
-
10
9
  local_config = config
11
10
 
12
11
 
@@ -1,8 +1,10 @@
1
- import time
2
1
  import multiprocessing
2
+ import random
3
+ import time
4
+
3
5
  import pytest
6
+
4
7
  from parsl.multiprocessing import MacSafeQueue
5
- import random
6
8
 
7
9
 
8
10
  def consumer(in_q, out_q, delay=0):
@@ -1,11 +1,10 @@
1
1
  import pytest
2
2
 
3
3
  import parsl
4
-
5
4
  from parsl.config import Config
6
5
  from parsl.executors import HighThroughputExecutor
7
- from parsl.providers import LocalProvider
8
6
  from parsl.launchers import SimpleLauncher
7
+ from parsl.providers import LocalProvider
9
8
 
10
9
 
11
10
  def local_config() -> Config:
@@ -6,7 +6,6 @@ import argparse
6
6
  import pytest
7
7
 
8
8
  import parsl
9
-
10
9
  from parsl.dataflow.dflow import DataFlowKernel
11
10
  from parsl.tests.configs.local_threads import config
12
11
 
@@ -1,11 +1,16 @@
1
+ from functools import partial
2
+ from unittest.mock import Mock
3
+
1
4
  import pytest
2
5
 
3
6
  from parsl.executors import HighThroughputExecutor
7
+ from parsl.jobs.error_handlers import (
8
+ noop_error_handler,
9
+ simple_error_handler,
10
+ windowed_error_handler,
11
+ )
12
+ from parsl.jobs.states import JobState, JobStatus
4
13
  from parsl.providers import LocalProvider
5
- from unittest.mock import Mock
6
- from parsl.jobs.states import JobStatus, JobState
7
- from parsl.jobs.error_handlers import simple_error_handler, windowed_error_handler, noop_error_handler
8
- from functools import partial
9
14
 
10
15
 
11
16
  @pytest.mark.local
@@ -4,13 +4,12 @@ import time
4
4
  import pytest
5
5
 
6
6
  import parsl
7
-
8
7
  from parsl import File, python_app
9
- from parsl.providers import LocalProvider
10
8
  from parsl.channels import LocalChannel
11
- from parsl.launchers import SingleNodeLauncher
12
9
  from parsl.config import Config
13
10
  from parsl.executors import HighThroughputExecutor
11
+ from parsl.launchers import SingleNodeLauncher
12
+ from parsl.providers import LocalProvider
14
13
 
15
14
  logger = logging.getLogger(__name__)
16
15
 
@@ -1,15 +1,14 @@
1
+ from threading import Event
2
+
1
3
  import pytest
2
4
 
3
5
  import parsl
4
-
5
6
  from parsl import File, python_app
6
- from parsl.providers import LocalProvider
7
7
  from parsl.channels import LocalChannel
8
- from parsl.launchers import SingleNodeLauncher
9
8
  from parsl.config import Config
10
9
  from parsl.executors import HighThroughputExecutor
11
-
12
- from threading import Event
10
+ from parsl.launchers import SingleNodeLauncher
11
+ from parsl.providers import LocalProvider
13
12
 
14
13
  _max_blocks = 5
15
14
  _min_blocks = 0
@@ -4,14 +4,13 @@ import time
4
4
  import pytest
5
5
 
6
6
  import parsl
7
-
8
7
  from parsl import File, python_app
9
- from parsl.jobs.states import JobState, TERMINAL_STATES
10
- from parsl.providers import LocalProvider
11
8
  from parsl.channels import LocalChannel
12
- from parsl.launchers import SingleNodeLauncher
13
9
  from parsl.config import Config
14
10
  from parsl.executors import HighThroughputExecutor
11
+ from parsl.jobs.states import TERMINAL_STATES, JobState
12
+ from parsl.launchers import SingleNodeLauncher
13
+ from parsl.providers import LocalProvider
15
14
 
16
15
  logger = logging.getLogger(__name__)
17
16
 
@@ -1,3 +1,4 @@
1
+ import random
1
2
  import threading
2
3
 
3
4
  import pytest
@@ -9,8 +10,6 @@ from parsl.executors import HighThroughputExecutor
9
10
  from parsl.launchers import SimpleLauncher
10
11
  from parsl.providers import LocalProvider
11
12
 
12
- import random
13
-
14
13
  # we need some blocks, but it doesn't matter too much how many, as long
15
14
  # as they can all start up and get registered within the try_assert
16
15
  # timeout later on.
@@ -1,6 +1,6 @@
1
- import parsl
2
1
  import pytest
3
2
 
3
+ import parsl
4
4
  from parsl.tests.configs.htex_local import fresh_config as local_config
5
5
 
6
6
 
@@ -1,5 +1,6 @@
1
1
  import pytest
2
- from parsl.serialize import serialize, deserialize
2
+
3
+ from parsl.serialize import deserialize, serialize
3
4
  from parsl.serialize.concretes import DillSerializer, PickleSerializer
4
5
 
5
6
 
@@ -1,10 +1,9 @@
1
- import parsl
2
- import pytest
3
-
4
1
  from typing import Any
5
2
 
6
- from parsl.serialize.facade import methods_for_code
3
+ import pytest
7
4
 
5
+ import parsl
6
+ from parsl.serialize.facade import methods_for_code
8
7
  from parsl.tests.configs.htex_local import fresh_config as local_config
9
8
 
10
9
 
@@ -1,5 +1,6 @@
1
1
  import pytest
2
- from parsl.serialize import unpack_res_spec_apply_message, pack_res_spec_apply_message
2
+
3
+ from parsl.serialize import pack_res_spec_apply_message, unpack_res_spec_apply_message
3
4
 
4
5
 
5
6
  def double(x: int, y: int = 2) -> int:
@@ -1,19 +1,24 @@
1
1
  import logging
2
- import pytest
3
2
  import uuid
4
3
 
4
+ import pytest
5
+
5
6
  import parsl
6
- from parsl.serialize.facade import additional_methods_for_deserialization, methods_for_data, register_method_for_data
7
+ from parsl.serialize.facade import (
8
+ additional_methods_for_deserialization,
9
+ methods_for_data,
10
+ register_method_for_data,
11
+ )
7
12
  from parsl.tests.configs.htex_local import fresh_config
8
13
 
9
-
10
14
  logger = logging.getLogger(__name__)
11
15
 
12
16
 
13
17
  def local_setup():
14
- from parsl.serialize.proxystore import ProxyStoreSerializer
15
- from proxystore.store import Store, register_store
16
18
  from proxystore.connectors.file import FileConnector
19
+ from proxystore.store import Store, register_store
20
+
21
+ from parsl.serialize.proxystore import ProxyStoreSerializer
17
22
 
18
23
  parsl.load(fresh_config())
19
24
 
@@ -1,6 +1,7 @@
1
- import pytest
2
1
  import uuid
3
2
 
3
+ import pytest
4
+
4
5
 
5
6
  def policy_example(o):
6
7
  """Example policy will proxy only lists."""
@@ -13,10 +14,11 @@ def test_proxystore_nonglobal():
13
14
  """
14
15
  # import in function, because proxystore is not importable in base parsl
15
16
  # installation.
16
- from parsl.serialize.proxystore import ProxyStoreSerializer
17
+ from proxystore.connectors.file import FileConnector
17
18
  from proxystore.proxy import Proxy
18
19
  from proxystore.store import Store, register_store
19
- from proxystore.connectors.file import FileConnector
20
+
21
+ from parsl.serialize.proxystore import ProxyStoreSerializer
20
22
 
21
23
  store = Store(name='parsl_store_' + str(uuid.uuid4()), connector=FileConnector(store_dir="/tmp"))
22
24
  register_store(store)
@@ -1,9 +1,10 @@
1
1
  import os
2
- import parsl
3
- import pytest
4
2
  import signal
5
3
  import time
6
4
 
5
+ import pytest
6
+
7
+ import parsl
7
8
  from parsl.tests.configs.htex_local_alternate import fresh_config
8
9
 
9
10
  # This is a very generous upper bound on expected shutdown time of target
@@ -62,8 +62,8 @@ def make_stage_out_app(executor, dfk):
62
62
 
63
63
 
64
64
  def stage_out_noop(app_fu, inputs=[], _parsl_staging_inhibit=True):
65
- import time
66
65
  import logging
66
+ import time
67
67
  logger = logging.getLogger(__name__)
68
68
  logger.info("stage_out_noop")
69
69
  time.sleep(1)
@@ -75,8 +75,8 @@ def make_stage_in_app(executor, dfk):
75
75
 
76
76
 
77
77
  def stage_in_noop(parent_fut=None, outputs=[], _parsl_staging_inhibit=True):
78
- import time
79
78
  import logging
79
+ import time
80
80
  logger = logging.getLogger(__name__)
81
81
  logger.info("stage_in_noop")
82
82
  time.sleep(1)
@@ -1,8 +1,9 @@
1
+ import time
2
+
1
3
  import pytest
2
4
 
3
5
  import parsl
4
- import time
5
- from parsl import python_app, ThreadPoolExecutor
6
+ from parsl import ThreadPoolExecutor, python_app
6
7
  from parsl.config import Config
7
8
  from parsl.data_provider.files import File
8
9
  from parsl.data_provider.staging import Staging
@@ -1,6 +1,6 @@
1
1
  import pytest
2
2
 
3
- from parsl import python_app, File
3
+ from parsl import File, python_app
4
4
 
5
5
 
6
6
  @python_app
@@ -1,5 +1,6 @@
1
1
  import pytest
2
- from parsl import bash_app, File
2
+
3
+ from parsl import File, bash_app
3
4
  from parsl.tests.configs.local_threads import fresh_config as local_config
4
5
 
5
6