parsl 2025.10.13__tar.gz → 2025.10.27__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.10.13/parsl.egg-info → parsl-2025.10.27}/PKG-INFO +3 -2
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/bash.py +1 -1
- parsl-2025.10.27/parsl/concurrent/__init__.py +166 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/globus.py +3 -1
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/dflow.py +92 -192
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/memoization.py +126 -2
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/states.py +5 -5
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/interchange.py +4 -7
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/strategy.py +7 -6
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_globus.py +18 -14
- parsl-2025.10.27/parsl/tests/sites/test_concurrent.py +96 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_priority_queue.py +18 -1
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_basic.py +0 -14
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_depfail_propagation.py +11 -1
- parsl-2025.10.27/parsl/tests/test_python_apps/test_exception.py +19 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_3696_oscillation.py +1 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_globus.py +2 -2
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_globus_compute_executor.py +11 -2
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/version.py +1 -1
- {parsl-2025.10.13 → parsl-2025.10.27/parsl.egg-info}/PKG-INFO +3 -2
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/SOURCES.txt +1 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/requires.txt +4 -1
- {parsl-2025.10.13 → parsl-2025.10.27}/requirements.txt +0 -1
- {parsl-2025.10.13 → parsl-2025.10.27}/setup.py +1 -0
- parsl-2025.10.13/parsl/concurrent/__init__.py +0 -85
- parsl-2025.10.13/parsl/tests/sites/test_concurrent.py +0 -48
- {parsl-2025.10.13 → parsl-2025.10.27}/LICENSE +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/MANIFEST.in +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/README.rst +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/addresses.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/app.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/futures.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/app/python.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/benchmark/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/benchmark/perf.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/config.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/ASPIRE1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/Azure.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/anvil.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/bridges.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/cc_in2p3.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/delta.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/ec2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/expanse.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/frontera.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/gc_multisite.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/gc_tutorial.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/htex_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/illinoiscluster.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/improv.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/kubernetes.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/local_threads.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/midway.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/osg.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/polaris.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/stampede2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/summit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/toss3_llnl.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/vineex_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/configs/wqex_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/curvezmq.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/data_manager.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/file_noop.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/files.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/ftp.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/http.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/rsync.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/staging.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/data_provider/zip.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/dependency_resolvers.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/futures.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/rundirs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/dataflow/taskrecord.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/base.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/execute_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/execute_parsl_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/flux/flux_instance_manager.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/globus_compute.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/manager_record.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/manager_selector.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/monitoring_info.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_prefix_composer.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/mpi_resource_management.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/probe.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/process_worker_pool.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/high_throughput/zmq_pipes.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/rpex_resources.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/radical/rpex_worker.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/status_handling.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/exec_parsl_function.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/factory.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/factory_config.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/manager.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/manager_config.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/taskvine/utils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/threads.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/exec_parsl_function.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/parsl_coprocess.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/executors/workqueue/parsl_coprocess_stub.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/error_handlers.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/job_status_poller.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/jobs/states.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/base.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/launchers/launchers.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/log_utils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/db_manager.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/message_type.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/monitoring.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/queries/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/queries/pandas.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/base.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/filesystem.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/filesystem_router.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/htex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/multiprocessing.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/udp.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/udp_router.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/zmq.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/radios/zmq_router.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/remote.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/types.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/app.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/models.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/task_plots.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/workflow_plots.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/plots/default/workflow_resource_plots.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/static/parsl-logo-white.png +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/static/parsl-monitor.css +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/app.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/dag.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/error.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/layout.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/resource_usage.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/task.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/workflow.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/templates/workflows_summary.html +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/utils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/version.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/monitoring/visualization/views.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/multiprocessing.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/process_loggers.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/aws.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/aws/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/azure.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/azure/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/base.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/cluster_provider.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/condor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/condor/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/googlecloud/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/googlecloud/googlecloud.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/grid_engine.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/grid_engine/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/kube.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/kubernetes/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/local/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/local/local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/lsf.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/lsf/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/pbspro.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/pbspro/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/slurm.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/slurm/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/providers/torque/torque.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/py.typed +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/base.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/concretes.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/facade.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/serialize/proxystore.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/callables_helper.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/azure_single_node.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/bluewaters.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/bridges.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/cc_in2p3.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/comet.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/ec2_single_node.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/ec2_spot.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/flux_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/frontera.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/globus_compute.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_alternate.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_intask_staging.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/htex_local_rsync_staging.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_radical.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_radical_mpi.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint_dfk_exit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_checkpoint_task_exit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_ftp_in_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/local_threads_http_in_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/midway.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/nscc_singapore.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/osg_htex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/petrelkube.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/slurm_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/summit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/taskvine_ex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/user_opts.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/configs/workqueue_ex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/conftest.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/latency.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_apps/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_parsl_load_default_config.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/test_python_simple.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/integration/test_stress/test_python_threads.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/htex_local.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_basic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_log_filter.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_memory_limits.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_regression_220.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/manual_tests/test_worker_count.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/site_tests/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/site_tests/site_config_selector.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_affinity.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_dynamic_executor.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_ec2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_launchers.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_mpi/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/sites/test_worker_info.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_apptimeout.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_basic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_error_codes.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_inputs_default.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_keyword_overlaps.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_kwarg_storage.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_memoize_ignore_args_regr.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_multiline.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_pipeline.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_std_uri.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_bash_apps/test_stdout.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_callables.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_periodic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_python_checkpoint_1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_python_checkpoint_2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_232.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_233.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_regression_239.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_checkpointing/test_task_exit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_curvezmq.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_from_slides.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_kwargs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_tutorial_1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_workflow1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_docs/test_workflow4.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_fail.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_python_walltime.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_resource_spec.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retries.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retry_handler.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_retry_handler_failure.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_serialization_fail.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_error_handling/test_wrap_with_logs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_execute_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_flowcontrol/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_flux.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_basic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_block_manager_selector_unit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_command_client_timeout.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_command_concurrency_regression_1321.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_connected_blocks.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_cpu_affinity_explicit.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_disconnected_blocks.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_disconnected_blocks_failing_provider.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_drain.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_htex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_interchange_exit_bad_registration.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_manager_failure.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_manager_selector_by_block.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_managers_command.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_missing_worker.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_multiple_disconnected_blocks.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_resource_spec_validation.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_worker_failure.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_htex/test_zmq_binding.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_app_names.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_basic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_db_locks.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_exit_helper.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_htex_fuzz_zmq.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_htex_init_blocks_vs_monitoring.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_incomplete_futures.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_memoization_representation.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_filesystem.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_multiprocessing.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_udp.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_radio_zmq.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_stdouterr.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_monitoring/test_viz_colouring.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_bad_mpi_config.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_mode_enabled.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_prefix.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpi_scheduler.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_mpiex.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_mpi_apps/test_resource_spec.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_kubernetes_provider.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_local_provider.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_pbspro_template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_slurm_instantiate.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_slurm_template.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_providers/test_submiterror_deprecation.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_arg_input_types.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_context_manager.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dep_standard_futures.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dependencies.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_dependencies_deep.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fail.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fibonacci_iterative.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_fibonacci_recursive.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_futures.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_garbage_collect.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_import_fail.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_inputs_default.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_join.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_lifted.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_mapred.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_4.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_bad_id_for_memo.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_exception.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_ignore_args.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_memoize_joinapp.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_outputs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_overview.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_pipeline.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_pluggable_future_resolution.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_simple.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_timeout.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_python_apps/test_type5.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_radical/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_radical/test_mpi_funcs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1480.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1606_wait_for_current_tasks.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_1653.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_221.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_226.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_2652.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_3874.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_69a.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_97_parallelism_0.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_regression/test_98.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_block_error_handler.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_1621.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_regression_3568_scaledown_vs_MISSING.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down_htex_auto_scale.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_scale_down_htex_unregistered.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_shutdown_scalein.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_scaling/test_worker_interchange_bad_messages_3262.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_2555_caching_deserializer.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_3495_deserialize_managerlost.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_basic.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_htex_code_cache.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_proxystore_configured.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_serialization/test_proxystore_impl.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_shutdown/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_shutdown/test_kill_monitoring.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/staging_provider.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_1316.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_docs_1.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_docs_2.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_elaborate_noop_file.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file_apps.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_file_staging.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_output_chain_filenames.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_ftp.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_ftp_in_task.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_https.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_staging_stdout.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_in.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_out.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_staging/test_zip_to_zip.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_summary.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_thread_parallelism.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/test_configs.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_threads/test_lazy_errors.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_execute_wait.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_logutils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_representation_mixin.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/test_utils/test_sanitize_dns.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_address.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_file.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/unit/test_usage_tracking.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/tests/utils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/__init__.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/api.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/levels.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/usage_tracking/usage.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl/utils.py +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/dependency_links.txt +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/entry_points.txt +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/parsl.egg-info/top_level.txt +0 -0
- {parsl-2025.10.13 → parsl-2025.10.27}/setup.cfg +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: parsl
|
|
3
|
-
Version: 2025.10.
|
|
3
|
+
Version: 2025.10.27
|
|
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.10.
|
|
6
|
+
Download-URL: https://github.com/Parsl/parsl/archive/2025.10.27.tar.gz
|
|
7
7
|
Author: The Parsl Team
|
|
8
8
|
Author-email: parsl@googlegroups.com
|
|
9
9
|
License: Apache 2.0
|
|
@@ -28,6 +28,7 @@ Provides-Extra: flux
|
|
|
28
28
|
Provides-Extra: proxystore
|
|
29
29
|
Provides-Extra: radical-pilot
|
|
30
30
|
Provides-Extra: globus_compute
|
|
31
|
+
Provides-Extra: globus_transfer
|
|
31
32
|
Provides-Extra: all
|
|
32
33
|
License-File: LICENSE
|
|
33
34
|
|
|
@@ -88,7 +88,7 @@ def remote_side_bash_executor(func, *args, **kwargs):
|
|
|
88
88
|
raise pe.AppTimeout(f"App {func_name} exceeded walltime: {timeout} seconds")
|
|
89
89
|
|
|
90
90
|
except Exception as e:
|
|
91
|
-
raise pe.AppException(f"App {func_name} caught exception
|
|
91
|
+
raise pe.AppException(f"App {func_name} caught exception", e)
|
|
92
92
|
|
|
93
93
|
if returncode != 0:
|
|
94
94
|
raise pe.BashExitFailure(func_name, proc.returncode)
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"""Interfaces modeled after Python's `concurrent library <https://docs.python.org/3/library/concurrent.html>`_"""
|
|
2
|
+
import time
|
|
3
|
+
from concurrent.futures import Executor
|
|
4
|
+
from contextlib import AbstractContextManager
|
|
5
|
+
from typing import Callable, Dict, Iterable, Iterator, Literal, Optional
|
|
6
|
+
from warnings import warn
|
|
7
|
+
|
|
8
|
+
from parsl import Config, DataFlowKernel, load
|
|
9
|
+
from parsl.app.python import PythonApp
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ParslPoolExecutor(Executor, AbstractContextManager):
|
|
13
|
+
"""An executor that uses a pool of workers managed by Parsl
|
|
14
|
+
|
|
15
|
+
Works just like a :class:`~concurrent.futures.ProcessPoolExecutor` except that tasks
|
|
16
|
+
are distributed across workers that can be on different machines.
|
|
17
|
+
|
|
18
|
+
Create a new executor using one of two methods:
|
|
19
|
+
|
|
20
|
+
1. Supplying a Parsl :class:`~parsl.Config` that defines how to create new workers.
|
|
21
|
+
The executor will start a new Parsl Data Flow Kernel (DFK) when it is entered as a context manager.
|
|
22
|
+
|
|
23
|
+
2. Supplying an already-started Parsl :class:`~parsl.DataFlowKernel` (DFK).
|
|
24
|
+
The executor assumes you will start and stop the Parsl DFK outside the Executor.
|
|
25
|
+
|
|
26
|
+
The futures returned by :meth:`submit` and :meth:`map` are Parsl futures and will work
|
|
27
|
+
with the same function chaining mechanisms as when using Parsl with decorators.
|
|
28
|
+
|
|
29
|
+
.. code-block:: python
|
|
30
|
+
|
|
31
|
+
def f(x):
|
|
32
|
+
return x + 1
|
|
33
|
+
|
|
34
|
+
@python_app
|
|
35
|
+
def parity(x):
|
|
36
|
+
return 'odd' if x % 2 == 1 else 'even'
|
|
37
|
+
|
|
38
|
+
with ParslPoolExecutor(config=my_parsl_config) as executor:
|
|
39
|
+
future_1 = executor.submit(f, 1)
|
|
40
|
+
assert parity(future_1) == 'even' # Function chaining, as expected
|
|
41
|
+
|
|
42
|
+
future_2 = executor.submit(f, future_1)
|
|
43
|
+
assert future_2.result() == 3 # Chaining works with `submit` too
|
|
44
|
+
|
|
45
|
+
Parsl does not support canceling tasks. The :meth:`map` method does not cancel work
|
|
46
|
+
when one member of the run fails or a timeout is reached
|
|
47
|
+
and :meth:`shutdown` does not cancel work on completion.
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
def __init__(self, config: Config | None = None, dfk: DataFlowKernel | None = None, executors: Literal['all'] | list[str] = 'all'):
|
|
51
|
+
"""Create the executor
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
config: Configuration for the Parsl Data Flow Kernel (DFK)
|
|
55
|
+
dfk: DataFlowKernel of an already-started parsl
|
|
56
|
+
executors: List of executors to use for supplied functions
|
|
57
|
+
"""
|
|
58
|
+
if (config is not None) and (dfk is not None):
|
|
59
|
+
raise ValueError('Specify only one of config or dfk')
|
|
60
|
+
if (config is None) and (dfk is None):
|
|
61
|
+
raise ValueError('Must specify one of config or dfk')
|
|
62
|
+
self._config = config
|
|
63
|
+
self._app_cache: Dict[Callable, PythonApp] = {} # Cache specific to this instance: https://stackoverflow.com/questions/33672412
|
|
64
|
+
self._dfk = dfk
|
|
65
|
+
self.executors = executors
|
|
66
|
+
|
|
67
|
+
# Start workers immediately
|
|
68
|
+
if self._config is not None:
|
|
69
|
+
self._dfk = load(self._config)
|
|
70
|
+
|
|
71
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
72
|
+
if self._dfk is None: # Nothing has been started, do nothing
|
|
73
|
+
return
|
|
74
|
+
elif self._config is not None: # The executors are being managed by this class, shut them down
|
|
75
|
+
self.shutdown(wait=True)
|
|
76
|
+
return
|
|
77
|
+
else: # The DFK is managed elsewhere, do nothing
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def app_count(self):
|
|
82
|
+
"""Number of functions currently registered with the executor"""
|
|
83
|
+
return len(self._app_cache)
|
|
84
|
+
|
|
85
|
+
def get_app(self, fn: Callable) -> PythonApp:
|
|
86
|
+
"""Create a PythonApp for a function
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
fn: Function to be turned into a Parsl app
|
|
90
|
+
Returns:
|
|
91
|
+
PythonApp version of that function
|
|
92
|
+
"""
|
|
93
|
+
if fn in self._app_cache:
|
|
94
|
+
return self._app_cache[fn]
|
|
95
|
+
app = PythonApp(fn, data_flow_kernel=self._dfk, executors=self.executors)
|
|
96
|
+
self._app_cache[fn] = app
|
|
97
|
+
return app
|
|
98
|
+
|
|
99
|
+
def submit(self, fn, *args, **kwargs):
|
|
100
|
+
"""Submits a callable to be executed with the given arguments.
|
|
101
|
+
|
|
102
|
+
Schedules the callable to be executed as ``fn(*args, **kwargs)`` and returns
|
|
103
|
+
a Future instance representing the execution of the callable.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
A Future representing the given call.
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
if self._dfk is None:
|
|
110
|
+
raise RuntimeError('Executor has been shut down.')
|
|
111
|
+
app = self.get_app(fn)
|
|
112
|
+
return app(*args, **kwargs)
|
|
113
|
+
|
|
114
|
+
# TODO (wardlt): This override can go away when Parsl supports cancel
|
|
115
|
+
def map(self, fn: Callable, *iterables: Iterable, timeout: Optional[float] = None, chunksize: int = 1) -> Iterator:
|
|
116
|
+
"""Returns an iterator equivalent to map(fn, iter).
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
fn: A callable that will take as many arguments as there are
|
|
120
|
+
passed iterables.
|
|
121
|
+
timeout: The maximum number of seconds to wait. If None, then there
|
|
122
|
+
is no limit on the wait time.
|
|
123
|
+
chunksize: If greater than one, the iterables will be chopped into
|
|
124
|
+
chunks of size chunksize and submitted to the process pool.
|
|
125
|
+
If set to one, the items in the list will be sent one at a time.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
An iterator equivalent to: map(func, ``*iterables``) but the calls may
|
|
129
|
+
be evaluated out-of-order.
|
|
130
|
+
|
|
131
|
+
Raises:
|
|
132
|
+
TimeoutError: If the entire result iterator could not be generated
|
|
133
|
+
before the given timeout.
|
|
134
|
+
Exception: If ``fn(*args)`` raises for any values.
|
|
135
|
+
"""
|
|
136
|
+
# This is a version of the CPython 3.9 `.map` implementation modified to not use `cancel`
|
|
137
|
+
if timeout is not None:
|
|
138
|
+
end_time = timeout + time.monotonic()
|
|
139
|
+
|
|
140
|
+
# Submit the applications
|
|
141
|
+
app = self.get_app(fn)
|
|
142
|
+
fs = [app(*args) for args in zip(*iterables)]
|
|
143
|
+
|
|
144
|
+
# Yield the futures as completed
|
|
145
|
+
def result_iterator():
|
|
146
|
+
# reverse to keep finishing order
|
|
147
|
+
fs.reverse()
|
|
148
|
+
while fs:
|
|
149
|
+
# Careful not to keep a reference to the popped future
|
|
150
|
+
if timeout is None:
|
|
151
|
+
yield fs.pop().result()
|
|
152
|
+
else:
|
|
153
|
+
yield fs.pop().result(end_time - time.monotonic())
|
|
154
|
+
|
|
155
|
+
return result_iterator()
|
|
156
|
+
|
|
157
|
+
def shutdown(self, wait: bool = True, *, cancel_futures: bool = False) -> None:
|
|
158
|
+
if self._dfk is None:
|
|
159
|
+
return # Do nothing. Nothing is active
|
|
160
|
+
if cancel_futures:
|
|
161
|
+
warn(message="Canceling on-going tasks is not supported in Parsl")
|
|
162
|
+
if wait:
|
|
163
|
+
self._dfk.wait_for_current_tasks()
|
|
164
|
+
if self._config is not None: # The executors are being managed
|
|
165
|
+
self._dfk.cleanup() # Shutdown the DFK
|
|
166
|
+
self._dfk = None
|
|
@@ -4,7 +4,6 @@ import os
|
|
|
4
4
|
from functools import partial
|
|
5
5
|
from typing import Optional
|
|
6
6
|
|
|
7
|
-
import globus_sdk
|
|
8
7
|
import typeguard
|
|
9
8
|
|
|
10
9
|
import parsl
|
|
@@ -79,6 +78,7 @@ class Globus:
|
|
|
79
78
|
|
|
80
79
|
@classmethod
|
|
81
80
|
def transfer_file(cls, src_ep, dst_ep, src_path, dst_path):
|
|
81
|
+
import globus_sdk
|
|
82
82
|
tc = globus_sdk.TransferClient(authorizer=cls.authorizer)
|
|
83
83
|
td = globus_sdk.TransferData(tc, src_ep, dst_ep)
|
|
84
84
|
td.add_item(src_path, dst_path)
|
|
@@ -140,6 +140,7 @@ class Globus:
|
|
|
140
140
|
def _do_native_app_authentication(cls, client_id, redirect_uri,
|
|
141
141
|
requested_scopes=None):
|
|
142
142
|
|
|
143
|
+
import globus_sdk
|
|
143
144
|
client = globus_sdk.NativeAppAuthClient(client_id=client_id)
|
|
144
145
|
client.oauth2_start_flow(
|
|
145
146
|
requested_scopes=requested_scopes,
|
|
@@ -154,6 +155,7 @@ class Globus:
|
|
|
154
155
|
|
|
155
156
|
@classmethod
|
|
156
157
|
def _get_native_app_authorizer(cls, client_id):
|
|
158
|
+
import globus_sdk
|
|
157
159
|
tokens = None
|
|
158
160
|
try:
|
|
159
161
|
tokens = cls._load_tokens_from_file(cls.TOKEN_FILE)
|
|
@@ -6,7 +6,6 @@ import datetime
|
|
|
6
6
|
import inspect
|
|
7
7
|
import logging
|
|
8
8
|
import os
|
|
9
|
-
import pickle
|
|
10
9
|
import random
|
|
11
10
|
import sys
|
|
12
11
|
import threading
|
|
@@ -50,7 +49,7 @@ from parsl.monitoring.radios.multiprocessing import MultiprocessingQueueRadioSen
|
|
|
50
49
|
from parsl.monitoring.remote import monitor_wrapper
|
|
51
50
|
from parsl.process_loggers import wrap_with_logs
|
|
52
51
|
from parsl.usage_tracking.usage import UsageTracker
|
|
53
|
-
from parsl.utils import
|
|
52
|
+
from parsl.utils import get_std_fname_mode, get_version
|
|
54
53
|
|
|
55
54
|
logger = logging.getLogger(__name__)
|
|
56
55
|
|
|
@@ -101,8 +100,6 @@ class DataFlowKernel:
|
|
|
101
100
|
|
|
102
101
|
logger.info("Parsl version: {}".format(get_version()))
|
|
103
102
|
|
|
104
|
-
self.checkpoint_lock = threading.Lock()
|
|
105
|
-
|
|
106
103
|
self.usage_tracker = UsageTracker(self)
|
|
107
104
|
self.usage_tracker.send_start_message()
|
|
108
105
|
|
|
@@ -168,18 +165,12 @@ class DataFlowKernel:
|
|
|
168
165
|
self.monitoring_radio.send((MessageType.WORKFLOW_INFO,
|
|
169
166
|
workflow_info))
|
|
170
167
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
self.memoizer = Memoizer(memoize=config.app_cache, checkpoint_files=checkpoint_files)
|
|
179
|
-
self.checkpointed_tasks = 0
|
|
180
|
-
self._checkpoint_timer = None
|
|
181
|
-
self.checkpoint_mode = config.checkpoint_mode
|
|
182
|
-
self.checkpointable_tasks: List[TaskRecord] = []
|
|
168
|
+
self.memoizer = Memoizer(memoize=config.app_cache,
|
|
169
|
+
checkpoint_mode=config.checkpoint_mode,
|
|
170
|
+
checkpoint_files=config.checkpoint_files,
|
|
171
|
+
checkpoint_period=config.checkpoint_period)
|
|
172
|
+
self.memoizer.run_dir = self.run_dir
|
|
173
|
+
self.memoizer.start()
|
|
183
174
|
|
|
184
175
|
# this must be set before executors are added since add_executors calls
|
|
185
176
|
# job_status_poller.add_executors.
|
|
@@ -195,22 +186,11 @@ class DataFlowKernel:
|
|
|
195
186
|
self.add_executors(config.executors)
|
|
196
187
|
self.add_executors([parsl_internal_executor])
|
|
197
188
|
|
|
198
|
-
if self.checkpoint_mode == "periodic":
|
|
199
|
-
if config.checkpoint_period is None:
|
|
200
|
-
raise ConfigurationError("Checkpoint period must be specified with periodic checkpoint mode")
|
|
201
|
-
else:
|
|
202
|
-
try:
|
|
203
|
-
h, m, s = map(int, config.checkpoint_period.split(':'))
|
|
204
|
-
except Exception:
|
|
205
|
-
raise ConfigurationError("invalid checkpoint_period provided: {0} expected HH:MM:SS".format(config.checkpoint_period))
|
|
206
|
-
checkpoint_period = (h * 3600) + (m * 60) + s
|
|
207
|
-
self._checkpoint_timer = Timer(self.checkpoint, interval=checkpoint_period, name="Checkpoint")
|
|
208
|
-
|
|
209
189
|
self.task_count = 0
|
|
210
190
|
self.tasks: Dict[int, TaskRecord] = {}
|
|
211
191
|
self.submitter_lock = threading.Lock()
|
|
212
192
|
|
|
213
|
-
self.
|
|
193
|
+
self._task_launch_pool = cf.ThreadPoolExecutor(max_workers=1, thread_name_prefix="Task-Launch")
|
|
214
194
|
|
|
215
195
|
self.dependency_resolver = self.config.dependency_resolver if self.config.dependency_resolver is not None \
|
|
216
196
|
else SHALLOW_DEPENDENCY_RESOLVER
|
|
@@ -371,13 +351,9 @@ class DataFlowKernel:
|
|
|
371
351
|
else:
|
|
372
352
|
task_record['fail_cost'] += 1
|
|
373
353
|
|
|
374
|
-
if
|
|
354
|
+
if isinstance(e, DependencyError):
|
|
375
355
|
logger.info("Task {} failed due to dependency failure so skipping retries".format(task_id))
|
|
376
|
-
task_record
|
|
377
|
-
self._send_task_log_info(task_record)
|
|
378
|
-
self.memoizer.update_memo(task_record)
|
|
379
|
-
with task_record['app_fu']._update_lock:
|
|
380
|
-
task_record['app_fu'].set_exception(e)
|
|
356
|
+
self._complete_task_exception(task_record, States.dep_fail, e)
|
|
381
357
|
|
|
382
358
|
elif task_record['fail_cost'] <= self._config.retries:
|
|
383
359
|
|
|
@@ -397,61 +373,48 @@ class DataFlowKernel:
|
|
|
397
373
|
else:
|
|
398
374
|
logger.exception("Task {} failed after {} retry attempts".format(task_id,
|
|
399
375
|
task_record['try_id']))
|
|
400
|
-
task_record
|
|
401
|
-
self.update_task_state(task_record, States.failed)
|
|
402
|
-
task_record['time_returned'] = datetime.datetime.now()
|
|
403
|
-
self._send_task_log_info(task_record)
|
|
404
|
-
self.memoizer.update_memo(task_record)
|
|
405
|
-
with task_record['app_fu']._update_lock:
|
|
406
|
-
task_record['app_fu'].set_exception(e)
|
|
376
|
+
self._complete_task_exception(task_record, States.failed, e)
|
|
407
377
|
|
|
408
378
|
else:
|
|
409
379
|
if task_record['from_memo']:
|
|
410
|
-
self.
|
|
411
|
-
|
|
380
|
+
self._complete_task_result(task_record, States.memo_done, res)
|
|
381
|
+
elif not task_record['join']:
|
|
382
|
+
self._complete_task_result(task_record, States.exec_done, res)
|
|
412
383
|
else:
|
|
413
|
-
|
|
414
|
-
|
|
384
|
+
# This is a join task, and the original task's function code has
|
|
385
|
+
# completed. That means that the future returned by that code
|
|
386
|
+
# will be available inside the executor future, so we can now
|
|
387
|
+
# record the inner app ID in monitoring, and add a completion
|
|
388
|
+
# listener to that inner future.
|
|
389
|
+
|
|
390
|
+
joinable = future.result()
|
|
391
|
+
|
|
392
|
+
# Fail with a TypeError if the joinapp python body returned
|
|
393
|
+
# something we can't join on.
|
|
394
|
+
if isinstance(joinable, Future):
|
|
395
|
+
self.update_task_state(task_record, States.joining)
|
|
396
|
+
task_record['joins'] = joinable
|
|
397
|
+
task_record['join_lock'] = threading.Lock()
|
|
398
|
+
self._send_task_log_info(task_record)
|
|
399
|
+
joinable.add_done_callback(partial(self.handle_join_update, task_record))
|
|
400
|
+
elif joinable == []: # got a list, but it had no entries, and specifically, no Futures.
|
|
401
|
+
self.update_task_state(task_record, States.joining)
|
|
402
|
+
task_record['joins'] = joinable
|
|
403
|
+
task_record['join_lock'] = threading.Lock()
|
|
415
404
|
self._send_task_log_info(task_record)
|
|
405
|
+
self.handle_join_update(task_record, None)
|
|
406
|
+
elif isinstance(joinable, list) and [j for j in joinable if not isinstance(j, Future)] == []:
|
|
407
|
+
self.update_task_state(task_record, States.joining)
|
|
408
|
+
task_record['joins'] = joinable
|
|
409
|
+
task_record['join_lock'] = threading.Lock()
|
|
410
|
+
self._send_task_log_info(task_record)
|
|
411
|
+
for inner_future in joinable:
|
|
412
|
+
inner_future.add_done_callback(partial(self.handle_join_update, task_record))
|
|
416
413
|
else:
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
# listener to that inner future.
|
|
422
|
-
|
|
423
|
-
joinable = future.result()
|
|
424
|
-
|
|
425
|
-
# Fail with a TypeError if the joinapp python body returned
|
|
426
|
-
# something we can't join on.
|
|
427
|
-
if isinstance(joinable, Future):
|
|
428
|
-
self.update_task_state(task_record, States.joining)
|
|
429
|
-
task_record['joins'] = joinable
|
|
430
|
-
task_record['join_lock'] = threading.Lock()
|
|
431
|
-
self._send_task_log_info(task_record)
|
|
432
|
-
joinable.add_done_callback(partial(self.handle_join_update, task_record))
|
|
433
|
-
elif joinable == []: # got a list, but it had no entries, and specifically, no Futures.
|
|
434
|
-
self.update_task_state(task_record, States.joining)
|
|
435
|
-
task_record['joins'] = joinable
|
|
436
|
-
task_record['join_lock'] = threading.Lock()
|
|
437
|
-
self._send_task_log_info(task_record)
|
|
438
|
-
self.handle_join_update(task_record, None)
|
|
439
|
-
elif isinstance(joinable, list) and [j for j in joinable if not isinstance(j, Future)] == []:
|
|
440
|
-
self.update_task_state(task_record, States.joining)
|
|
441
|
-
task_record['joins'] = joinable
|
|
442
|
-
task_record['join_lock'] = threading.Lock()
|
|
443
|
-
self._send_task_log_info(task_record)
|
|
444
|
-
for inner_future in joinable:
|
|
445
|
-
inner_future.add_done_callback(partial(self.handle_join_update, task_record))
|
|
446
|
-
else:
|
|
447
|
-
task_record['time_returned'] = datetime.datetime.now()
|
|
448
|
-
self.update_task_state(task_record, States.failed)
|
|
449
|
-
task_record['time_returned'] = datetime.datetime.now()
|
|
450
|
-
self._send_task_log_info(task_record)
|
|
451
|
-
self.memoizer.update_memo(task_record)
|
|
452
|
-
with task_record['app_fu']._update_lock:
|
|
453
|
-
task_record['app_fu'].set_exception(
|
|
454
|
-
TypeError(f"join_app body must return a Future or list of Futures, got {joinable} of type {type(joinable)}"))
|
|
414
|
+
self._complete_task_exception(
|
|
415
|
+
task_record,
|
|
416
|
+
States.failed,
|
|
417
|
+
TypeError(f"join_app body must return a Future or list of Futures, got {joinable} of type {type(joinable)}"))
|
|
455
418
|
|
|
456
419
|
self._log_std_streams(task_record)
|
|
457
420
|
|
|
@@ -522,11 +485,7 @@ class DataFlowKernel:
|
|
|
522
485
|
# no need to update the fail cost because join apps are never
|
|
523
486
|
# retried
|
|
524
487
|
|
|
525
|
-
self.
|
|
526
|
-
task_record['time_returned'] = datetime.datetime.now()
|
|
527
|
-
self.memoizer.update_memo(task_record)
|
|
528
|
-
with task_record['app_fu']._update_lock:
|
|
529
|
-
task_record['app_fu'].set_exception(e)
|
|
488
|
+
self._complete_task_exception(task_record, States.failed, e)
|
|
530
489
|
|
|
531
490
|
else:
|
|
532
491
|
# all the joinables succeeded, so construct a result:
|
|
@@ -539,12 +498,10 @@ class DataFlowKernel:
|
|
|
539
498
|
res.append(future.result())
|
|
540
499
|
else:
|
|
541
500
|
raise TypeError(f"Unknown joinable type {type(joinable)}")
|
|
542
|
-
self.
|
|
501
|
+
self._complete_task_result(task_record, States.exec_done, res)
|
|
543
502
|
|
|
544
503
|
self._log_std_streams(task_record)
|
|
545
504
|
|
|
546
|
-
self._send_task_log_info(task_record)
|
|
547
|
-
|
|
548
505
|
def handle_app_update(self, task_record: TaskRecord, future: AppFuture) -> None:
|
|
549
506
|
"""This function is called as a callback when an AppFuture
|
|
550
507
|
is in its final state.
|
|
@@ -565,23 +522,12 @@ class DataFlowKernel:
|
|
|
565
522
|
if not task_record['app_fu'] == future:
|
|
566
523
|
logger.error("Internal consistency error: callback future is not the app_fu in task structure, for task {}".format(task_id))
|
|
567
524
|
|
|
568
|
-
|
|
569
|
-
# Do we need to checkpoint now, or queue for later,
|
|
570
|
-
# or do nothing?
|
|
571
|
-
if self.checkpoint_mode == 'task_exit':
|
|
572
|
-
self.checkpoint(tasks=[task_record])
|
|
573
|
-
elif self.checkpoint_mode in ('manual', 'periodic', 'dfk_exit'):
|
|
574
|
-
with self.checkpoint_lock:
|
|
575
|
-
self.checkpointable_tasks.append(task_record)
|
|
576
|
-
elif self.checkpoint_mode is None:
|
|
577
|
-
pass
|
|
578
|
-
else:
|
|
579
|
-
raise InternalConsistencyError(f"Invalid checkpoint mode {self.checkpoint_mode}")
|
|
525
|
+
self.memoizer.update_checkpoint(task_record)
|
|
580
526
|
|
|
581
527
|
self.wipe_task(task_id)
|
|
582
528
|
return
|
|
583
529
|
|
|
584
|
-
def
|
|
530
|
+
def _complete_task_result(self, task_record: TaskRecord, new_state: States, result: Any) -> None:
|
|
585
531
|
"""Set a task into a completed state
|
|
586
532
|
"""
|
|
587
533
|
assert new_state in FINAL_STATES
|
|
@@ -594,9 +540,31 @@ class DataFlowKernel:
|
|
|
594
540
|
task_record['time_returned'] = datetime.datetime.now()
|
|
595
541
|
|
|
596
542
|
self.memoizer.update_memo(task_record)
|
|
543
|
+
|
|
544
|
+
self._send_task_log_info(task_record)
|
|
545
|
+
|
|
597
546
|
with task_record['app_fu']._update_lock:
|
|
598
547
|
task_record['app_fu'].set_result(result)
|
|
599
548
|
|
|
549
|
+
def _complete_task_exception(self, task_record: TaskRecord, new_state: States, exception: BaseException) -> None:
|
|
550
|
+
"""Set a task into a failure state
|
|
551
|
+
"""
|
|
552
|
+
assert new_state in FINAL_STATES
|
|
553
|
+
assert new_state in FINAL_FAILURE_STATES
|
|
554
|
+
old_state = task_record['status']
|
|
555
|
+
|
|
556
|
+
self.update_task_state(task_record, new_state)
|
|
557
|
+
|
|
558
|
+
logger.info(f"Task {task_record['id']} failed ({old_state.name} -> {new_state.name})")
|
|
559
|
+
task_record['time_returned'] = datetime.datetime.now()
|
|
560
|
+
|
|
561
|
+
self.memoizer.update_memo(task_record)
|
|
562
|
+
|
|
563
|
+
self._send_task_log_info(task_record)
|
|
564
|
+
|
|
565
|
+
with task_record['app_fu']._update_lock:
|
|
566
|
+
task_record['app_fu'].set_exception(exception)
|
|
567
|
+
|
|
600
568
|
def update_task_state(self, task_record: TaskRecord, new_state: States) -> None:
|
|
601
569
|
"""Updates a task record state, and recording an appropriate change
|
|
602
570
|
to task state counters.
|
|
@@ -640,7 +608,7 @@ class DataFlowKernel:
|
|
|
640
608
|
launch_if_ready is thread safe, so may be called from any thread
|
|
641
609
|
or callback.
|
|
642
610
|
"""
|
|
643
|
-
self.
|
|
611
|
+
self._task_launch_pool.submit(self._launch_if_ready_async, task_record)
|
|
644
612
|
|
|
645
613
|
@wrap_with_logs
|
|
646
614
|
def _launch_if_ready_async(self, task_record: TaskRecord) -> None:
|
|
@@ -648,7 +616,7 @@ class DataFlowKernel:
|
|
|
648
616
|
_launch_if_ready will launch the specified task, if it is ready
|
|
649
617
|
to run (for example, without dependencies, and in pending state).
|
|
650
618
|
"""
|
|
651
|
-
exec_fu
|
|
619
|
+
exec_fu: Future
|
|
652
620
|
|
|
653
621
|
task_id = task_record['id']
|
|
654
622
|
with task_record['task_launch_lock']:
|
|
@@ -687,28 +655,24 @@ class DataFlowKernel:
|
|
|
687
655
|
else:
|
|
688
656
|
logger.info(
|
|
689
657
|
"Task {} failed due to dependency failure".format(task_id))
|
|
690
|
-
# Raise a dependency exception
|
|
691
|
-
self.update_task_state(task_record, States.dep_fail)
|
|
692
|
-
|
|
693
|
-
self._send_task_log_info(task_record)
|
|
694
658
|
|
|
695
659
|
exec_fu = Future()
|
|
696
660
|
exec_fu.set_exception(DependencyError(exceptions_tids,
|
|
697
661
|
task_id))
|
|
698
662
|
|
|
699
|
-
|
|
700
|
-
assert isinstance(exec_fu, Future)
|
|
701
|
-
try:
|
|
702
|
-
exec_fu.add_done_callback(partial(self.handle_exec_update, task_record))
|
|
703
|
-
except Exception:
|
|
704
|
-
# this exception is ignored here because it is assumed that exception
|
|
705
|
-
# comes from directly executing handle_exec_update (because exec_fu is
|
|
706
|
-
# done already). If the callback executes later, then any exception
|
|
707
|
-
# coming out of the callback will be ignored and not propate anywhere,
|
|
708
|
-
# so this block attempts to keep the same behaviour here.
|
|
709
|
-
logger.error("add_done_callback got an exception which will be ignored", exc_info=True)
|
|
663
|
+
assert isinstance(exec_fu, Future), "Every code path leading here needs to define exec_fu"
|
|
710
664
|
|
|
711
|
-
|
|
665
|
+
try:
|
|
666
|
+
exec_fu.add_done_callback(partial(self.handle_exec_update, task_record))
|
|
667
|
+
except Exception:
|
|
668
|
+
# this exception is ignored here because it is assumed that exception
|
|
669
|
+
# comes from directly executing handle_exec_update (because exec_fu is
|
|
670
|
+
# done already). If the callback executes later, then any exception
|
|
671
|
+
# coming out of the callback will be ignored and not propate anywhere,
|
|
672
|
+
# so this block attempts to keep the same behaviour here.
|
|
673
|
+
logger.error("add_done_callback got an exception which will be ignored", exc_info=True)
|
|
674
|
+
|
|
675
|
+
task_record['exec_fu'] = exec_fu
|
|
712
676
|
|
|
713
677
|
def launch_task(self, task_record: TaskRecord) -> Future:
|
|
714
678
|
"""Handle the actual submission of the task to the executor layer.
|
|
@@ -1205,13 +1169,7 @@ class DataFlowKernel:
|
|
|
1205
1169
|
|
|
1206
1170
|
self.log_task_states()
|
|
1207
1171
|
|
|
1208
|
-
|
|
1209
|
-
if self.checkpoint_mode is not None:
|
|
1210
|
-
self.checkpoint()
|
|
1211
|
-
|
|
1212
|
-
if self._checkpoint_timer:
|
|
1213
|
-
logger.info("Stopping checkpoint timer")
|
|
1214
|
-
self._checkpoint_timer.close()
|
|
1172
|
+
self.memoizer.close()
|
|
1215
1173
|
|
|
1216
1174
|
# Send final stats
|
|
1217
1175
|
self.usage_tracker.send_end_message()
|
|
@@ -1245,9 +1203,9 @@ class DataFlowKernel:
|
|
|
1245
1203
|
self.monitoring.close()
|
|
1246
1204
|
logger.info("Terminated monitoring")
|
|
1247
1205
|
|
|
1248
|
-
logger.info("Terminating
|
|
1249
|
-
self.
|
|
1250
|
-
logger.info("Terminated
|
|
1206
|
+
logger.info("Terminating task launch pool")
|
|
1207
|
+
self._task_launch_pool.shutdown()
|
|
1208
|
+
logger.info("Terminated task launch pool")
|
|
1251
1209
|
|
|
1252
1210
|
logger.info("Unregistering atexit hook")
|
|
1253
1211
|
atexit.unregister(self.atexit_cleanup)
|
|
@@ -1269,66 +1227,8 @@ class DataFlowKernel:
|
|
|
1269
1227
|
# should still see it.
|
|
1270
1228
|
logger.info("DFK cleanup complete")
|
|
1271
1229
|
|
|
1272
|
-
def checkpoint(self
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
When called, every task that has been completed yet not
|
|
1276
|
-
checkpointed is checkpointed to a file.
|
|
1277
|
-
|
|
1278
|
-
Kwargs:
|
|
1279
|
-
- tasks (List of task records) : List of task ids to checkpoint. Default=None
|
|
1280
|
-
if set to None, we iterate over all tasks held by the DFK.
|
|
1281
|
-
|
|
1282
|
-
.. note::
|
|
1283
|
-
Checkpointing only works if memoization is enabled
|
|
1284
|
-
|
|
1285
|
-
Returns:
|
|
1286
|
-
Checkpoint dir if checkpoints were written successfully.
|
|
1287
|
-
By default the checkpoints are written to the RUNDIR of the current
|
|
1288
|
-
run under RUNDIR/checkpoints/tasks.pkl
|
|
1289
|
-
"""
|
|
1290
|
-
with self.checkpoint_lock:
|
|
1291
|
-
if tasks:
|
|
1292
|
-
checkpoint_queue = tasks
|
|
1293
|
-
else:
|
|
1294
|
-
checkpoint_queue = self.checkpointable_tasks
|
|
1295
|
-
self.checkpointable_tasks = []
|
|
1296
|
-
|
|
1297
|
-
checkpoint_dir = '{0}/checkpoint'.format(self.run_dir)
|
|
1298
|
-
checkpoint_tasks = checkpoint_dir + '/tasks.pkl'
|
|
1299
|
-
|
|
1300
|
-
if not os.path.exists(checkpoint_dir):
|
|
1301
|
-
os.makedirs(checkpoint_dir, exist_ok=True)
|
|
1302
|
-
|
|
1303
|
-
count = 0
|
|
1304
|
-
|
|
1305
|
-
with open(checkpoint_tasks, 'ab') as f:
|
|
1306
|
-
for task_record in checkpoint_queue:
|
|
1307
|
-
task_id = task_record['id']
|
|
1308
|
-
|
|
1309
|
-
app_fu = task_record['app_fu']
|
|
1310
|
-
|
|
1311
|
-
if app_fu.done() and app_fu.exception() is None:
|
|
1312
|
-
hashsum = task_record['hashsum']
|
|
1313
|
-
if not hashsum:
|
|
1314
|
-
continue
|
|
1315
|
-
t = {'hash': hashsum, 'exception': None, 'result': app_fu.result()}
|
|
1316
|
-
|
|
1317
|
-
# We are using pickle here since pickle dumps to a file in 'ab'
|
|
1318
|
-
# mode behave like a incremental log.
|
|
1319
|
-
pickle.dump(t, f)
|
|
1320
|
-
count += 1
|
|
1321
|
-
logger.debug("Task {} checkpointed".format(task_id))
|
|
1322
|
-
|
|
1323
|
-
self.checkpointed_tasks += count
|
|
1324
|
-
|
|
1325
|
-
if count == 0:
|
|
1326
|
-
if self.checkpointed_tasks == 0:
|
|
1327
|
-
logger.warning("No tasks checkpointed so far in this run. Please ensure caching is enabled")
|
|
1328
|
-
else:
|
|
1329
|
-
logger.debug("No tasks checkpointed in this pass.")
|
|
1330
|
-
else:
|
|
1331
|
-
logger.info("Done checkpointing {} tasks".format(count))
|
|
1230
|
+
def checkpoint(self) -> None:
|
|
1231
|
+
self.memoizer.checkpoint()
|
|
1332
1232
|
|
|
1333
1233
|
@staticmethod
|
|
1334
1234
|
def _log_std_streams(task_record: TaskRecord) -> None:
|