parsl 2025.9.22__tar.gz → 2025.9.29__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.
Potentially problematic release.
This version of parsl might be problematic. Click here for more details.
- {parsl-2025.9.22/parsl.egg-info → parsl-2025.9.29}/PKG-INFO +3 -4
- {parsl-2025.9.22 → parsl-2025.9.29}/README.rst +5 -2
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/benchmark/perf.py +22 -9
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/dflow.py +2 -3
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/memoization.py +9 -19
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/executor.py +10 -7
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/interchange.py +4 -3
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/mpi_executor.py +1 -2
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/mpi_resource_management.py +3 -4
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/process_worker_pool.py +10 -2
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/zmq_pipes.py +7 -24
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/executor.py +5 -1
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/taskvine_ex.py +1 -1
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_periodic.py +15 -9
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_interchange_exit_bad_registration.py +0 -1
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +12 -12
- parsl-2025.9.29/parsl/tests/test_regression/test_3874.py +47 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/version.py +1 -1
- {parsl-2025.9.22 → parsl-2025.9.29/parsl.egg-info}/PKG-INFO +3 -4
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl.egg-info/SOURCES.txt +1 -1
- {parsl-2025.9.22 → parsl-2025.9.29}/setup.py +1 -2
- parsl-2025.9.22/parsl/tests/configs/local_threads_checkpoint_periodic.py +0 -11
- {parsl-2025.9.22 → parsl-2025.9.29}/LICENSE +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/MANIFEST.in +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/addresses.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/app.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/bash.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/futures.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/app/python.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/benchmark/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/concurrent/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/config.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/ASPIRE1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/Azure.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/anvil.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/bridges.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/cc_in2p3.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/delta.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/ec2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/expanse.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/frontera.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/gc_multisite.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/gc_tutorial.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/htex_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/illinoiscluster.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/improv.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/kubernetes.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/local_threads.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/midway.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/osg.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/polaris.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/stampede2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/summit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/toss3_llnl.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/vineex_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/configs/wqex_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/curvezmq.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/data_manager.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/file_noop.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/files.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/ftp.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/globus.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/http.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/rsync.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/staging.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/data_provider/zip.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/dependency_resolvers.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/futures.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/rundirs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/states.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/dataflow/taskrecord.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/base.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/execute_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/flux/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/flux/execute_parsl_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/flux/executor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/flux/flux_instance_manager.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/globus_compute.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/manager_record.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/manager_selector.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/monitoring_info.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/probe.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/radical/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/radical/executor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/radical/rpex_resources.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/radical/rpex_worker.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/status_handling.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/factory.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/factory_config.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/manager.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/manager_config.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/taskvine/utils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/threads.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/executor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/error_handlers.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/job_status_poller.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/states.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/jobs/strategy.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/launchers/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/launchers/base.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/launchers/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/launchers/launchers.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/log_utils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/db_manager.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/message_type.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/monitoring.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/queries/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/queries/pandas.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/base.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/filesystem.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/filesystem_router.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/htex.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/multiprocessing.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/udp.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/udp_router.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/zmq.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/radios/zmq_router.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/remote.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/types.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/app.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/models.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/plots/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/app.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/dag.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/error.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/layout.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/task.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/workflow.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/utils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/version.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/monitoring/visualization/views.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/multiprocessing.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/process_loggers.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/aws/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/aws/aws.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/aws/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/azure/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/azure/azure.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/azure/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/base.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/cluster_provider.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/condor/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/condor/condor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/condor/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/googlecloud/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/googlecloud/googlecloud.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/grid_engine/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/grid_engine/grid_engine.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/grid_engine/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/kubernetes/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/kubernetes/kube.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/kubernetes/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/local/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/local/local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/lsf/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/lsf/lsf.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/lsf/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/pbspro/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/pbspro/pbspro.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/pbspro/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/slurm/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/slurm/slurm.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/slurm/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/torque/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/torque/template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/providers/torque/torque.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/py.typed +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/base.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/concretes.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/facade.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/serialize/proxystore.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/callables_helper.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/azure_single_node.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/bluewaters.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/bridges.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/cc_in2p3.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/comet.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/ec2_single_node.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/ec2_spot.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/flux_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/frontera.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/globus_compute.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/htex_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/htex_local_alternate.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_radical.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_radical_mpi.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_globus.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/local_threads_no_cache.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/midway.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/nscc_singapore.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/osg_htex.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/petrelkube.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/slurm_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/summit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/user_opts.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/configs/workqueue_ex.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/conftest.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/latency.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/test_apps/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/test_stress/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/htex_local.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/test_log_filter.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/test_regression_220.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/manual_tests/test_worker_count.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/site_tests/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/site_tests/site_config_selector.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_affinity.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_concurrent.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_dynamic_executor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_ec2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_launchers.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_mpi/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/sites/test_worker_info.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_inputs_default.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_std_uri.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_callables.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_curvezmq.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/test_from_slides.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/test_kwargs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/test_workflow1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_docs/test_workflow4.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_fail.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_retries.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_execute_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_flowcontrol/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_flux.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_block_manager_selector_unit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_command_client_timeout.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_command_concurrency_regression_1321.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_drain.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_htex.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_manager_failure.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_manager_selector_by_block.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_managers_command.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_missing_worker.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_priority_queue.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_resource_spec_validation.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_worker_failure.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_app_names.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_exit_helper.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_htex_fuzz_zmq.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_radio_filesystem.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_radio_multiprocessing.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_radio_udp.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_radio_zmq.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_stdouterr.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_mpiex.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_kubernetes_provider.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_local_provider.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_slurm_template.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_context_manager.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_dependencies_deep.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_depfail_propagation.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_fail.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_futures.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_inputs_default.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_join.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_lifted.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_mapred.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_exception.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_outputs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_overview.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_pluggable_future_resolution.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_simple.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_timeout.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_python_apps/test_type5.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_radical/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_1480.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_1653.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_221.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_226.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_2652.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_69a.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_regression/test_98.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_regression_3696_oscillation.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_scale_down.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_shutdown_scalein.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_basic.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_shutdown/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_shutdown/test_kill_monitoring.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/staging_provider.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_1316.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_docs_1.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_docs_2.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_file.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_file_apps.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_file_staging.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_output_chain_filenames.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_staging_globus.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_staging_https.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_staging_stdout.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_zip_in.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_zip_out.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_staging/test_zip_to_zip.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_summary.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_thread_parallelism.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_threads/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_threads/test_configs.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_utils/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_utils/test_execute_wait.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_utils/test_logutils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/test_utils/test_sanitize_dns.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/unit/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/unit/test_address.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/unit/test_file.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/unit/test_globus_compute_executor.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/unit/test_usage_tracking.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/tests/utils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/usage_tracking/__init__.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/usage_tracking/api.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/usage_tracking/levels.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/usage_tracking/usage.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl/utils.py +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl.egg-info/dependency_links.txt +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl.egg-info/entry_points.txt +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl.egg-info/requires.txt +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/parsl.egg-info/top_level.txt +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/requirements.txt +0 -0
- {parsl-2025.9.22 → parsl-2025.9.29}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: parsl
|
|
3
|
-
Version: 2025.9.
|
|
3
|
+
Version: 2025.9.29
|
|
4
4
|
Summary: Simple data dependent workflows in Python
|
|
5
5
|
Home-page: https://github.com/Parsl/parsl
|
|
6
|
-
Download-URL: https://github.com/Parsl/parsl/archive/2025.09.
|
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2025.09.29.tar.gz
|
|
7
7
|
Author: The Parsl Team
|
|
8
8
|
Author-email: parsl@googlegroups.com
|
|
9
9
|
License: Apache 2.0
|
|
@@ -11,11 +11,10 @@ Keywords: Workflows,Scientific computing
|
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.10.0
|
|
19
18
|
Provides-Extra: monitoring
|
|
20
19
|
Provides-Extra: visualization
|
|
21
20
|
Provides-Extra: aws
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Parsl - Parallel Scripting Library
|
|
2
2
|
==================================
|
|
3
|
-
|licence| |docs| |NSF-1550588| |NSF-1550476| |NSF-1550562| |NSF-1550528| |NumFOCUS| |CZI-EOSS|
|
|
3
|
+
|licence| |docs| |NSF-1550588| |NSF-1550476| |NSF-1550562| |NSF-1550528| |NumFOCUS| |CZI-EOSS| |paper|
|
|
4
4
|
|
|
5
5
|
Parsl extends parallelism in Python beyond a single computer.
|
|
6
6
|
|
|
@@ -67,6 +67,9 @@ then explore the `parallel computing patterns <https://parsl.readthedocs.io/en/s
|
|
|
67
67
|
.. |NumFOCUS| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A
|
|
68
68
|
:target: https://numfocus.org
|
|
69
69
|
:alt: Powered by NumFOCUS
|
|
70
|
+
.. |paper| image:: https://img.shields.io/badge/Software_DOI-10.1145/3307681.3325400-blue
|
|
71
|
+
:target: https://doi.org/10.1145/3307681.3325400
|
|
72
|
+
:alt: Conference proceedings paper
|
|
70
73
|
|
|
71
74
|
|
|
72
75
|
Quickstart
|
|
@@ -120,7 +123,7 @@ For Developers
|
|
|
120
123
|
Requirements
|
|
121
124
|
============
|
|
122
125
|
|
|
123
|
-
Parsl is supported in Python 3.
|
|
126
|
+
Parsl is supported in Python 3.10+. Requirements can be found `here <requirements.txt>`_. Requirements for running tests can be found `here <test-requirements.txt>`_.
|
|
124
127
|
|
|
125
128
|
Code of Conduct
|
|
126
129
|
===============
|
|
@@ -2,32 +2,45 @@ import argparse
|
|
|
2
2
|
import concurrent.futures
|
|
3
3
|
import importlib
|
|
4
4
|
import time
|
|
5
|
+
from typing import Any, Dict
|
|
5
6
|
|
|
6
7
|
import parsl
|
|
8
|
+
from parsl.dataflow.dflow import DataFlowKernel
|
|
7
9
|
|
|
8
10
|
min_iterations = 2
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
# TODO: factor with conftest.py where this is copy/pasted from?
|
|
12
|
-
def load_dfk_from_config(filename):
|
|
14
|
+
def load_dfk_from_config(filename: str) -> DataFlowKernel:
|
|
13
15
|
spec = importlib.util.spec_from_file_location('', filename)
|
|
16
|
+
|
|
17
|
+
if spec is None:
|
|
18
|
+
raise RuntimeError("Could not import configuration")
|
|
19
|
+
|
|
20
|
+
module = importlib.util.module_from_spec(spec)
|
|
21
|
+
|
|
22
|
+
if spec.loader is None:
|
|
23
|
+
raise RuntimeError("Could not load configuration")
|
|
24
|
+
|
|
25
|
+
spec.loader.exec_module(module)
|
|
26
|
+
|
|
14
27
|
module = importlib.util.module_from_spec(spec)
|
|
15
28
|
spec.loader.exec_module(module)
|
|
16
29
|
|
|
17
30
|
if hasattr(module, 'config'):
|
|
18
|
-
parsl.load(module.config)
|
|
31
|
+
return parsl.load(module.config)
|
|
19
32
|
elif hasattr(module, 'fresh_config'):
|
|
20
|
-
parsl.load(module.fresh_config())
|
|
33
|
+
return parsl.load(module.fresh_config())
|
|
21
34
|
else:
|
|
22
35
|
raise RuntimeError("Config module does not define config or fresh_config")
|
|
23
36
|
|
|
24
37
|
|
|
25
38
|
@parsl.python_app
|
|
26
|
-
def app(extra_payload, parsl_resource_specification={}):
|
|
39
|
+
def app(extra_payload: Any, parsl_resource_specification: Dict = {}) -> int:
|
|
27
40
|
return 7
|
|
28
41
|
|
|
29
42
|
|
|
30
|
-
def performance(*, resources: dict, target_t: float, args_extra_size: int):
|
|
43
|
+
def performance(*, resources: dict, target_t: float, args_extra_size: int) -> None:
|
|
31
44
|
n = 10
|
|
32
45
|
|
|
33
46
|
delta_t: float
|
|
@@ -82,6 +95,7 @@ Example usage: python -m parsl.benchmark.perf --config parsl/tests/configs/workq
|
|
|
82
95
|
parser.add_argument("--resources", metavar="EXPR", help="parsl_resource_specification dictionary")
|
|
83
96
|
parser.add_argument("--time", metavar="SECONDS", help="target number of seconds for an iteration", default=120, type=float)
|
|
84
97
|
parser.add_argument("--argsize", metavar="BYTES", help="extra bytes to add into app invocation arguments", default=0, type=int)
|
|
98
|
+
parser.add_argument("--version", action="version", version=f"parsl-perf from Parsl {parsl.__version__}")
|
|
85
99
|
|
|
86
100
|
args = parser.parse_args()
|
|
87
101
|
|
|
@@ -90,10 +104,9 @@ Example usage: python -m parsl.benchmark.perf --config parsl/tests/configs/workq
|
|
|
90
104
|
else:
|
|
91
105
|
resources = {}
|
|
92
106
|
|
|
93
|
-
load_dfk_from_config(args.config)
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
parsl.dfk().cleanup()
|
|
107
|
+
with load_dfk_from_config(args.config):
|
|
108
|
+
performance(resources=resources, target_t=args.time, args_extra_size=args.argsize)
|
|
109
|
+
print("Tests complete - leaving DFK block")
|
|
97
110
|
print("The end")
|
|
98
111
|
|
|
99
112
|
|
|
@@ -175,7 +175,7 @@ class DataFlowKernel:
|
|
|
175
175
|
else:
|
|
176
176
|
checkpoint_files = []
|
|
177
177
|
|
|
178
|
-
self.memoizer = Memoizer(
|
|
178
|
+
self.memoizer = Memoizer(memoize=config.app_cache, checkpoint_files=checkpoint_files)
|
|
179
179
|
self.checkpointed_tasks = 0
|
|
180
180
|
self._checkpoint_timer = None
|
|
181
181
|
self.checkpoint_mode = config.checkpoint_mode
|
|
@@ -561,7 +561,7 @@ class DataFlowKernel:
|
|
|
561
561
|
if not task_record['app_fu'] == future:
|
|
562
562
|
logger.error("Internal consistency error: callback future is not the app_fu in task structure, for task {}".format(task_id))
|
|
563
563
|
|
|
564
|
-
self.memoizer.update_memo(task_record
|
|
564
|
+
self.memoizer.update_memo(task_record)
|
|
565
565
|
|
|
566
566
|
# Cover all checkpointing cases here:
|
|
567
567
|
# Do we need to checkpoint now, or queue for later,
|
|
@@ -1202,7 +1202,6 @@ class DataFlowKernel:
|
|
|
1202
1202
|
|
|
1203
1203
|
self.log_task_states()
|
|
1204
1204
|
|
|
1205
|
-
# Checkpointing takes priority over the rest of the tasks
|
|
1206
1205
|
# checkpoint if any valid checkpoint method is specified
|
|
1207
1206
|
if self.checkpoint_mode is not None:
|
|
1208
1207
|
self.checkpoint()
|
|
@@ -4,20 +4,16 @@ import hashlib
|
|
|
4
4
|
import logging
|
|
5
5
|
import os
|
|
6
6
|
import pickle
|
|
7
|
+
import types
|
|
8
|
+
from concurrent.futures import Future
|
|
7
9
|
from functools import lru_cache, singledispatch
|
|
8
|
-
from typing import
|
|
10
|
+
from typing import Any, Dict, List, Optional, Sequence
|
|
9
11
|
|
|
10
12
|
import typeguard
|
|
11
13
|
|
|
12
14
|
from parsl.dataflow.errors import BadCheckpoint
|
|
13
15
|
from parsl.dataflow.taskrecord import TaskRecord
|
|
14
16
|
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
from parsl import DataFlowKernel # import loop at runtime - needed for typechecking - TODO turn into "if typing:"
|
|
17
|
-
|
|
18
|
-
import types
|
|
19
|
-
from concurrent.futures import Future
|
|
20
|
-
|
|
21
17
|
logger = logging.getLogger(__name__)
|
|
22
18
|
|
|
23
19
|
|
|
@@ -150,17 +146,13 @@ class Memoizer:
|
|
|
150
146
|
|
|
151
147
|
"""
|
|
152
148
|
|
|
153
|
-
def __init__(self,
|
|
149
|
+
def __init__(self, *, memoize: bool = True, checkpoint_files: Sequence[str]):
|
|
154
150
|
"""Initialize the memoizer.
|
|
155
151
|
|
|
156
|
-
Args:
|
|
157
|
-
- dfk (DFK obj): The DFK object
|
|
158
|
-
|
|
159
152
|
KWargs:
|
|
160
153
|
- memoize (Bool): enable memoization or not.
|
|
161
154
|
- checkpoint (Dict): A checkpoint loaded as a dict.
|
|
162
155
|
"""
|
|
163
|
-
self.dfk = dfk
|
|
164
156
|
self.memoize = memoize
|
|
165
157
|
|
|
166
158
|
checkpoint = self.load_checkpoints(checkpoint_files)
|
|
@@ -242,16 +234,14 @@ class Memoizer:
|
|
|
242
234
|
assert isinstance(result, Future) or result is None
|
|
243
235
|
return result
|
|
244
236
|
|
|
245
|
-
def update_memo(self, task: TaskRecord
|
|
237
|
+
def update_memo(self, task: TaskRecord) -> None:
|
|
246
238
|
"""Updates the memoization lookup table with the result from a task.
|
|
239
|
+
This doesn't move any values around but associates the memoization
|
|
240
|
+
hashsum with the completed (by success or failure) AppFuture.
|
|
247
241
|
|
|
248
242
|
Args:
|
|
249
|
-
- task (
|
|
250
|
-
- r (Result future): Result future
|
|
243
|
+
- task (TaskRecord) : A task record from dfk.tasks
|
|
251
244
|
"""
|
|
252
|
-
# TODO: could use typeguard
|
|
253
|
-
assert isinstance(r, Future)
|
|
254
|
-
|
|
255
245
|
task_id = task['id']
|
|
256
246
|
|
|
257
247
|
if not self.memoize or not task['memoize'] or 'hashsum' not in task:
|
|
@@ -265,7 +255,7 @@ class Memoizer:
|
|
|
265
255
|
logger.info(f"Replacing app cache entry {task['hashsum']} with result from task {task_id}")
|
|
266
256
|
else:
|
|
267
257
|
logger.debug(f"Storing app cache entry {task['hashsum']} with result from task {task_id}")
|
|
268
|
-
self.memo_lookup_table[task['hashsum']] =
|
|
258
|
+
self.memo_lookup_table[task['hashsum']] = task['app_fu']
|
|
269
259
|
|
|
270
260
|
def _load_checkpoints(self, checkpointDirs: Sequence[str]) -> Dict[str, Future[Any]]:
|
|
271
261
|
"""Load a checkpoint file into a lookup table.
|
|
@@ -237,7 +237,7 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
|
237
237
|
@typeguard.typechecked
|
|
238
238
|
def __init__(self,
|
|
239
239
|
label: str = 'HighThroughputExecutor',
|
|
240
|
-
provider: ExecutionProvider =
|
|
240
|
+
provider: Optional[ExecutionProvider] = None,
|
|
241
241
|
launch_cmd: Optional[str] = None,
|
|
242
242
|
interchange_launch_cmd: Optional[Sequence[str]] = None,
|
|
243
243
|
address: Optional[str] = None,
|
|
@@ -267,7 +267,9 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
|
267
267
|
|
|
268
268
|
logger.debug("Initializing HighThroughputExecutor")
|
|
269
269
|
|
|
270
|
-
BlockProviderExecutor.__init__(self,
|
|
270
|
+
BlockProviderExecutor.__init__(self,
|
|
271
|
+
provider=provider if provider else LocalProvider(),
|
|
272
|
+
block_error_handler=block_error_handler)
|
|
271
273
|
self.label = label
|
|
272
274
|
self.worker_debug = worker_debug
|
|
273
275
|
self.storage_access = storage_access
|
|
@@ -501,10 +503,7 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
|
501
503
|
else:
|
|
502
504
|
|
|
503
505
|
for serialized_msg in msgs:
|
|
504
|
-
|
|
505
|
-
msg = pickle.loads(serialized_msg)
|
|
506
|
-
except pickle.UnpicklingError:
|
|
507
|
-
raise BadMessage("Message received could not be unpickled")
|
|
506
|
+
msg = pickle.loads(serialized_msg)
|
|
508
507
|
|
|
509
508
|
if msg['type'] == 'result':
|
|
510
509
|
try:
|
|
@@ -712,7 +711,11 @@ class HighThroughputExecutor(BlockProviderExecutor, RepresentationMixin, UsageIn
|
|
|
712
711
|
except TypeError:
|
|
713
712
|
raise SerializationError(func.__name__)
|
|
714
713
|
|
|
715
|
-
|
|
714
|
+
context = {}
|
|
715
|
+
if resource_specification:
|
|
716
|
+
context["resource_spec"] = resource_specification
|
|
717
|
+
|
|
718
|
+
msg = {"task_id": task_id, "context": context, "buffer": fn_buf}
|
|
716
719
|
|
|
717
720
|
# Post task to the outgoing queue
|
|
718
721
|
self.outgoing_q.put(msg)
|
|
@@ -332,7 +332,7 @@ class Interchange:
|
|
|
332
332
|
msg = self.task_incoming.recv_pyobj()
|
|
333
333
|
|
|
334
334
|
# Process priority, higher number = lower priority
|
|
335
|
-
resource_spec = msg.get('resource_spec', {})
|
|
335
|
+
resource_spec = msg['context'].get('resource_spec', {})
|
|
336
336
|
priority = resource_spec.get('priority', float('inf'))
|
|
337
337
|
queue_entry = (-priority, -self.task_counter, msg)
|
|
338
338
|
|
|
@@ -360,9 +360,10 @@ class Interchange:
|
|
|
360
360
|
mtype = meta['type']
|
|
361
361
|
except Exception as e:
|
|
362
362
|
logger.warning(
|
|
363
|
-
|
|
363
|
+
'Failed to read manager message; ignoring message'
|
|
364
|
+
f' (Exception: [{type(e).__name__}] {e})'
|
|
364
365
|
)
|
|
365
|
-
logger.debug('
|
|
366
|
+
logger.debug('Raw message bytes:\n %r\n', msg_parts, exc_info=e)
|
|
366
367
|
return
|
|
367
368
|
|
|
368
369
|
logger.debug(
|
|
@@ -16,7 +16,6 @@ from parsl.executors.status_handling import BlockProviderExecutor
|
|
|
16
16
|
from parsl.jobs.states import JobStatus
|
|
17
17
|
from parsl.launchers import SimpleLauncher
|
|
18
18
|
from parsl.monitoring.radios.base import RadioConfig
|
|
19
|
-
from parsl.providers import LocalProvider
|
|
20
19
|
from parsl.providers.base import ExecutionProvider
|
|
21
20
|
|
|
22
21
|
|
|
@@ -47,7 +46,7 @@ class MPIExecutor(HighThroughputExecutor):
|
|
|
47
46
|
@typeguard.typechecked
|
|
48
47
|
def __init__(self,
|
|
49
48
|
label: str = 'MPIExecutor',
|
|
50
|
-
provider: ExecutionProvider =
|
|
49
|
+
provider: Optional[ExecutionProvider] = None,
|
|
51
50
|
launch_cmd: Optional[str] = None,
|
|
52
51
|
interchange_launch_cmd: Optional[str] = None,
|
|
53
52
|
address: Optional[str] = None,
|
{parsl-2025.9.22 → parsl-2025.9.29}/parsl/executors/high_throughput/mpi_resource_management.py
RENAMED
|
@@ -166,11 +166,10 @@ class MPITaskScheduler(TaskScheduler):
|
|
|
166
166
|
|
|
167
167
|
def put_task(self, task_package: dict):
|
|
168
168
|
"""Schedule task if resources are available otherwise backlog the task"""
|
|
169
|
-
resource_spec = task_package.get("resource_spec", {})
|
|
169
|
+
resource_spec = task_package.get("context", {}).get("resource_spec", {})
|
|
170
170
|
|
|
171
|
-
nodes_needed
|
|
172
|
-
|
|
173
|
-
if nodes_needed:
|
|
171
|
+
if nodes_needed := resource_spec.get("num_nodes"):
|
|
172
|
+
tid = task_package["task_id"]
|
|
174
173
|
try:
|
|
175
174
|
allocated_nodes = self._get_nodes(nodes_needed)
|
|
176
175
|
except MPINodesUnavailable:
|
|
@@ -373,6 +373,8 @@ class Manager:
|
|
|
373
373
|
if socks.get(ix_sock) == zmq.POLLIN:
|
|
374
374
|
pkl_msg = ix_sock.recv()
|
|
375
375
|
tasks = pickle.loads(pkl_msg)
|
|
376
|
+
del pkl_msg
|
|
377
|
+
|
|
376
378
|
last_interchange_contact = time.time()
|
|
377
379
|
|
|
378
380
|
if tasks == HEARTBEAT_CODE:
|
|
@@ -454,6 +456,7 @@ class Manager:
|
|
|
454
456
|
'exception': serialize(RemoteExceptionWrapper(*sys.exc_info()))}
|
|
455
457
|
pkl_package = pickle.dumps(result_package)
|
|
456
458
|
self.pending_result_queue.put(pkl_package)
|
|
459
|
+
del pkl_package
|
|
457
460
|
except KeyError:
|
|
458
461
|
logger.info("Worker {} was not busy when it died".format(worker_id))
|
|
459
462
|
|
|
@@ -770,7 +773,10 @@ def worker(
|
|
|
770
773
|
ready_worker_count.value -= 1
|
|
771
774
|
worker_enqueued = False
|
|
772
775
|
|
|
773
|
-
|
|
776
|
+
ctxt = req["context"]
|
|
777
|
+
res_spec = ctxt.get("resource_spec", {})
|
|
778
|
+
|
|
779
|
+
_init_mpi_env(mpi_launcher=mpi_launcher, resource_spec=res_spec)
|
|
774
780
|
|
|
775
781
|
try:
|
|
776
782
|
result = execute_task(req['buffer'])
|
|
@@ -780,7 +786,8 @@ def worker(
|
|
|
780
786
|
result_package = {'type': 'result', 'task_id': tid, 'exception': serialize(RemoteExceptionWrapper(*sys.exc_info()))}
|
|
781
787
|
else:
|
|
782
788
|
result_package = {'type': 'result', 'task_id': tid, 'result': serialized_result}
|
|
783
|
-
|
|
789
|
+
del serialized_result
|
|
790
|
+
del req
|
|
784
791
|
|
|
785
792
|
logger.info("Completed executor task {}".format(tid))
|
|
786
793
|
try:
|
|
@@ -792,6 +799,7 @@ def worker(
|
|
|
792
799
|
})
|
|
793
800
|
|
|
794
801
|
result_queue.put(pkl_package)
|
|
802
|
+
del pkl_package, result_package
|
|
795
803
|
tasks_in_progress.pop(worker_id)
|
|
796
804
|
logger.info("All processing finished for executor task {}".format(tid))
|
|
797
805
|
|
|
@@ -136,30 +136,18 @@ class TasksOutgoing:
|
|
|
136
136
|
self.port = self.zmq_socket.bind_to_random_port(tcp_url(ip_address),
|
|
137
137
|
min_port=port_range[0],
|
|
138
138
|
max_port=port_range[1])
|
|
139
|
-
self.poller = zmq.Poller()
|
|
140
|
-
self.poller.register(self.zmq_socket, zmq.POLLOUT)
|
|
141
139
|
|
|
142
140
|
def put(self, message):
|
|
143
141
|
""" This function needs to be fast at the same time aware of the possibility of
|
|
144
142
|
ZMQ pipes overflowing.
|
|
145
143
|
|
|
146
|
-
The timeout increases slowly if contention is detected on ZMQ pipes.
|
|
147
144
|
We could set copy=False and get slightly better latency but this results
|
|
148
145
|
in ZMQ sockets reaching a broken state once there are ~10k tasks in flight.
|
|
149
146
|
This issue can be magnified if each the serialized buffer itself is larger.
|
|
150
147
|
"""
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
if self.zmq_socket in socks and socks[self.zmq_socket] == zmq.POLLOUT:
|
|
155
|
-
# The copy option adds latency but reduces the risk of ZMQ overflow
|
|
156
|
-
logger.debug("Sending TasksOutgoing message")
|
|
157
|
-
self.zmq_socket.send_pyobj(message, copy=True)
|
|
158
|
-
logger.debug("Sent TasksOutgoing message")
|
|
159
|
-
return
|
|
160
|
-
else:
|
|
161
|
-
timeout_ms *= 2
|
|
162
|
-
logger.debug("Not sending due to non-ready zmq pipe, timeout: {} ms".format(timeout_ms))
|
|
148
|
+
logger.debug("Sending TasksOutgoing message")
|
|
149
|
+
self.zmq_socket.send_pyobj(message)
|
|
150
|
+
logger.debug("Sent TasksOutgoing message")
|
|
163
151
|
|
|
164
152
|
def close(self):
|
|
165
153
|
self.zmq_socket.close()
|
|
@@ -192,20 +180,15 @@ class ResultsIncoming:
|
|
|
192
180
|
self.port = self.results_receiver.bind_to_random_port(tcp_url(ip_address),
|
|
193
181
|
min_port=port_range[0],
|
|
194
182
|
max_port=port_range[1])
|
|
195
|
-
self.poller = zmq.Poller()
|
|
196
|
-
self.poller.register(self.results_receiver, zmq.POLLIN)
|
|
197
183
|
|
|
198
184
|
def get(self, timeout_ms=None):
|
|
199
185
|
"""Get a message from the queue, returning None if timeout expires
|
|
200
186
|
without a message. timeout is measured in milliseconds.
|
|
201
187
|
"""
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
return m
|
|
207
|
-
else:
|
|
208
|
-
return None
|
|
188
|
+
if zmq.POLLIN == self.results_receiver.poll(timeout_ms, zmq.POLLIN):
|
|
189
|
+
logger.debug("Receiving ResultsIncoming multipart message")
|
|
190
|
+
return self.results_receiver.recv_multipart()
|
|
191
|
+
return None
|
|
209
192
|
|
|
210
193
|
def close(self):
|
|
211
194
|
self.results_receiver.close()
|
|
@@ -107,13 +107,17 @@ class TaskVineExecutor(BlockProviderExecutor, putils.RepresentationMixin):
|
|
|
107
107
|
function_exec_mode: Union[Literal['regular'], Literal['serverless']] = 'regular',
|
|
108
108
|
manager_config: TaskVineManagerConfig = TaskVineManagerConfig(),
|
|
109
109
|
factory_config: TaskVineFactoryConfig = TaskVineFactoryConfig(),
|
|
110
|
-
provider: Optional[ExecutionProvider] =
|
|
110
|
+
provider: Optional[ExecutionProvider] = None,
|
|
111
111
|
storage_access: Optional[List[Staging]] = None,
|
|
112
112
|
remote_monitoring_radio: Optional[RadioConfig] = None):
|
|
113
113
|
|
|
114
114
|
# Set worker launch option for this executor
|
|
115
115
|
if worker_launch_method == 'factory' or worker_launch_method == 'manual':
|
|
116
116
|
provider = None
|
|
117
|
+
elif worker_launch_method == 'provider' and provider is None:
|
|
118
|
+
# provider method chosen, but no explicit provider supplied to __init__
|
|
119
|
+
# so default to LocalProvider
|
|
120
|
+
provider = LocalProvider(init_blocks=1)
|
|
117
121
|
|
|
118
122
|
# Initialize the parent class with the execution provider and block error handling enabled.
|
|
119
123
|
# If provider is None, then no worker is launched via the provider method.
|
|
@@ -2,11 +2,17 @@ import pytest
|
|
|
2
2
|
|
|
3
3
|
import parsl
|
|
4
4
|
from parsl.app.app import python_app
|
|
5
|
-
from parsl.
|
|
5
|
+
from parsl.config import Config
|
|
6
|
+
from parsl.executors.threads import ThreadPoolExecutor
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
def
|
|
9
|
-
|
|
9
|
+
def fresh_config():
|
|
10
|
+
tpe = ThreadPoolExecutor(label='local_threads_checkpoint_periodic', max_threads=1)
|
|
11
|
+
return Config(
|
|
12
|
+
executors=[tpe],
|
|
13
|
+
checkpoint_mode='periodic',
|
|
14
|
+
checkpoint_period='00:00:02'
|
|
15
|
+
)
|
|
10
16
|
|
|
11
17
|
|
|
12
18
|
@python_app(cache=True)
|
|
@@ -25,12 +31,12 @@ def tstamp_to_seconds(line):
|
|
|
25
31
|
def test_periodic():
|
|
26
32
|
"""Test checkpointing with task_periodic behavior
|
|
27
33
|
"""
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
with parsl.load(fresh_config()):
|
|
35
|
+
h, m, s = map(int, parsl.dfk().config.checkpoint_period.split(":"))
|
|
36
|
+
assert h == 0, "Verify test setup"
|
|
37
|
+
assert m == 0, "Verify test setup"
|
|
38
|
+
assert s > 0, "Verify test setup"
|
|
39
|
+
sleep_for = s + 1
|
|
34
40
|
futs = [slow_double(sleep_for) for _ in range(4)]
|
|
35
41
|
[f.result() for f in futs]
|
|
36
42
|
run_dir = parsl.dfk().run_dir
|
|
@@ -43,8 +43,8 @@ def test_MPISched_put_task():
|
|
|
43
43
|
assert len(scheduler.available_nodes) == 8
|
|
44
44
|
assert scheduler._free_node_counter.value == 8
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
task_package = {"task_id": 1, "buffer": mock_task_buffer, "
|
|
46
|
+
ctxt = {"resource_spec": {"num_nodes": 2, "ranks_per_node": 2}}
|
|
47
|
+
task_package = {"task_id": 1, "buffer": mock_task_buffer, "context": ctxt}
|
|
48
48
|
scheduler.put_task(task_package)
|
|
49
49
|
|
|
50
50
|
assert scheduler._free_node_counter.value == 6
|
|
@@ -82,8 +82,8 @@ def test_MPISched_roundtrip():
|
|
|
82
82
|
for trip in range(1, 9):
|
|
83
83
|
assert scheduler._free_node_counter.value == 8
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
task_package = {"task_id": trip, "buffer": mock_task_buffer, "
|
|
85
|
+
ctxt = {"resource_spec": {"num_nodes": trip, "ranks_per_node": 2}}
|
|
86
|
+
task_package = {"task_id": trip, "buffer": mock_task_buffer, "context": ctxt}
|
|
87
87
|
scheduler.put_task(task_package)
|
|
88
88
|
|
|
89
89
|
assert scheduler._free_node_counter.value == 8 - trip
|
|
@@ -107,15 +107,15 @@ def test_MPISched_contention():
|
|
|
107
107
|
|
|
108
108
|
assert scheduler._free_node_counter.value == 8
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
task_package = {"task_id": 1, "buffer": mock_task_buffer, "
|
|
110
|
+
ctxt_1 = {"resource_spec": {"num_nodes": 8, "ranks_per_node": 2}}
|
|
111
|
+
task_package = {"task_id": 1, "buffer": mock_task_buffer, "context": ctxt_1}
|
|
112
112
|
scheduler.put_task(task_package)
|
|
113
113
|
|
|
114
114
|
assert scheduler._free_node_counter.value == 0
|
|
115
115
|
assert scheduler._backlog_queue.empty()
|
|
116
116
|
|
|
117
|
-
|
|
118
|
-
task_package = {"task_id": 2, "buffer": mock_task_buffer, "
|
|
117
|
+
ctxt_2 = {"resource_spec": {"num_nodes": 8, "ranks_per_node": 2}}
|
|
118
|
+
task_package = {"task_id": 2, "buffer": mock_task_buffer, "context": ctxt_2}
|
|
119
119
|
scheduler.put_task(task_package)
|
|
120
120
|
|
|
121
121
|
# Second task should now be in the backlog_queue
|
|
@@ -124,7 +124,7 @@ def test_MPISched_contention():
|
|
|
124
124
|
# Confirm that the first task is available and has all 8 nodes provisioned
|
|
125
125
|
task_on_worker_side = task_q.get()
|
|
126
126
|
assert task_on_worker_side['task_id'] == 1
|
|
127
|
-
assert len(
|
|
127
|
+
assert len(ctxt_1["resource_spec"]["MPI_NODELIST"].split(",")) == 8
|
|
128
128
|
assert task_q.empty() # Confirm that task 2 is not yet scheduled
|
|
129
129
|
|
|
130
130
|
# Simulate worker returning result and the scheduler picking up result
|
|
@@ -139,7 +139,7 @@ def test_MPISched_contention():
|
|
|
139
139
|
# Pop in a mock result
|
|
140
140
|
task_on_worker_side = task_q.get()
|
|
141
141
|
assert task_on_worker_side['task_id'] == 2
|
|
142
|
-
assert len(
|
|
142
|
+
assert len(ctxt_2["resource_spec"]["MPI_NODELIST"].split(",")) == 8
|
|
143
143
|
|
|
144
144
|
|
|
145
145
|
@pytest.mark.local
|
|
@@ -157,7 +157,7 @@ def test_hashable_backlog_queue():
|
|
|
157
157
|
assert scheduler._free_node_counter.value == 8
|
|
158
158
|
|
|
159
159
|
for i in range(3):
|
|
160
|
-
|
|
161
|
-
task_package = {"task_id": i, "buffer": mock_task_buffer, "
|
|
160
|
+
ctxt = {"resource_spec": {"num_nodes": 8, "ranks_per_node": 2}}
|
|
161
|
+
task_package = {"task_id": i, "buffer": mock_task_buffer, "context": ctxt}
|
|
162
162
|
scheduler.put_task(task_package)
|
|
163
163
|
assert scheduler._backlog_queue.qsize() == 2, "Expected 2 backlogged tasks"
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
import parsl
|
|
6
|
+
from parsl.app.app import python_app
|
|
7
|
+
from parsl.config import Config
|
|
8
|
+
from parsl.executors import HighThroughputExecutor
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@python_app
|
|
12
|
+
def noop():
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.local
|
|
17
|
+
def test_regression_3874(tmpd_cwd_session):
|
|
18
|
+
# HTEX run 1
|
|
19
|
+
|
|
20
|
+
rundir_1 = str(tmpd_cwd_session / "1")
|
|
21
|
+
|
|
22
|
+
config = Config(executors=[HighThroughputExecutor()], strategy_period=0.5)
|
|
23
|
+
config.run_dir = rundir_1
|
|
24
|
+
|
|
25
|
+
with parsl.load(config):
|
|
26
|
+
noop().result()
|
|
27
|
+
|
|
28
|
+
# It is necessary to delete this rundir to exercise the bug. Otherwise,
|
|
29
|
+
# the next run will be able to continue looking at this directory - the
|
|
30
|
+
# bug manifests when it cannot.
|
|
31
|
+
|
|
32
|
+
shutil.rmtree(rundir_1)
|
|
33
|
+
|
|
34
|
+
# HTEX run 2
|
|
35
|
+
# In the case of issue 3874, this run hangs (rather than failing) as the
|
|
36
|
+
# JobStatusPoller fails to collect status of all of its managed tasks
|
|
37
|
+
# every iteration, without converging towards failure.
|
|
38
|
+
|
|
39
|
+
rundir_2 = str(tmpd_cwd_session / "2")
|
|
40
|
+
|
|
41
|
+
config = Config(executors=[HighThroughputExecutor()], strategy_period=0.5)
|
|
42
|
+
config.run_dir = rundir_2
|
|
43
|
+
|
|
44
|
+
with parsl.load(config):
|
|
45
|
+
noop().result()
|
|
46
|
+
|
|
47
|
+
shutil.rmtree(rundir_2)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: parsl
|
|
3
|
-
Version: 2025.9.
|
|
3
|
+
Version: 2025.9.29
|
|
4
4
|
Summary: Simple data dependent workflows in Python
|
|
5
5
|
Home-page: https://github.com/Parsl/parsl
|
|
6
|
-
Download-URL: https://github.com/Parsl/parsl/archive/2025.09.
|
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2025.09.29.tar.gz
|
|
7
7
|
Author: The Parsl Team
|
|
8
8
|
Author-email: parsl@googlegroups.com
|
|
9
9
|
License: Apache 2.0
|
|
@@ -11,11 +11,10 @@ Keywords: Workflows,Scientific computing
|
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
-
Requires-Python: >=3.
|
|
17
|
+
Requires-Python: >=3.10.0
|
|
19
18
|
Provides-Extra: monitoring
|
|
20
19
|
Provides-Extra: visualization
|
|
21
20
|
Provides-Extra: aws
|