parsl 2024.3.18__tar.gz → 2024.4.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {parsl-2024.3.18/parsl.egg-info → parsl-2024.4.1}/PKG-INFO +2 -2
- {parsl-2024.3.18 → parsl-2024.4.1}/README.rst +2 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/dflow.py +35 -36
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/base.py +11 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/executor.py +8 -20
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/process_worker_pool.py +5 -2
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/status_handling.py +8 -15
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/executor.py +35 -11
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/executor.py +33 -11
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/error_handlers.py +1 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/job_status_poller.py +12 -11
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/strategy.py +31 -18
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/monitoring.py +27 -237
- parsl-2024.4.1/parsl/monitoring/router.py +208 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/site_tests/test_provider.py +1 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_drain.py +1 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_fuzz_zmq.py +2 -2
- parsl-2024.4.1/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +85 -0
- parsl-2024.4.1/parsl/tests/test_python_apps/test_context_manager.py +40 -0
- parsl-2024.4.1/parsl/tests/test_scaling/test_shutdown_scalein.py +78 -0
- parsl-2024.4.1/parsl/tests/test_shutdown/test_kill_monitoring.py +65 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/version.py +1 -1
- {parsl-2024.3.18 → parsl-2024.4.1/parsl.egg-info}/PKG-INFO +2 -2
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl.egg-info/SOURCES.txt +10 -5
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl.egg-info/requires.txt +2 -2
- {parsl-2024.3.18 → parsl-2024.4.1}/setup.py +1 -1
- {parsl-2024.3.18 → parsl-2024.4.1}/LICENSE +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/MANIFEST.in +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/addresses.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/app.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/bash.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/futures.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/app/python.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/benchmark/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/benchmark/perf.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/base.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/local/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/local/local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/oauth_ssh/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/oauth_ssh/oauth_ssh.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/ssh/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/ssh/ssh.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/ssh_il/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/channels/ssh_il/ssh_il.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/concurrent/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/config.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/ASPIRE1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/Azure.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/ad_hoc.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/bridges.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/cc_in2p3.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/ec2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/expanse.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/frontera.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/htex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/illinoiscluster.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/kubernetes.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/local_threads.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/midway.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/osg.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/polaris.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/stampede2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/summit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/toss3_llnl.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/vineex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/configs/wqex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/curvezmq.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/data_manager.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/file_noop.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/files.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/ftp.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/globus.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/http.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/rsync.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/data_provider/staging.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/futures.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/memoization.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/rundirs.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/states.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/dataflow/taskrecord.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/flux/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/flux/execute_parsl_task.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/flux/executor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/flux/flux_instance_manager.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/interchange.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/manager_record.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/monitoring_info.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/mpi_resource_management.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/probe.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/high_throughput/zmq_pipes.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/radical/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/radical/executor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/radical/rpex_master.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/radical/rpex_resources.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/radical/rpex_worker.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/factory.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/factory_config.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/manager.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/manager_config.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/taskvine/utils.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/threads.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/jobs/states.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/launchers/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/launchers/base.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/launchers/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/launchers/launchers.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/log_utils.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/db_manager.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/message_type.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/queries/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/queries/pandas.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/radios.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/remote.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/types.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/app.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/models.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/plots/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/app.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/dag.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/error.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/layout.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/task.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/workflow.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/utils.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/version.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/monitoring/visualization/views.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/multiprocessing.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/process_loggers.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/ad_hoc/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/ad_hoc/ad_hoc.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/aws/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/aws/aws.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/aws/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/azure/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/azure/azure.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/azure/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/base.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/cluster_provider.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/cobalt/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/cobalt/cobalt.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/cobalt/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/condor/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/condor/condor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/condor/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/googlecloud/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/googlecloud/googlecloud.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/grid_engine/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/grid_engine/grid_engine.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/grid_engine/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/kubernetes/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/kubernetes/kube.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/kubernetes/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/local/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/local/local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/lsf/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/lsf/lsf.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/lsf/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/pbspro/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/pbspro/pbspro.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/pbspro/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/slurm/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/slurm/slurm.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/slurm/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/torque/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/torque/template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/providers/torque/torque.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/py.typed +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/base.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/concretes.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/facade.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/serialize/proxystore.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/callables_helper.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/ad_hoc_cluster_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/azure_single_node.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/bluewaters.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/bridges.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/cc_in2p3.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/comet.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/cooley_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/ec2_single_node.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/ec2_spot.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/frontera.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/htex_ad_hoc_cluster.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/htex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/htex_local_alternate.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_adhoc.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_radical.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_radical_mpi.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_checkpoint_periodic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_globus.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_monitoring.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/local_threads_no_cache.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/midway.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/nscc_singapore.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/osg_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/petrelkube.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/summit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/swan_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/taskvine_ex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/theta.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/user_opts.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/configs/workqueue_ex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/conftest.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/latency.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_apps/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_channels.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_local_channel.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_scp_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_ssh_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_ssh_errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_ssh_file_transport.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_channels/test_ssh_interactive.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_stress/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/htex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_ad_hoc_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_fan_in_out_htex_remote.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_log_filter.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_oauth_ssh.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_regression_220.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_udp_simple.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/manual_tests/test_worker_count.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/htex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/local_threads.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/test_scale.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/vineex_condor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/vineex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/wqex_condor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/scaling_tests/wqex_local.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/site_tests/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/site_tests/site_config_selector.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/site_tests/test_site.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_affinity.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_concurrent.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_dynamic_executor.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_ec2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_launchers.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_local_adhoc.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_mpi/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/sites/test_worker_info.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_aalst_patterns.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_callables.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_channels/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_channels/test_large_output.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_periodic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_python_checkpoint_3.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_curvezmq.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_data → parsl-2024.4.1/parsl/tests/test_docs}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_from_slides.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_kwargs.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_workflow1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_workflow2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_docs/test_workflow4.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_docs → parsl-2024.4.1/parsl/tests/test_error_handling}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_fail.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_rand_fail.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_retries.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_error_handling → parsl-2024.4.1/parsl/tests/test_flowcontrol}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_flux.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_flowcontrol → parsl-2024.4.1/parsl/tests/test_htex}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_htex.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_manager_failure.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_missing_worker.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_worker_failure.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_htex → parsl-2024.4.1/parsl/tests/test_monitoring}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_app_names.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_monitoring → parsl-2024.4.1/parsl/tests/test_mpi_apps}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_mpi_mode_disabled.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_mpi_apps → parsl-2024.4.1/parsl/tests/test_providers}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_cobalt_deprecation_warning.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_local_provider.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_slurm_template.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_providers → parsl-2024.4.1/parsl/tests/test_python_apps}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_depfail_propagation.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_fail.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_futures.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_join.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_lifted.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_mapred.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_outputs.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_overview.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_simple.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_timeout.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_python_apps/test_type5.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_python_apps → parsl-2024.4.1/parsl/tests/test_radical}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_radical → parsl-2024.4.1/parsl/tests/test_regression}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_1480.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_1653.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_221.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_226.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_2652.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_69a.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_854.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_regression/test_98.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_regression → parsl-2024.4.1/parsl/tests/test_scaling}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_scaling/test_scale_down.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_scaling → parsl-2024.4.1/parsl/tests/test_serialization}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_basic.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_pack_resource_spec.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_serialization → parsl-2024.4.1/parsl/tests/test_shutdown}/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/staging_provider.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_1316.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_docs_1.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_docs_2.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_data → parsl-2024.4.1/parsl/tests/test_staging}/test_file.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_data → parsl-2024.4.1/parsl/tests/test_staging}/test_file_apps.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_data → parsl-2024.4.1/parsl/tests/test_staging}/test_file_staging.py +0 -0
- {parsl-2024.3.18/parsl/tests/test_data → parsl-2024.4.1/parsl/tests/test_staging}/test_output_chain_filenames.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_staging_globus.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_staging/test_staging_https.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_summary.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_thread_parallelism.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_threads/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_threads/test_configs.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_utils/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/tests/utils.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/usage_tracking/__init__.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/usage_tracking/usage.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl/utils.py +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl.egg-info/dependency_links.txt +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl.egg-info/entry_points.txt +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/parsl.egg-info/top_level.txt +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/requirements.txt +0 -0
- {parsl-2024.3.18 → parsl-2024.4.1}/setup.cfg +0 -0
@@ -1,9 +1,9 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: parsl
|
3
|
-
Version: 2024.
|
3
|
+
Version: 2024.4.1
|
4
4
|
Summary: Simple data dependent workflows in Python
|
5
5
|
Home-page: https://github.com/Parsl/parsl
|
6
|
-
Download-URL: https://github.com/Parsl/parsl/archive/2024.
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2024.04.01.tar.gz
|
7
7
|
Author: The Parsl Team
|
8
8
|
Author-email: parsl@googlegroups.com
|
9
9
|
License: Apache 2.0
|
@@ -97,6 +97,7 @@ For Developers
|
|
97
97
|
|
98
98
|
2. Build and Test::
|
99
99
|
|
100
|
+
$ cd parsl # navigate to the root directory of the project
|
100
101
|
$ make # show all available makefile targets
|
101
102
|
$ make virtualenv # create a virtual environment
|
102
103
|
$ source .venv/bin/activate # activate the virtual environment
|
@@ -119,7 +120,7 @@ Parsl is supported in Python 3.8+. Requirements can be found `here <requirements
|
|
119
120
|
Code of Conduct
|
120
121
|
===============
|
121
122
|
|
122
|
-
Parsl seeks to foster an open and welcoming environment - Please see the `Parsl Code of Conduct <https://github.com/Parsl/parsl/blob/master/
|
123
|
+
Parsl seeks to foster an open and welcoming environment - Please see the `Parsl Code of Conduct <https://github.com/Parsl/parsl/blob/master/CODE_OF_CONDUCT.md>`_ for more details.
|
123
124
|
|
124
125
|
Contributing
|
125
126
|
============
|
@@ -34,12 +34,12 @@ from parsl.dataflow.states import States, FINAL_STATES, FINAL_FAILURE_STATES
|
|
34
34
|
from parsl.dataflow.taskrecord import TaskRecord
|
35
35
|
from parsl.errors import ConfigurationError, InternalConsistencyError, NoDataFlowKernelError
|
36
36
|
from parsl.jobs.job_status_poller import JobStatusPoller
|
37
|
-
from parsl.jobs.states import JobStatus, JobState
|
38
37
|
from parsl.usage_tracking.usage import UsageTracker
|
39
38
|
from parsl.executors.base import ParslExecutor
|
40
39
|
from parsl.executors.status_handling import BlockProviderExecutor
|
41
40
|
from parsl.executors.threads import ThreadPoolExecutor
|
42
41
|
from parsl.monitoring import MonitoringHub
|
42
|
+
from parsl.monitoring.remote import monitor_wrapper
|
43
43
|
from parsl.process_loggers import wrap_with_logs
|
44
44
|
from parsl.providers.base import ExecutionProvider
|
45
45
|
from parsl.utils import get_version, get_std_fname_mode, get_all_checkpoints, Timer
|
@@ -108,12 +108,12 @@ class DataFlowKernel:
|
|
108
108
|
|
109
109
|
# hub address and port for interchange to connect
|
110
110
|
self.hub_address = None # type: Optional[str]
|
111
|
-
self.
|
111
|
+
self.hub_zmq_port = None # type: Optional[int]
|
112
112
|
if self.monitoring:
|
113
113
|
if self.monitoring.logdir is None:
|
114
114
|
self.monitoring.logdir = self.run_dir
|
115
115
|
self.hub_address = self.monitoring.hub_address
|
116
|
-
self.
|
116
|
+
self.hub_zmq_port = self.monitoring.start(self.run_id, self.run_dir, self.config.run_dir)
|
117
117
|
|
118
118
|
self.time_began = datetime.datetime.now()
|
119
119
|
self.time_completed: Optional[datetime.datetime] = None
|
@@ -206,6 +206,13 @@ class DataFlowKernel:
|
|
206
206
|
|
207
207
|
atexit.register(self.atexit_cleanup)
|
208
208
|
|
209
|
+
def __enter__(self):
|
210
|
+
return self
|
211
|
+
|
212
|
+
def __exit__(self, exc_type, exc_value, traceback):
|
213
|
+
logger.debug("Exiting the context manager, calling cleanup for DFK")
|
214
|
+
self.cleanup()
|
215
|
+
|
209
216
|
def _send_task_log_info(self, task_record: TaskRecord) -> None:
|
210
217
|
if self.monitoring:
|
211
218
|
task_log_info = self._create_task_log_info(task_record)
|
@@ -707,14 +714,14 @@ class DataFlowKernel:
|
|
707
714
|
|
708
715
|
if self.monitoring is not None and self.monitoring.resource_monitoring_enabled:
|
709
716
|
wrapper_logging_level = logging.DEBUG if self.monitoring.monitoring_debug else logging.INFO
|
710
|
-
(function, args, kwargs) =
|
711
|
-
|
712
|
-
|
713
|
-
|
714
|
-
|
715
|
-
|
716
|
-
|
717
|
-
|
717
|
+
(function, args, kwargs) = monitor_wrapper(function, args, kwargs, try_id, task_id,
|
718
|
+
self.monitoring.monitoring_hub_url,
|
719
|
+
self.run_id,
|
720
|
+
wrapper_logging_level,
|
721
|
+
self.monitoring.resource_monitoring_interval,
|
722
|
+
executor.radio_mode,
|
723
|
+
executor.monitor_resources(),
|
724
|
+
self.run_dir)
|
718
725
|
|
719
726
|
with self.submitter_lock:
|
720
727
|
exec_fu = executor.submit(function, task_record['resource_specification'], *args, **kwargs)
|
@@ -1115,12 +1122,12 @@ class DataFlowKernel:
|
|
1115
1122
|
|
1116
1123
|
channel.makedirs(channel.script_dir, exist_ok=True)
|
1117
1124
|
|
1118
|
-
def add_executors(self, executors):
|
1125
|
+
def add_executors(self, executors: Sequence[ParslExecutor]) -> None:
|
1119
1126
|
for executor in executors:
|
1120
1127
|
executor.run_id = self.run_id
|
1121
1128
|
executor.run_dir = self.run_dir
|
1122
1129
|
executor.hub_address = self.hub_address
|
1123
|
-
executor.hub_port = self.
|
1130
|
+
executor.hub_port = self.hub_zmq_port
|
1124
1131
|
if hasattr(executor, 'provider'):
|
1125
1132
|
if hasattr(executor.provider, 'script_dir'):
|
1126
1133
|
executor.provider.script_dir = os.path.join(self.run_dir, 'submit_scripts')
|
@@ -1134,14 +1141,7 @@ class DataFlowKernel:
|
|
1134
1141
|
self._create_remote_dirs_over_channel(executor.provider, executor.provider.channel)
|
1135
1142
|
|
1136
1143
|
self.executors[executor.label] = executor
|
1137
|
-
|
1138
|
-
if self.monitoring and block_ids:
|
1139
|
-
new_status = {}
|
1140
|
-
for bid in block_ids:
|
1141
|
-
new_status[bid] = JobStatus(JobState.PENDING)
|
1142
|
-
msg = executor.create_monitoring_info(new_status)
|
1143
|
-
logger.debug("Sending monitoring message {} to hub from DFK".format(msg))
|
1144
|
-
self.monitoring.send(MessageType.BLOCK_INFO, msg)
|
1144
|
+
executor.start()
|
1145
1145
|
block_executors = [e for e in executors if isinstance(e, BlockProviderExecutor)]
|
1146
1146
|
self.job_status_poller.add_executors(block_executors)
|
1147
1147
|
|
@@ -1216,22 +1216,21 @@ class DataFlowKernel:
|
|
1216
1216
|
|
1217
1217
|
logger.info("Scaling in and shutting down executors")
|
1218
1218
|
|
1219
|
+
for ef in self.job_status_poller._executor_facades:
|
1220
|
+
if not ef.executor.bad_state_is_set:
|
1221
|
+
logger.info(f"Scaling in executor {ef.executor.label}")
|
1222
|
+
|
1223
|
+
# this code needs to be at least as many blocks as need
|
1224
|
+
# cancelling, but it is safe to be more, as the scaling
|
1225
|
+
# code will cope with being asked to cancel more blocks
|
1226
|
+
# than exist.
|
1227
|
+
block_count = len(ef.status)
|
1228
|
+
ef.scale_in(block_count)
|
1229
|
+
|
1230
|
+
else: # and bad_state_is_set
|
1231
|
+
logger.warning(f"Not scaling in executor {ef.executor.label} because it is in bad state")
|
1232
|
+
|
1219
1233
|
for executor in self.executors.values():
|
1220
|
-
if isinstance(executor, BlockProviderExecutor):
|
1221
|
-
if not executor.bad_state_is_set:
|
1222
|
-
logger.info(f"Scaling in executor {executor.label}")
|
1223
|
-
if executor.provider:
|
1224
|
-
job_ids = executor.provider.resources.keys()
|
1225
|
-
block_ids = executor.scale_in(len(job_ids))
|
1226
|
-
if self.monitoring and block_ids:
|
1227
|
-
new_status = {}
|
1228
|
-
for bid in block_ids:
|
1229
|
-
new_status[bid] = JobStatus(JobState.CANCELLED)
|
1230
|
-
msg = executor.create_monitoring_info(new_status)
|
1231
|
-
logger.debug("Sending message {} to hub from DFK".format(msg))
|
1232
|
-
self.monitoring.send(MessageType.BLOCK_INFO, msg)
|
1233
|
-
else: # and bad_state_is_set
|
1234
|
-
logger.warning(f"Not shutting down executor {executor.label} because it is in bad state")
|
1235
1234
|
logger.info(f"Shutting down executor {executor.label}")
|
1236
1235
|
executor.shutdown()
|
1237
1236
|
logger.info(f"Shut down executor {executor.label}")
|
@@ -53,7 +53,7 @@ class ParslExecutor(metaclass=ABCMeta):
|
|
53
53
|
return False
|
54
54
|
|
55
55
|
@abstractmethod
|
56
|
-
def start(self) ->
|
56
|
+
def start(self) -> None:
|
57
57
|
"""Start the executor.
|
58
58
|
|
59
59
|
Any spin-up operations (for example: starting thread pools) should be performed here.
|
@@ -106,6 +106,16 @@ class ParslExecutor(metaclass=ABCMeta):
|
|
106
106
|
def run_dir(self, value: str) -> None:
|
107
107
|
self._run_dir = value
|
108
108
|
|
109
|
+
@property
|
110
|
+
def run_id(self) -> Optional[str]:
|
111
|
+
"""UUID for the enclosing DFK.
|
112
|
+
"""
|
113
|
+
return self._run_id
|
114
|
+
|
115
|
+
@run_id.setter
|
116
|
+
def run_id(self, value: Optional[str]) -> None:
|
117
|
+
self._run_id = value
|
118
|
+
|
109
119
|
@property
|
110
120
|
def hub_address(self) -> Optional[str]:
|
111
121
|
"""Address to the Hub for monitoring.
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import typing
|
2
|
+
from collections import defaultdict
|
2
3
|
from concurrent.futures import Future
|
3
4
|
import typeguard
|
4
5
|
import logging
|
@@ -400,16 +401,6 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin):
|
|
400
401
|
|
401
402
|
logger.debug("Starting HighThroughputExecutor with provider:\n%s", self.provider)
|
402
403
|
|
403
|
-
# TODO: why is this a provider property?
|
404
|
-
block_ids = []
|
405
|
-
if hasattr(self.provider, 'init_blocks'):
|
406
|
-
try:
|
407
|
-
block_ids = self.scale_out(blocks=self.provider.init_blocks)
|
408
|
-
except Exception as e:
|
409
|
-
logger.error("Scaling out failed: {}".format(e))
|
410
|
-
raise e
|
411
|
-
return block_ids
|
412
|
-
|
413
404
|
def start(self):
|
414
405
|
"""Create the Interchange process and connect to it.
|
415
406
|
"""
|
@@ -439,8 +430,7 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin):
|
|
439
430
|
|
440
431
|
logger.debug("Created management thread: {}".format(self._queue_management_thread))
|
441
432
|
|
442
|
-
|
443
|
-
return block_ids
|
433
|
+
self.initialize_scaling()
|
444
434
|
|
445
435
|
@wrap_with_logs
|
446
436
|
def _queue_management_worker(self):
|
@@ -698,7 +688,7 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin):
|
|
698
688
|
d['status'] = s.status_name
|
699
689
|
d['timestamp'] = datetime.datetime.now()
|
700
690
|
d['executor_label'] = self.label
|
701
|
-
d['job_id'] = self.
|
691
|
+
d['job_id'] = self.blocks_to_job_id.get(bid, None)
|
702
692
|
d['block_id'] = bid
|
703
693
|
msg.append(d)
|
704
694
|
return msg
|
@@ -741,13 +731,11 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin):
|
|
741
731
|
idle: float # shortest idle time of any manager in this block
|
742
732
|
|
743
733
|
managers = self.connected_managers()
|
744
|
-
block_info: Dict[str, BlockInfo] =
|
734
|
+
block_info: Dict[str, BlockInfo] = defaultdict(lambda: BlockInfo(tasks=0, idle=float('inf')))
|
745
735
|
for manager in managers:
|
746
736
|
if not manager['active']:
|
747
737
|
continue
|
748
738
|
b_id = manager['block_id']
|
749
|
-
if b_id not in block_info:
|
750
|
-
block_info[b_id] = BlockInfo(tasks=0, idle=float('inf'))
|
751
739
|
block_info[b_id].tasks += manager['tasks']
|
752
740
|
block_info[b_id].idle = min(block_info[b_id].idle, manager['idle_duration'])
|
753
741
|
|
@@ -779,14 +767,14 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin):
|
|
779
767
|
|
780
768
|
# Now kill via provider
|
781
769
|
# Potential issue with multiple threads trying to remove the same blocks
|
782
|
-
to_kill = [self.
|
770
|
+
to_kill = [self.blocks_to_job_id[bid] for bid in block_ids_to_kill if bid in self.blocks_to_job_id]
|
783
771
|
|
784
772
|
r = self.provider.cancel(to_kill)
|
785
773
|
job_ids = self._filter_scale_in_ids(to_kill, r)
|
786
774
|
|
787
|
-
# to_kill block_ids are fetched from self.
|
788
|
-
# If a block_id is in self.
|
789
|
-
block_ids_killed = [self.
|
775
|
+
# to_kill block_ids are fetched from self.blocks_to_job_id
|
776
|
+
# If a block_id is in self.blocks_to_job_id, it must exist in self.job_ids_to_block
|
777
|
+
block_ids_killed = [self.job_ids_to_block[jid] for jid in job_ids]
|
790
778
|
|
791
779
|
return block_ids_killed
|
792
780
|
|
@@ -335,14 +335,17 @@ class Manager:
|
|
335
335
|
self.heartbeat_to_incoming()
|
336
336
|
last_beat = time.time()
|
337
337
|
|
338
|
-
if
|
338
|
+
if time.time() > self.drain_time:
|
339
339
|
logger.info("Requesting drain")
|
340
340
|
self.drain_to_incoming()
|
341
|
-
self.drain_time = None
|
342
341
|
# This will start the pool draining...
|
343
342
|
# Drained exit behaviour does not happen here. It will be
|
344
343
|
# driven by the interchange sending a DRAINED_CODE message.
|
345
344
|
|
345
|
+
# now set drain time to the far future so we don't send a drain
|
346
|
+
# message every iteration.
|
347
|
+
self.drain_time = float('inf')
|
348
|
+
|
346
349
|
poll_duration_s = max(0, next_interesting_event_time - time.time())
|
347
350
|
socks = dict(poller.poll(timeout=poll_duration_s * 1000))
|
348
351
|
|
@@ -61,15 +61,15 @@ class BlockProviderExecutor(ParslExecutor):
|
|
61
61
|
# errors can happen during the submit call to the provider; this is used
|
62
62
|
# to keep track of such errors so that they can be handled in one place
|
63
63
|
# together with errors reported by status()
|
64
|
-
self._simulated_status: Dict[
|
64
|
+
self._simulated_status: Dict[str, JobStatus] = {}
|
65
65
|
self._executor_bad_state = threading.Event()
|
66
66
|
self._executor_exception: Optional[Exception] = None
|
67
67
|
|
68
68
|
self._block_id_counter = AtomicIDCounter()
|
69
69
|
|
70
70
|
self._tasks = {} # type: Dict[object, Future]
|
71
|
-
self.
|
72
|
-
self.
|
71
|
+
self.blocks_to_job_id = {} # type: Dict[str, str]
|
72
|
+
self.job_ids_to_block = {} # type: Dict[str, str]
|
73
73
|
|
74
74
|
def _make_status_dict(self, block_ids: List[str], status_list: List[JobStatus]) -> Dict[str, JobStatus]:
|
75
75
|
"""Given a list of block ids and a list of corresponding status strings,
|
@@ -102,13 +102,10 @@ class BlockProviderExecutor(ParslExecutor):
|
|
102
102
|
else:
|
103
103
|
return self._provider.status_polling_interval
|
104
104
|
|
105
|
-
def _fail_job_async(self, block_id:
|
105
|
+
def _fail_job_async(self, block_id: str, message: str):
|
106
106
|
"""Marks a job that has failed to start but would not otherwise be included in status()
|
107
107
|
as failed and report it in status()
|
108
108
|
"""
|
109
|
-
if block_id is None:
|
110
|
-
block_id = str(self._block_id_counter.get_id())
|
111
|
-
logger.info(f"Allocated block ID {block_id} for simulated failure")
|
112
109
|
self._simulated_status[block_id] = JobStatus(JobState.FAILED, message)
|
113
110
|
|
114
111
|
@abstractproperty
|
@@ -197,8 +194,8 @@ class BlockProviderExecutor(ParslExecutor):
|
|
197
194
|
logger.info(f"Allocated block ID {block_id}")
|
198
195
|
try:
|
199
196
|
job_id = self._launch_block(block_id)
|
200
|
-
self.
|
201
|
-
self.
|
197
|
+
self.blocks_to_job_id[block_id] = job_id
|
198
|
+
self.job_ids_to_block[job_id] = block_id
|
202
199
|
block_ids.append(block_id)
|
203
200
|
except Exception as ex:
|
204
201
|
self._fail_job_async(block_id,
|
@@ -211,10 +208,6 @@ class BlockProviderExecutor(ParslExecutor):
|
|
211
208
|
|
212
209
|
Cause the executor to reduce the number of blocks by count.
|
213
210
|
|
214
|
-
We should have the scale in method simply take resource object
|
215
|
-
which will have the scaling methods, scale_in itself should be a coroutine, since
|
216
|
-
scaling tasks can be slow.
|
217
|
-
|
218
211
|
:return: A list of block ids corresponding to the blocks that were removed.
|
219
212
|
"""
|
220
213
|
pass
|
@@ -239,10 +232,10 @@ class BlockProviderExecutor(ParslExecutor):
|
|
239
232
|
# Not using self.blocks.keys() and self.blocks.values() simultaneously
|
240
233
|
# The dictionary may be changed during invoking this function
|
241
234
|
# As scale_in and scale_out are invoked in multiple threads
|
242
|
-
block_ids = list(self.
|
235
|
+
block_ids = list(self.blocks_to_job_id.keys())
|
243
236
|
job_ids = [] # types: List[Any]
|
244
237
|
for bid in block_ids:
|
245
|
-
job_ids.append(self.
|
238
|
+
job_ids.append(self.blocks_to_job_id[bid])
|
246
239
|
return block_ids, job_ids
|
247
240
|
|
248
241
|
@abstractproperty
|
@@ -4,6 +4,7 @@ high-throughput system for delegating Parsl tasks to thousands of remote machine
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
# Import Python built-in libraries
|
7
|
+
import atexit
|
7
8
|
import threading
|
8
9
|
import multiprocessing
|
9
10
|
import logging
|
@@ -171,7 +172,7 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
171
172
|
# Path to directory that holds all tasks' data and results.
|
172
173
|
self._function_data_dir = ""
|
173
174
|
|
174
|
-
#
|
175
|
+
# Helper scripts to prepare package tarballs for Parsl apps
|
175
176
|
self._package_analyze_script = shutil.which("poncho_package_analyze")
|
176
177
|
self._package_create_script = shutil.which("poncho_package_create")
|
177
178
|
if self._package_analyze_script is None or self._package_create_script is None:
|
@@ -179,6 +180,24 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
179
180
|
else:
|
180
181
|
self._poncho_available = True
|
181
182
|
|
183
|
+
# Register atexit handler to cleanup when Python shuts down
|
184
|
+
atexit.register(self.atexit_cleanup)
|
185
|
+
|
186
|
+
# Attribute indicating whether this executor was started to shut it down properly.
|
187
|
+
# This safeguards cases where an object of this executor is created but
|
188
|
+
# the executor never starts, so it shouldn't be shutdowned.
|
189
|
+
self._is_started = False
|
190
|
+
|
191
|
+
# Attribute indicating whether this executor was shutdown before.
|
192
|
+
# This safeguards cases where this object is automatically shut down (e.g.,
|
193
|
+
# via atexit) and the user also explicitly calls shut down. While this is
|
194
|
+
# permitted, the effect of an executor shutdown should happen only once.
|
195
|
+
self._is_shutdown = False
|
196
|
+
|
197
|
+
def atexit_cleanup(self):
|
198
|
+
# Calls this executor's shutdown method upon Python exiting the process.
|
199
|
+
self.shutdown()
|
200
|
+
|
182
201
|
def _get_launch_command(self, block_id):
|
183
202
|
# Implements BlockProviderExecutor's abstract method.
|
184
203
|
# This executor uses different terminology for worker/launch
|
@@ -238,6 +257,9 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
238
257
|
retrieve Parsl tasks within the TaskVine system.
|
239
258
|
"""
|
240
259
|
|
260
|
+
# Mark this executor object as started
|
261
|
+
self._is_started = True
|
262
|
+
|
241
263
|
# Synchronize connection and communication settings between the manager and factory
|
242
264
|
self.__synchronize_manager_factory_comm_settings()
|
243
265
|
|
@@ -564,13 +586,6 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
564
586
|
self._worker_command = self._construct_worker_command()
|
565
587
|
self._patch_providers()
|
566
588
|
|
567
|
-
if hasattr(self.provider, 'init_blocks'):
|
568
|
-
try:
|
569
|
-
self.scale_out(blocks=self.provider.init_blocks)
|
570
|
-
except Exception as e:
|
571
|
-
logger.error("Initial block scaling out failed: {}".format(e))
|
572
|
-
raise e
|
573
|
-
|
574
589
|
@property
|
575
590
|
def outstanding(self) -> int:
|
576
591
|
"""Count the number of outstanding tasks."""
|
@@ -585,8 +600,8 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
585
600
|
"""Scale in method. Cancel a given number of blocks
|
586
601
|
"""
|
587
602
|
# Obtain list of blocks to kill
|
588
|
-
to_kill = list(self.
|
589
|
-
kill_ids = [self.
|
603
|
+
to_kill = list(self.blocks_to_job_id.keys())[:count]
|
604
|
+
kill_ids = [self.blocks_to_job_id[block] for block in to_kill]
|
590
605
|
|
591
606
|
# Cancel the blocks provisioned
|
592
607
|
if self.provider:
|
@@ -598,11 +613,19 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
598
613
|
"""Shutdown the executor. Sets flag to cancel the submit process and
|
599
614
|
collector thread, which shuts down the TaskVine system submission.
|
600
615
|
"""
|
616
|
+
if not self._is_started:
|
617
|
+
# Don't shutdown if the executor never starts.
|
618
|
+
return
|
619
|
+
|
620
|
+
if self._is_shutdown:
|
621
|
+
# Don't shutdown this executor again.
|
622
|
+
return
|
623
|
+
|
601
624
|
logger.debug("TaskVine shutdown started")
|
602
625
|
self._should_stop.set()
|
603
626
|
|
604
627
|
# Remove the workers that are still going
|
605
|
-
kill_ids = [self.
|
628
|
+
kill_ids = [self.blocks_to_job_id[block] for block in self.blocks_to_job_id.keys()]
|
606
629
|
if self.provider:
|
607
630
|
logger.debug("Cancelling blocks")
|
608
631
|
self.provider.cancel(kill_ids)
|
@@ -616,6 +639,7 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
616
639
|
logger.debug("Joining on factory process")
|
617
640
|
self._factory_process.join()
|
618
641
|
|
642
|
+
self._is_shutdown = True
|
619
643
|
logger.debug("TaskVine shutdown completed")
|
620
644
|
|
621
645
|
@wrap_with_logs
|
@@ -3,6 +3,7 @@ Cooperative Computing Lab (CCL) at Notre Dame to provide a fault-tolerant,
|
|
3
3
|
high-throughput system for delegating Parsl tasks to thousands of remote machines
|
4
4
|
"""
|
5
5
|
|
6
|
+
import atexit
|
6
7
|
import threading
|
7
8
|
import multiprocessing
|
8
9
|
import logging
|
@@ -254,7 +255,6 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
254
255
|
self.label = label
|
255
256
|
self.task_queue = multiprocessing.Queue() # type: multiprocessing.Queue
|
256
257
|
self.collector_queue = multiprocessing.Queue() # type: multiprocessing.Queue
|
257
|
-
self.blocks = {} # type: Dict[str, str]
|
258
258
|
self.address = address
|
259
259
|
self.port = port
|
260
260
|
self.executor_task_counter = -1
|
@@ -298,6 +298,24 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
298
298
|
if self.init_command != "":
|
299
299
|
self.launch_cmd = self.init_command + "; " + self.launch_cmd
|
300
300
|
|
301
|
+
# register atexit handler to cleanup when Python shuts down
|
302
|
+
atexit.register(self.atexit_cleanup)
|
303
|
+
|
304
|
+
# Attribute indicating whether this executor was started to shut it down properly.
|
305
|
+
# This safeguards cases where an object of this executor is created but
|
306
|
+
# the executor never starts, so it shouldn't be shutdowned.
|
307
|
+
self.is_started = False
|
308
|
+
|
309
|
+
# Attribute indicating whether this executor was shutdown before.
|
310
|
+
# This safeguards cases where this object is automatically shut down (e.g.,
|
311
|
+
# via atexit) and the user also explicitly calls shut down. While this is
|
312
|
+
# permitted, the effect of an executor shutdown should happen only once.
|
313
|
+
self.is_shutdown = False
|
314
|
+
|
315
|
+
def atexit_cleanup(self):
|
316
|
+
# Calls this executor's shutdown method upon Python exiting the process.
|
317
|
+
self.shutdown()
|
318
|
+
|
301
319
|
def _get_launch_command(self, block_id):
|
302
320
|
# this executor uses different terminology for worker/launch
|
303
321
|
# commands than in htex
|
@@ -307,6 +325,8 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
307
325
|
"""Create submit process and collector thread to create, send, and
|
308
326
|
retrieve Parsl tasks within the Work Queue system.
|
309
327
|
"""
|
328
|
+
# Mark this executor object as started
|
329
|
+
self.is_started = True
|
310
330
|
self.tasks_lock = threading.Lock()
|
311
331
|
|
312
332
|
# Create directories for data and results
|
@@ -654,13 +674,6 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
654
674
|
self.worker_command = self._construct_worker_command()
|
655
675
|
self._patch_providers()
|
656
676
|
|
657
|
-
if hasattr(self.provider, 'init_blocks'):
|
658
|
-
try:
|
659
|
-
self.scale_out(blocks=self.provider.init_blocks)
|
660
|
-
except Exception as e:
|
661
|
-
logger.error("Initial block scaling out failed: {}".format(e))
|
662
|
-
raise e
|
663
|
-
|
664
677
|
@property
|
665
678
|
def outstanding(self) -> int:
|
666
679
|
"""Count the number of outstanding tasks. This is inefficiently
|
@@ -682,8 +695,8 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
682
695
|
"""Scale in method.
|
683
696
|
"""
|
684
697
|
# Obtain list of blocks to kill
|
685
|
-
to_kill = list(self.
|
686
|
-
kill_ids = [self.
|
698
|
+
to_kill = list(self.blocks_to_job_id.keys())[:count]
|
699
|
+
kill_ids = [self.blocks_to_job_id[block] for block in to_kill]
|
687
700
|
|
688
701
|
# Cancel the blocks provisioned
|
689
702
|
if self.provider:
|
@@ -695,11 +708,19 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
695
708
|
"""Shutdown the executor. Sets flag to cancel the submit process and
|
696
709
|
collector thread, which shuts down the Work Queue system submission.
|
697
710
|
"""
|
711
|
+
if not self.is_started:
|
712
|
+
# Don't shutdown if the executor never starts.
|
713
|
+
return
|
714
|
+
|
715
|
+
if self.is_shutdown:
|
716
|
+
# Don't shutdown this executor again.
|
717
|
+
return
|
718
|
+
|
698
719
|
logger.debug("Work Queue shutdown started")
|
699
720
|
self.should_stop.value = True
|
700
721
|
|
701
722
|
# Remove the workers that are still going
|
702
|
-
kill_ids = [self.
|
723
|
+
kill_ids = [self.blocks_to_job_id[block] for block in self.blocks_to_job_id.keys()]
|
703
724
|
if self.provider:
|
704
725
|
logger.debug("Cancelling blocks")
|
705
726
|
self.provider.cancel(kill_ids)
|
@@ -709,6 +730,7 @@ class WorkQueueExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
709
730
|
logger.debug("Joining on collector thread")
|
710
731
|
self.collector_thread.join()
|
711
732
|
|
733
|
+
self.is_shutdown = True
|
712
734
|
logger.debug("Work Queue shutdown completed")
|
713
735
|
|
714
736
|
@wrap_with_logs
|
@@ -20,7 +20,7 @@ def simple_error_handler(executor: status_handling.BlockProviderExecutor, status
|
|
20
20
|
executor.set_bad_state_and_fail_all(_get_error(status))
|
21
21
|
|
22
22
|
|
23
|
-
def windowed_error_handler(executor: status_handling.BlockProviderExecutor, status: Dict[str, JobStatus], threshold: int = 3):
|
23
|
+
def windowed_error_handler(executor: status_handling.BlockProviderExecutor, status: Dict[str, JobStatus], threshold: int = 3) -> None:
|
24
24
|
sorted_status = [(key, status[key]) for key in sorted(status, key=lambda x: int(x))]
|
25
25
|
current_window = dict(sorted_status[-threshold:])
|
26
26
|
total, failed = _count_jobs(current_window)
|
@@ -16,20 +16,21 @@ from parsl.utils import Timer
|
|
16
16
|
logger = logging.getLogger(__name__)
|
17
17
|
|
18
18
|
|
19
|
-
class
|
19
|
+
class PolledExecutorFacade:
|
20
20
|
def __init__(self, executor: BlockProviderExecutor, dfk: Optional["parsl.dataflow.dflow.DataFlowKernel"] = None):
|
21
21
|
self._executor = executor
|
22
22
|
self._dfk = dfk
|
23
23
|
self._interval = executor.status_polling_interval
|
24
24
|
self._last_poll_time = 0.0
|
25
25
|
self._status = {} # type: Dict[str, JobStatus]
|
26
|
+
self.first = True
|
26
27
|
|
27
28
|
# Create a ZMQ channel to send poll status to monitoring
|
28
29
|
self.monitoring_enabled = False
|
29
30
|
if self._dfk and self._dfk.monitoring is not None:
|
30
31
|
self.monitoring_enabled = True
|
31
32
|
hub_address = self._dfk.hub_address
|
32
|
-
hub_port = self._dfk.
|
33
|
+
hub_port = self._dfk.hub_zmq_port
|
33
34
|
context = zmq.Context()
|
34
35
|
self.hub_channel = context.socket(zmq.DEALER)
|
35
36
|
self.hub_channel.set_hwm(0)
|
@@ -72,7 +73,7 @@ class PollItem:
|
|
72
73
|
def executor(self) -> BlockProviderExecutor:
|
73
74
|
return self._executor
|
74
75
|
|
75
|
-
def scale_in(self, n, max_idletime=None):
|
76
|
+
def scale_in(self, n: int, max_idletime: Optional[float] = None) -> List[str]:
|
76
77
|
|
77
78
|
if max_idletime is None:
|
78
79
|
block_ids = self._executor.scale_in(n)
|
@@ -82,7 +83,7 @@ class PollItem:
|
|
82
83
|
# scale_in method really does come from HighThroughputExecutor,
|
83
84
|
# and so does have an extra max_idletime parameter not present
|
84
85
|
# in the executor interface.
|
85
|
-
block_ids = self._executor.scale_in(n, max_idletime=max_idletime)
|
86
|
+
block_ids = self._executor.scale_in(n, max_idletime=max_idletime) # type: ignore[call-arg]
|
86
87
|
if block_ids is not None:
|
87
88
|
new_status = {}
|
88
89
|
for block_id in block_ids:
|
@@ -91,7 +92,7 @@ class PollItem:
|
|
91
92
|
self.send_monitoring_info(new_status)
|
92
93
|
return block_ids
|
93
94
|
|
94
|
-
def scale_out(self, n):
|
95
|
+
def scale_out(self, n: int) -> List[str]:
|
95
96
|
block_ids = self._executor.scale_out(n)
|
96
97
|
if block_ids is not None:
|
97
98
|
new_status = {}
|
@@ -109,7 +110,7 @@ class JobStatusPoller(Timer):
|
|
109
110
|
def __init__(self, *, strategy: Optional[str], max_idletime: float,
|
110
111
|
strategy_period: Union[float, int],
|
111
112
|
dfk: Optional["parsl.dataflow.dflow.DataFlowKernel"] = None) -> None:
|
112
|
-
self.
|
113
|
+
self._executor_facades = [] # type: List[PolledExecutorFacade]
|
113
114
|
self.dfk = dfk
|
114
115
|
self._strategy = Strategy(strategy=strategy,
|
115
116
|
max_idletime=max_idletime)
|
@@ -117,21 +118,21 @@ class JobStatusPoller(Timer):
|
|
117
118
|
|
118
119
|
def poll(self) -> None:
|
119
120
|
self._update_state()
|
120
|
-
self._run_error_handlers(self.
|
121
|
-
self._strategy.strategize(self.
|
121
|
+
self._run_error_handlers(self._executor_facades)
|
122
|
+
self._strategy.strategize(self._executor_facades)
|
122
123
|
|
123
|
-
def _run_error_handlers(self, status: List[
|
124
|
+
def _run_error_handlers(self, status: List[PolledExecutorFacade]) -> None:
|
124
125
|
for es in status:
|
125
126
|
es.executor.handle_errors(es.status)
|
126
127
|
|
127
128
|
def _update_state(self) -> None:
|
128
129
|
now = time.time()
|
129
|
-
for item in self.
|
130
|
+
for item in self._executor_facades:
|
130
131
|
item.poll(now)
|
131
132
|
|
132
133
|
def add_executors(self, executors: Sequence[BlockProviderExecutor]) -> None:
|
133
134
|
for executor in executors:
|
134
135
|
if executor.status_polling_interval > 0:
|
135
136
|
logger.debug("Adding executor {}".format(executor.label))
|
136
|
-
self.
|
137
|
+
self._executor_facades.append(PolledExecutorFacade(executor, self.dfk))
|
137
138
|
self._strategy.add_executors(executors)
|