parsl 2024.3.11__py3-none-any.whl → 2025.1.13__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- parsl/__init__.py +9 -10
- parsl/addresses.py +29 -7
- parsl/app/app.py +7 -8
- parsl/app/bash.py +15 -8
- parsl/app/errors.py +10 -13
- parsl/app/futures.py +8 -10
- parsl/app/python.py +2 -1
- parsl/benchmark/perf.py +2 -1
- parsl/concurrent/__init__.py +2 -2
- parsl/config.py +57 -10
- parsl/configs/ASPIRE1.py +6 -5
- parsl/configs/Azure.py +9 -8
- parsl/configs/bridges.py +6 -4
- parsl/configs/cc_in2p3.py +3 -3
- parsl/configs/ec2.py +3 -1
- parsl/configs/expanse.py +4 -3
- parsl/configs/frontera.py +3 -4
- parsl/configs/htex_local.py +3 -4
- parsl/configs/illinoiscluster.py +3 -1
- parsl/configs/improv.py +34 -0
- parsl/configs/kubernetes.py +4 -3
- parsl/configs/local_threads.py +5 -1
- parsl/configs/midway.py +5 -3
- parsl/configs/osg.py +4 -2
- parsl/configs/polaris.py +4 -2
- parsl/configs/stampede2.py +6 -5
- parsl/configs/summit.py +3 -3
- parsl/configs/toss3_llnl.py +4 -3
- parsl/configs/vineex_local.py +6 -4
- parsl/configs/wqex_local.py +5 -3
- parsl/curvezmq.py +4 -0
- parsl/data_provider/data_manager.py +4 -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 +135 -0
- parsl/dataflow/dependency_resolvers.py +115 -0
- parsl/dataflow/dflow.py +262 -224
- parsl/dataflow/errors.py +3 -5
- parsl/dataflow/futures.py +27 -14
- parsl/dataflow/memoization.py +5 -5
- parsl/dataflow/rundirs.py +5 -6
- parsl/dataflow/taskrecord.py +4 -5
- parsl/executors/__init__.py +4 -2
- parsl/executors/base.py +45 -15
- parsl/executors/errors.py +13 -0
- parsl/executors/execute_task.py +37 -0
- parsl/executors/flux/execute_parsl_task.py +3 -3
- parsl/executors/flux/executor.py +18 -19
- parsl/executors/flux/flux_instance_manager.py +26 -27
- parsl/executors/high_throughput/errors.py +43 -3
- parsl/executors/high_throughput/executor.py +316 -282
- parsl/executors/high_throughput/interchange.py +158 -167
- parsl/executors/high_throughput/manager_record.py +5 -0
- parsl/executors/high_throughput/manager_selector.py +55 -0
- parsl/executors/high_throughput/monitoring_info.py +2 -1
- parsl/executors/high_throughput/mpi_executor.py +113 -0
- parsl/executors/high_throughput/mpi_prefix_composer.py +10 -11
- parsl/executors/high_throughput/mpi_resource_management.py +6 -17
- parsl/executors/high_throughput/probe.py +9 -7
- parsl/executors/high_throughput/process_worker_pool.py +115 -77
- parsl/executors/high_throughput/zmq_pipes.py +81 -23
- parsl/executors/radical/executor.py +130 -79
- parsl/executors/radical/rpex_resources.py +17 -15
- parsl/executors/radical/rpex_worker.py +4 -3
- parsl/executors/status_handling.py +157 -51
- 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 +41 -57
- parsl/executors/taskvine/factory.py +1 -1
- parsl/executors/taskvine/factory_config.py +1 -1
- parsl/executors/taskvine/manager.py +18 -13
- parsl/executors/taskvine/manager_config.py +9 -5
- parsl/executors/threads.py +6 -6
- parsl/executors/workqueue/errors.py +1 -1
- parsl/executors/workqueue/exec_parsl_function.py +6 -5
- parsl/executors/workqueue/executor.py +64 -63
- parsl/executors/workqueue/parsl_coprocess.py +1 -1
- parsl/jobs/error_handlers.py +2 -2
- parsl/jobs/job_status_poller.py +30 -113
- parsl/jobs/states.py +7 -2
- parsl/jobs/strategy.py +43 -31
- parsl/launchers/__init__.py +12 -3
- parsl/launchers/errors.py +1 -1
- parsl/launchers/launchers.py +6 -12
- parsl/log_utils.py +9 -6
- parsl/monitoring/db_manager.py +59 -95
- parsl/monitoring/errors.py +6 -0
- parsl/monitoring/monitoring.py +87 -356
- parsl/monitoring/queries/pandas.py +1 -2
- parsl/monitoring/radios/base.py +13 -0
- parsl/monitoring/radios/filesystem.py +52 -0
- parsl/monitoring/radios/htex.py +57 -0
- parsl/monitoring/radios/multiprocessing.py +17 -0
- parsl/monitoring/radios/udp.py +56 -0
- parsl/monitoring/radios/zmq.py +17 -0
- parsl/monitoring/remote.py +33 -37
- parsl/monitoring/router.py +212 -0
- parsl/monitoring/types.py +5 -6
- parsl/monitoring/visualization/app.py +4 -2
- parsl/monitoring/visualization/models.py +0 -1
- parsl/monitoring/visualization/plots/default/workflow_plots.py +11 -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 -8
- parsl/multiprocessing.py +0 -1
- parsl/process_loggers.py +1 -2
- parsl/providers/__init__.py +8 -17
- parsl/providers/aws/aws.py +2 -3
- parsl/providers/azure/azure.py +4 -5
- parsl/providers/base.py +2 -18
- parsl/providers/cluster_provider.py +4 -12
- parsl/providers/condor/condor.py +7 -17
- parsl/providers/errors.py +2 -2
- parsl/providers/googlecloud/googlecloud.py +2 -1
- parsl/providers/grid_engine/grid_engine.py +5 -14
- parsl/providers/kubernetes/kube.py +80 -40
- parsl/providers/local/local.py +13 -26
- parsl/providers/lsf/lsf.py +5 -23
- parsl/providers/pbspro/pbspro.py +5 -17
- parsl/providers/slurm/slurm.py +81 -39
- parsl/providers/torque/torque.py +3 -14
- parsl/serialize/__init__.py +8 -3
- parsl/serialize/base.py +1 -2
- parsl/serialize/concretes.py +5 -4
- parsl/serialize/facade.py +3 -3
- parsl/serialize/proxystore.py +3 -2
- parsl/tests/__init__.py +1 -1
- parsl/tests/configs/azure_single_node.py +4 -5
- parsl/tests/configs/bridges.py +3 -2
- parsl/tests/configs/cc_in2p3.py +1 -3
- 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/flux_local.py +11 -0
- parsl/tests/configs/frontera.py +2 -3
- parsl/tests/configs/htex_local.py +3 -5
- parsl/tests/configs/htex_local_alternate.py +11 -15
- parsl/tests/configs/htex_local_intask_staging.py +5 -9
- parsl/tests/configs/htex_local_rsync_staging.py +4 -8
- parsl/tests/configs/local_radical.py +1 -3
- parsl/tests/configs/local_radical_mpi.py +2 -2
- parsl/tests/configs/local_threads_checkpoint_periodic.py +8 -10
- parsl/tests/configs/local_threads_monitoring.py +0 -1
- 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/slurm_local.py +24 -0
- parsl/tests/configs/summit.py +1 -0
- parsl/tests/configs/taskvine_ex.py +4 -7
- parsl/tests/configs/user_opts.py +2 -8
- parsl/tests/configs/workqueue_ex.py +4 -6
- parsl/tests/conftest.py +27 -13
- 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 -6
- parsl/tests/manual_tests/test_basic.py +1 -0
- parsl/tests/manual_tests/test_log_filter.py +3 -1
- parsl/tests/manual_tests/test_memory_limits.py +6 -8
- parsl/tests/manual_tests/test_regression_220.py +2 -1
- parsl/tests/manual_tests/test_udp_simple.py +4 -4
- parsl/tests/manual_tests/test_worker_count.py +3 -2
- parsl/tests/scaling_tests/htex_local.py +2 -4
- 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/site_config_selector.py +1 -6
- parsl/tests/site_tests/test_provider.py +4 -2
- parsl/tests/site_tests/test_site.py +2 -0
- parsl/tests/sites/test_affinity.py +7 -7
- parsl/tests/sites/test_dynamic_executor.py +3 -4
- parsl/tests/sites/test_ec2.py +3 -2
- parsl/tests/sites/test_worker_info.py +4 -5
- parsl/tests/test_aalst_patterns.py +0 -1
- parsl/tests/test_bash_apps/test_apptimeout.py +2 -2
- parsl/tests/test_bash_apps/test_basic.py +10 -4
- parsl/tests/test_bash_apps/test_error_codes.py +5 -7
- parsl/tests/test_bash_apps/test_inputs_default.py +25 -0
- parsl/tests/test_bash_apps/test_kwarg_storage.py +1 -1
- parsl/tests/test_bash_apps/test_memoize.py +2 -8
- parsl/tests/test_bash_apps/test_memoize_ignore_args.py +9 -14
- parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +9 -14
- parsl/tests/test_bash_apps/test_multiline.py +1 -1
- parsl/tests/test_bash_apps/test_pipeline.py +1 -1
- parsl/tests/test_bash_apps/test_std_uri.py +123 -0
- parsl/tests/test_bash_apps/test_stdout.py +33 -8
- parsl/tests/test_callables.py +2 -2
- parsl/tests/test_checkpointing/test_periodic.py +21 -39
- 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 +2 -3
- parsl/tests/test_docs/test_from_slides.py +5 -2
- parsl/tests/test_docs/test_kwargs.py +4 -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 +10 -12
- parsl/tests/test_error_handling/test_retries.py +6 -16
- 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_execute_task.py +29 -0
- parsl/tests/test_flux.py +1 -1
- parsl/tests/test_htex/test_basic.py +2 -3
- parsl/tests/test_htex/test_block_manager_selector_unit.py +20 -0
- 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 -5
- parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +71 -0
- parsl/tests/test_htex/test_drain.py +79 -0
- parsl/tests/test_htex/test_htex.py +51 -25
- parsl/tests/test_htex/test_manager_failure.py +0 -1
- parsl/tests/test_htex/test_manager_selector_by_block.py +51 -0
- parsl/tests/test_htex/test_managers_command.py +36 -0
- parsl/tests/test_htex/test_missing_worker.py +2 -12
- parsl/tests/test_htex/test_multiple_disconnected_blocks.py +9 -9
- parsl/tests/test_htex/test_resource_spec_validation.py +45 -0
- parsl/tests/test_htex/test_zmq_binding.py +29 -8
- parsl/tests/test_monitoring/test_app_names.py +86 -0
- parsl/tests/test_monitoring/test_basic.py +73 -25
- parsl/tests/test_monitoring/test_db_locks.py +6 -4
- parsl/tests/test_monitoring/test_fuzz_zmq.py +19 -8
- parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +80 -0
- 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 +134 -0
- parsl/tests/test_monitoring/test_viz_colouring.py +1 -0
- parsl/tests/test_mpi_apps/test_bad_mpi_config.py +33 -26
- parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +28 -11
- 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 +64 -0
- parsl/tests/test_mpi_apps/test_resource_spec.py +42 -49
- parsl/tests/test_providers/test_kubernetes_provider.py +102 -0
- parsl/tests/test_providers/test_local_provider.py +3 -132
- parsl/tests/test_providers/test_pbspro_template.py +2 -3
- parsl/tests/test_providers/test_slurm_template.py +2 -3
- parsl/tests/test_providers/test_submiterror_deprecation.py +2 -1
- parsl/tests/test_python_apps/test_context_manager.py +128 -0
- parsl/tests/test_python_apps/test_dep_standard_futures.py +2 -1
- parsl/tests/test_python_apps/test_dependencies_deep.py +59 -0
- parsl/tests/test_python_apps/test_fail.py +0 -25
- parsl/tests/test_python_apps/test_futures.py +2 -1
- parsl/tests/test_python_apps/test_inputs_default.py +22 -0
- 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_outputs.py +1 -1
- parsl/tests/test_python_apps/test_pluggable_future_resolution.py +161 -0
- parsl/tests/test_radical/test_mpi_funcs.py +1 -2
- parsl/tests/test_regression/test_1480.py +2 -1
- parsl/tests/test_regression/test_1653.py +2 -1
- parsl/tests/test_regression/test_226.py +1 -0
- 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 +11 -15
- parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +84 -0
- parsl/tests/test_scaling/test_regression_3696_oscillation.py +103 -0
- parsl/tests/test_scaling/test_scale_down.py +2 -5
- parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +6 -18
- parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +71 -0
- parsl/tests/test_scaling/test_shutdown_scalein.py +73 -0
- parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +90 -0
- parsl/tests/test_serialization/test_2555_caching_deserializer.py +1 -1
- parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +47 -0
- 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 +64 -0
- 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 +2 -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_data → test_staging}/test_file.py +6 -6
- parsl/tests/{test_data → test_staging}/test_output_chain_filenames.py +3 -0
- parsl/tests/test_staging/test_staging_ftp.py +1 -0
- parsl/tests/test_staging/test_staging_https.py +5 -2
- parsl/tests/test_staging/test_staging_stdout.py +64 -0
- parsl/tests/test_staging/test_zip_in.py +39 -0
- parsl/tests/test_staging/test_zip_out.py +110 -0
- parsl/tests/test_staging/test_zip_to_zip.py +41 -0
- 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/tests/test_utils/test_execute_wait.py +35 -0
- parsl/tests/test_utils/test_sanitize_dns.py +76 -0
- parsl/tests/unit/test_address.py +20 -0
- parsl/tests/unit/test_file.py +99 -0
- parsl/tests/unit/test_usage_tracking.py +66 -0
- parsl/usage_tracking/api.py +65 -0
- parsl/usage_tracking/levels.py +6 -0
- parsl/usage_tracking/usage.py +104 -62
- parsl/utils.py +139 -6
- parsl/version.py +1 -1
- {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/exec_parsl_function.py +6 -5
- parsl-2025.1.13.data/scripts/interchange.py +649 -0
- {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/process_worker_pool.py +115 -77
- parsl-2025.1.13.dist-info/METADATA +96 -0
- parsl-2025.1.13.dist-info/RECORD +462 -0
- {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/WHEEL +1 -1
- parsl/channels/__init__.py +0 -7
- parsl/channels/base.py +0 -141
- parsl/channels/errors.py +0 -113
- parsl/channels/local/local.py +0 -164
- parsl/channels/oauth_ssh/oauth_ssh.py +0 -110
- parsl/channels/ssh/ssh.py +0 -276
- parsl/channels/ssh_il/__init__.py +0 -0
- parsl/channels/ssh_il/ssh_il.py +0 -74
- parsl/configs/ad_hoc.py +0 -35
- parsl/executors/radical/rpex_master.py +0 -42
- parsl/monitoring/radios.py +0 -175
- parsl/providers/ad_hoc/__init__.py +0 -0
- parsl/providers/ad_hoc/ad_hoc.py +0 -248
- parsl/providers/cobalt/__init__.py +0 -0
- parsl/providers/cobalt/cobalt.py +0 -236
- parsl/providers/cobalt/template.py +0 -17
- parsl/tests/configs/ad_hoc_cluster_htex.py +0 -35
- parsl/tests/configs/cooley_htex.py +0 -37
- parsl/tests/configs/htex_ad_hoc_cluster.py +0 -28
- parsl/tests/configs/local_adhoc.py +0 -18
- parsl/tests/configs/swan_htex.py +0 -43
- parsl/tests/configs/theta.py +0 -37
- parsl/tests/integration/test_channels/__init__.py +0 -0
- parsl/tests/integration/test_channels/test_channels.py +0 -17
- parsl/tests/integration/test_channels/test_local_channel.py +0 -42
- parsl/tests/integration/test_channels/test_scp_1.py +0 -45
- parsl/tests/integration/test_channels/test_ssh_1.py +0 -40
- parsl/tests/integration/test_channels/test_ssh_errors.py +0 -46
- parsl/tests/integration/test_channels/test_ssh_file_transport.py +0 -41
- parsl/tests/integration/test_channels/test_ssh_interactive.py +0 -24
- parsl/tests/manual_tests/test_ad_hoc_htex.py +0 -48
- parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +0 -88
- parsl/tests/manual_tests/test_oauth_ssh.py +0 -13
- parsl/tests/sites/test_local_adhoc.py +0 -61
- parsl/tests/test_channels/__init__.py +0 -0
- parsl/tests/test_channels/test_large_output.py +0 -22
- parsl/tests/test_data/__init__.py +0 -0
- parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +0 -51
- parsl/tests/test_providers/test_cobalt_deprecation_warning.py +0 -16
- parsl-2024.3.11.dist-info/METADATA +0 -98
- parsl-2024.3.11.dist-info/RECORD +0 -447
- parsl/{channels/local → monitoring/radios}/__init__.py +0 -0
- parsl/{channels/oauth_ssh → tests/test_shutdown}/__init__.py +0 -0
- parsl/tests/{test_data → test_staging}/test_file_apps.py +0 -0
- parsl/tests/{test_data → test_staging}/test_file_staging.py +0 -0
- parsl/{channels/ssh → tests/unit}/__init__.py +0 -0
- {parsl-2024.3.11.data → parsl-2025.1.13.data}/scripts/parsl_coprocess.py +1 -1
- {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/LICENSE +0 -0
- {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/entry_points.txt +0 -0
- {parsl-2024.3.11.dist-info → parsl-2025.1.13.dist-info}/top_level.txt +0 -0
parsl/configs/htex_local.py
CHANGED
@@ -1,8 +1,7 @@
|
|
1
|
-
from parsl.providers import LocalProvider
|
2
|
-
from parsl.channels import LocalChannel
|
3
|
-
|
4
1
|
from parsl.config import Config
|
5
2
|
from parsl.executors import HighThroughputExecutor
|
3
|
+
from parsl.providers import LocalProvider
|
4
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
5
|
|
7
6
|
config = Config(
|
8
7
|
executors=[
|
@@ -10,10 +9,10 @@ config = Config(
|
|
10
9
|
label="htex_local",
|
11
10
|
cores_per_worker=1,
|
12
11
|
provider=LocalProvider(
|
13
|
-
channel=LocalChannel(),
|
14
12
|
init_blocks=1,
|
15
13
|
max_blocks=1,
|
16
14
|
),
|
17
15
|
)
|
18
16
|
],
|
17
|
+
usage_tracking=LEVEL_1,
|
19
18
|
)
|
parsl/configs/illinoiscluster.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
from parsl.config import Config
|
2
|
-
from parsl.providers import SlurmProvider
|
3
2
|
from parsl.executors import HighThroughputExecutor
|
4
3
|
from parsl.launchers import SrunLauncher
|
4
|
+
from parsl.providers import SlurmProvider
|
5
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
5
6
|
|
6
7
|
""" This config assumes that it is used to launch parsl tasks from the login nodes
|
7
8
|
of the Campus Cluster at UIUC. Each job submitted to the scheduler will request 2 nodes for 10 minutes.
|
@@ -25,4 +26,5 @@ config = Config(
|
|
25
26
|
),
|
26
27
|
)
|
27
28
|
],
|
29
|
+
usage_tracking=LEVEL_1,
|
28
30
|
)
|
parsl/configs/improv.py
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
from parsl.config import Config
|
2
|
+
from parsl.executors import HighThroughputExecutor
|
3
|
+
from parsl.launchers import MpiRunLauncher
|
4
|
+
from parsl.providers import PBSProProvider
|
5
|
+
|
6
|
+
config = Config(
|
7
|
+
executors=[
|
8
|
+
HighThroughputExecutor(
|
9
|
+
label="Improv_multinode",
|
10
|
+
max_workers_per_node=32,
|
11
|
+
provider=PBSProProvider(
|
12
|
+
account="YOUR_ALLOCATION_ON_IMPROV",
|
13
|
+
# PBS directives (header lines), for example:
|
14
|
+
# scheduler_options='#PBS -l mem=4gb',
|
15
|
+
scheduler_options='',
|
16
|
+
|
17
|
+
queue="compute",
|
18
|
+
|
19
|
+
# Command to be run before starting a worker:
|
20
|
+
# **WARNING** Improv requires an openmpi module to be
|
21
|
+
# loaded for the MpiRunLauncher. Add additional env
|
22
|
+
# load commands to this multiline string.
|
23
|
+
worker_init='''
|
24
|
+
module load gcc/13.2.0;
|
25
|
+
module load openmpi/5.0.3-gcc-13.2.0; ''',
|
26
|
+
launcher=MpiRunLauncher(),
|
27
|
+
|
28
|
+
# number of compute nodes allocated for each block
|
29
|
+
nodes_per_block=2,
|
30
|
+
walltime='00:10:00'
|
31
|
+
),
|
32
|
+
),
|
33
|
+
],
|
34
|
+
)
|
parsl/configs/kubernetes.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
+
from parsl.addresses import address_by_route
|
1
2
|
from parsl.config import Config
|
2
3
|
from parsl.executors import HighThroughputExecutor
|
3
4
|
from parsl.providers import KubernetesProvider
|
4
|
-
from parsl.
|
5
|
-
|
5
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
6
|
|
7
7
|
config = Config(
|
8
8
|
executors=[
|
@@ -37,5 +37,6 @@ config = Config(
|
|
37
37
|
max_blocks=10,
|
38
38
|
),
|
39
39
|
),
|
40
|
-
]
|
40
|
+
],
|
41
|
+
usage_tracking=LEVEL_1,
|
41
42
|
)
|
parsl/configs/local_threads.py
CHANGED
@@ -1,4 +1,8 @@
|
|
1
1
|
from parsl.config import Config
|
2
2
|
from parsl.executors.threads import ThreadPoolExecutor
|
3
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
3
4
|
|
4
|
-
config = Config(
|
5
|
+
config = Config(
|
6
|
+
executors=[ThreadPoolExecutor()],
|
7
|
+
usage_tracking=LEVEL_1,
|
8
|
+
)
|
parsl/configs/midway.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
from parsl.addresses import address_by_interface
|
1
2
|
from parsl.config import Config
|
2
|
-
from parsl.providers import SlurmProvider
|
3
|
-
from parsl.launchers import SrunLauncher
|
4
3
|
from parsl.executors import HighThroughputExecutor
|
5
|
-
from parsl.
|
4
|
+
from parsl.launchers import SrunLauncher
|
5
|
+
from parsl.providers import SlurmProvider
|
6
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
7
|
|
7
8
|
config = Config(
|
8
9
|
executors=[
|
@@ -28,4 +29,5 @@ config = Config(
|
|
28
29
|
),
|
29
30
|
)
|
30
31
|
],
|
32
|
+
usage_tracking=LEVEL_1,
|
31
33
|
)
|
parsl/configs/osg.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from parsl.config import Config
|
2
|
-
from parsl.providers import CondorProvider
|
3
2
|
from parsl.executors import HighThroughputExecutor
|
3
|
+
from parsl.providers import CondorProvider
|
4
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
4
5
|
|
5
6
|
config = Config(
|
6
7
|
executors=[
|
@@ -26,5 +27,6 @@ python3 -m venv parsl_env; source parsl_env/bin/activate; python3 -m pip install
|
|
26
27
|
worker_logdir_root='$OSG_WN_TMP',
|
27
28
|
worker_ports=(31000, 31001)
|
28
29
|
)
|
29
|
-
]
|
30
|
+
],
|
31
|
+
usage_tracking=LEVEL_1,
|
30
32
|
)
|
parsl/configs/polaris.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
from parsl.addresses import address_by_interface
|
2
|
+
from parsl.config import Config
|
2
3
|
from parsl.executors import HighThroughputExecutor
|
3
4
|
from parsl.launchers import MpiExecLauncher
|
4
5
|
from parsl.providers import PBSProProvider
|
5
|
-
from parsl.
|
6
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
7
|
|
7
8
|
# There are three user parameters to change for the PBSProProvider:
|
8
9
|
# YOUR_ACCOUNT: Account to charge usage
|
@@ -34,5 +35,6 @@ config = Config(
|
|
34
35
|
cpus_per_node=64,
|
35
36
|
),
|
36
37
|
),
|
37
|
-
]
|
38
|
+
],
|
39
|
+
usage_tracking=LEVEL_1,
|
38
40
|
)
|
parsl/configs/stampede2.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
+
from parsl.addresses import address_by_interface
|
1
2
|
from parsl.config import Config
|
2
|
-
from parsl.providers import SlurmProvider
|
3
|
-
from parsl.launchers import SrunLauncher
|
4
|
-
from parsl.executors import HighThroughputExecutor
|
5
3
|
from parsl.data_provider.globus import GlobusStaging
|
6
|
-
from parsl.
|
7
|
-
|
4
|
+
from parsl.executors import HighThroughputExecutor
|
5
|
+
from parsl.launchers import SrunLauncher
|
6
|
+
from parsl.providers import SlurmProvider
|
7
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
8
8
|
|
9
9
|
config = Config(
|
10
10
|
executors=[
|
@@ -35,4 +35,5 @@ config = Config(
|
|
35
35
|
)
|
36
36
|
|
37
37
|
],
|
38
|
+
usage_tracking=LEVEL_1,
|
38
39
|
)
|
parsl/configs/summit.py
CHANGED
@@ -1,10 +1,9 @@
|
|
1
|
+
from parsl.addresses import address_by_interface
|
1
2
|
from parsl.config import Config
|
2
3
|
from parsl.executors import HighThroughputExecutor
|
3
|
-
|
4
4
|
from parsl.launchers import JsrunLauncher
|
5
5
|
from parsl.providers import LSFProvider
|
6
|
-
|
7
|
-
from parsl.addresses import address_by_interface
|
6
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
8
7
|
|
9
8
|
config = Config(
|
10
9
|
executors=[
|
@@ -28,4 +27,5 @@ config = Config(
|
|
28
27
|
)
|
29
28
|
|
30
29
|
],
|
30
|
+
usage_tracking=LEVEL_1,
|
31
31
|
)
|
parsl/configs/toss3_llnl.py
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
from parsl.config import Config
|
2
2
|
from parsl.executors import FluxExecutor
|
3
|
-
from parsl.providers import SlurmProvider
|
4
3
|
from parsl.launchers import SrunLauncher
|
5
|
-
|
4
|
+
from parsl.providers import SlurmProvider
|
5
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
6
|
|
7
7
|
config = Config(
|
8
8
|
executors=[
|
@@ -25,5 +25,6 @@ config = Config(
|
|
25
25
|
cmd_timeout=120,
|
26
26
|
),
|
27
27
|
)
|
28
|
-
]
|
28
|
+
],
|
29
|
+
usage_tracking=LEVEL_1,
|
29
30
|
)
|
parsl/configs/vineex_local.py
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
from parsl.config import Config
|
2
|
-
from parsl.executors.taskvine import TaskVineExecutor
|
3
|
-
from parsl.executors.taskvine import TaskVineManagerConfig
|
4
1
|
import uuid
|
5
2
|
|
3
|
+
from parsl.config import Config
|
4
|
+
from parsl.executors.taskvine import TaskVineExecutor, TaskVineManagerConfig
|
5
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
6
|
+
|
6
7
|
config = Config(
|
7
8
|
executors=[
|
8
9
|
TaskVineExecutor(
|
@@ -15,5 +16,6 @@ config = Config(
|
|
15
16
|
# To disable status reporting, comment out the project_name.
|
16
17
|
manager_config=TaskVineManagerConfig(project_name="parsl-vine-" + str(uuid.uuid4())),
|
17
18
|
)
|
18
|
-
]
|
19
|
+
],
|
20
|
+
usage_tracking=LEVEL_1,
|
19
21
|
)
|
parsl/configs/wqex_local.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
|
+
import uuid
|
2
|
+
|
1
3
|
from parsl.config import Config
|
2
4
|
from parsl.executors import WorkQueueExecutor
|
3
|
-
|
4
|
-
import uuid
|
5
|
+
from parsl.usage_tracking.levels import LEVEL_1
|
5
6
|
|
6
7
|
config = Config(
|
7
8
|
executors=[
|
@@ -21,5 +22,6 @@ config = Config(
|
|
21
22
|
# A shared filesystem is not needed when using Work Queue.
|
22
23
|
shared_fs=False
|
23
24
|
)
|
24
|
-
]
|
25
|
+
],
|
26
|
+
usage_tracking=LEVEL_1,
|
25
27
|
)
|
parsl/curvezmq.py
CHANGED
@@ -160,6 +160,9 @@ class ServerContext(BaseContext):
|
|
160
160
|
except zmq.ZMQError as e:
|
161
161
|
raise ValueError("Invalid CurveZMQ key format") from e
|
162
162
|
sock.setsockopt(zmq.CURVE_SERVER, True) # Must come before bind
|
163
|
+
|
164
|
+
# This flag enables IPV6 in addition to IPV4
|
165
|
+
sock.setsockopt(zmq.IPV6, True)
|
163
166
|
return sock
|
164
167
|
|
165
168
|
def term(self):
|
@@ -202,4 +205,5 @@ class ClientContext(BaseContext):
|
|
202
205
|
sock.setsockopt(zmq.CURVE_SERVERKEY, server_public_key)
|
203
206
|
except zmq.ZMQError as e:
|
204
207
|
raise ValueError("Invalid CurveZMQ key format") from e
|
208
|
+
sock.setsockopt(zmq.IPV6, True)
|
205
209
|
return sock
|
@@ -1,13 +1,14 @@
|
|
1
1
|
import logging
|
2
2
|
from concurrent.futures import Future
|
3
|
-
from typing import Any, Callable, List, Optional
|
3
|
+
from typing import TYPE_CHECKING, Any, Callable, List, Optional
|
4
4
|
|
5
5
|
from parsl.app.futures import DataFuture
|
6
|
-
from parsl.data_provider.files import File
|
7
6
|
from parsl.data_provider.file_noop import NoOpFileStaging
|
7
|
+
from parsl.data_provider.files import File
|
8
8
|
from parsl.data_provider.ftp import FTPSeparateTaskStaging
|
9
9
|
from parsl.data_provider.http import HTTPSeparateTaskStaging
|
10
10
|
from parsl.data_provider.staging import Staging
|
11
|
+
from parsl.data_provider.zip import ZipFileStaging
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
13
14
|
from parsl.dataflow.dflow import DataFlowKernel
|
@@ -17,7 +18,7 @@ logger = logging.getLogger(__name__)
|
|
17
18
|
# these will be shared between all executors that do not explicitly
|
18
19
|
# override, so should not contain executor-specific state
|
19
20
|
default_staging: List[Staging]
|
20
|
-
default_staging = [NoOpFileStaging(), FTPSeparateTaskStaging(), HTTPSeparateTaskStaging()]
|
21
|
+
default_staging = [NoOpFileStaging(), FTPSeparateTaskStaging(), HTTPSeparateTaskStaging(), ZipFileStaging()]
|
21
22
|
|
22
23
|
|
23
24
|
class DataManager:
|
parsl/data_provider/file_noop.py
CHANGED
parsl/data_provider/files.py
CHANGED
@@ -5,13 +5,13 @@ to transfer the file as well as to give the appropriate filepath depending
|
|
5
5
|
on where (client-side, remote-side, intermediary-side) the File.filepath is
|
6
6
|
being called from.
|
7
7
|
"""
|
8
|
-
import os
|
9
|
-
|
10
|
-
import typeguard
|
11
8
|
import logging
|
9
|
+
import os
|
12
10
|
from typing import Optional, Union
|
13
11
|
from urllib.parse import urlparse
|
14
12
|
|
13
|
+
import typeguard
|
14
|
+
|
15
15
|
logger = logging.getLogger(__name__)
|
16
16
|
|
17
17
|
|
parsl/data_provider/ftp.py
CHANGED
parsl/data_provider/globus.py
CHANGED
@@ -1,15 +1,16 @@
|
|
1
|
-
import logging
|
2
1
|
import json
|
3
|
-
import
|
2
|
+
import logging
|
4
3
|
import os
|
5
|
-
import parsl
|
6
|
-
import typeguard
|
7
|
-
|
8
4
|
from functools import partial
|
9
5
|
from typing import Optional
|
6
|
+
|
7
|
+
import globus_sdk
|
8
|
+
import typeguard
|
9
|
+
|
10
|
+
import parsl
|
10
11
|
from parsl.app.app import python_app
|
11
|
-
from parsl.utils import RepresentationMixin
|
12
12
|
from parsl.data_provider.staging import Staging
|
13
|
+
from parsl.utils import RepresentationMixin
|
13
14
|
|
14
15
|
logger = logging.getLogger(__name__)
|
15
16
|
|
parsl/data_provider/http.py
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
import logging
|
2
2
|
import os
|
3
|
+
|
3
4
|
import requests
|
4
5
|
|
5
6
|
import parsl
|
6
|
-
|
7
|
-
from parsl.utils import RepresentationMixin
|
8
7
|
from parsl.data_provider.staging import Staging
|
8
|
+
from parsl.utils import RepresentationMixin
|
9
9
|
|
10
10
|
logger = logging.getLogger(__name__)
|
11
11
|
|
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
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
import logging
|
2
|
+
import os
|
3
|
+
import zipfile
|
4
|
+
from typing import Tuple
|
5
|
+
|
6
|
+
import filelock
|
7
|
+
|
8
|
+
import parsl
|
9
|
+
from parsl.data_provider.files import File
|
10
|
+
from parsl.data_provider.staging import Staging
|
11
|
+
from parsl.errors import ParslError
|
12
|
+
|
13
|
+
logger = logging.getLogger(__name__)
|
14
|
+
|
15
|
+
|
16
|
+
class ZipAuthorityError(ParslError):
|
17
|
+
def __init__(self, file):
|
18
|
+
self.file = file
|
19
|
+
|
20
|
+
def __str__(self):
|
21
|
+
return f"ZipFileStaging cannot stage Files with an authority (netloc) section ({self.file.netloc}), for {self.file.url}"
|
22
|
+
|
23
|
+
|
24
|
+
class ZipFileStaging(Staging):
|
25
|
+
"""A stage-out provider for zip files.
|
26
|
+
|
27
|
+
This provider will stage out files by writing them into the specified zip
|
28
|
+
file.
|
29
|
+
|
30
|
+
The filename of both the zip file and the file contained in that zip are
|
31
|
+
specified using a zip: URL, like this:
|
32
|
+
|
33
|
+
zip:/tmp/foo/this.zip/inside/here.txt
|
34
|
+
|
35
|
+
This URL names a zip file ``/tmp/foo/this.zip`` containing a file
|
36
|
+
``inside/here.txt``.
|
37
|
+
|
38
|
+
The provider will use the Python filelock package to lock the zip file so
|
39
|
+
that it does not conflict with other instances of itself. This lock will
|
40
|
+
not protect against other modifications to the zip file.
|
41
|
+
"""
|
42
|
+
|
43
|
+
def can_stage_out(self, file: File) -> bool:
|
44
|
+
return self.is_zip_url(file)
|
45
|
+
|
46
|
+
def can_stage_in(self, file: File) -> bool:
|
47
|
+
return self.is_zip_url(file)
|
48
|
+
|
49
|
+
def is_zip_url(self, file: File) -> bool:
|
50
|
+
logger.debug("archive provider checking File {}".format(repr(file)))
|
51
|
+
|
52
|
+
# First check if this is the scheme we care about
|
53
|
+
if file.scheme != "zip":
|
54
|
+
return False
|
55
|
+
|
56
|
+
# This is some basic validation to check that the user isn't specifying
|
57
|
+
# an authority section and expecting it to mean something.
|
58
|
+
if file.netloc != "":
|
59
|
+
raise ZipAuthorityError(file)
|
60
|
+
|
61
|
+
# If we got this far, we can stage this file
|
62
|
+
return True
|
63
|
+
|
64
|
+
def stage_out(self, dm, executor, file, parent_fut):
|
65
|
+
assert file.scheme == 'zip'
|
66
|
+
|
67
|
+
zip_path, inside_path = zip_path_split(file.path)
|
68
|
+
|
69
|
+
working_dir = dm.dfk.executors[executor].working_dir
|
70
|
+
|
71
|
+
if working_dir:
|
72
|
+
file.local_path = os.path.join(working_dir, inside_path)
|
73
|
+
|
74
|
+
# TODO: I think its the right behaviour that a staging out provider should create the directory structure
|
75
|
+
# for the file to be placed in?
|
76
|
+
os.makedirs(os.path.dirname(file.local_path), exist_ok=True)
|
77
|
+
else:
|
78
|
+
raise RuntimeError("zip file staging requires a working_dir to be specified")
|
79
|
+
|
80
|
+
stage_out_app = _zip_stage_out_app(dm)
|
81
|
+
app_fut = stage_out_app(zip_path, inside_path, working_dir, inputs=[file], _parsl_staging_inhibit=True, parent_fut=parent_fut)
|
82
|
+
return app_fut
|
83
|
+
|
84
|
+
def stage_in(self, dm, executor, file, parent_fut):
|
85
|
+
assert file.scheme == 'zip'
|
86
|
+
|
87
|
+
zip_path, inside_path = zip_path_split(file.path)
|
88
|
+
|
89
|
+
working_dir = dm.dfk.executors[executor].working_dir
|
90
|
+
|
91
|
+
if working_dir:
|
92
|
+
file.local_path = os.path.join(working_dir, inside_path)
|
93
|
+
|
94
|
+
stage_in_app = _zip_stage_in_app(dm)
|
95
|
+
app_fut = stage_in_app(zip_path, inside_path, working_dir, outputs=[file], _parsl_staging_inhibit=True, parent_fut=parent_fut)
|
96
|
+
return app_fut._outputs[0]
|
97
|
+
|
98
|
+
|
99
|
+
def _zip_stage_out(zip_file, inside_path, working_dir, parent_fut=None, inputs=[], _parsl_staging_inhibit=True):
|
100
|
+
file = inputs[0]
|
101
|
+
|
102
|
+
os.makedirs(os.path.dirname(zip_file), exist_ok=True)
|
103
|
+
|
104
|
+
with filelock.FileLock(zip_file + ".lock"):
|
105
|
+
with zipfile.ZipFile(zip_file, mode='a', compression=zipfile.ZIP_DEFLATED) as z:
|
106
|
+
z.write(file, arcname=inside_path)
|
107
|
+
|
108
|
+
os.remove(file)
|
109
|
+
|
110
|
+
|
111
|
+
def _zip_stage_out_app(dm):
|
112
|
+
return parsl.python_app(executors=['_parsl_internal'], data_flow_kernel=dm.dfk)(_zip_stage_out)
|
113
|
+
|
114
|
+
|
115
|
+
def _zip_stage_in(zip_file, inside_path, working_dir, *, parent_fut, outputs, _parsl_staging_inhibit=True):
|
116
|
+
with filelock.FileLock(zip_file + ".lock"):
|
117
|
+
with zipfile.ZipFile(zip_file, mode='r') as z:
|
118
|
+
content = z.read(inside_path)
|
119
|
+
with open(outputs[0], "wb") as of:
|
120
|
+
of.write(content)
|
121
|
+
|
122
|
+
|
123
|
+
def _zip_stage_in_app(dm):
|
124
|
+
return parsl.python_app(executors=['_parsl_internal'], data_flow_kernel=dm.dfk)(_zip_stage_in)
|
125
|
+
|
126
|
+
|
127
|
+
def zip_path_split(path: str) -> Tuple[str, str]:
|
128
|
+
"""Split zip: path into a zipfile name and a contained-file name.
|
129
|
+
"""
|
130
|
+
index = path.find(".zip/")
|
131
|
+
|
132
|
+
zip_path = path[:index + 4]
|
133
|
+
inside_path = path[index + 5:]
|
134
|
+
|
135
|
+
return (zip_path, inside_path)
|
@@ -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)
|