parsl 2024.5.20__py3-none-any.whl → 2024.6.3__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.
- parsl/__init__.py +9 -10
- parsl/addresses.py +6 -4
- parsl/app/app.py +3 -6
- parsl/app/bash.py +4 -4
- parsl/app/errors.py +5 -3
- parsl/app/futures.py +3 -3
- parsl/app/python.py +2 -1
- parsl/benchmark/perf.py +2 -1
- parsl/channels/__init__.py +2 -2
- parsl/channels/base.py +0 -1
- parsl/channels/errors.py +2 -1
- parsl/channels/oauth_ssh/oauth_ssh.py +4 -3
- parsl/channels/ssh/ssh.py +9 -1
- parsl/channels/ssh_il/ssh_il.py +1 -0
- parsl/concurrent/__init__.py +2 -2
- parsl/config.py +12 -6
- parsl/configs/ASPIRE1.py +3 -3
- parsl/configs/Azure.py +6 -7
- parsl/configs/ad_hoc.py +4 -3
- parsl/configs/bridges.py +3 -3
- parsl/configs/cc_in2p3.py +2 -2
- parsl/configs/ec2.py +1 -1
- parsl/configs/expanse.py +1 -2
- parsl/configs/frontera.py +2 -3
- parsl/configs/htex_local.py +1 -2
- parsl/configs/illinoiscluster.py +1 -1
- parsl/configs/kubernetes.py +1 -2
- parsl/configs/midway.py +3 -3
- parsl/configs/osg.py +1 -1
- parsl/configs/polaris.py +1 -1
- parsl/configs/stampede2.py +4 -5
- parsl/configs/summit.py +1 -3
- parsl/configs/toss3_llnl.py +1 -2
- parsl/configs/vineex_local.py +3 -3
- parsl/configs/wqex_local.py +2 -2
- parsl/data_provider/data_manager.py +3 -3
- parsl/data_provider/file_noop.py +1 -2
- parsl/data_provider/files.py +3 -3
- parsl/data_provider/ftp.py +1 -3
- parsl/data_provider/globus.py +7 -6
- parsl/data_provider/http.py +2 -2
- parsl/data_provider/rsync.py +1 -1
- parsl/data_provider/staging.py +2 -2
- parsl/data_provider/zip.py +4 -5
- parsl/dataflow/dependency_resolvers.py +115 -0
- parsl/dataflow/dflow.py +65 -54
- parsl/dataflow/errors.py +2 -1
- parsl/dataflow/futures.py +1 -2
- parsl/dataflow/memoization.py +5 -5
- parsl/dataflow/rundirs.py +1 -1
- parsl/dataflow/taskrecord.py +4 -5
- parsl/executors/__init__.py +3 -3
- parsl/executors/base.py +1 -0
- parsl/executors/flux/execute_parsl_task.py +2 -2
- parsl/executors/flux/executor.py +11 -12
- parsl/executors/flux/flux_instance_manager.py +3 -3
- parsl/executors/high_throughput/errors.py +10 -0
- parsl/executors/high_throughput/executor.py +31 -36
- parsl/executors/high_throughput/interchange.py +16 -18
- parsl/executors/high_throughput/manager_record.py +1 -0
- parsl/executors/high_throughput/monitoring_info.py +2 -1
- parsl/executors/high_throughput/mpi_executor.py +6 -3
- parsl/executors/high_throughput/mpi_prefix_composer.py +19 -3
- parsl/executors/high_throughput/mpi_resource_management.py +1 -2
- parsl/executors/high_throughput/probe.py +6 -4
- parsl/executors/high_throughput/process_worker_pool.py +31 -20
- parsl/executors/high_throughput/zmq_pipes.py +63 -15
- parsl/executors/radical/executor.py +15 -15
- parsl/executors/radical/rpex_master.py +1 -2
- parsl/executors/radical/rpex_resources.py +4 -9
- parsl/executors/radical/rpex_worker.py +2 -1
- parsl/executors/status_handling.py +5 -4
- parsl/executors/taskvine/__init__.py +1 -1
- parsl/executors/taskvine/errors.py +1 -1
- parsl/executors/taskvine/exec_parsl_function.py +2 -2
- parsl/executors/taskvine/executor.py +23 -24
- parsl/executors/taskvine/factory.py +1 -1
- parsl/executors/taskvine/manager.py +11 -13
- parsl/executors/threads.py +4 -5
- parsl/executors/workqueue/errors.py +1 -1
- parsl/executors/workqueue/exec_parsl_function.py +5 -4
- parsl/executors/workqueue/executor.py +26 -27
- parsl/executors/workqueue/parsl_coprocess.py +1 -1
- parsl/jobs/error_handlers.py +1 -1
- parsl/jobs/job_status_poller.py +2 -5
- parsl/jobs/states.py +1 -1
- parsl/jobs/strategy.py +2 -2
- parsl/launchers/__init__.py +12 -3
- parsl/launchers/errors.py +1 -1
- parsl/log_utils.py +1 -2
- parsl/monitoring/db_manager.py +16 -10
- parsl/monitoring/monitoring.py +11 -15
- parsl/monitoring/queries/pandas.py +1 -2
- parsl/monitoring/radios.py +2 -4
- parsl/monitoring/remote.py +13 -8
- parsl/monitoring/router.py +8 -11
- parsl/monitoring/types.py +2 -0
- parsl/monitoring/visualization/app.py +4 -2
- parsl/monitoring/visualization/models.py +0 -1
- parsl/monitoring/visualization/plots/default/workflow_plots.py +8 -4
- parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +1 -0
- parsl/monitoring/visualization/utils.py +0 -1
- parsl/monitoring/visualization/views.py +16 -9
- parsl/multiprocessing.py +0 -1
- parsl/process_loggers.py +1 -2
- parsl/providers/__init__.py +9 -12
- parsl/providers/ad_hoc/ad_hoc.py +1 -1
- parsl/providers/aws/aws.py +2 -3
- parsl/providers/azure/azure.py +4 -5
- parsl/providers/base.py +1 -1
- parsl/providers/cluster_provider.py +1 -1
- parsl/providers/cobalt/cobalt.py +3 -3
- parsl/providers/condor/condor.py +4 -2
- parsl/providers/errors.py +2 -2
- parsl/providers/googlecloud/googlecloud.py +2 -1
- parsl/providers/grid_engine/grid_engine.py +2 -2
- parsl/providers/kubernetes/kube.py +5 -3
- parsl/providers/local/local.py +5 -1
- parsl/providers/lsf/lsf.py +2 -2
- parsl/providers/pbspro/pbspro.py +1 -1
- parsl/providers/slurm/slurm.py +5 -5
- parsl/providers/torque/torque.py +1 -1
- parsl/serialize/__init__.py +8 -3
- parsl/serialize/base.py +1 -2
- parsl/serialize/concretes.py +5 -4
- parsl/serialize/proxystore.py +3 -2
- parsl/tests/__init__.py +1 -1
- parsl/tests/configs/ad_hoc_cluster_htex.py +4 -4
- parsl/tests/configs/azure_single_node.py +4 -5
- parsl/tests/configs/bridges.py +3 -2
- parsl/tests/configs/cc_in2p3.py +2 -2
- parsl/tests/configs/comet.py +2 -1
- parsl/tests/configs/ec2_single_node.py +1 -2
- parsl/tests/configs/ec2_spot.py +1 -2
- parsl/tests/configs/frontera.py +3 -2
- parsl/tests/configs/htex_ad_hoc_cluster.py +2 -4
- parsl/tests/configs/htex_local.py +2 -3
- parsl/tests/configs/htex_local_alternate.py +8 -11
- parsl/tests/configs/htex_local_intask_staging.py +5 -7
- parsl/tests/configs/htex_local_rsync_staging.py +4 -6
- parsl/tests/configs/local_adhoc.py +1 -1
- parsl/tests/configs/local_radical.py +1 -3
- parsl/tests/configs/local_radical_mpi.py +2 -2
- parsl/tests/configs/midway.py +2 -2
- parsl/tests/configs/nscc_singapore.py +3 -3
- parsl/tests/configs/osg_htex.py +1 -1
- parsl/tests/configs/petrelkube.py +3 -2
- parsl/tests/configs/summit.py +1 -0
- parsl/tests/configs/swan_htex.py +2 -2
- parsl/tests/configs/taskvine_ex.py +3 -5
- parsl/tests/configs/theta.py +2 -2
- parsl/tests/configs/workqueue_ex.py +3 -4
- parsl/tests/conftest.py +6 -6
- parsl/tests/integration/test_channels/test_ssh_errors.py +1 -1
- parsl/tests/integration/test_stress/test_python_simple.py +3 -4
- parsl/tests/integration/test_stress/test_python_threads.py +3 -5
- parsl/tests/manual_tests/htex_local.py +4 -4
- parsl/tests/manual_tests/test_ad_hoc_htex.py +2 -1
- parsl/tests/manual_tests/test_basic.py +1 -0
- parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +4 -4
- parsl/tests/manual_tests/test_log_filter.py +3 -1
- parsl/tests/manual_tests/test_memory_limits.py +6 -6
- parsl/tests/manual_tests/test_regression_220.py +2 -1
- parsl/tests/manual_tests/test_udp_simple.py +4 -3
- parsl/tests/manual_tests/test_worker_count.py +3 -2
- parsl/tests/scaling_tests/htex_local.py +2 -2
- parsl/tests/scaling_tests/test_scale.py +0 -9
- parsl/tests/scaling_tests/vineex_condor.py +1 -2
- parsl/tests/scaling_tests/vineex_local.py +1 -2
- parsl/tests/site_tests/test_provider.py +3 -1
- parsl/tests/site_tests/test_site.py +2 -0
- parsl/tests/sites/test_affinity.py +7 -5
- parsl/tests/sites/test_dynamic_executor.py +3 -4
- parsl/tests/sites/test_ec2.py +3 -2
- parsl/tests/sites/test_local_adhoc.py +2 -1
- parsl/tests/sites/test_worker_info.py +4 -3
- parsl/tests/test_aalst_patterns.py +0 -1
- parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
- parsl/tests/test_bash_apps/test_error_codes.py +1 -4
- parsl/tests/test_bash_apps/test_memoize_ignore_args.py +1 -0
- parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +2 -2
- parsl/tests/test_bash_apps/test_pipeline.py +1 -1
- parsl/tests/test_bash_apps/test_std_uri.py +4 -9
- parsl/tests/test_callables.py +2 -2
- parsl/tests/test_checkpointing/test_periodic.py +2 -7
- parsl/tests/test_checkpointing/test_python_checkpoint_1.py +1 -0
- parsl/tests/test_checkpointing/test_python_checkpoint_2.py +2 -2
- parsl/tests/test_checkpointing/test_python_checkpoint_3.py +0 -1
- parsl/tests/test_checkpointing/test_regression_239.py +1 -1
- parsl/tests/test_checkpointing/test_task_exit.py +1 -2
- parsl/tests/test_docs/test_from_slides.py +2 -2
- parsl/tests/test_docs/test_kwargs.py +1 -1
- parsl/tests/test_docs/test_tutorial_1.py +1 -2
- parsl/tests/test_docs/test_workflow1.py +2 -2
- parsl/tests/test_docs/test_workflow2.py +0 -1
- parsl/tests/test_error_handling/test_rand_fail.py +2 -2
- parsl/tests/test_error_handling/test_resource_spec.py +4 -2
- parsl/tests/test_error_handling/test_retries.py +2 -1
- parsl/tests/test_error_handling/test_retry_handler.py +1 -0
- parsl/tests/test_error_handling/test_retry_handler_failure.py +2 -1
- parsl/tests/test_error_handling/test_serialization_fail.py +1 -1
- parsl/tests/test_error_handling/test_wrap_with_logs.py +1 -0
- parsl/tests/test_flux.py +1 -1
- parsl/tests/test_htex/test_basic.py +0 -1
- parsl/tests/test_htex/test_command_client_timeout.py +66 -0
- parsl/tests/test_htex/test_connected_blocks.py +3 -2
- parsl/tests/test_htex/test_cpu_affinity_explicit.py +6 -10
- parsl/tests/test_htex/test_disconnected_blocks.py +6 -4
- parsl/tests/test_htex/test_drain.py +5 -5
- parsl/tests/test_htex/test_htex.py +1 -2
- parsl/tests/test_htex/test_manager_failure.py +0 -1
- parsl/tests/test_htex/test_managers_command.py +5 -9
- parsl/tests/test_htex/test_missing_worker.py +2 -8
- parsl/tests/test_htex/test_multiple_disconnected_blocks.py +6 -4
- parsl/tests/test_monitoring/test_app_names.py +3 -3
- parsl/tests/test_monitoring/test_basic.py +4 -6
- parsl/tests/test_monitoring/test_db_locks.py +6 -4
- parsl/tests/test_monitoring/test_fuzz_zmq.py +6 -4
- parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +5 -7
- parsl/tests/test_monitoring/test_incomplete_futures.py +5 -4
- parsl/tests/test_monitoring/test_memoization_representation.py +4 -2
- parsl/tests/test_monitoring/test_stdouterr.py +4 -6
- parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
- parsl/tests/test_mpi_apps/test_bad_mpi_config.py +1 -1
- parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +4 -7
- parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +15 -4
- parsl/tests/test_mpi_apps/test_mpi_prefix.py +4 -4
- parsl/tests/test_mpi_apps/test_mpi_scheduler.py +7 -2
- parsl/tests/test_mpi_apps/test_mpiex.py +4 -3
- parsl/tests/test_mpi_apps/test_resource_spec.py +21 -17
- parsl/tests/test_providers/test_cobalt_deprecation_warning.py +2 -0
- parsl/tests/test_providers/test_local_provider.py +2 -1
- parsl/tests/test_providers/test_pbspro_template.py +1 -1
- parsl/tests/test_providers/test_slurm_template.py +1 -1
- parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
- parsl/tests/test_python_apps/test_context_manager.py +5 -12
- parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
- parsl/tests/test_python_apps/test_futures.py +2 -1
- parsl/tests/test_python_apps/test_join.py +0 -1
- parsl/tests/test_python_apps/test_lifted.py +11 -7
- parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +1 -0
- parsl/tests/test_python_apps/test_pluggable_future_resolution.py +161 -0
- parsl/tests/test_radical/test_mpi_funcs.py +1 -1
- parsl/tests/test_regression/test_1480.py +2 -1
- parsl/tests/test_regression/test_1653.py +2 -1
- parsl/tests/test_regression/test_2652.py +1 -0
- parsl/tests/test_regression/test_69a.py +0 -1
- parsl/tests/test_regression/test_854.py +4 -2
- parsl/tests/test_regression/test_97_parallelism_0.py +1 -2
- parsl/tests/test_regression/test_98.py +0 -1
- parsl/tests/test_scaling/test_block_error_handler.py +9 -4
- parsl/tests/test_scaling/test_regression_1621.py +0 -2
- parsl/tests/test_scaling/test_scale_down.py +2 -3
- parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +4 -5
- parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +3 -4
- parsl/tests/test_scaling/test_shutdown_scalein.py +1 -4
- parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
- parsl/tests/test_serialization/test_basic.py +2 -1
- parsl/tests/test_serialization/test_htex_code_cache.py +3 -4
- parsl/tests/test_serialization/test_pack_resource_spec.py +2 -1
- parsl/tests/test_serialization/test_proxystore_configured.py +10 -6
- parsl/tests/test_serialization/test_proxystore_impl.py +5 -3
- parsl/tests/test_shutdown/test_kill_monitoring.py +3 -4
- parsl/tests/test_staging/staging_provider.py +2 -2
- parsl/tests/test_staging/test_1316.py +3 -4
- parsl/tests/test_staging/test_docs_1.py +1 -1
- parsl/tests/test_staging/test_docs_2.py +2 -1
- parsl/tests/test_staging/test_elaborate_noop_file.py +2 -3
- parsl/tests/test_staging/test_staging_https.py +2 -2
- parsl/tests/test_staging/test_staging_stdout.py +4 -3
- parsl/tests/test_staging/test_zip_in.py +6 -8
- parsl/tests/test_staging/test_zip_out.py +7 -9
- parsl/tests/test_staging/test_zip_to_zip.py +6 -8
- parsl/tests/test_summary.py +2 -2
- parsl/tests/test_thread_parallelism.py +0 -1
- parsl/tests/test_threads/test_configs.py +1 -2
- parsl/tests/test_threads/test_lazy_errors.py +2 -2
- parsl/usage_tracking/api.py +2 -3
- parsl/usage_tracking/usage.py +8 -18
- parsl/utils.py +13 -2
- parsl/version.py +1 -1
- {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/exec_parsl_function.py +5 -4
- {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/process_worker_pool.py +31 -20
- {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/METADATA +6 -6
- parsl-2024.6.3.dist-info/RECORD +471 -0
- parsl-2024.5.20.dist-info/RECORD +0 -468
- {parsl-2024.5.20.data → parsl-2024.6.3.data}/scripts/parsl_coprocess.py +1 -1
- {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/LICENSE +0 -0
- {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/WHEEL +0 -0
- {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/entry_points.txt +0 -0
- {parsl-2024.5.20.dist-info → parsl-2024.6.3.dist-info}/top_level.txt +0 -0
parsl/data_provider/rsync.py
CHANGED
parsl/data_provider/staging.py
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
from concurrent.futures import Future
|
2
|
-
from typing import
|
2
|
+
from typing import TYPE_CHECKING, Callable, Optional
|
3
|
+
|
3
4
|
from parsl.app.futures import DataFuture
|
4
5
|
from parsl.data_provider.files import File
|
5
6
|
|
6
|
-
from typing import TYPE_CHECKING
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from parsl.data_provider.data_manager import DataManager
|
9
9
|
|
parsl/data_provider/zip.py
CHANGED
@@ -1,16 +1,15 @@
|
|
1
|
-
import filelock
|
2
1
|
import logging
|
3
2
|
import os
|
4
|
-
import parsl
|
5
3
|
import zipfile
|
6
|
-
|
7
4
|
from typing import Tuple
|
8
5
|
|
9
|
-
|
6
|
+
import filelock
|
7
|
+
|
8
|
+
import parsl
|
10
9
|
from parsl.data_provider.files import File
|
10
|
+
from parsl.data_provider.staging import Staging
|
11
11
|
from parsl.errors import ParslError
|
12
12
|
|
13
|
-
|
14
13
|
logger = logging.getLogger(__name__)
|
15
14
|
|
16
15
|
|
@@ -0,0 +1,115 @@
|
|
1
|
+
from concurrent.futures import Future
|
2
|
+
from dataclasses import dataclass
|
3
|
+
from functools import singledispatch
|
4
|
+
from typing import Callable, Sequence
|
5
|
+
|
6
|
+
|
7
|
+
@dataclass
|
8
|
+
class DependencyResolver:
|
9
|
+
"""A DependencyResolver describes how app dependencies can be resolved.
|
10
|
+
It is specified as two functions: `traverse_to_gather` which turns an
|
11
|
+
app parameter into a sequence of futures which must be waited for before
|
12
|
+
the task can be executed (for example, in the case of
|
13
|
+
`DEEP_DEPENDENCY_RESOLVER` this traverses structures such as lists to
|
14
|
+
find every contained ``Future``), and `traverse_to_unwrap` which turns an
|
15
|
+
app parameter into its value to be passed to the app on execution
|
16
|
+
(for example in the case of `DEEP_DEPENDENCY_RESOLVER` this replaces a
|
17
|
+
list containing futures with a new list containing the values of those
|
18
|
+
resolved futures).
|
19
|
+
|
20
|
+
By default, Parsl will use `SHALLOW_DEPENDENCY_RESOLVER` which only
|
21
|
+
resolves Futures passed directly as arguments.
|
22
|
+
"""
|
23
|
+
traverse_to_gather: Callable[[object], Sequence[Future]]
|
24
|
+
traverse_to_unwrap: Callable[[object], object]
|
25
|
+
|
26
|
+
|
27
|
+
@singledispatch
|
28
|
+
def shallow_traverse_to_gather(o):
|
29
|
+
# objects in general do not expose futures that we can see
|
30
|
+
return []
|
31
|
+
|
32
|
+
|
33
|
+
@singledispatch
|
34
|
+
def shallow_traverse_to_unwrap(o):
|
35
|
+
# objects in general unwrap to themselves
|
36
|
+
return o
|
37
|
+
|
38
|
+
|
39
|
+
@shallow_traverse_to_gather.register
|
40
|
+
def _(fut: Future):
|
41
|
+
return [fut]
|
42
|
+
|
43
|
+
|
44
|
+
@shallow_traverse_to_unwrap.register
|
45
|
+
@singledispatch
|
46
|
+
def _(fut: Future):
|
47
|
+
assert fut.done()
|
48
|
+
return fut.result()
|
49
|
+
|
50
|
+
|
51
|
+
@singledispatch
|
52
|
+
def deep_traverse_to_gather(o):
|
53
|
+
# objects in general do not expose futures that we can see
|
54
|
+
return []
|
55
|
+
|
56
|
+
|
57
|
+
@singledispatch
|
58
|
+
def deep_traverse_to_unwrap(o):
|
59
|
+
# objects in general unwrap to themselves
|
60
|
+
return o
|
61
|
+
|
62
|
+
|
63
|
+
@deep_traverse_to_gather.register
|
64
|
+
def _(fut: Future):
|
65
|
+
return [fut]
|
66
|
+
|
67
|
+
|
68
|
+
@deep_traverse_to_unwrap.register
|
69
|
+
@singledispatch
|
70
|
+
def _(fut: Future):
|
71
|
+
assert fut.done()
|
72
|
+
return fut.result()
|
73
|
+
|
74
|
+
|
75
|
+
@deep_traverse_to_gather.register(tuple)
|
76
|
+
@deep_traverse_to_gather.register(list)
|
77
|
+
@deep_traverse_to_gather.register(set)
|
78
|
+
def _(iterable):
|
79
|
+
return [e for v in iterable for e in deep_traverse_to_gather(v)]
|
80
|
+
|
81
|
+
|
82
|
+
@deep_traverse_to_unwrap.register(tuple)
|
83
|
+
@deep_traverse_to_unwrap.register(list)
|
84
|
+
@deep_traverse_to_unwrap.register(set)
|
85
|
+
@singledispatch
|
86
|
+
def _(iterable):
|
87
|
+
|
88
|
+
type_ = type(iterable)
|
89
|
+
return type_(map(deep_traverse_to_unwrap, iterable))
|
90
|
+
|
91
|
+
|
92
|
+
@deep_traverse_to_gather.register(dict)
|
93
|
+
def _(dictionary):
|
94
|
+
futures = []
|
95
|
+
for key, value in dictionary.items():
|
96
|
+
futures.extend(deep_traverse_to_gather(key))
|
97
|
+
futures.extend(deep_traverse_to_gather(value))
|
98
|
+
return futures
|
99
|
+
|
100
|
+
|
101
|
+
@deep_traverse_to_unwrap.register(dict)
|
102
|
+
def _(dictionary):
|
103
|
+
unwrapped_dict = {}
|
104
|
+
for key, value in dictionary.items():
|
105
|
+
key = deep_traverse_to_unwrap(key)
|
106
|
+
value = deep_traverse_to_unwrap(value)
|
107
|
+
unwrapped_dict[key] = value
|
108
|
+
return unwrapped_dict
|
109
|
+
|
110
|
+
|
111
|
+
DEEP_DEPENDENCY_RESOLVER = DependencyResolver(traverse_to_gather=deep_traverse_to_gather,
|
112
|
+
traverse_to_unwrap=deep_traverse_to_unwrap)
|
113
|
+
|
114
|
+
SHALLOW_DEPENDENCY_RESOLVER = DependencyResolver(traverse_to_gather=shallow_traverse_to_gather,
|
115
|
+
traverse_to_unwrap=shallow_traverse_to_unwrap)
|
parsl/dataflow/dflow.py
CHANGED
@@ -1,23 +1,25 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
|
2
3
|
import atexit
|
4
|
+
import datetime
|
5
|
+
import inspect
|
3
6
|
import logging
|
4
7
|
import os
|
5
8
|
import pathlib
|
6
9
|
import pickle
|
7
10
|
import random
|
8
|
-
import time
|
9
|
-
import typeguard
|
10
|
-
import inspect
|
11
|
-
import threading
|
12
11
|
import sys
|
13
|
-
import
|
12
|
+
import threading
|
13
|
+
import time
|
14
|
+
from concurrent.futures import Future
|
15
|
+
from functools import partial
|
14
16
|
from getpass import getuser
|
15
|
-
from
|
17
|
+
from socket import gethostname
|
16
18
|
from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
|
17
19
|
from uuid import uuid4
|
18
|
-
|
19
|
-
|
20
|
-
from
|
20
|
+
|
21
|
+
import typeguard
|
22
|
+
from typeguard import typechecked
|
21
23
|
|
22
24
|
import parsl
|
23
25
|
from parsl.app.errors import RemoteExceptionWrapper
|
@@ -26,25 +28,29 @@ from parsl.channels import Channel
|
|
26
28
|
from parsl.config import Config
|
27
29
|
from parsl.data_provider.data_manager import DataManager
|
28
30
|
from parsl.data_provider.files import File
|
31
|
+
from parsl.dataflow.dependency_resolvers import SHALLOW_DEPENDENCY_RESOLVER
|
29
32
|
from parsl.dataflow.errors import BadCheckpoint, DependencyError, JoinError
|
30
33
|
from parsl.dataflow.futures import AppFuture
|
31
34
|
from parsl.dataflow.memoization import Memoizer
|
32
35
|
from parsl.dataflow.rundirs import make_rundir
|
33
|
-
from parsl.dataflow.states import
|
36
|
+
from parsl.dataflow.states import FINAL_FAILURE_STATES, FINAL_STATES, States
|
34
37
|
from parsl.dataflow.taskrecord import TaskRecord
|
35
|
-
from parsl.errors import
|
36
|
-
|
37
|
-
|
38
|
+
from parsl.errors import (
|
39
|
+
ConfigurationError,
|
40
|
+
InternalConsistencyError,
|
41
|
+
NoDataFlowKernelError,
|
42
|
+
)
|
38
43
|
from parsl.executors.base import ParslExecutor
|
39
44
|
from parsl.executors.status_handling import BlockProviderExecutor
|
40
45
|
from parsl.executors.threads import ThreadPoolExecutor
|
46
|
+
from parsl.jobs.job_status_poller import JobStatusPoller
|
41
47
|
from parsl.monitoring import MonitoringHub
|
48
|
+
from parsl.monitoring.message_type import MessageType
|
42
49
|
from parsl.monitoring.remote import monitor_wrapper
|
43
50
|
from parsl.process_loggers import wrap_with_logs
|
44
51
|
from parsl.providers.base import ExecutionProvider
|
45
|
-
from parsl.
|
46
|
-
|
47
|
-
from parsl.monitoring.message_type import MessageType
|
52
|
+
from parsl.usage_tracking.usage import UsageTracker
|
53
|
+
from parsl.utils import Timer, get_all_checkpoints, get_std_fname_mode, get_version
|
48
54
|
|
49
55
|
logger = logging.getLogger(__name__)
|
50
56
|
|
@@ -203,6 +209,9 @@ class DataFlowKernel:
|
|
203
209
|
self.tasks: Dict[int, TaskRecord] = {}
|
204
210
|
self.submitter_lock = threading.Lock()
|
205
211
|
|
212
|
+
self.dependency_resolver = self.config.dependency_resolver if self.config.dependency_resolver is not None \
|
213
|
+
else SHALLOW_DEPENDENCY_RESOLVER
|
214
|
+
|
206
215
|
atexit.register(self.atexit_cleanup)
|
207
216
|
|
208
217
|
def __enter__(self):
|
@@ -852,8 +861,11 @@ class DataFlowKernel:
|
|
852
861
|
depends: List[Future] = []
|
853
862
|
|
854
863
|
def check_dep(d: Any) -> None:
|
855
|
-
|
856
|
-
depends.extend(
|
864
|
+
try:
|
865
|
+
depends.extend(self.dependency_resolver.traverse_to_gather(d))
|
866
|
+
except Exception:
|
867
|
+
logger.exception("Exception in dependency_resolver.traverse_to_gather")
|
868
|
+
raise
|
857
869
|
|
858
870
|
# Check the positional args
|
859
871
|
for dep in args:
|
@@ -870,7 +882,8 @@ class DataFlowKernel:
|
|
870
882
|
|
871
883
|
return depends
|
872
884
|
|
873
|
-
def _unwrap_futures(self, args, kwargs)
|
885
|
+
def _unwrap_futures(self, args: Sequence[Any], kwargs: Dict[str, Any]) \
|
886
|
+
-> Tuple[Sequence[Any], Dict[str, Any], Sequence[Tuple[Exception, str]]]:
|
874
887
|
"""This function should be called when all dependencies have completed.
|
875
888
|
|
876
889
|
It will rewrite the arguments for that task, replacing each Future
|
@@ -891,53 +904,40 @@ class DataFlowKernel:
|
|
891
904
|
"""
|
892
905
|
dep_failures = []
|
893
906
|
|
907
|
+
def append_failure(e: Exception, dep: Future) -> None:
|
908
|
+
# If this Future is associated with a task inside this DFK,
|
909
|
+
# then refer to the task ID.
|
910
|
+
# Otherwise make a repr of the Future object.
|
911
|
+
if hasattr(dep, 'task_record') and dep.task_record['dfk'] == self:
|
912
|
+
tid = "task " + repr(dep.task_record['id'])
|
913
|
+
else:
|
914
|
+
tid = repr(dep)
|
915
|
+
dep_failures.extend([(e, tid)])
|
916
|
+
|
894
917
|
# Replace item in args
|
895
918
|
new_args = []
|
896
919
|
for dep in args:
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
# If this Future is associated with a task inside this DFK,
|
902
|
-
# then refer to the task ID.
|
903
|
-
# Otherwise make a repr of the Future object.
|
904
|
-
if hasattr(dep, 'task_record') and dep.task_record['dfk'] == self:
|
905
|
-
tid = "task " + repr(dep.task_record['id'])
|
906
|
-
else:
|
907
|
-
tid = repr(dep)
|
908
|
-
dep_failures.extend([(e, tid)])
|
909
|
-
else:
|
910
|
-
new_args.extend([dep])
|
920
|
+
try:
|
921
|
+
new_args.extend([self.dependency_resolver.traverse_to_unwrap(dep)])
|
922
|
+
except Exception as e:
|
923
|
+
append_failure(e, dep)
|
911
924
|
|
912
925
|
# Check for explicit kwargs ex, fu_1=<fut>
|
913
926
|
for key in kwargs:
|
914
927
|
dep = kwargs[key]
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
if hasattr(dep, 'task_record'):
|
920
|
-
tid = dep.task_record['id']
|
921
|
-
else:
|
922
|
-
tid = None
|
923
|
-
dep_failures.extend([(e, tid)])
|
928
|
+
try:
|
929
|
+
kwargs[key] = self.dependency_resolver.traverse_to_unwrap(dep)
|
930
|
+
except Exception as e:
|
931
|
+
append_failure(e, dep)
|
924
932
|
|
925
933
|
# Check for futures in inputs=[<fut>...]
|
926
934
|
if 'inputs' in kwargs:
|
927
935
|
new_inputs = []
|
928
936
|
for dep in kwargs['inputs']:
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
if hasattr(dep, 'task_record'):
|
934
|
-
tid = dep.task_record['id']
|
935
|
-
else:
|
936
|
-
tid = None
|
937
|
-
dep_failures.extend([(e, tid)])
|
938
|
-
|
939
|
-
else:
|
940
|
-
new_inputs.extend([dep])
|
937
|
+
try:
|
938
|
+
new_inputs.extend([self.dependency_resolver.traverse_to_unwrap(dep)])
|
939
|
+
except Exception as e:
|
940
|
+
append_failure(e, dep)
|
941
941
|
kwargs['inputs'] = new_inputs
|
942
942
|
|
943
943
|
return new_args, kwargs, dep_failures
|
@@ -1042,6 +1042,8 @@ class DataFlowKernel:
|
|
1042
1042
|
|
1043
1043
|
func = self._add_output_deps(executor, app_args, app_kwargs, app_fu, func)
|
1044
1044
|
|
1045
|
+
logger.debug("Added output dependencies")
|
1046
|
+
|
1045
1047
|
# Replace the function invocation in the TaskRecord with whatever file-staging
|
1046
1048
|
# substitutions have been made.
|
1047
1049
|
task_record.update({
|
@@ -1053,8 +1055,10 @@ class DataFlowKernel:
|
|
1053
1055
|
|
1054
1056
|
self.tasks[task_id] = task_record
|
1055
1057
|
|
1058
|
+
logger.debug("Gathering dependencies")
|
1056
1059
|
# Get the list of dependencies for the task
|
1057
1060
|
depends = self._gather_all_deps(app_args, app_kwargs)
|
1061
|
+
logger.debug("Gathered dependencies")
|
1058
1062
|
task_record['depends'] = depends
|
1059
1063
|
|
1060
1064
|
depend_descs = []
|
@@ -1271,6 +1275,13 @@ class DataFlowKernel:
|
|
1271
1275
|
atexit.unregister(self.atexit_cleanup)
|
1272
1276
|
logger.info("Unregistered atexit hook")
|
1273
1277
|
|
1278
|
+
if DataFlowKernelLoader._dfk is self:
|
1279
|
+
logger.info("Unregistering default DFK")
|
1280
|
+
parsl.clear()
|
1281
|
+
logger.info("Unregistered default DFK")
|
1282
|
+
else:
|
1283
|
+
logger.debug("Cleaning up non-default DFK - not unregistering")
|
1284
|
+
|
1274
1285
|
logger.info("DFK cleanup complete")
|
1275
1286
|
|
1276
1287
|
def checkpoint(self, tasks: Optional[Sequence[TaskRecord]] = None) -> str:
|
parsl/dataflow/errors.py
CHANGED
parsl/dataflow/futures.py
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from concurrent.futures import Future
|
4
3
|
import logging
|
5
4
|
import threading
|
5
|
+
from concurrent.futures import Future
|
6
6
|
from typing import Any, Optional, Sequence, Union
|
7
7
|
|
8
8
|
import parsl.app.app as app
|
9
|
-
|
10
9
|
from parsl.app.futures import DataFuture
|
11
10
|
from parsl.dataflow.taskrecord import TaskRecord
|
12
11
|
|
parsl/dataflow/memoization.py
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
from __future__ import annotations
|
2
|
+
|
2
3
|
import hashlib
|
3
|
-
from functools import lru_cache, singledispatch
|
4
4
|
import logging
|
5
5
|
import pickle
|
6
|
-
from
|
6
|
+
from functools import lru_cache, singledispatch
|
7
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional
|
7
8
|
|
8
|
-
from
|
9
|
+
from parsl.dataflow.taskrecord import TaskRecord
|
9
10
|
|
10
11
|
if TYPE_CHECKING:
|
11
12
|
from parsl import DataFlowKernel # import loop at runtime - needed for typechecking - TODO turn into "if typing:"
|
12
13
|
|
13
|
-
from concurrent.futures import Future
|
14
|
-
|
15
14
|
import types
|
15
|
+
from concurrent.futures import Future
|
16
16
|
|
17
17
|
logger = logging.getLogger(__name__)
|
18
18
|
|
parsl/dataflow/rundirs.py
CHANGED
parsl/dataflow/taskrecord.py
CHANGED
@@ -1,19 +1,18 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
import threading
|
4
3
|
import datetime
|
5
|
-
|
4
|
+
import threading
|
6
5
|
from concurrent.futures import Future
|
7
6
|
|
8
|
-
|
9
7
|
# only for type checking:
|
10
|
-
from typing import Any, Callable, Dict,
|
8
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Sequence, Union
|
9
|
+
|
10
|
+
from typing_extensions import TypedDict
|
11
11
|
|
12
12
|
if TYPE_CHECKING:
|
13
13
|
from parsl.dataflow.futures import AppFuture
|
14
14
|
|
15
15
|
import parsl.dataflow.dflow as dflow
|
16
|
-
|
17
16
|
from parsl.dataflow.states import States
|
18
17
|
|
19
18
|
|
parsl/executors/__init__.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
from parsl.executors.
|
2
|
-
from parsl.executors.workqueue.executor import WorkQueueExecutor
|
1
|
+
from parsl.executors.flux.executor import FluxExecutor
|
3
2
|
from parsl.executors.high_throughput.executor import HighThroughputExecutor
|
4
3
|
from parsl.executors.high_throughput.mpi_executor import MPIExecutor
|
5
|
-
from parsl.executors.
|
4
|
+
from parsl.executors.threads import ThreadPoolExecutor
|
5
|
+
from parsl.executors.workqueue.executor import WorkQueueExecutor
|
6
6
|
|
7
7
|
__all__ = ['ThreadPoolExecutor',
|
8
8
|
'HighThroughputExecutor',
|
parsl/executors/base.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
"""Script for executing tasks inside of Flux jobs."""
|
2
2
|
|
3
3
|
import argparse
|
4
|
-
import os
|
5
4
|
import logging
|
5
|
+
import os
|
6
6
|
|
7
|
+
from parsl.executors.flux import TaskResult
|
7
8
|
from parsl.executors.high_throughput.process_worker_pool import execute_task
|
8
9
|
from parsl.serialize import serialize
|
9
|
-
from parsl.executors.flux import TaskResult
|
10
10
|
|
11
11
|
|
12
12
|
def main():
|
parsl/executors/flux/executor.py
CHANGED
@@ -1,33 +1,32 @@
|
|
1
1
|
"""Defines the FluxExecutor class."""
|
2
2
|
|
3
|
+
import collections
|
3
4
|
import concurrent.futures as cf
|
4
5
|
import functools
|
6
|
+
import itertools
|
5
7
|
import os
|
8
|
+
import queue
|
9
|
+
import shutil
|
6
10
|
import sys
|
7
|
-
import uuid
|
8
11
|
import threading
|
9
|
-
import
|
10
|
-
import shutil
|
11
|
-
import queue
|
12
|
-
from socket import gethostname
|
13
|
-
import collections
|
14
|
-
from collections.abc import Mapping, Callable
|
15
|
-
from typing import Optional, Any, Dict
|
12
|
+
import uuid
|
16
13
|
import weakref
|
14
|
+
from collections.abc import Callable, Mapping
|
15
|
+
from socket import gethostname
|
16
|
+
from typing import Any, Dict, Optional
|
17
17
|
|
18
18
|
import zmq
|
19
19
|
|
20
|
-
from parsl.
|
20
|
+
from parsl.app.errors import AppException
|
21
21
|
from parsl.executors.base import ParslExecutor
|
22
|
+
from parsl.executors.errors import ScalingFailed
|
22
23
|
from parsl.executors.flux.execute_parsl_task import __file__ as _WORKER_PATH
|
23
24
|
from parsl.executors.flux.flux_instance_manager import __file__ as _MANAGER_PATH
|
24
|
-
from parsl.executors.errors import ScalingFailed
|
25
25
|
from parsl.providers import LocalProvider
|
26
26
|
from parsl.providers.base import ExecutionProvider
|
27
27
|
from parsl.serialize import deserialize, pack_res_spec_apply_message
|
28
28
|
from parsl.serialize.errors import SerializationError
|
29
|
-
from parsl.
|
30
|
-
|
29
|
+
from parsl.utils import RepresentationMixin
|
31
30
|
|
32
31
|
_WORKER_PATH = os.path.realpath(_WORKER_PATH)
|
33
32
|
_MANAGER_PATH = os.path.realpath(_MANAGER_PATH)
|
@@ -1,10 +1,10 @@
|
|
1
1
|
"""Script meant to be the initial program of a Flux instance."""
|
2
2
|
|
3
3
|
import argparse
|
4
|
+
import logging
|
4
5
|
import os
|
5
6
|
from os.path import dirname
|
6
|
-
import
|
7
|
-
from socket import gethostname, gethostbyname
|
7
|
+
from socket import gethostbyname, gethostname
|
8
8
|
|
9
9
|
import zmq
|
10
10
|
|
@@ -16,8 +16,8 @@ def main():
|
|
16
16
|
encapsulating Flux instance.
|
17
17
|
"""
|
18
18
|
# flux imports only available when launched under Flux instance
|
19
|
-
import flux.job
|
20
19
|
import flux
|
20
|
+
import flux.job
|
21
21
|
|
22
22
|
logging.basicConfig(
|
23
23
|
level=logging.DEBUG, format="%(asctime)s [%(levelname)s] %(message)s"
|
@@ -10,3 +10,13 @@ class WorkerLost(Exception):
|
|
10
10
|
|
11
11
|
def __str__(self):
|
12
12
|
return self.__repr__()
|
13
|
+
|
14
|
+
|
15
|
+
class CommandClientTimeoutError(Exception):
|
16
|
+
"""Raised when the command client times out waiting for a response.
|
17
|
+
"""
|
18
|
+
|
19
|
+
|
20
|
+
class CommandClientBadError(Exception):
|
21
|
+
"""Raised when the command client is bad from an earlier timeout.
|
22
|
+
"""
|